Skip to content

Commit c6efda7

Browse files
committed
Added upstream OffsetsMask classes
1 parent 2987550 commit c6efda7

File tree

6 files changed

+546
-8
lines changed

6 files changed

+546
-8
lines changed

worldedit-core/src/main/java/com/fastasyncworldedit/core/extension/factory/parser/mask/RichOffsetMaskParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import com.sk89q.worldedit.extension.input.InputParseException;
77
import com.sk89q.worldedit.extension.input.ParserContext;
88
import com.sk89q.worldedit.function.mask.Mask;
9-
import com.sk89q.worldedit.function.mask.OffsetMask;
9+
import com.sk89q.worldedit.function.mask.OffsetsMask;
1010
import com.sk89q.worldedit.math.BlockVector3;
1111

1212
import javax.annotation.Nonnull;
@@ -43,7 +43,7 @@ protected Mask parseFromInput(@Nonnull String[] arguments, ParserContext context
4343
int y = Integer.parseInt(arguments[1]);
4444
int z = Integer.parseInt(arguments[2]);
4545
Mask submask = worldEdit.getMaskFactory().parseFromInput(arguments[3], context);
46-
return new OffsetMask(submask, BlockVector3.at(x, y, z), context.getMinY(), context.getMaxY());
46+
return OffsetsMask.single(submask, BlockVector3.at(x, y, z), context.getMinY(), context.getMaxY());
4747
}
4848

4949
}

worldedit-core/src/main/java/com/sk89q/worldedit/extension/factory/parser/mask/OffsetMaskParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import com.sk89q.worldedit.extension.input.ParserContext;
2727
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
2828
import com.sk89q.worldedit.function.mask.Mask;
29-
import com.sk89q.worldedit.function.mask.OffsetMask;
29+
import com.sk89q.worldedit.function.mask.OffsetsMask;
3030
import com.sk89q.worldedit.internal.registry.InputParser;
3131
import com.sk89q.worldedit.math.BlockVector3;
3232

@@ -69,7 +69,7 @@ public Mask parseFromInput(String input, ParserContext context) throws InputPars
6969
submask = new ExistingBlockMask(context.requireExtent());
7070
}
7171
//FAWE start - OffsetMask > OffsetsMask
72-
return new OffsetMask(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0), context.getMinY(), context.getMaxY());
72+
return OffsetsMask.single(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0), context.getMinY(), context.getMaxY());
7373
//FAWE end
7474
}
7575

worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@
3030
/**
3131
* Checks whether another mask tests true for a position that is offset
3232
* a given vector.
33+
*
34+
* @deprecated Use {@link OffsetsMask#single}
3335
*/
36+
@Deprecated
3437
public class OffsetMask extends AbstractMask {
3538

3639
//FAWE start - ignore resultant position outside world height range
@@ -71,8 +74,8 @@ public OffsetMask(Mask mask, BlockVector3 offset, int minY, int maxY) {
7174
this.offset = offset;
7275
this.minY = minY;
7376
this.maxY = maxY;
74-
//FAWE end
7577
}
78+
//FAWE end
7679

7780
/**
7881
* Get the mask.
@@ -128,7 +131,7 @@ public boolean test(BlockVector3 vector) {
128131
public Mask2D toMask2D() {
129132
Mask2D childMask = getMask().toMask2D();
130133
if (childMask != null) {
131-
return new OffsetMask2D(childMask, getOffset().toBlockVector2());
134+
return OffsetsMask2D.single(childMask, getOffset().toBlockVector2());
132135
} else {
133136
return null;
134137
}
@@ -137,7 +140,7 @@ public Mask2D toMask2D() {
137140
//FAWE start
138141
@Override
139142
public Mask copy() {
140-
return new OffsetMask(mask.copy(), offset.toImmutable(), minY, maxY);
143+
return OffsetsMask.single(mask.copy(), offset.toImmutable(), minY, maxY);
141144
}
142145
//FAWE end
143146

worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/OffsetMask2D.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@
2727
/**
2828
* Checks whether another mask tests true for a position that is offset
2929
* a given vector.
30+
*
31+
* @deprecated Use {@link OffsetsMask2D#single}
3032
*/
33+
@Deprecated
3134
public class OffsetMask2D extends AbstractMask2D {
3235

3336
private Mask2D mask;
@@ -95,7 +98,7 @@ public boolean test(BlockVector2 vector) {
9598

9699
@Override
97100
public Mask2D copy2D() {
98-
return new OffsetMask2D(mask.copy2D(), BlockVector2.at(offset.getX(), offset.getZ()));
101+
return OffsetsMask2D.single(mask.copy2D(), BlockVector2.at(offset.getX(), offset.getZ()));
99102
}
100103
//FAWE end
101104

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
/*
2+
* WorldEdit, a Minecraft world manipulation toolkit
3+
* Copyright (C) sk89q <http://www.sk89q.com>
4+
* Copyright (C) WorldEdit team and contributors
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License as published by
8+
* the Free Software Foundation, either version 3 of the License, or
9+
* (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
* GNU General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU General Public License
17+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
18+
*/
19+
20+
package com.sk89q.worldedit.function.mask;
21+
22+
import com.google.common.collect.ImmutableList;
23+
import com.google.common.collect.ImmutableSet;
24+
import com.google.common.collect.Iterables;
25+
import com.sk89q.worldedit.EditSessionBuilder;
26+
import com.sk89q.worldedit.math.BlockVector3;
27+
import com.sk89q.worldedit.util.Direction;
28+
import com.sk89q.worldedit.util.Direction.Flag;
29+
30+
import javax.annotation.Nullable;
31+
32+
import static com.google.common.base.Preconditions.checkArgument;
33+
import static com.google.common.base.Preconditions.checkNotNull;
34+
35+
/**
36+
* Checks whether any face of the given offsets to a block match a given mask.
37+
*/
38+
public class OffsetsMask extends AbstractMask {
39+
40+
private static final ImmutableSet<BlockVector3> OFFSET_LIST =
41+
Direction.valuesOf(Flag.CARDINAL | Flag.UPRIGHT)
42+
.stream()
43+
.map(Direction::toBlockVector)
44+
.collect(ImmutableSet.toImmutableSet());
45+
46+
//FAWE start
47+
/**
48+
* Create an offsets mask for a single offset.
49+
*
50+
* @param mask the mask to use
51+
* @param offset the offset
52+
* @param minY
53+
* @param maxY
54+
* @return the new offsets mask
55+
*/
56+
public static OffsetsMask single(Mask mask, BlockVector3 offset, int minY, int maxY) {
57+
return builder(mask).maxMatches(1).offsets(ImmutableList.of(offset)).minY(minY).maxY(maxY).build();
58+
}
59+
//FAWE end
60+
61+
/**
62+
* Create a new builder, using the given mask.
63+
* @param mask the mask to use
64+
* @return the builder
65+
*/
66+
public static Builder builder(Mask mask) {
67+
return new Builder().mask(mask);
68+
}
69+
70+
/**
71+
* A builder for an {@link OffsetsMask}.
72+
*/
73+
public static final class Builder {
74+
private Mask mask;
75+
private boolean excludeSelf;
76+
private int minMatches = 1;
77+
private int maxMatches = Integer.MAX_VALUE;
78+
private ImmutableSet<BlockVector3> offsets = OFFSET_LIST;
79+
//FAWE start - ignore resultant position outside world height range
80+
private int minY;
81+
private int maxY;
82+
//FAWE end
83+
84+
private Builder() {
85+
}
86+
87+
/**
88+
* Set the mask to test.
89+
* @param mask the mask to test
90+
* @return this builder, for chaining
91+
*/
92+
public Builder mask(Mask mask) {
93+
this.mask = mask;
94+
return this;
95+
}
96+
97+
/**
98+
* Set whether the mask should fail if the original position matches. Defaults to
99+
* {@code false}.
100+
*
101+
* @param excludeSelf {@code true} to exclude the original position if it matches
102+
* @return this builder, for chaining
103+
*/
104+
public Builder excludeSelf(boolean excludeSelf) {
105+
this.excludeSelf = excludeSelf;
106+
return this;
107+
}
108+
109+
/**
110+
* Set the minimum amount of matches required. Defaults to {@code 1}. Must be smaller than
111+
* or equal to the {@linkplain #maxMatches(int) max matches} and the {@link #offsets} size,
112+
* and greater than or equal to {@code 0}.
113+
*
114+
* @param minMatches the minimum amount of matches required
115+
* @return this builder, for chaining
116+
*/
117+
public Builder minMatches(int minMatches) {
118+
this.minMatches = minMatches;
119+
return this;
120+
}
121+
122+
/**
123+
* Set the maximum amount of matches allowed. Defaults to {@link Integer#MAX_VALUE}. Must
124+
* be greater than or equal to {@linkplain #minMatches(int)}.
125+
*
126+
* @param maxMatches the maximum amount of matches allowed
127+
* @return this builder, for chaining
128+
*/
129+
public Builder maxMatches(int maxMatches) {
130+
this.maxMatches = maxMatches;
131+
return this;
132+
}
133+
134+
/**
135+
* Set the offsets to test. Defaults to all {@linkplain Flag#CARDINAL cardinal}
136+
* and {@linkplain Flag#UPRIGHT upright} directions.
137+
*
138+
* @param offsets the offsets to test
139+
* @return this builder, for chaining
140+
*/
141+
public Builder offsets(Iterable<BlockVector3> offsets) {
142+
this.offsets = ImmutableSet.copyOf(offsets);
143+
return this;
144+
}
145+
146+
//FAWE start
147+
public Builder minY(int minY) {
148+
this.minY = minY;
149+
return null;
150+
}
151+
152+
public Builder maxY(int maxY) {
153+
this.maxY = maxY;
154+
return this;
155+
}
156+
//FAWE end
157+
158+
/**
159+
* Build an offsets mask.
160+
*
161+
* @return the new mask
162+
*/
163+
public OffsetsMask build() {
164+
return new OffsetsMask(mask, excludeSelf, minMatches, maxMatches, offsets, minY, maxY);
165+
}
166+
}
167+
168+
//FAWE start - ignore resultant position outside world height range
169+
private final int minY;
170+
private final int maxY;
171+
//FAWE end
172+
173+
private final Mask mask;
174+
private final boolean excludeSelf;
175+
private final int minMatches;
176+
private final int maxMatches;
177+
private final ImmutableSet<BlockVector3> offsets;
178+
179+
//FAWE start - ignore resultant position outside world height range
180+
private OffsetsMask(Mask mask, boolean excludeSelf, int minMatches, int maxMatches, ImmutableSet<BlockVector3> offsets, int minY, int maxY) {
181+
checkNotNull(mask);
182+
checkNotNull(offsets);
183+
// Validate match args. No need to test maxMatches as it must be >=0 based on the conditions here.
184+
checkArgument(minMatches <= maxMatches, "minMatches must be less than or equal to maxMatches");
185+
checkArgument(minMatches >= 0, "minMatches must be greater than or equal to 0");
186+
checkArgument(minMatches <= offsets.size(), "minMatches must be less than or equal to the number of offsets");
187+
checkArgument(offsets.size() > 0, "offsets must have at least one element");
188+
this.minY = minY;
189+
this.maxY = maxY;
190+
this.mask = mask;
191+
this.excludeSelf = excludeSelf;
192+
this.minMatches = minMatches;
193+
this.maxMatches = maxMatches;
194+
this.offsets = offsets;
195+
}
196+
//FAWE end
197+
198+
/**
199+
* Get the mask.
200+
*
201+
* @return the mask
202+
*/
203+
public Mask getMask() {
204+
return mask;
205+
}
206+
207+
/**
208+
* Get the flag determining if matching the current block should fail the mask.
209+
*
210+
* @return if it should exclude self-matches
211+
*/
212+
public boolean getExcludeSelf() {
213+
return this.excludeSelf;
214+
}
215+
216+
/**
217+
* Gets the minimum number of matches to pass.
218+
*
219+
* @return the minimum number of matches
220+
*/
221+
public int getMinMatches() {
222+
return this.minMatches;
223+
}
224+
225+
/**
226+
* Gets the maximum number of matches to pass.
227+
*
228+
* @return the maximum number of matches
229+
*/
230+
public int getMaxMatches() {
231+
return this.maxMatches;
232+
}
233+
234+
/**
235+
* Get the offsets.
236+
*
237+
* @return the offsets
238+
*/
239+
public ImmutableSet<BlockVector3> getOffsets() {
240+
return this.offsets;
241+
}
242+
243+
//
244+
@Override
245+
public boolean test(BlockVector3 vector) {
246+
if (excludeSelf && getMask().test(vector)) {
247+
return false;
248+
}
249+
250+
int matches = 0;
251+
252+
//FAWE start - ignore resultant position outside world height range
253+
for (BlockVector3 offset : offsets) {
254+
BlockVector3 testPos = vector.add(offset);
255+
if (testPos.getBlockY() < minY || testPos.getBlockY() > maxY) {
256+
continue;
257+
}
258+
if (getMask().test(testPos)) {
259+
matches++;
260+
if (matches > maxMatches) {
261+
return false;
262+
}
263+
}
264+
}
265+
//FAWE end
266+
267+
return minMatches <= matches && matches <= maxMatches;
268+
}
269+
270+
@Nullable
271+
@Override
272+
public Mask2D toMask2D() {
273+
Mask2D childMask = getMask().toMask2D();
274+
if (childMask != null) {
275+
return OffsetsMask2D.builder(childMask)
276+
.excludeSelf(excludeSelf)
277+
.minMatches(minMatches)
278+
.maxMatches(maxMatches)
279+
.offsets(Iterables.transform(offsets, BlockVector3::toBlockVector2))
280+
.build();
281+
} else {
282+
return null;
283+
}
284+
}
285+
286+
//FAWE start
287+
@Override
288+
public Mask copy() {
289+
return new OffsetsMask(mask.copy(),excludeSelf,minMatches,maxMatches,ImmutableSet.copyOf(this.offsets),minY,maxY);
290+
}
291+
//FAWE end
292+
}

0 commit comments

Comments
 (0)