diff options
Diffstat (limited to 'src/main/java/org/challman/pantheon_parser/EntityMap.java')
| -rw-r--r-- | src/main/java/org/challman/pantheon_parser/EntityMap.java | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/src/main/java/org/challman/pantheon_parser/EntityMap.java b/src/main/java/org/challman/pantheon_parser/EntityMap.java new file mode 100644 index 0000000..36d96d6 --- /dev/null +++ b/src/main/java/org/challman/pantheon_parser/EntityMap.java @@ -0,0 +1,355 @@ +package org.challman.pantheon_parser; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class EntityMap extends JPanel { + private Map<String, Entity> entities = new ConcurrentHashMap<>(); + private Entity player; + private long entityTimeout = 10000; + private volatile boolean needsRepaint = false; + private double scale = 1.0; + private JButton zoomInButton, zoomOutButton; + private JButton closeButton; + private int controlPanelHeight = 25; + + // Drag variables + private Point dragStartPoint; + private Point windowStartPoint; + + public EntityMap() { + setOpaque(true); + setBackground(new Color(30, 30, 30)); + setPreferredSize(new Dimension(300, 300)); + setLayout(new BorderLayout()); + + // Create control panel + JPanel controlPanel = createControlPanel(); + add(controlPanel, BorderLayout.NORTH); + + // Add mouse listeners for dragging + addMouseListeners(); + + Timer timer = new Timer(33, e -> { + if (needsRepaint) { + repaint(); + needsRepaint = false; + } + }); + timer.start(); + } + + public Entity getEntity(String id) { + return entities.get(id); + } + + private JPanel createControlPanel() { + JPanel panel = new JPanel(new BorderLayout()); + panel.setOpaque(false); + panel.setPreferredSize(new Dimension(300, controlPanelHeight)); + panel.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5)); + + // Left side: drag handle + JLabel dragHandle = new JLabel("≡ Minimap"); + dragHandle.setForeground(Color.LIGHT_GRAY); + dragHandle.setFont(new Font("Arial", Font.PLAIN, 10)); + dragHandle.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); + + // Right side: control buttons + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 3, 0)); + buttonPanel.setOpaque(false); + + zoomOutButton = new JButton("-"); + zoomInButton = new JButton("+"); + closeButton = new JButton("×"); + + styleButton(zoomOutButton); + styleButton(zoomInButton); + styleCloseButton(closeButton); + + zoomOutButton.addActionListener(e -> zoomOut()); + zoomInButton.addActionListener(e -> zoomIn()); + closeButton.addActionListener(e -> System.exit(0)); + + buttonPanel.add(zoomOutButton); + buttonPanel.add(zoomInButton); + buttonPanel.add(closeButton); + + panel.add(dragHandle, BorderLayout.WEST); + panel.add(buttonPanel, BorderLayout.EAST); + + return panel; + } + + private void styleButton(JButton button) { + button.setPreferredSize(new Dimension(25, 18)); + button.setFont(new Font("Arial", Font.BOLD, 10)); + button.setFocusable(false); + button.setBackground(new Color(60, 60, 60)); + button.setForeground(Color.WHITE); + button.setBorder(BorderFactory.createLineBorder(Color.GRAY)); + + button.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + button.setBackground(new Color(80, 80, 80)); + } + + @Override + public void mouseExited(MouseEvent e) { + button.setBackground(new Color(60, 60, 60)); + } + }); + } + + private void styleCloseButton(JButton button) { + button.setPreferredSize(new Dimension(25, 18)); + button.setFont(new Font("Arial", Font.BOLD, 12)); + button.setFocusable(false); + button.setBackground(new Color(100, 60, 60)); + button.setForeground(Color.WHITE); + button.setBorder(BorderFactory.createLineBorder(new Color(120, 80, 80))); + + button.addMouseListener(new MouseAdapter() { + @Override + public void mouseEntered(MouseEvent e) { + button.setBackground(new Color(140, 80, 80)); + } + + @Override + public void mouseExited(MouseEvent e) { + button.setBackground(new Color(100, 60, 60)); + } + }); + } + + private void addMouseListeners() { + MouseAdapter dragAdapter = new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + dragStartPoint = e.getPoint(); + Window window = SwingUtilities.getWindowAncestor(EntityMap.this); + if (window != null) { + windowStartPoint = window.getLocation(); + } + } + + @Override + public void mouseDragged(MouseEvent e) { + if (dragStartPoint != null && windowStartPoint != null) { + Point currentPoint = e.getPoint(); + int deltaX = currentPoint.x - dragStartPoint.x; + int deltaY = currentPoint.y - dragStartPoint.y; + + Window window = SwingUtilities.getWindowAncestor(EntityMap.this); + if (window != null) { + Point newLocation = new Point( + windowStartPoint.x + deltaX, + windowStartPoint.y + deltaY + ); + window.setLocation(newLocation); + } + } + } + + @Override + public void mouseReleased(MouseEvent e) { + dragStartPoint = null; + windowStartPoint = null; + } + }; + + // Add listeners to the entire panel for dragging + addMouseListener(dragAdapter); + addMouseMotionListener(dragAdapter); + + // Also add to control panel for easier dragging + Component[] components = getComponents(); + for (Component comp : components) { + if (comp instanceof JPanel) { + comp.addMouseListener(dragAdapter); + comp.addMouseMotionListener(dragAdapter); + } + } + } + + private void zoomIn() { + scale *= 1.2; + if (scale > 10.0) scale = 10.0; + needsRepaint = true; + } + + private void zoomOut() { + scale /= 1.2; + if (scale < 0.1) scale = 0.1; + needsRepaint = true; + } + + public void updateEntity(Entity entity, Entity currentPlayer) { + entities.put(entity.id, entity); + if (currentPlayer != null) { + this.player = currentPlayer; + } + cleanupOldEntities(); + needsRepaint = true; + } + + public Collection<Entity> getAllEntities() { + return entities.values(); + } + + private void cleanupOldEntities() { + long currentTime = System.currentTimeMillis(); + entities.entrySet().removeIf(entry -> { + Entity entity = entry.getValue(); + return entity != player && entity.lastUpdated != -1 && (currentTime - entity.lastUpdated) > entityTimeout; + }); + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + Graphics2D g2d = (Graphics2D) g.create(); + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + if (player == null) { + g2d.dispose(); + return; + } + + // Calculate available space for the circle + int width = getWidth(); + int height = getHeight() - controlPanelHeight; + int size = Math.min(width, height); + int mapRadius = size / 2; + int centerX = width / 2; + int centerY = controlPanelHeight + (height / 2); + + // Draw circular map background (maximized) + g2d.setColor(new Color(20, 20, 20)); + g2d.fillOval(centerX - mapRadius, centerY - mapRadius, size, size); + + // Draw map border + g2d.setColor(new Color(100, 100, 100)); + g2d.setStroke(new BasicStroke(2)); + g2d.drawOval(centerX - mapRadius, centerY - mapRadius, size, size); + + // Draw grid lines + g2d.setColor(new Color(50, 50, 50)); + g2d.setStroke(new BasicStroke(1)); + g2d.drawLine(centerX, centerY - mapRadius, centerX, centerY + mapRadius); + g2d.drawLine(centerX - mapRadius, centerY, centerX + mapRadius, centerY); + + // Calculate scale with zoom factor + double maxDistance = 50.0 / scale; + double distanceScale = mapRadius / maxDistance; + + // Draw other entities + g2d.setFont(new Font("Arial", Font.PLAIN, 9)); + for (Entity entity : entities.values()) { + if (entity.id.equals(player.id)) continue; + + double dx = entity.x - player.x; + double dz = entity.z - player.z; + double distance = Math.sqrt(dx * dx + dz * dz); + + if (distance <= maxDistance) { + int x = centerX + (int)(dx * distanceScale); + int y = centerY - (int)(dz * distanceScale); + + double distFromCenter = Math.sqrt((x - centerX) * (x - centerX) + (y - centerY) * (y - centerY)); + if (distFromCenter <= mapRadius - 5) { + if (entity.type == 2) { + g2d.setColor(Color.CYAN); + } else if (entity.type == 3) { + g2d.setColor(Color.ORANGE); + } else { + g2d.setColor(Color.WHITE); + } + g2d.fillOval(x - 3, y - 3, 6, 6); + + if (distance < maxDistance * 0.9) { + g2d.setColor(Color.WHITE); + g2d.drawString(entity.id, x + 5, y); + } + } + } + } + + // Draw player + g2d.setColor(Color.RED); + g2d.fillOval(centerX - 4, centerY - 4, 8, 8); + + // Draw direction indicator + double directionAngle = Math.toRadians(player.heading); + int dirX = centerX + (int)((mapRadius - 10) * Math.sin(directionAngle)); + int dirY = centerY - (int)((mapRadius - 10) * Math.cos(directionAngle)); + g2d.setColor(Color.YELLOW); + g2d.setStroke(new BasicStroke(2)); + g2d.drawLine(centerX, centerY, dirX, dirY); + + // Draw UI elements in corners + drawCornerElements(g2d, centerX, centerY, mapRadius); + + g2d.dispose(); + } + + private void drawCornerElements(Graphics2D g2d, int centerX, int centerY, int mapRadius) { + g2d.setColor(Color.WHITE); + g2d.setFont(new Font("Arial", Font.PLAIN, 10)); + + // Top-left: Scale indicator + int topLeftX = centerX - mapRadius + 5; + int topLeftY = centerY - mapRadius + 15; + g2d.drawString(String.format("Zoom: %.1fx", scale), topLeftX, topLeftY); + + // Top-right: Entity count + int topRightX = centerX + mapRadius - 60; + int topRightY = centerY - mapRadius + 15; + int entityCount = entities.size() - (player != null ? 1 : 0); + g2d.drawString(String.format("Entities: %d", entityCount), topRightX, topRightY); + + // Bottom-left: Player coordinates + int bottomLeftX = centerX - mapRadius + 5; + int bottomLeftY = centerY + mapRadius - 5; + g2d.drawString(String.format("(%.1f, %.1f)", player.x, player.z), bottomLeftX - 10, bottomLeftY); + + // Bottom-right: Compass heading + int bottomRightX = centerX + mapRadius - 50; + int bottomRightY = centerY + mapRadius - 5; + g2d.drawString(String.format("%.0f°", player.heading), bottomRightX, bottomRightY); + + // Draw mini compass in top-right corner + drawMiniCompass(g2d, centerX + mapRadius - 20, centerY - mapRadius + 35, player.heading); + } + + private void drawMiniCompass(Graphics2D g2d, int x, int y, float heading) { + int radius = 8; + + g2d.setColor(new Color(50, 50, 50, 200)); + g2d.fillOval(x - radius, y - radius, radius * 2, radius * 2); + g2d.setColor(Color.WHITE); + g2d.drawOval(x - radius, y - radius, radius * 2, radius * 2); + + // Draw N indicator + g2d.setFont(new Font("Arial", Font.BOLD, 8)); + g2d.drawString("N", x - 2, y - radius - 1); + + double needleAngle = Math.toRadians(heading); + int needleX = x + (int)(radius * Math.sin(needleAngle)); + int needleY = y - (int)(radius * Math.cos(needleAngle)); + + g2d.setColor(Color.RED); + g2d.setStroke(new BasicStroke(1.5f)); + g2d.drawLine(x, y, needleX, needleY); + g2d.setStroke(new BasicStroke(1)); + } +}
\ No newline at end of file |