geforkt von Mirrors/FastAsyncWorldEdit
Fixes to BlockMask and "char" masks (#1787)
* If a char mask is successfully created from the full input, return it * Don't double-up adding a block to a BlockMaskBuilder (if adding by regex is successful) - InputParseException is thrown if unsuccessful * Fix optimisation of BlockMask for negation of a single block type - Fixes #1755 * Allow early returning of an optimized MaskIntersection to avoid unnecessary work * Actually allow underscore in isAlphanumericUnd - Fixes #1626 * Replace a few more hard-coded air internal IDs * Don't fail silently if BlockMaskBuilder#addRegex doesn't work when testing all block types * Remove unused import
Dieser Commit ist enthalten in:
Ursprung
f2bab901f4
Commit
fd00635533
@ -127,6 +127,9 @@ public class RichMaskParser extends FaweParser<Mask> {
|
|||||||
case '%', '$', '<', '>', '!' -> {
|
case '%', '$', '<', '>', '!' -> {
|
||||||
input = input.substring(input.indexOf(char0) + 1);
|
input = input.substring(input.indexOf(char0) + 1);
|
||||||
mask = parseFromInput(char0 + "[" + input + "]", context);
|
mask = parseFromInput(char0 + "[" + input + "]", context);
|
||||||
|
if (mask != null) {
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case '#' -> {
|
case '#' -> {
|
||||||
if (!(input.charAt(1) == '#')) {
|
if (!(input.charAt(1) == '#')) {
|
||||||
@ -145,6 +148,10 @@ public class RichMaskParser extends FaweParser<Mask> {
|
|||||||
try {
|
try {
|
||||||
builder.addRegex(full);
|
builder.addRegex(full);
|
||||||
} catch (InputParseException ignored) {
|
} catch (InputParseException ignored) {
|
||||||
|
context.setPreferringWildcard(false);
|
||||||
|
context.setRestricted(false);
|
||||||
|
BaseBlock block = worldEdit.getBlockFactory().parseFromInput(full, context);
|
||||||
|
builder.add(block);
|
||||||
} catch (PatternSyntaxException e) {
|
} catch (PatternSyntaxException e) {
|
||||||
throw new SuggestInputParseException(
|
throw new SuggestInputParseException(
|
||||||
new NoMatchException(Caption.of("fawe.error.parse.unknown-mask", full,
|
new NoMatchException(Caption.of("fawe.error.parse.unknown-mask", full,
|
||||||
@ -166,10 +173,6 @@ public class RichMaskParser extends FaweParser<Mask> {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
context.setPreferringWildcard(false);
|
|
||||||
context.setRestricted(false);
|
|
||||||
BaseBlock block = worldEdit.getBlockFactory().parseFromInput(full, context);
|
|
||||||
builder.add(block);
|
|
||||||
mask = builder.build(extent);
|
mask = builder.build(extent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ public class BlockMaskBuilder {
|
|||||||
if (input.charAt(input.length() - 1) == ']') {
|
if (input.charAt(input.length() - 1) == ']') {
|
||||||
int propStart = StringMan.findMatchingBracket(input, input.length() - 1);
|
int propStart = StringMan.findMatchingBracket(input, input.length() - 1);
|
||||||
if (propStart == -1) {
|
if (propStart == -1) {
|
||||||
return;
|
throw new InputParseException(Caption.of("fawe.error.no-block-found", TextComponent.of(input)));
|
||||||
}
|
}
|
||||||
|
|
||||||
MutableCharSequence charSequence = MutableCharSequence.getTemporal();
|
MutableCharSequence charSequence = MutableCharSequence.getTemporal();
|
||||||
@ -250,11 +250,16 @@ public class BlockMaskBuilder {
|
|||||||
if (StringMan.isAlphanumericUnd(input)) {
|
if (StringMan.isAlphanumericUnd(input)) {
|
||||||
add(BlockTypes.parse(input));
|
add(BlockTypes.parse(input));
|
||||||
} else {
|
} else {
|
||||||
|
boolean success = false;
|
||||||
for (BlockType myType : BlockTypesCache.values) {
|
for (BlockType myType : BlockTypesCache.values) {
|
||||||
if (myType.getId().matches(input)) {
|
if (myType.getId().matches(input)) {
|
||||||
add(myType);
|
add(myType);
|
||||||
|
success = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!success) {
|
||||||
|
throw new InputParseException(Caption.of("fawe.error.no-block-found", TextComponent.of(input)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -295,7 +295,7 @@ public class StringMan {
|
|||||||
public static boolean isAlphanumericUnd(CharSequence str) {
|
public static boolean isAlphanumericUnd(CharSequence str) {
|
||||||
for (int i = 0; i < str.length(); i++) {
|
for (int i = 0; i < str.length(); i++) {
|
||||||
final char c = str.charAt(i);
|
final char c = str.charAt(i);
|
||||||
if (c < 0x30 || c >= 0x3a && c <= 0x40 || c > 0x5a && c <= 0x60 || c > 0x7a) {
|
if (c < 0x30 || c >= 0x3a && c <= 0x40 || c > 0x5a && c <= 0x60 && c != 0x5f || c > 0x7a) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -210,15 +210,14 @@ public class BlockMask extends ABlockMask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean replacesAir() {
|
public boolean replacesAir() {
|
||||||
return ordinals[1]
|
return ordinals[BlockTypesCache.ReservedIDs.AIR]
|
||||||
|| ordinals[2]
|
|| ordinals[BlockTypesCache.ReservedIDs.CAVE_AIR]
|
||||||
|| ordinals[3];
|
|| ordinals[BlockTypesCache.ReservedIDs.VOID_AIR];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mask tryCombine(Mask mask) {
|
public Mask tryCombine(Mask mask) {
|
||||||
if (mask instanceof ABlockMask) {
|
if (mask instanceof ABlockMask other) {
|
||||||
ABlockMask other = (ABlockMask) mask;
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
boolean hasAny = false;
|
boolean hasAny = false;
|
||||||
for (int i = 0; i < ordinals.length; i++) {
|
for (int i = 0; i < ordinals.length; i++) {
|
||||||
@ -241,8 +240,7 @@ public class BlockMask extends ABlockMask {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mask tryOr(Mask mask) {
|
public Mask tryOr(Mask mask) {
|
||||||
if (mask instanceof ABlockMask) {
|
if (mask instanceof ABlockMask other) {
|
||||||
ABlockMask other = (ABlockMask) mask;
|
|
||||||
boolean modified = false;
|
boolean modified = false;
|
||||||
for (int i = 0; i < ordinals.length; i++) {
|
for (int i = 0; i < ordinals.length; i++) {
|
||||||
if (!ordinals[i]) {
|
if (!ordinals[i]) {
|
||||||
@ -273,23 +271,27 @@ public class BlockMask extends ABlockMask {
|
|||||||
|
|
||||||
int setTypes = 0;
|
int setTypes = 0;
|
||||||
BlockType setType = null;
|
BlockType setType = null;
|
||||||
|
BlockType unsetType = null;
|
||||||
int totalTypes = 0;
|
int totalTypes = 0;
|
||||||
|
|
||||||
for (BlockType type : BlockTypesCache.values) {
|
for (BlockType type : BlockTypesCache.values) {
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
totalTypes++;
|
totalTypes++;
|
||||||
boolean hasAll = true;
|
boolean hasAll = true;
|
||||||
|
boolean hasAny = false;
|
||||||
List<BlockState> all = type.getAllStates();
|
List<BlockState> all = type.getAllStates();
|
||||||
for (BlockState state : all) {
|
for (BlockState state : all) {
|
||||||
totalStates++;
|
totalStates++;
|
||||||
hasAll &= test(state);
|
boolean result = test(state);
|
||||||
|
hasAll &= result;
|
||||||
|
hasAny |= result;
|
||||||
}
|
}
|
||||||
if (hasAll) {
|
if (hasAll) {
|
||||||
setTypes++;
|
setTypes++;
|
||||||
setType = type;
|
setType = type;
|
||||||
setStates += all.size();
|
setStates += all.size();
|
||||||
setState = type.getDefaultState();
|
setState = type.getDefaultState();
|
||||||
} else {
|
} else if (hasAny) {
|
||||||
for (BlockState state : all) {
|
for (BlockState state : all) {
|
||||||
if (test(state)) {
|
if (test(state)) {
|
||||||
setStates++;
|
setStates++;
|
||||||
@ -298,6 +300,10 @@ public class BlockMask extends ABlockMask {
|
|||||||
unsetState = state;
|
unsetState = state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (all.size() == 1) {
|
||||||
|
unsetState = all.get(0);
|
||||||
|
} else {
|
||||||
|
unsetType = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,7 +319,11 @@ public class BlockMask extends ABlockMask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setStates == totalStates - 1) {
|
if (setStates == totalStates - 1) {
|
||||||
|
if (unsetState != null) {
|
||||||
return new InverseSingleBlockStateMask(getExtent(), unsetState);
|
return new InverseSingleBlockStateMask(getExtent(), unsetState);
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("unsetState cannot be null when passed to InverseSingleBlockStateMask");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setTypes == 1) {
|
if (setTypes == 1) {
|
||||||
@ -321,23 +331,27 @@ public class BlockMask extends ABlockMask {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (setTypes == totalTypes - 1) {
|
if (setTypes == totalTypes - 1) {
|
||||||
|
if (unsetType != null) {
|
||||||
|
return new InverseSingleBlockTypeMask(getExtent(), unsetType);
|
||||||
|
} else {
|
||||||
throw new IllegalArgumentException("unsetType cannot be null when passed to InverseSingleBlockTypeMask");
|
throw new IllegalArgumentException("unsetType cannot be null when passed to InverseSingleBlockTypeMask");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mask inverse() {
|
public Mask inverse() {
|
||||||
boolean[] cloned = ordinals.clone();
|
boolean[] cloned = new boolean[ordinals.length];
|
||||||
for (int i = 0; i < cloned.length; i++) {
|
for (int i = 0; i < cloned.length; i++) {
|
||||||
cloned[i] = !cloned[i];
|
cloned[i] = !ordinals[i];
|
||||||
}
|
}
|
||||||
if (replacesAir()) {
|
if (replacesAir()) {
|
||||||
cloned[1] = false;
|
cloned[BlockTypesCache.ReservedIDs.__RESERVED__] = false;
|
||||||
cloned[2] = false;
|
cloned[BlockTypesCache.ReservedIDs.AIR] = false;
|
||||||
cloned[3] = false;
|
cloned[BlockTypesCache.ReservedIDs.CAVE_AIR] = false;
|
||||||
cloned[0] = false;
|
cloned[BlockTypesCache.ReservedIDs.VOID_AIR] = false;
|
||||||
}
|
}
|
||||||
return new BlockMask(getExtent(), cloned);
|
return new BlockMask(getExtent(), cloned);
|
||||||
}
|
}
|
||||||
|
@ -163,6 +163,14 @@ public class MaskIntersection extends AbstractMask {
|
|||||||
while (combineMasks(pairingFunction(), failedCombines)) {
|
while (combineMasks(pairingFunction(), failedCombines)) {
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
if (masks.isEmpty()) {
|
||||||
|
formArray(); // This MaskIntersection instance may be reused for whatever reason, so ensure the array is correct.
|
||||||
|
return Masks.alwaysTrue();
|
||||||
|
}
|
||||||
|
if (masks.size() == 1) {
|
||||||
|
formArray(); // This MaskIntersection instance may be reused for whatever reason, so ensure the array is correct.
|
||||||
|
return masks.iterator().next();
|
||||||
|
}
|
||||||
// Optimize / combine
|
// Optimize / combine
|
||||||
do {
|
do {
|
||||||
changed |= optimizeMasks(optimized);
|
changed |= optimizeMasks(optimized);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren