Skip to content

Commit e556215

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents 660169c + 4dc2e97 commit e556215

File tree

5 files changed

+376
-27
lines changed

5 files changed

+376
-27
lines changed

.github/dependabot.yml

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/main/java/io/luna/game/model/area/PolygonArea.java

Lines changed: 110 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
import com.google.common.collect.ImmutableSet;
55
import io.luna.game.model.Position;
66

7-
import java.awt.*;
8-
import java.awt.geom.Rectangle2D;
7+
import java.awt.Point;
98
import java.util.LinkedHashSet;
109
import java.util.List;
1110
import java.util.Set;
@@ -17,9 +16,19 @@
1716
public class PolygonArea extends Area {
1817

1918
/**
20-
* The representation of our arbitrary polygon.
19+
* The rectangular bounding box constraints of this polygon.
2120
*/
22-
private final Polygon polygon;
21+
private int southWestX;
22+
private int southWestY;
23+
private int northEastX;
24+
private int northEastY;
25+
26+
/**
27+
* The points of this polygon.
28+
*/
29+
private int npoints;
30+
private int[] xpoints;
31+
private int[] ypoints;
2332

2433
/**
2534
* The precomputed hashcode.
@@ -46,7 +55,7 @@ public class PolygonArea extends Area {
4655
// Precompute hashcode
4756
hashCode = Objects.hashCode(vertices);
4857

49-
// Reformat to create java.awt.Polygon
58+
// Extract the points for this polygon from the vertices
5059
int index = 0;
5160
int totalSize = vertices.size();
5261
int[] x = new int[totalSize];
@@ -56,7 +65,11 @@ public class PolygonArea extends Area {
5665
y[index] = (int) point.getY();
5766
index++;
5867
}
59-
polygon = new Polygon(x, y, totalSize);
68+
69+
this.npoints = totalSize;
70+
this.xpoints = x;
71+
this.ypoints = y;
72+
calculateBounds(xpoints, ypoints, npoints);
6073
}
6174

6275
@Override
@@ -74,7 +87,69 @@ public int hashCode() {
7487

7588
@Override
7689
public boolean contains(Position position) {
77-
return polygon.contains(position.getX(), position.getY());
90+
int x = position.getX();
91+
int y = position.getY();
92+
93+
if (npoints <= 2 || !inBounds(x, y)) {
94+
return false;
95+
}
96+
int hits = 0;
97+
98+
int lastx = xpoints[npoints - 1];
99+
int lasty = ypoints[npoints - 1];
100+
int curx, cury;
101+
102+
// Walk the edges of the polygon
103+
for (int i = 0; i < npoints; lastx = curx, lasty = cury, i++) {
104+
curx = xpoints[i];
105+
cury = ypoints[i];
106+
107+
if (cury == lasty) {
108+
continue;
109+
}
110+
111+
int leftx;
112+
if (curx < lastx) {
113+
if (x >= lastx) {
114+
continue;
115+
}
116+
leftx = curx;
117+
} else {
118+
if (x >= curx) {
119+
continue;
120+
}
121+
leftx = lastx;
122+
}
123+
124+
double test1, test2;
125+
if (cury < lasty) {
126+
if (y < cury || y >= lasty) {
127+
continue;
128+
}
129+
if (x < leftx) {
130+
hits++;
131+
continue;
132+
}
133+
test1 = x - curx;
134+
test2 = y - cury;
135+
} else {
136+
if (y < lasty || y >= cury) {
137+
continue;
138+
}
139+
if (x < leftx) {
140+
hits++;
141+
continue;
142+
}
143+
test1 = x - lastx;
144+
test2 = y - lasty;
145+
}
146+
147+
if (test1 < (test2 / (lasty - cury) * (lastx - curx))) {
148+
hits++;
149+
}
150+
}
151+
152+
return ((hits & 1) != 0);
78153
}
79154

80155
@Override
@@ -97,12 +172,6 @@ public Position randomPosition() {
97172

98173
@Override
99174
public ImmutableSet<Position> computePositionSet() {
100-
// Create a rectangle that encompasses our polygon.
101-
Rectangle2D outer = polygon.getBounds2D();
102-
int southWestX = (int) outer.getMinX();
103-
int southWestY = (int) outer.getMinY();
104-
int northEastX = (int) outer.getMaxX();
105-
int northEastY = (int) outer.getMaxY();
106175

107176
// Build it into a simple box area, get every position inside.
108177
ImmutableSet<Position> outerPositionSet =
@@ -111,12 +180,37 @@ public ImmutableSet<Position> computePositionSet() {
111180
// Loop through the positions, save the ones contained within our actual polygon.
112181
ImmutableSet.Builder<Position> innerPositionSet = ImmutableSet.builder();
113182
for (Position outerPosition : outerPositionSet) {
114-
int outerPositionX = outerPosition.getX();
115-
int outerPositionY = outerPosition.getY();
116-
if (polygon.contains(outerPositionX, outerPositionY)) {
183+
if (contains(outerPosition)) {
117184
innerPositionSet.add(outerPosition);
118185
}
119186
}
120187
return innerPositionSet.build();
121188
}
189+
190+
private void calculateBounds(int[] xpoints, int[] ypoints, int npoints) {
191+
int boundsMinX = Integer.MAX_VALUE;
192+
int boundsMinY = Integer.MAX_VALUE;
193+
int boundsMaxX = Integer.MIN_VALUE;
194+
int boundsMaxY = Integer.MIN_VALUE;
195+
196+
for (int i = 0; i < npoints; i++) {
197+
int x = xpoints[i];
198+
boundsMinX = Math.min(boundsMinX, x);
199+
boundsMaxX = Math.max(boundsMaxX, x);
200+
int y = ypoints[i];
201+
boundsMinY = Math.min(boundsMinY, y);
202+
boundsMaxY = Math.max(boundsMaxY, y);
203+
}
204+
this.southWestX = boundsMinX;
205+
this.southWestY = boundsMinY;
206+
this.northEastX = boundsMaxX;
207+
this.northEastY = boundsMaxY;
208+
}
209+
210+
/**
211+
* Checks if a point is within the bounds. This is an early check to avoid checking all the points via the logic in contains.
212+
*/
213+
private boolean inBounds(int x, int y) {
214+
return x >= this.southWestX && y >= this.southWestY && x < northEastX && y < northEastY;
215+
}
122216
}

src/main/java/io/luna/game/model/mob/InteractionTask.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,13 @@ protected boolean onSchedule() {
101101

102102
@Override
103103
protected void execute() {
104+
int distance = event.distance();
104105
boolean isMob = interactWith instanceof Mob;
105106
boolean standing = player.getWalking().isEmpty();
106107
CollisionManager collision = player.getWorld().getCollisionManager();
107-
boolean reached = collision.reached(player, interactWith, event.distance());
108+
boolean reached = collision.reached(player, interactWith, distance);
108109
if (reached) {
110+
player.getWalking().clear();
109111
if (isMob || interactWith.size() == 1) {
110112
boolean delayed = false;
111113
Position current = player.getPosition();
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package io.luna.game.model.area;
2+
3+
import com.google.common.base.Objects;
4+
import com.google.common.collect.ImmutableSet;
5+
import io.luna.game.model.Position;
6+
7+
import java.awt.*;
8+
import java.awt.geom.Rectangle2D;
9+
import java.util.LinkedHashSet;
10+
import java.util.List;
11+
import java.util.Set;
12+
import java.util.concurrent.ThreadLocalRandom;
13+
14+
/**
15+
* The polygonal implementation.
16+
*/
17+
public class OldPolygonArea extends Area {
18+
19+
/**
20+
* The representation of our arbitrary polygon.
21+
*/
22+
private final Polygon polygon;
23+
24+
/**
25+
* The precomputed hashcode.
26+
*/
27+
private final int hashCode;
28+
29+
/**
30+
* The set of vertices that make up this polygon.
31+
*/
32+
private final Set<Point> vertices;
33+
34+
/**
35+
* Creates a new {@link PolygonArea}.
36+
*
37+
* @param verticesList The set of vertices that make up this polygon.
38+
*/
39+
OldPolygonArea(List<Point> verticesList) {
40+
// Deep copy of vertices.
41+
vertices = new LinkedHashSet<>();
42+
for (Point point : verticesList) {
43+
vertices.add(point.getLocation());
44+
}
45+
46+
// Precompute hashcode
47+
hashCode = Objects.hashCode(vertices);
48+
49+
// Reformat to create java.awt.Polygon
50+
int index = 0;
51+
int totalSize = vertices.size();
52+
int[] x = new int[totalSize];
53+
int[] y = new int[totalSize];
54+
for (Point point : vertices) {
55+
x[index] = (int) point.getX();
56+
y[index] = (int) point.getY();
57+
index++;
58+
}
59+
polygon = new Polygon(x, y, totalSize);
60+
}
61+
62+
@Override
63+
public boolean equals(Object o) {
64+
if (this == o) return true;
65+
if (o == null || getClass() != o.getClass()) return false;
66+
OldPolygonArea that = (OldPolygonArea) o;
67+
return Objects.equal(vertices, that.vertices);
68+
}
69+
70+
@Override
71+
public int hashCode() {
72+
return hashCode;
73+
}
74+
75+
@Override
76+
public boolean contains(Position position) {
77+
return polygon.contains(position.getX(), position.getY());
78+
}
79+
80+
@Override
81+
public int size() {
82+
return getPositionSet().size();
83+
}
84+
85+
@Override
86+
public Position randomPosition() {
87+
ImmutableSet<Position> positionSet = getPositionSet();
88+
int counter = 0;
89+
int n = ThreadLocalRandom.current().nextInt(0, positionSet.size());
90+
for (Position position : positionSet) {
91+
if (counter++ == n) {
92+
return position;
93+
}
94+
}
95+
throw new IllegalStateException("unexpected");
96+
}
97+
98+
@Override
99+
public ImmutableSet<Position> computePositionSet() {
100+
// Create a rectangle that encompasses our polygon.
101+
Rectangle2D outer = polygon.getBounds2D();
102+
int southWestX = (int) outer.getMinX();
103+
int southWestY = (int) outer.getMinY();
104+
int northEastX = (int) outer.getMaxX();
105+
int northEastY = (int) outer.getMaxY();
106+
107+
// Build it into a simple box area, get every position inside.
108+
ImmutableSet<Position> outerPositionSet =
109+
Area.of(southWestX, southWestY, northEastX, northEastY).getPositionSet();
110+
111+
// Loop through the positions, save the ones contained within our actual polygon.
112+
ImmutableSet.Builder<Position> innerPositionSet = ImmutableSet.builder();
113+
for (Position outerPosition : outerPositionSet) {
114+
int outerPositionX = outerPosition.getX();
115+
int outerPositionY = outerPosition.getY();
116+
if (polygon.contains(outerPositionX, outerPositionY)) {
117+
innerPositionSet.add(outerPosition);
118+
}
119+
}
120+
return innerPositionSet.build();
121+
}
122+
}

0 commit comments

Comments
 (0)