package server.maps; import tools.FileoutputUtil; import java.awt.Point; import java.util.Collections; import java.util.LinkedList; import java.util.List; public class MapleFootholdTree { private MapleFootholdTree nw = null; private MapleFootholdTree ne = null; private MapleFootholdTree sw = null; private MapleFootholdTree se = null; private final List<MapleFoothold> footholds = new LinkedList(); private final Point p1; private final Point p2; private final Point center; private int depth = 0; private static byte maxDepth = 8; private int maxDropX; private int minDropX; public MapleFootholdTree(Point p1, Point p2) { this.p1 = p1; this.p2 = p2; this.center = new Point((p2.x - p1.x) / 2, (p2.y - p1.y) / 2); } public MapleFootholdTree(Point p1, Point p2, int depth) { this.p1 = p1; this.p2 = p2; this.depth = depth; this.center = new Point((p2.x - p1.x) / 2, (p2.y - p1.y) / 2); } public void insert(MapleFoothold f) { if (this.depth == 0) { if (f.getX1() > this.maxDropX) { this.maxDropX = f.getX1(); } if (f.getX1() < this.minDropX) { this.minDropX = f.getX1(); } if (f.getX2() > this.maxDropX) { this.maxDropX = f.getX2(); } if (f.getX2() < this.minDropX) { this.minDropX = f.getX2(); } } if ((this.depth == maxDepth) || ((f.getX1() >= this.p1.x) && (f.getX2() <= this.p2.x) && (f.getY1() >= this.p1.y) && (f.getY2() <= this.p2.y))) { this.footholds.add(f); } else { if (this.nw == null) { this.nw = new MapleFootholdTree(this.p1, this.center, this.depth + 1); this.ne = new MapleFootholdTree(new Point(this.center.x, this.p1.y), new Point(this.p2.x, this.center.y), this.depth + 1); this.sw = new MapleFootholdTree(new Point(this.p1.x, this.center.y), new Point(this.center.x, this.p2.y), this.depth + 1); this.se = new MapleFootholdTree(this.center, this.p2, this.depth + 1); } if ((f.getX2() <= this.center.x) && (f.getY2() <= this.center.y)) { this.nw.insert(f); } else if ((f.getX1() > this.center.x) && (f.getY2() <= this.center.y)) { this.ne.insert(f); } else if ((f.getX2() <= this.center.x) && (f.getY1() > this.center.y)) { this.sw.insert(f); } else { this.se.insert(f); } } } public List<MapleFoothold> getAllRelevants() { return getAllRelevants(new LinkedList()); } private List<MapleFoothold> getAllRelevants(List<MapleFoothold> list) { list.addAll(this.footholds); if (this.nw != null) { this.nw.getAllRelevants(list); this.ne.getAllRelevants(list); this.sw.getAllRelevants(list); this.se.getAllRelevants(list); } return list; } private List<MapleFoothold> getRelevants(Point p) { return getRelevants(p, new LinkedList()); } private List<MapleFoothold> getRelevants(Point p, List<MapleFoothold> list) { list.addAll(this.footholds); if (this.nw != null) { if ((p.x <= this.center.x) && (p.y <= this.center.y)) { this.nw.getRelevants(p, list); } else if ((p.x > this.center.x) && (p.y <= this.center.y)) { this.ne.getRelevants(p, list); } else if ((p.x <= this.center.x) && (p.y > this.center.y)) { this.sw.getRelevants(p, list); } else { this.se.getRelevants(p, list); } } return list; } private MapleFoothold findWallR(Point p1, Point p2) { for (MapleFoothold f : this.footholds) { if ((f.isWall()) && (f.getX1() >= p1.x) && (f.getX1() <= p2.x) && (f.getY1() >= p1.y) && (f.getY2() <= p1.y)) { return f; } } if (this.nw != null) { if ((p1.x <= this.center.x) && (p1.y <= this.center.y)) { MapleFoothold ret = this.nw.findWallR(p1, p2); if (ret != null) { return ret; } } if (((p1.x > this.center.x) || (p2.x > this.center.x)) && (p1.y <= this.center.y)) { MapleFoothold ret = this.ne.findWallR(p1, p2); if (ret != null) { return ret; } } if ((p1.x <= this.center.x) && (p1.y > this.center.y)) { MapleFoothold ret = this.sw.findWallR(p1, p2); if (ret != null) { return ret; } } if (((p1.x > this.center.x) || (p2.x > this.center.x)) && (p1.y > this.center.y)) { MapleFoothold ret = this.se.findWallR(p1, p2); if (ret != null) { return ret; } } } return null; } public MapleFoothold findWall(Point p1, Point p2) { if (p1.y != p2.y) { throw new IllegalArgumentException(); } return findWallR(p1, p2); } public boolean checkRelevantFH(short fromx, short fromy, short tox, short toy) { MapleFoothold fhdata = null; for (MapleFoothold fh : this.footholds) { if ((fh.getX1() <= fromx) && (fh.getX2() >= fromx) && (fh.getY1() <= fromy) && (fh.getY2() >= fromy)) { fhdata = fh; break; } } for (MapleFoothold fh2 : this.footholds) { if ((fh2.getX1() <= tox) && (fh2.getX2() >= tox) && (fh2.getY1() <= toy) && (fh2.getY2() >= toy)) { if (fhdata != null && (fhdata.getId() != fh2.getId()) && (fh2.getId() != fhdata.getNext()) && (fh2.getId() != fhdata.getPrev())) { FileoutputUtil.log("Couldn't find the correct pos for next/prev"); return false; } return true; } } return false; } public MapleFoothold findBelow(Point p) { List<MapleFoothold> relevants = getRelevants(p); List<MapleFoothold> xMatches = new LinkedList(); for (MapleFoothold fh : relevants) { if ((fh.getX1() <= p.x) && (fh.getX2() >= p.x)) { xMatches.add(fh); } } Collections.sort(xMatches); for (MapleFoothold fh : xMatches) { if ((!fh.isWall()) && (fh.getY1() != fh.getY2())) { double s1 = Math.abs(fh.getY2() - fh.getY1()); double s2 = Math.abs(fh.getX2() - fh.getX1()); double s4 = Math.abs(p.x - fh.getX1()); double alpha = Math.atan(s2 / s1); double beta = Math.atan(s1 / s2); double s5 = Math.cos(alpha) * (s4 / Math.cos(beta)); int calcY; if (fh.getY2() < fh.getY1()) { calcY = fh.getY1() - (int) s5; } else { calcY = fh.getY1() + (int) s5; } if (calcY >= p.y) { return fh; } } else if ((!fh.isWall()) && (fh.getY1() >= p.y)) { return fh; } } return null; } public int getX1() { return this.p1.x; } public int getX2() { return this.p2.x; } public int getY1() { return this.p1.y; } public int getY2() { return this.p2.y; } public int getMaxDropX() { return this.maxDropX; } public int getMinDropX() { return this.minDropX; } }