feat: implement a new "type swap" pattern (#2346)

This commit is contained in:
Jordan 2023-07-20 16:57:48 +01:00 committed by GitHub
parent 0a8a479214
commit 18df87a4e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 159 additions and 0 deletions

View File

@ -0,0 +1,54 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.function.pattern.TypeSwapPattern;
import com.fastasyncworldedit.core.util.Permission;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.List;
import java.util.stream.Stream;
public class TypeSwapPatternParser extends RichParser<Pattern> {
private static final List<String> SUGGESTIONS = List.of("oak", "spruce", "stone", "sandstone");
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public TypeSwapPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#typeswap", "#ts", "#swaptype");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index > 2) {
return Stream.empty();
}
return SUGGESTIONS.stream();
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 2) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[input][output] (e.g. " + getPrefix() + "[spruce][oak])")
));
}
return new TypeSwapPattern(
context.requireExtent(),
input[0],
input[1],
Permission.hasPermission(context.requireActor(), "fawe.pattern.typeswap.regex")
);
}
}

View File

@ -0,0 +1,103 @@
package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.extent.filter.block.FilterBlock;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.regex.Pattern;
/**
* Pattern that replaces blocks based on their ID, matching for an "input" and replacing with an "output" string. The "input"
* string may be regex. Keeps as much of the block state as possible, excluding NBT data.
*
* @since TODO
*/
public class TypeSwapPattern extends AbstractExtentPattern {
private static final Pattern SPLITTER = Pattern.compile("[|,]");
private final String inputString;
private final String outputString;
private final String[] inputs;
private Pattern inputPattern = null;
/**
* Create a new instance
*
* @param extent extent to use
* @param inputString string to replace. May be regex.
* @param outputString string to replace with
* @param allowRegex if regex should be allowed for input string matching
* @since TODO
*/
public TypeSwapPattern(Extent extent, String inputString, String outputString, boolean allowRegex) {
super(extent);
this.inputString = inputString;
this.outputString = outputString;
if (!StringMan.isAlphanumericUnd(inputString)) {
if (allowRegex) {
this.inputPattern = Pattern.compile(inputString.replace(",", "|"));
inputs = null;
} else {
inputs = SPLITTER.split(inputString);
}
} else {
inputs = null;
}
}
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
BlockState existing = get.getBlock(extent);
BlockState newBlock = getNewBlock(existing);
if (newBlock == null) {
return false;
}
return set.setBlock(extent, newBlock);
}
@Override
public void applyBlock(final FilterBlock block) {
BlockState existing = block.getBlock();
BlockState newState = getNewBlock(existing);
if (newState != null) {
block.setBlock(newState);
}
}
@Override
public BaseBlock applyBlock(final BlockVector3 position) {
BaseBlock existing = position.getFullBlock(getExtent());
BlockState newState = getNewBlock(existing.toBlockState());
return newState == null ? existing : newState.toBaseBlock();
}
private BlockState getNewBlock(BlockState existing) {
String oldId = existing.getBlockType().getId();
String newId = oldId;
if (inputPattern != null) {
newId = inputPattern.matcher(oldId).replaceAll(outputString);
} else if (inputs != null && inputs.length > 0) {
for (String input : inputs) {
newId = newId.replace(input, outputString);
}
} else {
newId = oldId.replace(inputString, outputString);
}
if (newId.equals(oldId)) {
return null;
}
BlockType newType = BlockTypes.get(newId);
if (newType == null) {
return null;
}
return newType.getDefaultState().withProperties(existing);
}
}

View File

@ -42,6 +42,7 @@ import com.fastasyncworldedit.core.extension.factory.parser.pattern.OffsetPatter
import com.fastasyncworldedit.core.extension.factory.parser.pattern.PerlinPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomFullClipboardPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomOffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.TypeSwapPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RelativePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser;
@ -133,6 +134,7 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
register(new SimplexPatternParser(worldEdit));
register(new SolidRandomOffsetPatternParser(worldEdit));
register(new SurfaceRandomOffsetPatternParser(worldEdit));
register(new TypeSwapPatternParser(worldEdit));
register(new VoronoiPatternParser(worldEdit));
//FAWE end
}