package de.steamwar.bausystem.tracer; import org.bukkit.entity.Player; import java.util.*; public class TraceCache { private static final Set empty = new HashSet<>(); private Map> playerMap = new HashMap<>(); private Map playerDisplayMap = new HashMap<>(); public Set get(Player player) { return playerMap.getOrDefault(player.getUniqueId().toString(), empty); } Set update(Player player, boolean dirty) { if (!dirty) return empty; String key = player.getUniqueId().toString(); Set locOld; ShowManager.DisplayType displayMode; if (!playerMap.containsKey(key)) { locOld = new HashSet<>(); displayMode = getDisplayType(player); } else { locOld = playerMap.get(key); displayMode = playerDisplayMap.get(key); } Set locSet = new HashSet<>(); updatePoints(player).forEach(loc -> { loc.updatePoint = true; locSet.add(loc); }); updateLocations(player).forEach(loc -> { loc.updatePoint = false; locSet.add(loc); }); playerMap.put(key, locSet); ShowManager.DisplayType currentMode = getDisplayType(player); playerDisplayMap.put(key, currentMode); if (currentMode == ShowManager.DisplayType.Particle && displayMode == ShowManager.DisplayType.Block) return locOld; if (currentMode == ShowManager.DisplayType.Block) return diff(locOld, locSet); return empty; } public static class Loc { final float x; final float y; final float z; private final float dx; private final float dy; private final float dz; boolean updatePoint = false; public Loc(float x, float y, float z) { this.x = x; this.y = y; this.z = z; this.dx = round(x); this.dy = round(y); this.dz = round(z); } private static float round(float toRound) { final int roundNumber = 10; float r = (toRound * roundNumber); float t = r - (int) r; if (t >= 0.5) { return (((float)(int)r) + 1) / roundNumber; } else { return (((float)(int)r) + 0) / roundNumber; } } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Loc)) return false; Loc loc = (Loc) o; return Float.compare(loc.dx, dx) == 0 && Float.compare(loc.dy, dy) == 0 && Float.compare(loc.dz, dz) == 0; } @Override public int hashCode() { return Objects.hash(dx, dy, dz); } @Override public String toString() { return "Loc{" + "x=" + x + ", y=" + y + ", z=" + z + '}'; } public boolean remove(Player player, double radius) { double x = player.getLocation().getX(); double y = player.getLocation().getY(); double z = player.getLocation().getZ(); double dx = (this.x - x) * (this.x - x); double dy = (this.y - y) * (this.y - y); double dz = (this.z - z) * (this.z - z); return (dx + dy + dz) > radius * radius; } } private Set diff(Set locOld, Set locNew) { if (locOld.isEmpty()) return empty; if (locNew.isEmpty()) return locOld; for (Loc l : locNew) { locOld.remove(l); } return locOld; } private Set updateLocations(Player player) { Iterator traces = ShowManager.get(player).getTraces().descendingIterator(); Set locSet = new HashSet<>(); while (traces.hasNext()) { locSet.addAll(traces.next().locs()); } double radius = ShowManager.get(player).getShowRadius(); locSet.removeIf(loc -> loc.remove(player, radius)); return locSet; } private Set updatePoints(Player player) { Iterator traces = ShowManager.get(player).getTraces().descendingIterator(); Set locSet = new HashSet<>(); while (traces.hasNext()) { locSet.addAll(traces.next().locsUpdate(ShowManager.get(player).getDisplayMode())); } double radius = ShowManager.get(player).getShowRadius(); locSet.removeIf(loc -> loc.remove(player, radius)); return locSet; } private ShowManager.DisplayType getDisplayType(Player player) { return ShowManager.get(player).getDisplayType(); } }