summaryrefslogtreecommitdiff
path: root/src/main/java/org/challman/pantheon_parser/EntityMap.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/challman/pantheon_parser/EntityMap.java')
-rw-r--r--src/main/java/org/challman/pantheon_parser/EntityMap.java355
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