3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-11-16 16:10:07 +01:00

Added upstream OffsetsMask classes

Dieser Commit ist enthalten in:
Matt 2023-05-04 22:01:32 -04:00
Ursprung 2987550e9b
Commit c6efda75a0
6 geänderte Dateien mit 546 neuen und 8 gelöschten Zeilen

Datei anzeigen

@ -6,7 +6,7 @@ import com.sk89q.worldedit.command.util.SuggestionHelper;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.OffsetMask;
import com.sk89q.worldedit.function.mask.OffsetsMask;
import com.sk89q.worldedit.math.BlockVector3;
import javax.annotation.Nonnull;
@ -43,7 +43,7 @@ public class RichOffsetMaskParser extends RichParser<Mask> {
int y = Integer.parseInt(arguments[1]);
int z = Integer.parseInt(arguments[2]);
Mask submask = worldEdit.getMaskFactory().parseFromInput(arguments[3], context);
return new OffsetMask(submask, BlockVector3.at(x, y, z), context.getMinY(), context.getMaxY());
return OffsetsMask.single(submask, BlockVector3.at(x, y, z), context.getMinY(), context.getMaxY());
}
}

Datei anzeigen

@ -26,7 +26,7 @@ import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.OffsetMask;
import com.sk89q.worldedit.function.mask.OffsetsMask;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.math.BlockVector3;
@ -69,7 +69,7 @@ public class OffsetMaskParser extends InputParser<Mask> implements AliasedParser
submask = new ExistingBlockMask(context.requireExtent());
}
//FAWE start - OffsetMask > OffsetsMask
return new OffsetMask(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0), context.getMinY(), context.getMaxY());
return OffsetsMask.single(submask, BlockVector3.at(0, firstChar == '>' ? -1 : 1, 0), context.getMinY(), context.getMaxY());
//FAWE end
}

Datei anzeigen

@ -30,7 +30,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Checks whether another mask tests true for a position that is offset
* a given vector.
*
* @deprecated Use {@link OffsetsMask#single}
*/
@Deprecated
public class OffsetMask extends AbstractMask {
//FAWE start - ignore resultant position outside world height range
@ -71,8 +74,8 @@ public class OffsetMask extends AbstractMask {
this.offset = offset;
this.minY = minY;
this.maxY = maxY;
//FAWE end
}
//FAWE end
/**
* Get the mask.
@ -128,7 +131,7 @@ public class OffsetMask extends AbstractMask {
public Mask2D toMask2D() {
Mask2D childMask = getMask().toMask2D();
if (childMask != null) {
return new OffsetMask2D(childMask, getOffset().toBlockVector2());
return OffsetsMask2D.single(childMask, getOffset().toBlockVector2());
} else {
return null;
}
@ -137,7 +140,7 @@ public class OffsetMask extends AbstractMask {
//FAWE start
@Override
public Mask copy() {
return new OffsetMask(mask.copy(), offset.toImmutable(), minY, maxY);
return OffsetsMask.single(mask.copy(), offset.toImmutable(), minY, maxY);
}
//FAWE end

Datei anzeigen

@ -27,7 +27,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Checks whether another mask tests true for a position that is offset
* a given vector.
*
* @deprecated Use {@link OffsetsMask2D#single}
*/
@Deprecated
public class OffsetMask2D extends AbstractMask2D {
private Mask2D mask;
@ -95,7 +98,7 @@ public class OffsetMask2D extends AbstractMask2D {
@Override
public Mask2D copy2D() {
return new OffsetMask2D(mask.copy2D(), BlockVector2.at(offset.getX(), offset.getZ()));
return OffsetsMask2D.single(mask.copy2D(), BlockVector2.at(offset.getX(), offset.getZ()));
}
//FAWE end

Datei anzeigen

@ -0,0 +1,292 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.function.mask;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.sk89q.worldedit.EditSessionBuilder;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Direction.Flag;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Checks whether any face of the given offsets to a block match a given mask.
*/
public class OffsetsMask extends AbstractMask {
private static final ImmutableSet<BlockVector3> OFFSET_LIST =
Direction.valuesOf(Flag.CARDINAL | Flag.UPRIGHT)
.stream()
.map(Direction::toBlockVector)
.collect(ImmutableSet.toImmutableSet());
//FAWE start
/**
* Create an offsets mask for a single offset.
*
* @param mask the mask to use
* @param offset the offset
* @param minY
* @param maxY
* @return the new offsets mask
*/
public static OffsetsMask single(Mask mask, BlockVector3 offset, int minY, int maxY) {
return builder(mask).maxMatches(1).offsets(ImmutableList.of(offset)).minY(minY).maxY(maxY).build();
}
//FAWE end
/**
* Create a new builder, using the given mask.
* @param mask the mask to use
* @return the builder
*/
public static Builder builder(Mask mask) {
return new Builder().mask(mask);
}
/**
* A builder for an {@link OffsetsMask}.
*/
public static final class Builder {
private Mask mask;
private boolean excludeSelf;
private int minMatches = 1;
private int maxMatches = Integer.MAX_VALUE;
private ImmutableSet<BlockVector3> offsets = OFFSET_LIST;
//FAWE start - ignore resultant position outside world height range
private int minY;
private int maxY;
//FAWE end
private Builder() {
}
/**
* Set the mask to test.
* @param mask the mask to test
* @return this builder, for chaining
*/
public Builder mask(Mask mask) {
this.mask = mask;
return this;
}
/**
* Set whether the mask should fail if the original position matches. Defaults to
* {@code false}.
*
* @param excludeSelf {@code true} to exclude the original position if it matches
* @return this builder, for chaining
*/
public Builder excludeSelf(boolean excludeSelf) {
this.excludeSelf = excludeSelf;
return this;
}
/**
* Set the minimum amount of matches required. Defaults to {@code 1}. Must be smaller than
* or equal to the {@linkplain #maxMatches(int) max matches} and the {@link #offsets} size,
* and greater than or equal to {@code 0}.
*
* @param minMatches the minimum amount of matches required
* @return this builder, for chaining
*/
public Builder minMatches(int minMatches) {
this.minMatches = minMatches;
return this;
}
/**
* Set the maximum amount of matches allowed. Defaults to {@link Integer#MAX_VALUE}. Must
* be greater than or equal to {@linkplain #minMatches(int)}.
*
* @param maxMatches the maximum amount of matches allowed
* @return this builder, for chaining
*/
public Builder maxMatches(int maxMatches) {
this.maxMatches = maxMatches;
return this;
}
/**
* Set the offsets to test. Defaults to all {@linkplain Flag#CARDINAL cardinal}
* and {@linkplain Flag#UPRIGHT upright} directions.
*
* @param offsets the offsets to test
* @return this builder, for chaining
*/
public Builder offsets(Iterable<BlockVector3> offsets) {
this.offsets = ImmutableSet.copyOf(offsets);
return this;
}
//FAWE start
public Builder minY(int minY) {
this.minY = minY;
return null;
}
public Builder maxY(int maxY) {
this.maxY = maxY;
return this;
}
//FAWE end
/**
* Build an offsets mask.
*
* @return the new mask
*/
public OffsetsMask build() {
return new OffsetsMask(mask, excludeSelf, minMatches, maxMatches, offsets, minY, maxY);
}
}
//FAWE start - ignore resultant position outside world height range
private final int minY;
private final int maxY;
//FAWE end
private final Mask mask;
private final boolean excludeSelf;
private final int minMatches;
private final int maxMatches;
private final ImmutableSet<BlockVector3> offsets;
//FAWE start - ignore resultant position outside world height range
private OffsetsMask(Mask mask, boolean excludeSelf, int minMatches, int maxMatches, ImmutableSet<BlockVector3> offsets, int minY, int maxY) {
checkNotNull(mask);
checkNotNull(offsets);
// Validate match args. No need to test maxMatches as it must be >=0 based on the conditions here.
checkArgument(minMatches <= maxMatches, "minMatches must be less than or equal to maxMatches");
checkArgument(minMatches >= 0, "minMatches must be greater than or equal to 0");
checkArgument(minMatches <= offsets.size(), "minMatches must be less than or equal to the number of offsets");
checkArgument(offsets.size() > 0, "offsets must have at least one element");
this.minY = minY;
this.maxY = maxY;
this.mask = mask;
this.excludeSelf = excludeSelf;
this.minMatches = minMatches;
this.maxMatches = maxMatches;
this.offsets = offsets;
}
//FAWE end
/**
* Get the mask.
*
* @return the mask
*/
public Mask getMask() {
return mask;
}
/**
* Get the flag determining if matching the current block should fail the mask.
*
* @return if it should exclude self-matches
*/
public boolean getExcludeSelf() {
return this.excludeSelf;
}
/**
* Gets the minimum number of matches to pass.
*
* @return the minimum number of matches
*/
public int getMinMatches() {
return this.minMatches;
}
/**
* Gets the maximum number of matches to pass.
*
* @return the maximum number of matches
*/
public int getMaxMatches() {
return this.maxMatches;
}
/**
* Get the offsets.
*
* @return the offsets
*/
public ImmutableSet<BlockVector3> getOffsets() {
return this.offsets;
}
//
@Override
public boolean test(BlockVector3 vector) {
if (excludeSelf && getMask().test(vector)) {
return false;
}
int matches = 0;
//FAWE start - ignore resultant position outside world height range
for (BlockVector3 offset : offsets) {
BlockVector3 testPos = vector.add(offset);
if (testPos.getBlockY() < minY || testPos.getBlockY() > maxY) {
continue;
}
if (getMask().test(testPos)) {
matches++;
if (matches > maxMatches) {
return false;
}
}
}
//FAWE end
return minMatches <= matches && matches <= maxMatches;
}
@Nullable
@Override
public Mask2D toMask2D() {
Mask2D childMask = getMask().toMask2D();
if (childMask != null) {
return OffsetsMask2D.builder(childMask)
.excludeSelf(excludeSelf)
.minMatches(minMatches)
.maxMatches(maxMatches)
.offsets(Iterables.transform(offsets, BlockVector3::toBlockVector2))
.build();
} else {
return null;
}
}
//FAWE start
@Override
public Mask copy() {
return new OffsetsMask(mask.copy(),excludeSelf,minMatches,maxMatches,ImmutableSet.copyOf(this.offsets),minY,maxY);
}
//FAWE end
}

Datei anzeigen

@ -0,0 +1,240 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.function.mask;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Direction.Flag;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Checks whether any face of the given offsets to a block match a given mask.
*/
public class OffsetsMask2D extends AbstractMask2D {
private static final ImmutableSet<BlockVector2> OFFSET_LIST =
Direction.valuesOf(Flag.CARDINAL)
.stream()
.map(Direction::toBlockVector)
.map(BlockVector3::toBlockVector2)
.collect(ImmutableSet.toImmutableSet());
/**
* Create an offsets mask for a single offset.
*
* @param mask the mask to use
* @param offset the offset
* @return the new offsets mask
*/
public static OffsetsMask2D single(Mask2D mask, BlockVector2 offset) {
return builder(mask).maxMatches(1).offsets(ImmutableList.of(offset)).build();
}
/**
* Create a new builder, using the given mask.
* @param mask the mask to use
* @return the builder
*/
public static Builder builder(Mask2D mask) {
return new Builder().mask(mask);
}
/**
* A builder for an {@link OffsetsMask}.
*/
public static final class Builder {
private Mask2D mask;
private boolean excludeSelf;
private int minMatches = 1;
private int maxMatches = Integer.MAX_VALUE;
private ImmutableSet<BlockVector2> offsets = OFFSET_LIST;
private Builder() {
}
/**
* Set the mask to test.
* @param mask the mask to test
* @return this builder, for chaining
*/
public Builder mask(Mask2D mask) {
this.mask = mask;
return this;
}
/**
* Set whether the mask should fail if the original position matches. Defaults to
* {@code false}.
*
* @param excludeSelf {@code true} to exclude the original position if it matches
* @return this builder, for chaining
*/
public Builder excludeSelf(boolean excludeSelf) {
this.excludeSelf = excludeSelf;
return this;
}
/**
* Set the minimum amount of matches required. Defaults to {@code 1}. Must be smaller than
* or equal to the {@linkplain #maxMatches(int) max matches} and the {@link #offsets} size,
* and greater than or equal to {@code 0}.
*
* @param minMatches the minimum amount of matches required
* @return this builder, for chaining
*/
public Builder minMatches(int minMatches) {
this.minMatches = minMatches;
return this;
}
/**
* Set the maximum amount of matches allowed. Defaults to {@link Integer#MAX_VALUE}. Must
* be greater than or equal to {@linkplain #minMatches(int)}.
*
* @param maxMatches the maximum amount of matches allowed
* @return this builder, for chaining
*/
public Builder maxMatches(int maxMatches) {
this.maxMatches = maxMatches;
return this;
}
/**
* Set the offsets to test. Defaults to all {@linkplain Flag#CARDINAL cardinal}
* directions.
*
* @param offsets the offsets to test
* @return this builder, for chaining
*/
public Builder offsets(Iterable<BlockVector2> offsets) {
this.offsets = ImmutableSet.copyOf(offsets);
return this;
}
/**
* Build an offsets mask.
*
* @return the new mask
*/
public OffsetsMask2D build() {
return new OffsetsMask2D(mask, excludeSelf, minMatches, maxMatches, offsets);
}
}
private final Mask2D mask;
private final boolean excludeSelf;
private final int minMatches;
private final int maxMatches;
private final ImmutableSet<BlockVector2> offsets;
private OffsetsMask2D(Mask2D mask, boolean excludeSelf, int minMatches, int maxMatches, ImmutableSet<BlockVector2> offsets) {
checkNotNull(mask);
checkNotNull(offsets);
// Validate match args. No need to test maxMatches as it must be >=0 based on the conditions here.
checkArgument(minMatches <= maxMatches, "minMatches must be less than or equal to maxMatches");
checkArgument(minMatches >= 0, "minMatches must be greater than or equal to 0");
checkArgument(minMatches <= offsets.size(), "minMatches must be less than or equal to the number of offsets");
checkArgument(offsets.size() > 0, "offsets must have at least one element");
this.mask = mask;
this.excludeSelf = excludeSelf;
this.minMatches = minMatches;
this.maxMatches = maxMatches;
this.offsets = offsets;
}
/**
* Get the mask.
*
* @return the mask
*/
public Mask2D getMask() {
return mask;
}
/**
* Get the flag determining if matching the current block should fail the mask.
*
* @return if it should exclude self-matches
*/
public boolean getExcludeSelf() {
return this.excludeSelf;
}
/**
* Gets the minimum number of matches to pass.
*
* @return the minimum number of matches
*/
public int getMinMatches() {
return this.minMatches;
}
/**
* Gets the maximum number of matches to pass.
*
* @return the maximum number of matches
*/
public int getMaxMatches() {
return this.maxMatches;
}
/**
* Get the offsets.
*
* @return the offsets
*/
public ImmutableSet<BlockVector2> getOffsets() {
return this.offsets;
}
@Override
public boolean test(BlockVector2 vector) {
if (excludeSelf && mask.test(vector)) {
return false;
}
int matches = 0;
for (BlockVector2 offset : offsets) {
if (mask.test(vector.add(offset))) {
matches++;
if (matches > maxMatches) {
return false;
}
}
}
return minMatches <= matches && matches <= maxMatches;
}
//FAWE start
@Override
public Mask2D copy2D() {
return new OffsetsMask2D(mask.copy2D(), excludeSelf, minMatches, maxMatches, ImmutableSet.copyOf(offsets));
}
//FAWE end
}