Re-implement richer mask and transform parsing (#1223)

Co-authored-by: dordsor21 <dordsor21@gmail.com>
Co-authored-by: Hannes Greule <SirYwell@users.noreply.github.com>
Dieser Commit ist enthalten in:
dordsor21 2021-08-16 10:03:06 +01:00 committet von GitHub
Ursprung 50137b31c4
Commit d4d98708f9
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
109 geänderte Dateien mit 4068 neuen und 2414 gelöschten Zeilen

Datei anzeigen

@ -1,114 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.boydti.fawe.command;
//
//import com.boydti.fawe.util.StringMan;
//import com.sk89q.worldedit.WorldEdit;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.input.ParserContext;
//import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
//import com.sk89q.worldedit.internal.registry.InputParser;
//import org.enginehub.piston.inject.InjectedValueAccess;
//
//import java.util.*;
//
//public abstract class FaweParser<T> extends InputParser<T> {
//
// private final String prefix;
//
// protected FaweParser(WorldEdit worldEdit, String prefix) {
// super(worldEdit);
// this.prefix = prefix;
// }
//
// public PlatformCommandManager getPlatform() {
// return PlatformCommandManager.getInstance();
// }
//
// public T parse(String input, ParserContext context) {
// input = prefix + " " + input;
// InjectedValueAccess injected = context.getInjected();
// if (injected != null) {
// return getPlatform().parseCommand(input, injected);
// } else {
// return getPlatform().parseCommand(input, context.getActor());
// }
// }
//
// public T catchSuggestion(String currentInput, String nextInput, ParserContext context) throws InputParseException {
// try {
// return parseFromInput(nextInput, context);
// } catch (SuggestInputParseException e) {
// e.prepend(currentInput.substring(0, currentInput.length() - nextInput.length()));
// throw e;
// }
// }
//
// protected static class ParseEntry {
// public boolean and;
// public String input;
// public String full;
//
// public ParseEntry(String full, String input, boolean type) {
// this.full = full;
// this.input = input;
// this.and = type;
// }
//
// @Override
// public String toString() {
// return input + " | " + and;
// }
// }
//
// public static List<Map.Entry<ParseEntry, List<String>>> parse(String toParse) throws InputParseException {
// List<Map.Entry<ParseEntry, List<String>>> keys = new ArrayList<>();
// List<String> inputs = new ArrayList<>();
// List<Boolean> and = new ArrayList<>();
// int last = 0;
// outer:
// for (int i = 0; i < toParse.length(); i++) {
// char c = toParse.charAt(i);
// switch (c) {
// case ',':
// case '&':
// String result = toParse.substring(last, i);
// if (!result.isEmpty()) {
// inputs.add(result);
// and.add(c == '&');
// } else {
// throw new InputParseException("Invalid dangling character " + c);
// }
// last = i + 1;
// continue outer;
// default:
// if (c == '[' && StringMan.getMatchingBracket(c) != c) {
// int next = StringMan.findMatchingBracket(toParse, i);
// if (next != -1) {
// i = next;
// } else {
// toParse += "]";
// i = toParse.length();
// }
// continue outer;
// }
// }
// }
// inputs.add(toParse.substring(last));
// for (int i = 0; i < inputs.size(); i++) {
// String full = inputs.get(i);
// String command = full;
// List<String> args = new ArrayList<>();
// while (!command.isEmpty() && command.charAt(command.length() - 1) == ']') {
// int startPos = StringMan.findMatchingBracket(command, command.length() - 1);
// if (startPos == -1) break;
// String arg = command.substring(startPos + 1, command.length() - 1);
// args.add(arg);
// command = full.substring(0, startPos);
// }
// Collections.reverse(args);
// ParseEntry entry = new ParseEntry(full, command, i > 0 ? and.get(i - 1) : false);
// keys.add(new AbstractMap.SimpleEntry<>(entry, args));
// }
// return keys;
// }
//}

Datei anzeigen

@ -1,132 +0,0 @@
// TODO: Ping @MattBDev to reimplement (or remove because this class is stupid) 2020-02-04
//package com.fastasyncworldedit.core.command;
//
//import com.boydti.fawe.object.mask.AdjacentAnyMask;
//import com.boydti.fawe.object.mask.AdjacentMask;
//import com.boydti.fawe.object.mask.AngleMask;
//import com.boydti.fawe.object.mask.BiomeMask;
//import com.boydti.fawe.object.mask.BlockLightMask;
//import com.boydti.fawe.object.mask.BrightnessMask;
//import com.boydti.fawe.object.mask.ExtremaMask;
//import com.boydti.fawe.object.mask.LightMask;
//import com.boydti.fawe.object.mask.OpacityMask;
//import com.boydti.fawe.object.mask.ROCAngleMask;
//import com.boydti.fawe.object.mask.RadiusMask;
//import com.boydti.fawe.object.mask.RandomMask;
//import com.boydti.fawe.object.mask.SimplexMask;
//import com.boydti.fawe.object.mask.SkyLightMask;
//import com.boydti.fawe.object.mask.SurfaceMask;
//import com.boydti.fawe.object.mask.WallMask;
//import com.boydti.fawe.function.mask.XAxisMask;
//import com.boydti.fawe.function.mask.YAxisMask;
//import com.boydti.fawe.function.mask.ZAxisMask;
//import com.sk89q.worldedit.IncompleteRegionException;
//import com.sk89q.worldedit.LocalSession;
//import com.sk89q.worldedit.WorldEdit;
//import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
//import com.sk89q.worldedit.entity.Player;
//import com.sk89q.worldedit.extent.Extent;
//import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
//import com.sk89q.worldedit.function.mask.ExistingBlockMask;
//import com.sk89q.worldedit.function.mask.ExpressionMask;
//import com.sk89q.worldedit.function.mask.Mask;
//import com.sk89q.worldedit.function.mask.MaskIntersection;
//import com.sk89q.worldedit.function.mask.MaskUnion;
//import com.sk89q.worldedit.function.mask.Masks;
//import com.sk89q.worldedit.function.mask.OffsetMask;
//import com.sk89q.worldedit.function.mask.RegionMask;
//import com.sk89q.worldedit.function.mask.SolidBlockMask;
//import com.sk89q.worldedit.internal.expression.Expression;
//import com.sk89q.worldedit.internal.expression.ExpressionEnvironment;
//import com.sk89q.worldedit.internal.expression.ExpressionException;
//import com.sk89q.worldedit.math.BlockVector3;
//import com.sk89q.worldedit.math.Vector3;
//import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
//import com.sk89q.worldedit.session.request.RequestSelection;
//import com.sk89q.worldedit.world.biome.BiomeType;
//import org.enginehub.piston.annotation.Command;
//import org.enginehub.piston.annotation.CommandContainer;
//import org.enginehub.piston.annotation.param.Arg;
//import org.enginehub.piston.annotation.param.Switch;
//
////@Command(aliases = {"masks"},
//// desc = "Help for the various masks. [More Info](https://git.io/v9r4K)",
//// descFooter = "Masks determine if a block can be placed\n" +
//// " - Use [brackets] for arguments\n" +
//// " - Use , to OR multiple\n" +
//// " - Use & to AND multiple\n" +
//// "e.g. >[stone,dirt],#light[0][5],$jungle\n" +
//// "More Info: https://git.io/v9r4K"
////)
//@CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//public class MaskCommands {
// private final WorldEdit worldEdit;
//
// public MaskCommands(WorldEdit worldEdit) {
// this.worldEdit = worldEdit;
// }
// @Command(
// name = "#light",
// desc = "Restrict to specific light levels"
// )
// public Mask light(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new LightMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#skylight",
// desc = "Restrict to specific sky light levels"
// )
// public Mask skylight(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new SkyLightMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#blocklight",
// aliases = {"#emittedlight"},
// desc = "Restrict to specific block light levels"
// )
// public Mask blocklight(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new BlockLightMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#opacity",
// desc = "Restrict to specific opacity levels"
// )
// public Mask opacity(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new OpacityMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#brightness",
// desc = "Restrict to specific block brightness"
// )
// public Mask brightness(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new BrightnessMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#haslight",
// desc = "Restricts to blocks with light (sky or emitted)"
// )
// public Mask haslight(Extent extent) {
// return new LightMask(extent, 1, Integer.MAX_VALUE);
// }
//
// @Command(
// name = "#nolight",
// desc = "Restrict to blocks without light (sky or emitted)"
// )
// public Mask nolight(Extent extent) {
// return new LightMask(extent, 0, 0);
// }
// @Command(
// name = "#iddata",
// desc = "Restrict to initial block id and data"
// )
// public Mask iddata(Extent extent) {
// return new IdDataMask(extent);
// }
//}

Datei anzeigen

@ -1,356 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.sk89q.worldedit.command;
//
//import com.boydti.fawe.object.DataAnglePattern;
//import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
//import com.boydti.fawe.object.collection.RandomCollection;
//import com.boydti.fawe.object.pattern.AngleColorPattern;
//import com.boydti.fawe.object.pattern.AverageColorPattern;
//import com.boydti.fawe.object.pattern.BiomePattern;
//import com.boydti.fawe.object.pattern.BufferedPattern;
//import com.boydti.fawe.object.pattern.BufferedPattern2D;
//import com.boydti.fawe.object.pattern.DataPattern;
//import com.boydti.fawe.object.pattern.DesaturatePattern;
//import com.boydti.fawe.object.pattern.ExistingPattern;
//import com.boydti.fawe.object.pattern.ExpressionPattern;
//import com.boydti.fawe.object.pattern.FullClipboardPattern;
//import com.boydti.fawe.object.pattern.IdDataMaskPattern;
//import com.boydti.fawe.object.pattern.IdPattern;
//import com.boydti.fawe.object.pattern.Linear2DBlockPattern;
//import com.boydti.fawe.object.pattern.Linear3DBlockPattern;
//import com.boydti.fawe.object.pattern.LinearBlockPattern;
//import com.boydti.fawe.object.pattern.MaskedPattern;
//import com.boydti.fawe.object.pattern.NoXPattern;
//import com.boydti.fawe.object.pattern.NoYPattern;
//import com.boydti.fawe.object.pattern.NoZPattern;
//import com.boydti.fawe.object.pattern.OffsetPattern;
//import com.boydti.fawe.object.pattern.PropertyPattern;
//import com.boydti.fawe.object.pattern.RandomFullClipboardPattern;
//import com.boydti.fawe.object.pattern.RandomOffsetPattern;
//import com.boydti.fawe.object.pattern.RelativePattern;
//import com.boydti.fawe.object.pattern.SaturatePattern;
//import com.boydti.fawe.object.pattern.ShadePattern;
//import com.boydti.fawe.object.pattern.SolidRandomOffsetPattern;
//import com.boydti.fawe.object.pattern.SurfaceRandomOffsetPattern;
//import com.boydti.fawe.object.random.SimplexRandom;
//import com.boydti.fawe.util.ColorUtil;
//import com.boydti.fawe.util.TextureUtil;
//import com.sk89q.worldedit.EmptyClipboardException;
//import com.sk89q.worldedit.LocalSession;
//import com.sk89q.worldedit.entity.Player;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extent.Extent;
//import com.sk89q.worldedit.extent.clipboard.Clipboard;
//import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
//import com.sk89q.worldedit.function.mask.Mask;
//import com.sk89q.worldedit.function.pattern.ClipboardPattern;
//import com.sk89q.worldedit.function.pattern.Pattern;
//import com.sk89q.worldedit.function.pattern.RandomPattern;
//import com.sk89q.worldedit.internal.expression.Expression;
//import com.sk89q.worldedit.internal.expression.ExpressionException;
//import com.sk89q.worldedit.math.Vector3;
//import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
//import com.sk89q.worldedit.session.ClipboardHolder;
//import com.sk89q.worldedit.world.biome.BiomeType;
//import java.awt.Color;
//import java.io.IOException;
//import java.util.Collections;
//import java.util.List;
//import java.util.Set;
//import org.enginehub.piston.annotation.Command;
//import org.enginehub.piston.annotation.CommandContainer;
//import org.enginehub.piston.annotation.param.Arg;
//import org.jetbrains.annotations.Range;
//
////@Command(aliases = {"patterns"},
//// desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)",
//// descFooter = "Patterns determine what blocks are placed\n" +
//// " - Use [brackets] for arguments\n" +
//// " - Use , to OR multiple\n" +
//// "e.g., #surfacespread[10][#existing],andesite\n" +
//// "More Info: https://git.io/vSPmA"
////)
//@CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//public class PatternCommands {
//
//
// @Command(
// name = "#simplex",
// desc = "Use simplex noise to randomize blocks. Tutorial: https://imgur.com/a/rwVAE"
//)
// public Pattern simplex(@Arg(desc = "scale factor") double scale, @Arg(desc = "Pattern") Pattern other) {
// if (other instanceof RandomPattern) {
// scale = (1d / Math.max(1, scale));
// RandomCollection<Pattern> collection = ((RandomPattern) other).getCollection();
// collection.setRandom(new SimplexRandom(scale));
// }
// return other;
// }
//
// @Command(
// name = "#color",
// desc = "Use the block closest to a specific color"
//)
// public Pattern color(TextureUtil textureUtil, @Arg(desc = "String color") String color) {
// Color colorObj = ColorUtil.parseColor(color);
// return textureUtil.getNearestBlock(colorObj.getRGB()).getDefaultState();
// }
//
// @Command(
// name = "#anglecolor",
// desc = "A darker block based on the existing terrain angle"
//)
// public Pattern anglecolor(Extent extent, LocalSession session, @Arg(desc = "int", def = "1") int distance) {
// return new AngleColorPattern(extent, session, distance);
// }
//
// @Command(
// name = "#angledata",
// desc = "Block data based on the existing terrain angle"
// )
// public Pattern angledata(Extent extent, @Arg(desc = "int", def = "1") int distance) {
// return new DataAnglePattern(extent, distance);
// }
//
// @Command(
// name = "#saturate",
// desc = "Saturate the existing block with a color"
//)
// public Pattern saturate(Extent extent, LocalSession session, @Arg(desc = "Color code") String colorStr) {
// Color color = ColorUtil.parseColor(colorStr);
// return new SaturatePattern(extent, color.getRGB(), session);
// }
//
// @Command(
// name = "#averagecolor",
// desc = "Average between the existing block and a color"
//)
// public Pattern averagecolor(Extent extent, LocalSession session, @Arg(desc = "Color code") String colorStr) {
// Color color = ColorUtil.parseColor(colorStr);
// return new AverageColorPattern(extent, color.getRGB(), session);
// }
//
// @Command(
// name = "#desaturate",
// desc = "Desaturated color of the existing block"
//)
// public Pattern desaturate(Extent extent, LocalSession session, @Arg(desc = "double", def = "100") double percent) {
// return new DesaturatePattern(extent, percent / 100d, session);
// }
//
// @Command(
// name = "#lighten",
// desc = "Lighten the existing block"
//)
// public Pattern lighten(Extent extent, TextureUtil util) {
// return new ShadePattern(extent, false, util);
// }
//
// @Command(
// name = "#darken",
// desc = "Darken the existing block"
//)
// public Pattern darken(Extent extent, TextureUtil util) {
// return new ShadePattern(extent, true, util);
// }
//
// @Command(
// name = "#buffer",
// desc = "Only place a block once while a pattern is in use",
// descFooter = "Only place a block once while a pattern is in use\n" +
// "Use with a brush when you don't want to apply to the same spot twice"
//)
// public Pattern buffer(Actor actor, @Arg(desc = "Pattern")Pattern pattern) {
// return new BufferedPattern(actor, pattern);
// }
//
// @Command(
// name = "#buffer2d",
// desc = "Only place a block once in a column while a pattern is in use"
//)
// public Pattern buffer2d(Actor actor, @Arg(desc = "Pattern")Pattern pattern) {
// return new BufferedPattern2D(actor, pattern);
// }
//
// @Command(
// name = "#iddatamask",
// desc = "Use the pattern's id and the existing blocks data with the provided mask",
// descFooter = "Use the pattern's id and the existing blocks data with the provided mask\n" +
// " - Use to replace slabs or where the data values needs to be shifted instead of set"
//)
// public Pattern iddatamask(Extent extent, @Range(from = 0, to = 15) @Arg(desc = "bit mask") int bitmask, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new IdDataMaskPattern(extent, pattern, bitmask);
// }
//
// @Command(
// name = "#id",
// desc = "Only change the block id"
//)
// public Pattern id(Extent extent, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new IdPattern(extent, pattern);
// }
//
// @Command(
// name = "#data",
// desc = "Only change the block data"
//)
// public Pattern data(Extent extent, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new DataPattern(extent, pattern);
// }
//
// @Command(
// name = "#biome",
// aliases = {"$"},
// desc = "Set the biome"
//)
// public Pattern biome(Extent extent, @Arg(desc = "Biome type") BiomeType biome) {
//
// return new BiomePattern(extent, biome);
// }
//
// @Command(
// name = "#relative",
// aliases = {"#~", "#r", "#rel"},
// desc = "Offset the pattern to where you click"
//)
// public Pattern relative(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new RelativePattern(pattern);
// }
//
// @Command(
// name = "#!x",
// aliases = {"#nx", "#nox"},
// desc = "The pattern will not be provided the x axis info",
// descFooter = "The pattern will not be provided the z axis info.\n" +
// "Example: #!x[#!z[#~[#l3d[pattern]]]]"
//)
// public Pattern nox(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new NoXPattern(pattern);
// }
//
// @Command(
// name = "#!y",
// aliases = {"#ny", "#noy"},
// desc = "The pattern will not be provided the y axis info"
//)
// public Pattern noy(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new NoYPattern(pattern);
// }
//
// @Command(
// name = "#!z",
// aliases = {"#nz", "#noz"},
// desc = "The pattern will not be provided the z axis info"
//)
// public Pattern noz(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new NoZPattern(pattern);
// }
//
// @Command(
// name = "#mask",
// desc = "Apply a pattern depending on a mask"
//)
// public Pattern mask(@Arg(desc = "Mask") Mask mask, @Arg(desc = "Pattern")Pattern pass, @Arg(desc = "Pattern")Pattern fail) {
// return new MaskedPattern(mask, pass, fail);
// }
//
// @Command(
// name = "#offset",
// desc = "Offset a pattern"
//)
// public Pattern offset(@Arg(desc = "x offset") double x, @Arg(desc = "y offset") double y, @Arg(desc = "z offset") double z, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new OffsetPattern(pattern, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#surfacespread",
// desc = "Applies to only blocks on a surface. Selects a block from provided pattern with a given randomized offset `[0, <distance>)`. e.g., Use `#existing` to randomly offset blocks in the world, or `#copy` to offset blocks in your clipboard"
//)
// public Pattern surfacespread(@Arg(desc = "spread distance (blocks)") double distance, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new SurfaceRandomOffsetPattern(pattern, (int) distance);
// }
//
// @Command(
// name = "#solidspread",
// desc = "Randomly spread solid blocks"
//)
// public Pattern solidspread(@Arg(desc = "x offset") double x, @Arg(desc = "y offset") double y, @Arg(desc = "z offset") double z, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new SolidRandomOffsetPattern(pattern, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#spread",
// aliases = {"#randomoffset"},
// desc = "Randomly spread blocks"
//)
// public Pattern spread(@Arg(desc = "x offset") double x, @Arg(desc = "y offset") double y, @Arg(desc = "z offset") double z, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new RandomOffsetPattern(pattern, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#linear",
// aliases = {"#l"},
// desc = "Sequentially set blocks from a list of patterns"
//)
// public Pattern linear(@Arg(desc = "Pattern") Pattern other) {
//
// if (other instanceof RandomPattern) {
// Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
// return new LinearBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
// }
// return other;
// }
//
// @Command(
// name = "#linear3d",
// aliases = {"#l3d"},
// desc = "Use the x,y,z coordinate to pick a block from the list"
//)
// public Pattern linear3d(@Arg(desc = "Pattern") Pattern other) {
//
// if (other instanceof RandomPattern) {
// Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
// return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
// }
// return other;
// }
//
// @Command(
// name = "#linear2d",
// aliases = {"#l2d"},
// desc = "Use the x,z coordinate to pick a block from the list"
//)
// public Pattern linear2d(@Arg(desc = "Pattern") Pattern other) {
//
// if (other instanceof RandomPattern) {
// Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
// return new Linear2DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
// }
// return other;
// }
//
// @Command(
// name = "=",
// aliases = {"#=", "#expression"},
// desc = "Expression pattern: http://wiki.sk89q.com/wiki/WorldEdit/Expression_syntax"
//)
// public Pattern expression(Extent extent, @Arg(desc = "Expression") String input) throws ExpressionException {
//
// Expression exp = Expression.compile(input, "x", "y", "z");
// WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(extent, Vector3.ONE, Vector3.ZERO);
// exp.setEnvironment(env);
// return new ExpressionPattern(exp);
// }
//}

Datei anzeigen

@ -1,105 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.sk89q.worldedit.command;
//
//import com.boydti.fawe.object.extent.Linear3DTransform;
//import com.boydti.fawe.object.extent.LinearTransform;
//import com.boydti.fawe.object.extent.OffsetExtent;
//import com.boydti.fawe.object.extent.PatternTransform;
//import com.boydti.fawe.object.extent.RandomOffsetTransform;
//import com.boydti.fawe.object.extent.RandomTransform;
//import com.boydti.fawe.object.extent.ResettableExtent;
//import com.boydti.fawe.object.extent.ScaleTransform;
//import com.boydti.fawe.object.extent.TransformExtent;
//import com.boydti.fawe.util.ExtentTraverser;
//import com.sk89q.worldedit.LocalSession;
//import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
//import com.sk89q.worldedit.entity.Player;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
//import com.sk89q.worldedit.function.pattern.Pattern;
//import com.sk89q.worldedit.math.transform.AffineTransform;
//import java.util.Set;
//import org.enginehub.piston.annotation.Command;
//import org.enginehub.piston.annotation.CommandContainer;
//import org.enginehub.piston.annotation.param.Arg;
//
//@CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//public class TransformCommands {
//
// @Command(
// name = "#linear",
// aliases = {"#l"},
// desc = "Sequentially pick from a list of transform"
// )
// public ResettableExtent linear(Actor actor, LocalSession session, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// if (other instanceof RandomTransform) {
// Set<ResettableExtent> extents = ((RandomTransform) other).getExtents();
// return new LinearTransform(extents.toArray(new ResettableExtent[0]));
// }
// return other;
// }
//
// @Command(
// name = "#linear3d",
// aliases = {"#l3d"},
// desc = "Use the x,y,z coordinate to pick a transform from the list"
// )
// public ResettableExtent linear3d(Actor actor, LocalSession session, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// if (other instanceof RandomTransform) {
// Set<ResettableExtent> extents = ((RandomTransform) other).getExtents();
// return new Linear3DTransform(extents.toArray(new ResettableExtent[0]));
// }
// return other;
// }
//
// @Command(
// name = "#pattern",
// desc = "Always use a specific pattern"
// )
// public ResettableExtent pattern(Actor actor, LocalSession session, @Arg(desc = "Pattern") Pattern pattern, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new PatternTransform(other, pattern);
// }
//
// @Command(
// name = "#offset",
// desc = "Offset transform"
// )
// public ResettableExtent offset(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new OffsetExtent(other, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#spread",
// aliases = {"#randomoffset"},
// desc = "Random offset transform"
//)
// public ResettableExtent randomOffset(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new RandomOffsetTransform(other, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#scale",
// desc = "All changes will be scaled"
// )
// public ResettableExtent scale(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new ScaleTransform(other, x, y, z);
// }
//
// @Command(
// name = "#rotate",
// desc = "All changes will be rotate around the initial position"
// )
// public ResettableExtent rotate(Player player, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// ExtentTraverser<TransformExtent> traverser = new ExtentTraverser<>(other).find(TransformExtent.class);
// BlockTransformExtent affine = traverser != null ? traverser.get() : null;
// if (affine == null) {
// other = affine = new TransformExtent(other);
// }
// AffineTransform transform = (AffineTransform) affine.getTransform();
// transform = transform.rotateX(x);
// transform = transform.rotateY(y);
// transform = transform.rotateZ(z);
// affine.setTransform(transform);
// return other;
// }
//}

Datei anzeigen

@ -18,6 +18,8 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
@ -54,8 +56,14 @@ public class ImageBrush implements Brush {
default: default:
BlockState block = extent.getBlock(pos); BlockState block = extent.getBlock(pos);
TextureUtil tu = session.getTextureUtil(); TextureUtil tu = session.getTextureUtil();
int existingColor = tu.getColor(block.getBlockType()); BlockType type = block.getBlockType();
return tu.combineTransparency(color, existingColor); int existingColor;
if (type == BlockTypes.GRASS_BLOCK) {
existingColor = tu.getColor(extent.getBiome(pos));
} else {
existingColor = tu.getColor(type);
}
return TextureUtil.combineTransparency(color, existingColor);
} }
}; };

Datei anzeigen

@ -1,136 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.sk89q.worldedit.extension.factory;
//
//import com.boydti.fawe.command.FaweParser;
//import com.boydti.fawe.command.SuggestInputParseException;
//import com.boydti.fawe.object.extent.MultiTransform;
//import com.boydti.fawe.object.extent.RandomTransform;
//import com.boydti.fawe.object.extent.ResettableExtent;
//import com.boydti.fawe.object.random.TrueRandom;
//import com.boydti.fawe.util.StringMan;
//import com.google.common.collect.Iterables;
//import com.sk89q.minecraft.util.commands.CommandLocals;
//import com.sk89q.worldedit.WorldEdit;
////import com.sk89q.worldedit.command.TransformCommands;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.input.NoMatchException;
//import com.sk89q.worldedit.extension.input.ParserContext;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.internal.expression.Expression;
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//
//public class DefaultTransformParser extends FaweParser<ResettableExtent> {
//
// public DefaultTransformParser(WorldEdit worldEdit) {
// super(worldEdit, "transforms");
// }
//
// @Override
// public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
// if (input.isEmpty()) return null;
//
// List<Double> unionChances = new ArrayList<>();
// List<Double> intersectionChances = new ArrayList<>();
//
// List<ResettableExtent> intersection = new ArrayList<>();
// List<ResettableExtent> union = new ArrayList<>();
// final CommandLocals locals = new CommandLocals();
// Actor actor = context != null ? context.getActor() : null;
// if (actor != null) {
// locals.put(Actor.class, actor);
// }
// try {
// List<Map.Entry<ParseEntry, List<String>>> parsed = parse(input);
// for (Map.Entry<ParseEntry, List<String>> entry : parsed) {
// ParseEntry pe = entry.getKey();
// String command = pe.input;
// ResettableExtent transform;
// double chance = 1;
// if (command.isEmpty()) {
// transform = parseFromInput(StringMan.join(entry.getValue(), ','), context);
// } else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// transform = parse(command + cmdArgs, context);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// throw new NoMatchException("See: //transforms");
// }
// if (transform == null) {
// // Legacy syntax
// int percentIndex = command.indexOf('%');
// if (percentIndex != -1) { // Legacy percent pattern
// chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
// command = command.substring(percentIndex + 1);
// if (!entry.getValue().isEmpty()) {
// if (!command.isEmpty()) command += " ";
// command += StringMan.join(entry.getValue(), " ");
// }
// transform = parseFromInput(command, context);
// } else {
// throw new NoMatchException("See: //transforms");
// }
// }
// if (pe.and) { // &
// intersectionChances.add(chance);
// intersection.add(transform);
// } else {
// if (!intersection.isEmpty()) {
// if (intersection.size() == 1) {
// throw new InputParseException("Error, floating &");
// }
// MultiTransform multi = new MultiTransform();
// double total = 0;
// for (int i = 0; i < intersection.size(); i++) {
// Double value = intersectionChances.get(i);
// total += value;
// multi.add(intersection.get(i), value);
// }
// union.add(multi);
// unionChances.add(total);
// intersection.clear();
// intersectionChances.clear();
// }
// unionChances.add(chance);
// union.add(transform);
// }
// }
// }
// } catch (Throwable e) {
// throw new InputParseException(e.getMessage(), e);
// }
// if (!intersection.isEmpty()) {
// if (intersection.size() == 1) {
// throw new InputParseException("Error, floating &");
// }
// MultiTransform multi = new MultiTransform();
// double total = 0;
// for (int i = 0; i < intersection.size(); i++) {
// Double value = intersectionChances.get(i);
// total += value;
// multi.add(intersection.get(i), value);
// }
// union.add(multi);
// unionChances.add(total);
// intersection.clear();
// intersectionChances.clear();
// }
// if (union.isEmpty()) {
// throw new NoMatchException("See: //transforms");
// } else if (union.size() == 1) {
// return union.get(0);
// } else {
// RandomTransform random = new RandomTransform(new TrueRandom());
// for (int i = 0; i < union.size(); i++) {
// random.add(union.get(i), unionChances.get(i));
// }
// return random;
// }
// }
//
//
//}

Datei anzeigen

@ -0,0 +1,144 @@
package com.fastasyncworldedit.core.extension.factory;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.transform.RichTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.Linear3DTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.LinearTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.OffsetTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.PatternTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.RandomTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.RotateTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.ScaleTransformParser;
import com.fastasyncworldedit.core.extension.factory.parser.transform.SpreadTransformParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.RandomTransform;
import com.fastasyncworldedit.core.math.random.TrueRandom;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.internal.registry.AbstractFactory;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.ArrayList;
import java.util.List;
public class TransformFactory extends AbstractFactory<ResettableExtent> {
private final RichTransformParser richTransformParser;
/**
* Create a new factory.
*
* @param worldEdit the WorldEdit instance
*/
public TransformFactory(WorldEdit worldEdit) {
super(worldEdit, new NullTransformParser(worldEdit));
richTransformParser = new RichTransformParser(worldEdit);
// split and parse each sub-transform
register(new RandomTransformParser(worldEdit));
register(new OffsetTransformParser(worldEdit));
register(new ScaleTransformParser(worldEdit));
register(new RotateTransformParser(worldEdit));
register(new SpreadTransformParser(worldEdit));
register(new PatternTransformParser(worldEdit));
register(new LinearTransformParser(worldEdit));
register(new Linear3DTransformParser(worldEdit));
}
@Override
public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
List<ResettableExtent> transforms = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
ResettableExtent match = richTransformParser.parseFromInput(component, context);
if (match != null) {
transforms.add(match);
continue;
}
parseFromParsers(context, transforms, component);
}
return getResettableExtent(input, transforms);
}
private void parseFromParsers(
final ParserContext context,
final List<ResettableExtent> transforms,
final String component
) {
ResettableExtent match = null;
for (InputParser<ResettableExtent> parser : getParsers()) {
match = parser.parseFromInput(component, context);
if (match != null) {
break;
}
}
if (match == null) {
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
}
transforms.add(match);
}
/**
* Parses a transform without considering parsing through the {@link RichTransformParser}, therefore not accepting
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
*
* @param input input string
* @param context input context
* @return parsed result
* @throws InputParseException if no result found
*/
public ResettableExtent parseWithoutRich(String input, ParserContext context) throws InputParseException {
List<ResettableExtent> transforms = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
parseFromParsers(context, transforms, component);
}
return getResettableExtent(input, transforms);
}
private ResettableExtent getResettableExtent(final String input, final List<ResettableExtent> transforms) {
switch (transforms.size()) {
case 0:
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
case 1:
return transforms.get(0);
default:
RandomTransform randomTransform = new RandomTransform(new TrueRandom());
for (ResettableExtent transform : transforms) {
randomTransform.add(transform, 1d);
}
return randomTransform;
}
}
// TODO is there a better default?
private static final class NullTransformParser extends InputParser<ResettableExtent> {
private NullTransformParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
return null;
}
}
}

Datei anzeigen

@ -0,0 +1,14 @@
package com.fastasyncworldedit.core.extension.factory.parser;
import java.util.List;
public interface AliasedParser {
/**
* The strings this parser matches.
*
* @return the matching aliases
*/
List<String> getMatchedAliases();
}

Datei anzeigen

@ -0,0 +1,134 @@
package com.fastasyncworldedit.core.extension.factory.parser;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public abstract class FaweParser<T> extends InputParser<T> implements AliasedParser {
protected FaweParser(WorldEdit worldEdit) {
super(worldEdit);
}
/**
* Parse an input into a list of {@link java.util.Map.Entry} of {@link ParseEntry} and a list of the given arguments, where
* arguments are given in square brackets, e.g. {@code #offset[2][10][2]}. Different entries may be separated by , or &
* (OR and AND respectively)
*
* @param toParse the string to parse
* @return a list of parsed entries and their arguments
* @throws InputParseException if the input is not complete (has dangling characters)
*/
public static List<Map.Entry<ParseEntry, List<String>>> parse(String toParse) throws InputParseException {
List<Map.Entry<ParseEntry, List<String>>> keys = new ArrayList<>();
List<String> inputs = new ArrayList<>();
List<Boolean> and = new ArrayList<>();
int last = 0;
outer:
for (int i = 0; i < toParse.length(); i++) {
char c = toParse.charAt(i);
switch (c) {
case ',':
case '&':
String result = toParse.substring(last, i);
if (!result.isEmpty()) {
inputs.add(result);
and.add(c == '&');
} else {
throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", c));
}
last = i + 1;
continue outer;
default:
if (c == '[') {
int next = StringMan.findMatchingBracket(toParse, i);
if (next != -1) {
i = next;
} else {
toParse += "]";
i = toParse.length();
}
}
}
}
inputs.add(toParse.substring(last));
for (int i = 0; i < inputs.size(); i++) {
String full = inputs.get(i);
String command = full;
List<String> args = new ArrayList<>();
while (!command.isEmpty() && command.charAt(command.length() - 1) == ']') {
int startPos = StringMan.findMatchingBracket(command, command.length() - 1);
if (startPos == -1) {
break;
}
String arg = command.substring(startPos + 1, command.length() - 1);
args.add(arg);
command = full.substring(0, startPos);
}
Collections.reverse(args);
ParseEntry entry = new ParseEntry(full, command, i > 0 ? and.get(i - 1) : false);
keys.add(new AbstractMap.SimpleEntry<>(entry, args));
}
return keys;
}
protected PlatformCommandManager getPlatform() {
return PlatformCommandManager.getInstance();
}
public static class ParseEntry {
private final boolean and;
private final String input;
private final String full;
public ParseEntry(String full, String input, boolean type) {
this.full = full;
this.input = input;
this.and = type;
}
/**
* Gives if the parsed entry was appended to the original input as an AND.
*
* @return if appended to input with '&' rather than ','
*/
public boolean isAnd() {
return and;
}
/**
* The input "name" e.g. for {@code #offset[2][10][2]}, returns "offset"
*
* @return input name
*/
public String getInput() {
return input;
}
/**
* The original full input, including arguments e.g. for {@code #offset[2][10][2]}, returns "#offset[2][10][2]"
*
* @return original full input
*/
public String getFull() {
return full;
}
@Override
public String toString() {
return input + " | " + and;
}
}
}

Datei anzeigen

@ -22,7 +22,7 @@ import java.util.stream.Stream;
* *
* @param <E> the parse result. * @param <E> the parse result.
*/ */
public abstract class RichParser<E> extends InputParser<E> { public abstract class RichParser<E> extends InputParser<E> implements AliasedParser {
private final String[] prefixes; private final String[] prefixes;
@ -51,7 +51,7 @@ public abstract class RichParser<E> extends InputParser<E> {
@Nonnull @Nonnull
private Function<String, Stream<? extends String>> extractArguments(String input) { private Function<String, Stream<? extends String>> extractArguments(String input) {
return prefix -> { return prefix -> {
if (input.length() > prefix.length()) { if (input.length() > prefix.length() && prefix.startsWith(input + "[")) {
// input already contains argument(s) -> extract them // input already contains argument(s) -> extract them
String[] strings = extractArguments(input.substring(prefix.length()), false); String[] strings = extractArguments(input.substring(prefix.length()), false);
// rebuild the argument string without the last argument // rebuild the argument string without the last argument
@ -69,10 +69,24 @@ public abstract class RichParser<E> extends InputParser<E> {
}; };
} }
/**
* Gives the default prefix/name of the pattern/mask/transform.
*
* @return default prefix
*/
public String getPrefix() { public String getPrefix() {
return this.prefixes[0]; return this.prefixes[0];
} }
/**
* Return all prefix/name aliases of the pattern/mask/transform
*
* @return all prefix/name aliases
*/
public List<String> getMatchedAliases() {
return Arrays.asList(prefixes);
}
@Override @Override
public Stream<String> getSuggestions(String input) { public Stream<String> getSuggestions(String input) {
return Arrays.stream(this.prefixes) return Arrays.stream(this.prefixes)
@ -140,8 +154,15 @@ public abstract class RichParser<E> extends InputParser<E> {
} }
} }
} }
if (!requireClosing && open > 0) { if (!requireClosing) {
if (open > 0) {
arguments.add(input.substring(openIndex + 1)); arguments.add(input.substring(openIndex + 1));
} else {
int last = input.lastIndexOf(']');
if (last != -1) {
arguments.add(input.substring(last));
}
}
} }
if (requireClosing && open != 0) { if (requireClosing && open != 0) {
throw new InputParseException(Caption.of("fawe.error.invalid-bracketing", TextComponent.of("'[' or ']'?"))); throw new InputParseException(Caption.of("fawe.error.invalid-bracketing", TextComponent.of("'[' or ']'?")));

Datei anzeigen

@ -1,189 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//*
//package com.fastasyncworldedit.core.extension.factory.parser.mask;
//
//import com.boydti.fawe.command.FaweParser;
//import com.boydti.fawe.command.SuggestInputParseException;
//import com.boydti.fawe.config.Caption;
//import com.boydti.fawe.util.StringMan;
//import com.sk89q.minecraft.util.commands.CommandLocals;
//import com.sk89q.worldedit.WorldEdit;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.input.ParserContext;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extent.Extent;
//import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
//import com.sk89q.worldedit.function.mask.Mask;
//import com.sk89q.worldedit.function.mask.MaskIntersection;
//import com.sk89q.worldedit.function.mask.MaskUnion;
//import com.sk89q.worldedit.session.request.Request;
//import com.sk89q.worldedit.world.block.BaseBlock;
//import com.sk89q.worldedit.world.block.BlockStateHolder;
//import com.sk89q.worldedit.world.block.BlockTypes;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//import java.util.stream.Stream;
//
//public class DefaultMaskParser extends FaweParser<Mask> {
// public DefaultMaskParser(WorldEdit worldEdit) {
// super(worldEdit, "masks");
// }
//
// @Override
// public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
// if (input.isEmpty()) {
// throw new SuggestInputParseException("No input provided", "", () -> Stream.concat(Stream.of("#", ",", "&"), BlockTypes.getNameSpaces().stream().map(n -> n + ":")).collect(Collectors.toList()));
// }
// Extent extent = Request.request().getExtent();
// if (extent == null) extent = context.getExtent();
// List<List<Mask>> masks = new ArrayList<>();
// masks.add(new ArrayList<>());
//
// final CommandLocals locals = new CommandLocals();
// Actor actor = context != null ? context.getActor() : null;
// if (actor != null) {
// locals.put(Actor.class, actor);
// }
// try {
// List<Map.Entry<ParseEntry, List<String>>> parsed = parse(input);
// for (Map.Entry<ParseEntry, List<String>> entry : parsed) {
// ParseEntry pe = entry.getKey();
// final String command = pe.input;
// String full = pe.full;
// Mask mask = null;
// if (command.isEmpty()) {
// mask = parseFromInput(StringMan.join(entry.getValue(), ','), context);
// } else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// mask = parse(command + cmdArgs, context);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// // TODO NOT IMPLEMENTED
//// throw SuggestInputParseException.of(e, full, () -> {
//// try {
//// List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
//// if (suggestions.size() <= 2) {
//// for (int i = 0; i < suggestions.size(); i++) {
//// String suggestion = suggestions.get(i);
//// if (suggestion.indexOf(' ') != 0) {
//// String[] split = suggestion.split(" ");
//// suggestion = "[" + StringMan.join(split, "][") + "]";
//// suggestions.set(i, suggestion);
//// }
//// }
//// }
//// return suggestions;
//// } catch (CommandException e1) {
//// throw new InputParseException(e1.getMessage());
//// } catch (Throwable e2) {
//// e2.printStackTrace();
//// throw new InputParseException(e2.getMessage());
//// }
//// });
// }
// if (mask == null) {
// // Legacy patterns
// char char0 = command.charAt(0);
// boolean charMask = input.length() > 1 && input.charAt(1) != '[';
// if (charMask && input.charAt(0) == '=') {
// return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
// }
// if (char0 == '#' || char0 == '?') {
// // TODO NOT IMPLEMENTED
//// throw new SuggestInputParseException(new NoMatchException("Unknown mask: " + full + ", See: //masks"), full,
//// () -> {
//// if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
//// return dispatcher.getAliases().stream().filter(
//// s -> s.startsWith(command.toLowerCase(Locale.ROOT))
//// ).collect(Collectors.toList());
//// }
//// );
// }
// // Legacy syntax
// if (charMask) {
// switch (char0) {
// case '\\': //
// case '/': //
// case '{': //
// case '$': //
// case '%': {
// String value = command.substring(1) + ((entry.getValue().isEmpty()) ? "" : "[" + StringMan.join(entry.getValue(), "][") + "]");
// if (value.contains(":")) {
// if (value.charAt(0) == ':') value.replaceFirst(":", "");
// value = value.replaceAll(":", "][");
// }
// mask = parseFromInput("#" + char0 + "[" + value + "]", context);
// break;
// }
// case '|':
// case '~':
// case '<':
// case '>':
// case '!':
// input = input.substring(input.indexOf(char0) + 1);
// mask = parseFromInput(char0 + "[" + input + "]", context);
// if (actor != null) {
// actor.print(Caption.of("fawe.worldedit.help.command.clarifying.bracket", char0 + "[" + input + "]"));
// }
// return mask;
// }
// }
// }
// if (mask == null) {
// if (command.startsWith("[")) {
// int end = command.lastIndexOf(']');
// mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
// } else {
// List<String> entries = entry.getValue();
// BlockMaskBuilder builder = new BlockMaskBuilder();
//// if (StringMan.containsAny(full, "\\^$.|?+(){}<>~$!%^&*+-/"))
// {
// try {
// builder.addRegex(full);
// } catch (InputParseException ignored) {}
// }
// if (mask == null) {
// context.setPreferringWildcard(false);
// context.setRestricted(false);
// BaseBlock block = worldEdit.getBlockFactory().parseFromInput(full, context);
// builder.add(block);
// mask = builder.build(extent);
// }
// }
// }
// }
// if (pe.and) {
// masks.add(new ArrayList<>());
// }
// masks.get(masks.size() - 1).add(mask);
// }
// } catch (InputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// e.printStackTrace();
// throw new InputParseException(e.getMessage(), e);
// }
// List<Mask> maskUnions = new ArrayList<>();
// for (List<Mask> maskList : masks) {
// if (maskList.size() == 1) {
// maskUnions.add(maskList.get(0));
// } else if (maskList.size() != 0) {
// maskUnions.add(new MaskUnion(maskList));
// }
// }
// if (maskUnions.size() == 1) {
// return maskUnions.get(0);
// } else if (maskUnions.size() != 0) {
// return new MaskIntersection(maskUnions);
// } else {
// return null;
// }
//
// }
//}

Datei anzeigen

@ -0,0 +1,241 @@
package com.fastasyncworldedit.core.extension.factory.parser.mask;
import com.fastasyncworldedit.core.command.SuggestInputParseException;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.FaweParser;
import com.fastasyncworldedit.core.function.mask.BlockMaskBuilder;
import com.fastasyncworldedit.core.function.mask.MaskUnion;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.MaskIntersection;
import com.sk89q.worldedit.internal.command.CommandArgParser;
import com.sk89q.worldedit.internal.util.Substring;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.world.block.BaseBlock;
import org.enginehub.piston.inject.MemoizingValueAccess;
import org.enginehub.piston.suggestion.Suggestion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Attempts to parse masks given rich inputs, allowing for & and ,. Also allows for nested masks
*/
public class RichMaskParser extends FaweParser<Mask> {
/**
* New instance
*
* @param worldEdit {@link WorldEdit} instance.
*/
public RichMaskParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Mask parseFromInput(String input, ParserContext context) throws InputParseException {
if (input.isEmpty()) {
throw new SuggestInputParseException("No input provided", "", () -> Stream
.of("#", ",", "&")
.map(n -> n + ":")
.collect(Collectors.toList())
// TODO namespaces
);
}
Extent extent = context.getExtent();
if (extent == null) {
extent = Request.request().getExtent();
}
List<List<Mask>> masks = new ArrayList<>();
masks.add(new ArrayList<>());
final CommandLocals locals = new CommandLocals();
Actor actor = context.getActor();
if (actor != null) {
locals.put(Actor.class, actor);
}
try {
List<Map.Entry<ParseEntry, List<String>>> parsed = parse(input);
for (Map.Entry<ParseEntry, List<String>> entry : parsed) {
ParseEntry pe = entry.getKey();
final String command = pe.getInput();
String full = pe.getFull();
Mask mask = null;
if (command.isEmpty()) {
mask = parseFromInput(StringMan.join(entry.getValue(), ','), context);
} else if (!worldEdit.getMaskFactory().containsAlias(command)) {
// Legacy patterns
char char0 = command.charAt(0);
boolean charMask = input.length() > 1 && input.charAt(1) != '[';
if (charMask && input.charAt(0) == '=') {
return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
}
if (char0 == '#') {
throw new SuggestInputParseException(
new NoMatchException(Caption.of("fawe.error.parse.unknown-mask", full,
TextComponent
.of("https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
)
.clickEvent(ClickEvent.openUrl(
"https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
))
)),
full,
() -> {
if (full.length() == 1) {
return new ArrayList<>(worldEdit.getMaskFactory().getSuggestions(""));
}
return new ArrayList<>(worldEdit
.getMaskFactory()
.getSuggestions(command.toLowerCase(Locale.ROOT)));
}
);
}
// Legacy syntax
if (charMask) {
switch (char0) {
case '\\': //
case '/': //
case '{': //
case '$': //
case '%': {
String value = command.substring(1) + ((entry.getValue().isEmpty())
? ""
: "[" + StringMan.join(
entry.getValue(),
"]["
) + "]");
if (value.contains(":")) {
if (value.charAt(0) == ':') {
value = value.replaceFirst(":", "");
}
value = value.replaceAll(":", "][");
}
mask = parseFromInput("#" + char0 + "[" + value + "]", context);
break;
}
case '|':
case '~':
case '<':
case '>':
case '!':
input = input.substring(input.indexOf(char0) + 1);
mask = parseFromInput(char0 + "[" + input + "]", context);
if (actor != null) {
actor.print(Caption.of(
"fawe.worldedit.help.command.clarifying.bracket",
char0 + "[" + input +
"]"
));
}
return mask;
}
}
if (mask == null) {
if (command.startsWith("[")) {
int end = command.lastIndexOf(']');
mask = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
} else {
BlockMaskBuilder builder = new BlockMaskBuilder();
try {
builder.addRegex(full);
} catch (InputParseException ignored) {
}
context.setPreferringWildcard(false);
context.setRestricted(false);
BaseBlock block = worldEdit.getBlockFactory().parseFromInput(full, context);
builder.add(block);
mask = builder.build(extent);
}
}
} else {
List<String> args = entry.getValue();
try {
mask = worldEdit.getMaskFactory().parseWithoutRich(full, context);
} catch (SuggestInputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
throw SuggestInputParseException.of(e, full, () -> {
try {
String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
List<Substring> split =
CommandArgParser.forArgString(cmdArgs).parseArgs().collect(Collectors.toList());
List<String> argStrings = split
.stream()
.map(Substring::getSubstring)
.collect(Collectors.toList());
MemoizingValueAccess access = getPlatform().initializeInjectedValues(() -> cmdArgs,
actor,
null, true
);
List<String> suggestions = getPlatform().getCommandManager().getSuggestions(
access,
argStrings
).stream().map(Suggestion::getSuggestion).collect(Collectors.toUnmodifiableList());
List<String> result = new ArrayList<>();
if (suggestions.size() <= 2) {
for (int i = 0; i < suggestions.size(); i++) {
String suggestion = suggestions.get(i);
if (suggestion.indexOf(' ') != 0) {
String[] splitSuggestion = suggestion.split(" ");
suggestion = "[" + StringMan.join(splitSuggestion, "][") + "]";
result.set(i, suggestion);
}
}
}
return result;
} catch (Throwable e2) {
e2.printStackTrace();
throw new InputParseException(Caption.of(e2.getMessage()));
}
});
}
}
if (pe.isAnd()) {
masks.add(new ArrayList<>());
}
masks.get(masks.size() - 1).add(mask);
}
} catch (InputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
e.printStackTrace();
throw new InputParseException(Caption.of(e.getMessage()), e);
}
List<Mask> maskUnions = new ArrayList<>();
for (List<Mask> maskList : masks) {
if (maskList.size() == 1) {
maskUnions.add(maskList.get(0));
} else if (maskList.size() != 0) {
maskUnions.add(new MaskUnion(maskList));
}
}
if (maskUnions.size() == 1) {
return maskUnions.get(0);
} else if (maskUnions.size() != 0) {
return new MaskIntersection(maskUnions);
} else {
return null;
}
}
@Override
public List<String> getMatchedAliases() {
return Collections.emptyList();
}
}

Datei anzeigen

@ -0,0 +1,47 @@
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.AngleColorPattern;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class AngleColorPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public AngleColorPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#anglecolor", "#anglecolour");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index != 0) {
return Stream.empty();
}
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[distance] (e.g. " + getPrefix() + "[10])")
));
}
int distance = Integer.parseInt(input[0]);
return new AngleColorPattern(context.requireExtent(), context.requireSession(), distance);
}
}

Datei anzeigen

@ -0,0 +1,53 @@
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.AverageColorPattern;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class AverageColorPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public AverageColorPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#averagecolor", "#averagecolour");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index > 4) {
return Stream.empty();
}
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 4) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[r][g][b][a] (e.g. " + getPrefix() + "[156][100][0][120])")
));
}
return new AverageColorPattern(
context.requireExtent(),
context.requireSession(),
Integer.parseInt(input[0]),
Integer.parseInt(input[1]),
Integer.parseInt(input[2]),
Integer.parseInt(input[3])
);
}
}

Datei anzeigen

@ -25,7 +25,7 @@ public class BiomePatternParser extends RichParser<Pattern> {
* @param worldEdit the worldedit instance. * @param worldEdit the worldedit instance.
*/ */
public BiomePatternParser(WorldEdit worldEdit) { public BiomePatternParser(WorldEdit worldEdit) {
super(worldEdit, "#biome"); super(worldEdit, "#biome", "$");
} }
// overridden to provide $<biome> too // overridden to provide $<biome> too

Datei anzeigen

@ -0,0 +1,46 @@
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.BufferedPattern2D;
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.stream.Stream;
public class BufferedPattern2DParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public BufferedPattern2DParser(WorldEdit worldEdit) {
super(worldEdit, "#buffer2d");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(input[0], context);
return new BufferedPattern2D(context.requireActor(), inner);
}
}

Datei anzeigen

@ -0,0 +1,53 @@
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.util.MathMan;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.awt.Color;
import java.util.stream.Stream;
public class ColorPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public ColorPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#color", "#colour");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index > 4) {
return Stream.empty();
}
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 4) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[r][g][b][a] (e.g. " + getPrefix() + "[156][100][0][120])")
));
}
Color color = new Color(
MathMan.clamp(Integer.parseInt(input[0]), 0, 255),
MathMan.clamp(Integer.parseInt(input[1]), 0, 255),
MathMan.clamp(Integer.parseInt(input[2]), 0, 255),
MathMan.clamp(Integer.parseInt(input[3]), 0, 255)
);
return context.requireSession().getTextureUtil().getNearestBlock(color.getRGB());
}
}

Datei anzeigen

@ -0,0 +1,36 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.function.pattern.ShadePattern;
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.internal.registry.SimpleInputParser;
import java.util.Collections;
import java.util.List;
public class DarkenPatternParser extends SimpleInputParser<Pattern> {
private final List<String> aliases = Collections.singletonList("#darken");
/**
* Create a new simple parser with a defined prefix for the result.
*
* @param worldEdit the worldedit instance.
*/
public DarkenPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return this.aliases;
}
@Override
public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
return new ShadePattern(context.requireExtent(), context.requireSession(), true);
}
}

Datei anzeigen

@ -1,167 +0,0 @@
// TODO: Ping @MattBDev to reimplement (or remove because this class is stupid) 2020-02-04
///*
//package com.fastasyncworldedit.core.extension.factory.parser.pattern;
//
//import com.boydti.fawe.command.FaweParser;
//import com.boydti.fawe.command.SuggestInputParseException;
//import com.boydti.fawe.object.random.TrueRandom;
//import com.boydti.fawe.util.StringMan;
//import com.google.common.collect.Iterables;
//import com.sk89q.minecraft.util.commands.CommandLocals;
//import com.sk89q.worldedit.WorldEdit;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.input.NoMatchException;
//import com.sk89q.worldedit.extension.input.ParserContext;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extension.platform.PlatformCommandManager;
//import com.sk89q.worldedit.function.pattern.Pattern;
//import com.sk89q.worldedit.function.pattern.RandomPattern;
//import com.sk89q.worldedit.internal.expression.Expression;
//import com.sk89q.worldedit.world.block.BlockTypes;
//
//import java.util.ArrayList;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//import java.util.stream.Stream;
//
//public class DefaultPatternParser extends FaweParser<Pattern> {
//
// public DefaultPatternParser(WorldEdit worldEdit) {
// super(worldEdit, "patterns");
// }
//
// @Override
// public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
// if (input.isEmpty()) {
// throw new SuggestInputParseException("No input provided", "", () -> Stream.concat(Stream.of("#", ",", "&"), BlockTypes.getNameSpaces().stream().map(n -> n + ":")).collect(Collectors.toList()));
// }
// List<Double> chances = new ArrayList<>();
// List<Pattern> patterns = new ArrayList<>();
// final CommandLocals locals = new CommandLocals();
// Actor actor = context != null ? context.getActor() : null;
// if (actor != null) {
// locals.put(Actor.class, actor);
// }
// try {
// for (Map.Entry<ParseEntry, List<String>> entry : parse(input)) {
// ParseEntry pe = entry.getKey();
// final String command = pe.input;
// String full = pe.full;
// Pattern pattern = null;
// double chance = 1;
// if (command.isEmpty()) {
// pattern = parseFromInput(StringMan.join(entry.getValue(), ','), context);
// } else {
// List<String> args = entry.getValue();
// String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
// try {
// pattern = parse(command + cmdArgs, context);
// } catch (SuggestInputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// // TODO NOT IMPLEMENTED
//// throw SuggestInputParseException.of(e, full, () -> {
//// try {
//// List<String> suggestions = dispatcher.get(command).getCallable().getSuggestions(cmdArgs, locals);
//// if (suggestions.size() <= 2) {
//// for (int i = 0; i < suggestions.size(); i++) {
//// String suggestion = suggestions.get(i);
//// if (suggestion.indexOf(' ') != 0) {
//// String[] split = suggestion.split(" ");
//// suggestion = "[" + StringMan.join(split, "][") + "]";
//// suggestions.set(i, suggestion);
//// }
//// }
//// }
//// return suggestions;
//// } catch (CommandException e1) {
//// throw new InputParseException(e1.getMessage());
//// } catch (Throwable e2) {
//// e2.printStackTrace();
//// throw new InputParseException(e2.getMessage());
//// }
//// });
// }
// if (pattern == null) {
// // Legacy patterns
// char char0 = command.charAt(0);
// boolean charMask = input.length() > 1 && input.charAt(1) != '[';
// if (charMask && input.charAt(0) == '=') {
// return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
// }
// if (char0 == '#') {
// // TODO NOT IMPLEMENTED
//// throw new SuggestInputParseException(new NoMatchException("Unknown pattern: " + full + ", See: //patterns"), full,
//// () -> {
//// if (full.length() == 1) return new ArrayList<>(dispatcher.getPrimaryAliases());
//// return dispatcher.getAliases().stream().filter(
//// s -> s.startsWith(command.toLowerCase(Locale.ROOT))
//// ).collect(Collectors.toList());
//// }
//// );
// }
//
//
// if (charMask) {
// if (char0 == '$') {
// String value = command.substring(1) + ((entry.getValue().isEmpty()) ? ""
// : "[" + StringMan.join(entry.getValue(), "][") + "]");
// if (value.contains(":")) {
// if (value.charAt(0) == ':') {
// value.replaceFirst(":", "");
// }
// value = value.replaceAll(":", "][");
// }
// pattern = parseFromInput(char0 + "[" + value + "]", context);
// }
// }
// if (pattern == null) {
// if (command.startsWith("[")) {
// int end = command.lastIndexOf(']');
// pattern = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
// } else {
// int percentIndex = command.indexOf('%');
// if (percentIndex != -1) { // Legacy percent pattern
// chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
// String value = command.substring(percentIndex + 1);
// if (!entry.getValue().isEmpty()) {
// if (!value.isEmpty()) value += " ";
// value += StringMan.join(entry.getValue(), " ");
// }
// pattern = parseFromInput(value, context);
// } else { // legacy block pattern
// try {
// pattern = worldEdit.getBlockFactory().parseFromInput(pe.full, context);
// } catch (NoMatchException e) {
// throw new NoMatchException(e.getMessage() + " See: //patterns");
// }
// }
// }
// }
// }
// }
// if (pattern != null) {
// patterns.add(pattern);
// chances.add(chance);
// }
// }
// } catch (InputParseException rethrow) {
// throw rethrow;
// } catch (Throwable e) {
// e.printStackTrace();
// throw new InputParseException(e.getMessage(), e);
// }
// if (patterns.isEmpty()) {
// return null;
// }
// if (patterns.size() == 1) {
// return patterns.get(0);
// }
// RandomPattern random = new RandomPattern(new TrueRandom());
// for (int i = 0; i < patterns.size(); i++) {
// random.add(patterns.get(i), chances.get(i));
// }
// return random;
// }
//}

Datei anzeigen

@ -0,0 +1,46 @@
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.DesaturatePattern;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class DesaturatePatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public DesaturatePatternParser(WorldEdit worldEdit) {
super(worldEdit, "#desaturate");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
return Stream.empty();
}
@Override
public Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[percent] (e.g. " + getPrefix() + "[90])")
));
}
return new DesaturatePattern(context.requireExtent(), context.requireSession(), Double.parseDouble(arguments[0]) / 100);
}
}

Datei anzeigen

@ -14,6 +14,11 @@ public class ExistingPatternParser extends SimpleInputParser<Pattern> {
private final List<String> aliases = Collections.singletonList("#existing"); private final List<String> aliases = Collections.singletonList("#existing");
/**
* Create a new simple parser with a defined prefix for the result.
*
* @param worldEdit the worldedit instance.
*/
public ExistingPatternParser(WorldEdit worldEdit) { public ExistingPatternParser(WorldEdit worldEdit) {
super(worldEdit); super(worldEdit);
} }

Datei anzeigen

@ -0,0 +1,53 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.function.pattern.ExpressionPattern;
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.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.registry.SimpleInputParser;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.Collections;
import java.util.List;
public class ExpressionPatternParser extends SimpleInputParser<Pattern> {
private final List<String> aliases = Collections.singletonList("=");
/**
* Create a new simple parser with a defined prefix for the result.
*
* @param worldEdit the worldedit instance.
*/
public ExpressionPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return this.aliases;
}
@Override
public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
try {
Expression exp = Expression.compile(input.substring(1), "x", "y", "z");
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(
context.requireExtent(), Vector3.ONE, Vector3.ZERO);
exp.setEnvironment(env);
return new ExpressionPattern(exp);
} catch (ExpressionException e) {
throw new InputParseException(Caption.of(
"worldedit.error.parser.invalid-expression",
TextComponent.of(e.getMessage())
));
}
}
}

Datei anzeigen

@ -0,0 +1,36 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.function.pattern.ShadePattern;
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.internal.registry.SimpleInputParser;
import java.util.Collections;
import java.util.List;
public class LightenPatternParser extends SimpleInputParser<Pattern> {
private final List<String> aliases = Collections.singletonList("#lighten");
/**
* Create a new simple parser with a defined prefix for the result.
*
* @param worldEdit the worldedit instance.
*/
public LightenPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public List<String> getMatchedAliases() {
return this.aliases;
}
@Override
public Pattern parseFromSimpleInput(String input, ParserContext context) throws InputParseException {
return new ShadePattern(context.requireExtent(), context.requireSession(), false);
}
}

Datei anzeigen

@ -0,0 +1,64 @@
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.LinearBlockPattern;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import javax.annotation.Nonnull;
import java.util.Set;
import java.util.stream.Stream;
public class LinearPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public LinearPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#linear", "#l");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
case 3:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
if (inner instanceof BlockStateHolder) {
return inner;
}
if (inner instanceof RandomPattern) {
Set<Pattern> patterns = ((RandomPattern) inner).getPatterns();
return new LinearBlockPattern(patterns.toArray(new Pattern[0]));
}
throw new InputParseException(Caption.of("Pattern " + inner.getClass().getSimpleName()
+ " cannot be used with " + getPrefix()));
}
}

Datei anzeigen

@ -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.MaskedPattern;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class MaskedPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public MaskedPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#mask");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getMaskFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 3) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[mask][pattern][pattern] (e.g. " + getPrefix() + "[oak_planks][dirt][stone])")
));
}
Mask mask = this.worldEdit.getMaskFactory().parseFromInput(arguments[0], context);
Pattern inner1 = this.worldEdit.getPatternFactory().parseFromInput(arguments[1], context);
Pattern inner2 = this.worldEdit.getPatternFactory().parseFromInput(arguments[2], context);
return new MaskedPattern(mask, inner1, inner2);
}
}

Datei anzeigen

@ -0,0 +1,46 @@
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.NoXPattern;
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.stream.Stream;
public class NoXPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public NoXPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#!x", "#nx", "#nox");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(input[0], context);
return new NoXPattern(inner);
}
}

Datei anzeigen

@ -0,0 +1,46 @@
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.NoYPattern;
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.stream.Stream;
public class NoYPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public NoYPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#!y", "#ny", "#noy");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(input[0], context);
return new NoYPattern(inner);
}
}

Datei anzeigen

@ -0,0 +1,46 @@
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.NoZPattern;
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.stream.Stream;
public class NoZPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public NoZPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#!z", "#nz", "#noz");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(input[0], context);
return new NoZPattern(inner);
}
}

Datei anzeigen

@ -0,0 +1,67 @@
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.OffsetPattern;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class OffsetPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public OffsetPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#offset");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
case 3:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 2 && arguments.length != 4) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone][2][0][4])")
));
}
int x;
int y;
int z;
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
if (arguments.length == 4) {
x = Integer.parseInt(arguments[1]);
y = Integer.parseInt(arguments[2]);
z = Integer.parseInt(arguments[3]);
} else {
x = y = z = Integer.parseInt(arguments[1]);
}
Extent extent = context.requireExtent();
int minY = extent.getMinY();
int maxY = extent.getMaxY();
return new OffsetPattern(inner, x, y, z, minY, maxY);
}
}

Datei anzeigen

@ -0,0 +1,93 @@
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.extent.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.function.pattern.RandomFullClipboardPattern;
import com.sk89q.worldedit.WorldEdit;
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.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class RandomFullClipboardPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public RandomFullClipboardPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#fullcopy");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 1:
case 2:
return SuggestionHelper.suggestBoolean(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length == 0 || arguments.length > 3) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[#copy][true][false])")
));
}
try {
boolean rotate = arguments.length >= 2 && Boolean.getBoolean(arguments[1]);
boolean flip = arguments.length == 3 && Boolean.getBoolean(arguments[2]);
List<ClipboardHolder> clipboards;
switch (arguments[0].toLowerCase()) {
case "#copy":
case "#clipboard":
ClipboardHolder clipboard = context.requireSession().getExistingClipboard();
if (clipboard == null) {
throw new InputParseException(Caption.of("fawe.error.parse.no-clipboard", getPrefix()));
}
clipboards = Collections.singletonList(clipboard);
break;
default:
Actor player = context.requireActor();
MultiClipboardHolder multi = ClipboardFormats.loadAllFromInput(player,
arguments[0], ClipboardFormats.findByAlias("fast"), true
);
if (multi == null) {
multi = ClipboardFormats.loadAllFromInput(player,
arguments[0], ClipboardFormats.findByAlias("sponge"), true
);
}
if (multi == null) {
multi = ClipboardFormats.loadAllFromInput(player,
arguments[0], ClipboardFormats.findByAlias("mcedit"), true
);
}
if (multi == null) {
throw new InputParseException(Caption.of("fawe.error.parse.no-clipboard-source", arguments[0]));
}
clipboards = multi.getHolders();
break;
}
return new RandomFullClipboardPattern(clipboards, rotate, flip);
} catch (IOException e) {
throw new InputParseException(Caption.of(e.getMessage()), e);
}
}
}

Datei anzeigen

@ -0,0 +1,65 @@
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.RandomOffsetPattern;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class RandomOffsetPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public RandomOffsetPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#spread", "#randomoffset");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
case 3:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 2 && arguments.length != 4) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone][2][0][4])")
));
}
int x;
int y;
int z;
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
if (arguments.length == 4) {
x = Integer.parseInt(arguments[1]);
y = Integer.parseInt(arguments[2]);
z = Integer.parseInt(arguments[3]);
} else {
x = y = z = Integer.parseInt(arguments[1]);
}
Extent extent = context.requireExtent();
return new RandomOffsetPattern(inner, x, y, z, extent.getMinY(), extent.getMaxY());
}
}

Datei anzeigen

@ -15,6 +15,11 @@ import java.util.stream.Stream;
public class RandomPatternParser extends InputParser<Pattern> { public class RandomPatternParser extends InputParser<Pattern> {
/**
* Create a new input parser.
*
* @param worldEdit the worldedit instance.
*/
public RandomPatternParser(WorldEdit worldEdit) { public RandomPatternParser(WorldEdit worldEdit) {
super(worldEdit); super(worldEdit);
} }

Datei anzeigen

@ -0,0 +1,48 @@
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.RelativePattern;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class RelativePatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public RelativePatternParser(WorldEdit worldEdit) {
super(worldEdit, "#relative", "#~", "#r", "#rel");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 1) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone,dirt])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(input[0], context);
Extent extent = context.requireExtent();
return new RelativePattern(inner, extent.getMinY(), extent.getMaxY());
}
}

Datei anzeigen

@ -0,0 +1,211 @@
package com.fastasyncworldedit.core.extension.factory.parser.pattern;
import com.fastasyncworldedit.core.command.SuggestInputParseException;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.FaweParser;
import com.fastasyncworldedit.core.math.random.TrueRandom;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.internal.command.CommandArgParser;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.util.Substring;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.world.block.BlockTypes;
import org.enginehub.piston.inject.MemoizingValueAccess;
import org.enginehub.piston.suggestion.Suggestion;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class RichPatternParser extends FaweParser<Pattern> {
/**
* Create a new rich pattern-parser.
*
* @param worldEdit the worldedit instance.
*/
public RichPatternParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
if (input.isEmpty()) {
throw new SuggestInputParseException(
"No input provided",
"",
() -> Stream
.concat(Stream.of("#", ",", "&"), BlockTypes.getNameSpaces().stream().map(n -> n + ":"))
.collect(Collectors.toList())
);
}
List<Double> chances = new ArrayList<>();
List<Pattern> patterns = new ArrayList<>();
final CommandLocals locals = new CommandLocals();
Actor actor = context != null ? context.getActor() : null;
if (actor != null) {
locals.put(Actor.class, actor);
}
try {
for (Map.Entry<ParseEntry, List<String>> entry : parse(input)) {
ParseEntry pe = entry.getKey();
final String command = pe.getInput();
String full = pe.getFull();
Pattern pattern = null;
double chance = 1;
if (command.isEmpty()) {
pattern = parseFromInput(StringMan.join(entry.getValue(), ','), context);
} else if (!worldEdit.getPatternFactory().containsAlias(command)) {
// Legacy patterns
char char0 = command.charAt(0);
boolean charPattern = input.length() > 1 && input.charAt(1) != '[';
if (charPattern && input.charAt(0) == '=') {
return parseFromInput(char0 + "[" + input.substring(1) + "]", context);
}
if (char0 == '#' && command.length() > 1 && command.charAt(1) != '#') {
throw new SuggestInputParseException(
new NoMatchException(Caption.of("fawe.error.parse.unknown-pattern", full,
TextComponent
.of("https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
)
.clickEvent(
ClickEvent.openUrl(
"https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
))
)),
full,
() -> {
if (full.length() == 1) {
return new ArrayList<>(worldEdit.getPatternFactory().getSuggestions(""));
}
return new ArrayList<>(worldEdit
.getPatternFactory()
.getSuggestions(command.toLowerCase(Locale.ROOT)));
}
);
}
if (charPattern) {
if (char0 == '$' || char0 == '^' || char0 == '*' || (char0 == '#' && input.charAt(1) == '#')) {
pattern = worldEdit.getPatternFactory().parseWithoutRich(full, context);
}
}
if (pattern == null) {
if (command.startsWith("[")) {
int end = command.lastIndexOf(']');
pattern = parseFromInput(command.substring(1, end == -1 ? command.length() : end), context);
} else {
int percentIndex = command.indexOf('%');
if (percentIndex != -1) { // Legacy percent pattern
chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
String value = command.substring(percentIndex + 1);
if (!entry.getValue().isEmpty()) {
if (!value.isEmpty()) {
value += " ";
}
value += StringMan.join(entry.getValue(), " ");
}
pattern = parseFromInput(value, context);
} else { // legacy block pattern
try {
pattern = worldEdit.getBlockFactory().parseFromInput(pe.getFull(), context);
} catch (NoMatchException e) {
throw new NoMatchException(Caption.of("fawe.error.parse.unknown-pattern", full,
TextComponent
.of("https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
)
.clickEvent(
com.sk89q.worldedit.util.formatting.text.event.ClickEvent.openUrl(
"https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
))
));
}
}
}
}
} else {
List<String> args = entry.getValue();
try {
pattern = worldEdit.getPatternFactory().parseWithoutRich(full, context);
} catch (SuggestInputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
throw SuggestInputParseException.of(e, full, () -> {
try {
String cmdArgs = ((args.isEmpty()) ? "" : " " + StringMan.join(args, " "));
List<Substring> split =
CommandArgParser.forArgString(cmdArgs).parseArgs().collect(Collectors.toList());
List<String> argStrings = split
.stream()
.map(Substring::getSubstring)
.collect(Collectors.toList());
MemoizingValueAccess access = getPlatform().initializeInjectedValues(() -> cmdArgs,
actor,
null, true
);
List<String> suggestions = getPlatform().getCommandManager().getSuggestions(
access,
argStrings
).stream().map(Suggestion::getSuggestion).collect(Collectors.toUnmodifiableList());
List<String> result = new ArrayList<>();
if (suggestions.size() <= 2) {
for (int i = 0; i < suggestions.size(); i++) {
String suggestion = suggestions.get(i);
if (suggestion.indexOf(' ') != 0) {
String[] splitSuggestion = suggestion.split(" ");
suggestion = "[" + StringMan.join(splitSuggestion, "][") + "]";
result.set(i, suggestion);
}
}
}
return result;
} catch (Throwable e2) {
e2.printStackTrace();
throw new InputParseException(Caption.of(e2.getMessage()));
}
});
}
}
if (pattern != null) {
patterns.add(pattern);
chances.add(chance);
}
}
} catch (InputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
e.printStackTrace();
throw new InputParseException(Caption.of(e.getMessage()), e);
}
if (patterns.isEmpty()) {
return null;
}
if (patterns.size() == 1) {
return patterns.get(0);
}
RandomPattern random = new RandomPattern(new TrueRandom());
for (int i = 0; i < patterns.size(); i++) {
random.add(patterns.get(i), chances.get(i));
}
return random;
}
@Override
public List<String> getMatchedAliases() {
return Collections.emptyList();
}
}

Datei anzeigen

@ -0,0 +1,51 @@
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.SaturatePattern;
import com.sk89q.worldedit.WorldEdit;
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.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class SaturatePatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public SaturatePatternParser(WorldEdit worldEdit) {
super(worldEdit, "#saturate");
}
@Override
public Stream<String> getSuggestions(String argumentInput, int index) {
if (index > 3) {
return Stream.empty();
}
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
}
@Override
public Pattern parseFromInput(@Nonnull String[] input, ParserContext context) throws InputParseException {
if (input.length != 4) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[r][g][b][a] (e.g. " + getPrefix() + "[156][100][0][120])")
));
}
return new SaturatePattern(context.requireExtent(), context.requireSession(),
Integer.parseInt(input[0]),
Integer.parseInt(input[1]),
Integer.parseInt(input[2]),
Integer.parseInt(input[3])
);
}
}

Datei anzeigen

@ -7,6 +7,11 @@ public class SimplexPatternParser extends NoisePatternParser {
private static final String SIMPLEX_NAME = "simplex"; private static final String SIMPLEX_NAME = "simplex";
/**
* Create a new rich pattern parser with a defined prefix for the result.
*
* @param worldEdit the worldedit instance.
*/
public SimplexPatternParser(WorldEdit worldEdit) { public SimplexPatternParser(WorldEdit worldEdit) {
super(worldEdit, SIMPLEX_NAME, SimplexNoiseGenerator::new); super(worldEdit, SIMPLEX_NAME, SimplexNoiseGenerator::new);
} }

Datei anzeigen

@ -0,0 +1,65 @@
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.SolidRandomOffsetPattern;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class SolidRandomOffsetPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public SolidRandomOffsetPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#solidspread");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
case 2:
case 3:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 2 && arguments.length != 4) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone][2][0][4])")
));
}
int x;
int y;
int z;
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
if (arguments.length == 4) {
x = Integer.parseInt(arguments[1]);
y = Integer.parseInt(arguments[2]);
z = Integer.parseInt(arguments[3]);
} else {
x = y = z = Integer.parseInt(arguments[1]);
}
Extent extent = context.requireExtent();
return new SolidRandomOffsetPattern(inner, x, y, z, extent.getMinY(), extent.getMaxY());
}
}

Datei anzeigen

@ -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.SurfaceRandomOffsetPattern;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nonnull;
import java.util.stream.Stream;
public class SurfaceRandomOffsetPatternParser extends RichParser<Pattern> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public SurfaceRandomOffsetPatternParser(WorldEdit worldEdit) {
super(worldEdit, "#surfacespread");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
switch (index) {
case 0:
return this.worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
case 1:
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
default:
return Stream.empty();
}
}
@Override
protected Pattern parseFromInput(@Nonnull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 2) {
throw new InputParseException(Caption.of(
"fawe.error.command.syntax",
TextComponent.of(getPrefix() + "[pattern] (e.g. " + getPrefix() + "[stone][2])")
));
}
Pattern inner = this.worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
int distance = Integer.parseInt(arguments[1]);
Extent extent = context.requireExtent();
return new SurfaceRandomOffsetPattern(inner, distance, extent.getMinY(), extent.getMaxY());
}
}

Datei anzeigen

@ -0,0 +1,45 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.Linear3DTransform;
import com.fastasyncworldedit.core.extent.transform.RandomTransform;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class Linear3DTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public Linear3DTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#linear3d", "#l3d");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 1) {
return null;
}
ResettableExtent inner = worldEdit.getTransformFactory().parseFromInput(arguments[0], context);
if (inner instanceof RandomTransform) {
return new Linear3DTransform(((RandomTransform) inner).getExtents().toArray(new ResettableExtent[0]));
}
return inner; // TODO what about non-random transforms?
}
}

Datei anzeigen

@ -0,0 +1,45 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.LinearTransform;
import com.fastasyncworldedit.core.extent.transform.RandomTransform;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class LinearTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public LinearTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#linear", "#l");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 1) {
return null;
}
ResettableExtent inner = worldEdit.getTransformFactory().parseFromInput(arguments[0], context);
if (inner instanceof RandomTransform) {
return new LinearTransform(((RandomTransform) inner).getExtents().toArray(new ResettableExtent[0]));
}
return inner; // TODO what about non-random transforms?
}
}

Datei anzeigen

@ -0,0 +1,55 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.transform.OffsetTransform;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class OffsetTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public OffsetTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#offset");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index < 3) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
} else if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 3 && arguments.length != 4) {
throw new InputParseException(TranslatableComponent.of(
"fawe.error.command.syntax",
TextComponent.of("#offset[x][y][z]")
));
}
int xOffset = Integer.parseInt(arguments[0]);
int yOffset = Integer.parseInt(arguments[1]);
int zOffset = Integer.parseInt(arguments[2]);
Extent extent;
extent = arguments.length == 4 ? worldEdit.getTransformFactory().parseFromInput(arguments[3], context) :
context.requireExtent();
return new OffsetTransform(extent, xOffset, yOffset, zOffset);
}
}

Datei anzeigen

@ -0,0 +1,47 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.PatternTransform;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class PatternTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public PatternTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#pattern");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index == 0) {
return worldEdit.getPatternFactory().getSuggestions(argumentInput).stream();
} else if (index == 1) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length > 2) {
return null;
}
Pattern pattern = worldEdit.getPatternFactory().parseFromInput(arguments[0], context);
Extent extent = arguments.length == 2 ? worldEdit.getTransformFactory().parseFromInput(arguments[1], context) :
context.requireExtent();
return new PatternTransform(extent, pattern);
}
}

Datei anzeigen

@ -0,0 +1,60 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.RandomTransform;
import com.sk89q.util.StringUtil;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.internal.registry.InputParser;
import java.util.List;
import java.util.stream.Stream;
public class RandomTransformParser extends InputParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public RandomTransformParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public Stream<String> getSuggestions(String input) {
if (input.isEmpty()) {
return Stream.empty();
}
List<String> split = StringUtil.split(input, ',', '[', ']');
if (split.size() == 1) {
return Stream.empty();
}
StringBuilder builder = new StringBuilder();
for (int i = 0; i < split.size() - 1; i++) {
builder.append(split.get(i)).append(',');
}
String previous = builder.toString();
return worldEdit.getTransformFactory().getSuggestions(split.get(split.size() - 1)).stream()
.map(s -> previous + s);
}
@Override
public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
if (input.isEmpty()) {
return null;
}
List<String> split = StringUtil.split(input, ',', '[', ']');
if (split.size() == 1) {
return null;
}
RandomTransform randomTransform = new RandomTransform();
for (int i = 0; i < split.size(); i++) {
ResettableExtent transform = worldEdit.getTransformFactory().parseFromInput(split.get(i), context);
randomTransform.add(transform, 1d);
}
return randomTransform;
}
}

Datei anzeigen

@ -0,0 +1,170 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.command.SuggestInputParseException;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.FaweParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.MultiTransform;
import com.fastasyncworldedit.core.extent.transform.RandomTransform;
import com.fastasyncworldedit.core.math.random.TrueRandom;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* Attempts to parse transforms given rich inputs, allowing for & and ,. Also allows for nested transforms
*/
public class RichTransformParser extends FaweParser<ResettableExtent> {
/**
* New instance
*
* @param worldEdit {@link WorldEdit} instance.
*/
public RichTransformParser(WorldEdit worldEdit) {
super(worldEdit);
}
@Override
public ResettableExtent parseFromInput(String input, ParserContext context) throws InputParseException {
if (input.isEmpty()) {
return null;
}
List<Double> unionChances = new ArrayList<>();
List<Double> intersectionChances = new ArrayList<>();
List<ResettableExtent> intersection = new ArrayList<>();
List<ResettableExtent> union = new ArrayList<>();
final CommandLocals locals = new CommandLocals();
Actor actor = context != null ? context.getActor() : null;
if (actor != null) {
locals.put(Actor.class, actor);
}
try {
List<Map.Entry<ParseEntry, List<String>>> parsed = parse(input);
for (Map.Entry<ParseEntry, List<String>> entry : parsed) {
ParseEntry pe = entry.getKey();
String command = pe.getInput();
ResettableExtent transform;
double chance = 1;
if (command.isEmpty()) {
transform = parseFromInput(StringMan.join(entry.getValue(), ','), context);
} else if (!worldEdit.getTransformFactory().containsAlias(command)) {
// Legacy syntax
int percentIndex = command.indexOf('%');
if (percentIndex != -1) { // Legacy percent pattern
chance = Expression.compile(command.substring(0, percentIndex)).evaluate();
command = command.substring(percentIndex + 1);
if (!entry.getValue().isEmpty()) {
if (!command.isEmpty()) {
command += " ";
}
command += StringMan.join(entry.getValue(), " ");
}
transform = parseFromInput(command, context);
} else {
throw new NoMatchException(Caption.of("fawe.error.parse.unknown-transform", pe.getFull(),
TextComponent
.of("https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
)
.clickEvent(ClickEvent.openUrl(
"https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
))
));
}
} else {
try {
transform = worldEdit.getTransformFactory().parseWithoutRich(pe.getFull(), context);
} catch (SuggestInputParseException rethrow) {
throw rethrow;
} catch (Throwable e) {
throw new NoMatchException(Caption.of("fawe.error.parse.unknown-transform", pe.getFull(),
TextComponent
.of("https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
)
.clickEvent(ClickEvent.openUrl(
"https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
))
));
}
}
if (pe.isAnd()) { // &
intersectionChances.add(chance);
intersection.add(transform);
} else {
if (!intersection.isEmpty()) {
if (intersection.size() == 1) {
throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", "&"));
}
MultiTransform multi = new MultiTransform();
double total = 0;
for (int i = 0; i < intersection.size(); i++) {
Double value = intersectionChances.get(i);
total += value;
multi.add(intersection.get(i), value);
}
union.add(multi);
unionChances.add(total);
intersection.clear();
intersectionChances.clear();
}
unionChances.add(chance);
union.add(transform);
}
}
} catch (Throwable e) {
throw new InputParseException(Caption.of(e.getMessage()), e);
}
if (!intersection.isEmpty()) {
if (intersection.size() == 1) {
throw new InputParseException(Caption.of("fawe.error.parse.invalid-dangling-character", "&"));
}
MultiTransform multi = new MultiTransform();
double total = 0;
for (int i = 0; i < intersection.size(); i++) {
Double value = intersectionChances.get(i);
total += value;
multi.add(intersection.get(i), value);
}
union.add(multi);
unionChances.add(total);
intersection.clear();
intersectionChances.clear();
}
if (union.isEmpty()) {
throw new NoMatchException(Caption.of("fawe.error.parse.unknown-transform", input,
TextComponent.of("https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
).clickEvent(ClickEvent.openUrl(
"https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki/Transforms"
))
));
} else if (union.size() == 1) {
return union.get(0);
} else {
RandomTransform random = new RandomTransform(new TrueRandom());
for (int i = 0; i < union.size(); i++) {
random.add(union.get(i), unionChances.get(i));
}
return random;
}
}
@Override
public List<String> getMatchedAliases() {
return Collections.emptyList();
}
}

Datei anzeigen

@ -0,0 +1,57 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.math.transform.AffineTransform;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class RotateTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public RotateTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#rotate");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index < 3) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
}
if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
AffineTransform transform = new AffineTransform();
Extent extent;
if (arguments.length == 1) {
transform = transform.rotateY(Double.parseDouble(arguments[0]));
extent = context.requireExtent();
} else if (arguments.length == 3 || arguments.length == 4) {
transform = transform.rotateX(Double.parseDouble(arguments[0]));
transform = transform.rotateY(Double.parseDouble(arguments[1]));
transform = transform.rotateZ(Double.parseDouble(arguments[2]));
extent = arguments.length == 4 ? worldEdit.getTransformFactory().parseFromInput(arguments[3], context) :
context.requireExtent();
} else {
return null;
}
return new BlockTransformExtent(extent, transform);
}
}

Datei anzeigen

@ -0,0 +1,57 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.ScaleTransform;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class ScaleTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #scale}.
*
* @param worldEdit the worldedit instance.
*/
public ScaleTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#scale");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index < 3) {
return SuggestionHelper.suggestPositiveDoubles(argumentInput);
} else if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
double xScale;
double yScale;
double zScale;
Extent extent;
if (arguments.length == 1) {
xScale = yScale = zScale = Double.parseDouble(arguments[0]);
extent = context.requireExtent();
} else if (arguments.length == 3 || arguments.length == 4) {
xScale = Double.parseDouble(arguments[0]);
yScale = Double.parseDouble(arguments[1]);
zScale = Double.parseDouble(arguments[2]);
extent = arguments.length == 4 ? worldEdit.getTransformFactory().parseFromInput(arguments[3], context) :
context.requireExtent();
} else {
return null;
}
return new ScaleTransform(extent, xScale, yScale, zScale);
}
}

Datei anzeigen

@ -0,0 +1,49 @@
package com.fastasyncworldedit.core.extension.factory.parser.transform;
import com.fastasyncworldedit.core.extension.factory.parser.RichParser;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.transform.RandomOffsetTransform;
import com.sk89q.worldedit.WorldEdit;
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.extent.Extent;
import org.jetbrains.annotations.NotNull;
import java.util.stream.Stream;
public class SpreadTransformParser extends RichParser<ResettableExtent> {
/**
* Create a new rich parser with a defined prefix for the result, e.g. {@code #simplex}.
*
* @param worldEdit the worldedit instance.
*/
public SpreadTransformParser(WorldEdit worldEdit) {
super(worldEdit, "#spread", "#randomoffset");
}
@Override
protected Stream<String> getSuggestions(String argumentInput, int index) {
if (index < 3) {
return SuggestionHelper.suggestPositiveIntegers(argumentInput);
} else if (index == 3) {
return worldEdit.getTransformFactory().getSuggestions(argumentInput).stream();
}
return Stream.empty();
}
@Override
protected ResettableExtent parseFromInput(@NotNull String[] arguments, ParserContext context) throws InputParseException {
if (arguments.length != 3 && arguments.length != 4) {
return null;
}
int xOffset = Integer.parseInt(arguments[0]);
int yOffset = Integer.parseInt(arguments[1]);
int zOffset = Integer.parseInt(arguments[2]);
Extent extent = arguments.length == 4 ? worldEdit.getTransformFactory().parseFromInput(arguments[3], context) :
context.requireExtent();
return new RandomOffsetTransform(extent, xOffset, yOffset, zOffset);
}
}

Datei anzeigen

@ -39,32 +39,6 @@ public class PrimitiveBindings extends Bindings {
} }
} }
// TODO: Ping @MattBDev to reimplement 2020-02-04
//
// /**
// * Gets an {@link Extent} from a {@link Binding}.
// *
// * @param argument the context
// * @return an extent
// * @throws InputParseException on other error
// */
// @Binding
// public ResettableExtent getResettableExtent(Actor actor, String argument) throws InputParseException {
// if (argument.equalsIgnoreCase("#null")) {
// return new NullExtent();
// }
// DefaultTransformParser parser = Fawe.get().getTransformParser();
// ParserContext parserContext = new ParserContext();
// if (actor instanceof Entity) {
// Extent extent = ((Entity) actor).getExtent();
// if (extent instanceof World) {
// parserContext.setWorld((World) extent);
// }
// }
// parserContext.setSession(WorldEdit.getInstance().getSessionManager().get(actor));
// return parser.parseFromInput(argument, parserContext);
// }
/** /**
* Gets a type from a {@link Binding}. * Gets a type from a {@link Binding}.
* *

Datei anzeigen

@ -37,6 +37,7 @@ public abstract class FaweRegionExtent extends ResettableExtent implements IBatc
this.limit = limit; this.limit = limit;
} }
@Override
public abstract boolean contains(int x, int y, int z); public abstract boolean contains(int x, int y, int z);
public abstract boolean contains(int x, int z); public abstract boolean contains(int x, int z);

Datei anzeigen

@ -81,74 +81,74 @@ public class NullExtent extends FaweRegionExtent implements IBatchProcessor {
@Override @Override
public List<Entity> getEntities() { public List<Entity> getEntities() {
return Collections.emptyList(); throw reason;
} }
@Nullable @Nullable
@Override @Override
public Entity createEntity(Location arg0, BaseEntity arg1) { public Entity createEntity(Location arg0, BaseEntity arg1) {
return null; throw reason;
} }
@Override @Override
public BlockState getBlock(BlockVector3 position) { public BlockState getBlock(BlockVector3 position) {
return BlockTypes.AIR.getDefaultState(); throw reason;
} }
@Override @Override
public BlockState getBlock(int x, int y, int z) { public BlockState getBlock(int x, int y, int z) {
return BlockTypes.AIR.getDefaultState(); throw reason;
} }
@Override @Override
public BaseBlock getFullBlock(BlockVector3 position) { public BaseBlock getFullBlock(BlockVector3 position) {
return getBlock(position).toBaseBlock(); throw reason;
} }
@Override @Override
public BaseBlock getFullBlock(int x, int y, int z) { public BaseBlock getFullBlock(int x, int y, int z) {
return getBlock(x, y, z).toBaseBlock(); throw reason;
} }
@Override @Override
public BiomeType getBiome(BlockVector3 position) { public BiomeType getBiome(BlockVector3 position) {
return BiomeTypes.THE_VOID; throw reason;
} }
@Override @Override
public BiomeType getBiomeType(int x, int y, int z) { public BiomeType getBiomeType(int x, int y, int z) {
return BiomeTypes.THE_VOID; throw reason;
} }
@Override @Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block) throws WorldEditException { public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 position, B block) throws WorldEditException {
return false; throw reason;
} }
@Override @Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException { throws WorldEditException {
return false; throw reason;
} }
@Override @Override
public ResettableExtent setExtent(Extent extent) { public ResettableExtent setExtent(Extent extent) {
return this; throw reason;
} }
@Override @Override
public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException {
return false; throw reason;
} }
@Override @Override
public boolean setBiome(BlockVector3 position, BiomeType biome) { public boolean setBiome(BlockVector3 position, BiomeType biome) {
return false; throw reason;
} }
@Override @Override
public boolean setBiome(int x, int y, int z, BiomeType biome) { public boolean setBiome(int x, int y, int z, BiomeType biome) {
return false; throw reason;
} }
@Override @Override
@ -371,7 +371,7 @@ public class NullExtent extends FaweRegionExtent implements IBatchProcessor {
@Override @Override
public ProcessorScope getScope() { public ProcessorScope getScope() {
return ProcessorScope.ADDING_BLOCKS; throw reason;
} }
} }

Datei anzeigen

@ -1,49 +0,0 @@
package com.fastasyncworldedit.core.extent;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
public class OffsetExtent extends ResettableExtent {
private final int dx;
private final int dy;
private final int dz;
public OffsetExtent(Extent parent, int dx, int dy, int dz) {
super(parent);
this.dx = dx;
this.dy = dy;
this.dz = dz;
}
@Override
public boolean setBiome(BlockVector3 position, BiomeType biome) {
return getExtent()
.setBiome(position.getBlockX() + dx, position.getBlockY() + dy, position.getBlockZ() + dz,
biome
);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
return getExtent().setBiome(x + dx, y + dy, z + dz, biome);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block)
throws WorldEditException {
return getExtent().setBlock(location.getBlockX() + dx, location.getBlockY() + dy,
location.getBlockZ() + dz, block
);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException {
return getExtent().setBlock(x + dx, y + dy, z + dz, block);
}
}

Datei anzeigen

@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.extent;
import com.fastasyncworldedit.core.util.ExtentTraverser; import com.fastasyncworldedit.core.util.ExtentTraverser;
import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.ReflectionUtils;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -38,7 +39,7 @@ public class ResettableExtent extends AbstractDelegateExtent implements Serializ
&& next instanceof ResettableExtent) { && next instanceof ResettableExtent) {
((ResettableExtent) next).setExtent(extent); ((ResettableExtent) next).setExtent(extent);
} else { } else {
new ExtentTraverser(this).setNext(new AbstractDelegateExtent(extent)); new ExtentTraverser<Extent>(this).setNext(extent);
} }
return this; return this;
} }

Datei anzeigen

@ -8,6 +8,8 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStream;
@ -136,7 +138,14 @@ public class PNGWriter implements ClipboardWriter {
poly3X[3] = (int) cpx; poly3X[3] = (int) cpx;
poly3Y[3] = (int) (cpy + dpxi[1]); poly3Y[3] = (int) (cpy + dpxi[1]);
Color colorTop = new Color(tu.getColor(block.getBlockType())); BlockType type = block.getBlockType();
int color;
if (type == BlockTypes.GRASS_BLOCK) {
color = tu.getColor(clipboard.getBiome(mutable));
} else {
color = tu.getColor(type);
}
Color colorTop = new Color(color);
g2.setColor(colorTop); g2.setColor(colorTop);
if (fill) { if (fill) {

Datei anzeigen

@ -8,12 +8,18 @@ public class Linear3DTransform extends SelectTransform {
private final ResettableExtent[] extentsArray; private final ResettableExtent[] extentsArray;
/**
* New instance
*
* @param extents list of extents to choose from
*/
public Linear3DTransform(ResettableExtent[] extents) { public Linear3DTransform(ResettableExtent[] extents) {
this.extentsArray = extents; this.extentsArray = extents;
} }
@Override @Override
public ResettableExtent setExtent(Extent extent) { public ResettableExtent setExtent(Extent extent) {
super.setExtent(extent);
for (ResettableExtent cur : extentsArray) { for (ResettableExtent cur : extentsArray) {
cur.setExtent(extent); cur.setExtent(extent);
} }

Datei anzeigen

@ -9,12 +9,18 @@ public class LinearTransform extends SelectTransform {
private final ResettableExtent[] extentsArray; private final ResettableExtent[] extentsArray;
private int index; private int index;
/**
* New instance
*
* @param extents list of extents to choose from
*/
public LinearTransform(ResettableExtent[] extents) { public LinearTransform(ResettableExtent[] extents) {
this.extentsArray = extents; this.extentsArray = extents;
} }
@Override @Override
public ResettableExtent setExtent(Extent extent) { public ResettableExtent setExtent(Extent extent) {
super.setExtent(extent);
for (ResettableExtent cur : extentsArray) { for (ResettableExtent cur : extentsArray) {
cur.setExtent(extent); cur.setExtent(extent);
} }
@ -26,7 +32,7 @@ public class LinearTransform extends SelectTransform {
if (index == extentsArray.length) { if (index == extentsArray.length) {
index = 0; index = 0;
} }
return extentsArray[index]; return extentsArray[index++];
} }
@Override @Override

Datei anzeigen

@ -17,6 +17,11 @@ public class MultiTransform extends RandomTransform {
private ResettableExtent[] extents; private ResettableExtent[] extents;
/**
* New instance
*
* @param extents list of extents to set blocks to
*/
public MultiTransform(Collection<ResettableExtent> extents) { public MultiTransform(Collection<ResettableExtent> extents) {
for (ResettableExtent extent : extents) { for (ResettableExtent extent : extents) {
add(extent, 1); add(extent, 1);
@ -65,6 +70,16 @@ public class MultiTransform extends RandomTransform {
return result; return result;
} }
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
// don't use streams for each block place, it'd be incredibly slow
boolean result = false;
for (AbstractDelegateExtent extent : extents) {
result |= extent.setBiome(x, y, z, biome);
}
return result;
}
@Nullable @Nullable
@Override @Override
public Entity createEntity(Location location, BaseEntity entity) { public Entity createEntity(Location location, BaseEntity entity) {

Datei anzeigen

@ -0,0 +1,77 @@
package com.fastasyncworldedit.core.extent.transform;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
public class OffsetTransform extends ResettableExtent {
private final int dx;
private final int dy;
private final int dz;
/**
* New instance
*
* @param parent extent to set to
* @param dx offset x
* @param dy offset y
* @param dz offset z
*/
public OffsetTransform(Extent parent, int dx, int dy, int dz) {
super(parent);
this.dx = dx;
this.dy = dy;
this.dz = dz;
}
@Override
public boolean setBiome(BlockVector3 location, BiomeType biome) {
int x = location.getX() + dx;
int y = location.getX() + dy;
int z = location.getX() + dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBiome(x, y, z, biome);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
x += dx;
y += dy;
z += dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBiome(x, y, z, biome);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 location, T block)
throws WorldEditException {
int x = location.getX() + dx;
int y = location.getX() + dy;
int z = location.getX() + dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBlock(x, y, z, block);
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException {
x += dx;
y += dy;
z += dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBlock(x, y, z, block);
}
}

Datei anzeigen

@ -1,7 +1,6 @@
package com.fastasyncworldedit.core.extent.transform; package com.fastasyncworldedit.core.extent.transform;
import com.fastasyncworldedit.core.extent.ResettableExtent; import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
@ -12,6 +11,12 @@ public class PatternTransform extends ResettableExtent {
private final Pattern pattern; private final Pattern pattern;
/**
* New instance
*
* @param parent extent to set to
* @param pattern pattern to apply
*/
public PatternTransform(Extent parent, Pattern pattern) { public PatternTransform(Extent parent, Pattern pattern) {
super(parent); super(parent);
this.pattern = pattern; this.pattern = pattern;

Datei anzeigen

@ -1,5 +1,6 @@
package com.fastasyncworldedit.core.extent; package com.fastasyncworldedit.core.extent.transform;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
@ -15,6 +16,14 @@ public class RandomOffsetTransform extends ResettableExtent {
private final int dz; private final int dz;
private transient SplittableRandom random; private transient SplittableRandom random;
/**
* New instance
*
* @param parent extent to set to
* @param dx range of x values to choose from (0 -> x)
* @param dy range of y values to choose from (0 -> y)
* @param dz range of z values to choose from (0 -> z)
*/
public RandomOffsetTransform(Extent parent, int dx, int dy, int dz) { public RandomOffsetTransform(Extent parent, int dx, int dy, int dz) {
super(parent); super(parent);
this.dx = dx + 1; this.dx = dx + 1;
@ -24,10 +33,24 @@ public class RandomOffsetTransform extends ResettableExtent {
} }
@Override @Override
public boolean setBiome(BlockVector3 pos, BiomeType biome) { public boolean setBiome(BlockVector3 position, BiomeType biome) {
int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx; int x = position.getBlockX() + random.nextInt(1 + (dx << 1)) - dx;
int y = pos.getBlockY() + random.nextInt(1 + (dy << 1)) - dy; int y = position.getBlockY() + random.nextInt(1 + (dy << 1)) - dy;
int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz; int z = position.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBiome(x, y, z, biome);
}
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
x = x + random.nextInt(1 + (dx << 1)) - dx;
y = y + random.nextInt(1 + (dy << 1)) - dy;
z = z + random.nextInt(1 + (dz << 1)) - dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBiome(x, y, z, biome); return getExtent().setBiome(x, y, z, biome);
} }
@ -37,6 +60,9 @@ public class RandomOffsetTransform extends ResettableExtent {
int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx; int x = pos.getBlockX() + random.nextInt(1 + (dx << 1)) - dx;
int y = pos.getBlockY() + random.nextInt(1 + (dy << 1)) - dy; int y = pos.getBlockY() + random.nextInt(1 + (dy << 1)) - dy;
int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz; int z = pos.getBlockZ() + random.nextInt(1 + (dz << 1)) - dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBlock(x, y, z, block); return getExtent().setBlock(x, y, z, block);
} }
@ -46,6 +72,9 @@ public class RandomOffsetTransform extends ResettableExtent {
x = x + random.nextInt(1 + (dx << 1)) - dx; x = x + random.nextInt(1 + (dx << 1)) - dx;
y = y + random.nextInt(1 + (dy << 1)) - dy; y = y + random.nextInt(1 + (dy << 1)) - dy;
z = z + random.nextInt(1 + (dz << 1)) - dz; z = z + random.nextInt(1 + (dz << 1)) - dz;
if (!getExtent().contains(x, y, z)) {
return false;
}
return getExtent().setBlock(x, y, z, block); return getExtent().setBlock(x, y, z, block);
} }

Datei anzeigen

@ -29,6 +29,11 @@ public class RandomTransform extends SelectTransform {
this(new TrueRandom()); this(new TrueRandom());
} }
/**
* New instance
*
* @param random {@link SimpleRandom} used to choose between transforms, given weights
*/
public RandomTransform(SimpleRandom random) { public RandomTransform(SimpleRandom random) {
this.random = random; this.random = random;
} }
@ -49,6 +54,7 @@ public class RandomTransform extends SelectTransform {
collection = RandomCollection.of(weights, random); collection = RandomCollection.of(weights, random);
extents = new LinkedHashSet<>(weights.keySet()); extents = new LinkedHashSet<>(weights.keySet());
} }
super.setExtent(extent);
for (ResettableExtent current : extents) { for (ResettableExtent current : extents) {
current.setExtent(extent); current.setExtent(extent);
} }

Datei anzeigen

@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.extent.transform;
import com.fastasyncworldedit.core.extent.ResettableExtent; import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.math.MutableBlockVector3;
import com.fastasyncworldedit.core.math.MutableVector3;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
@ -18,61 +19,76 @@ public class ScaleTransform extends ResettableExtent {
private final double dx; private final double dx;
private final double dy; private final double dy;
private final double dz; private final double dz;
private transient MutableBlockVector3 mutable = new MutableBlockVector3(); private transient MutableVector3 mutable = new MutableVector3();
private transient int minY;
private transient int maxy; private transient int maxy;
private transient BlockVector3 min; private transient BlockVector3 min;
/**
* New instance
*
* @param parent extent to set to
* @param dx x axis scaling
* @param dy y axis scaling
* @param dz z axis scaling
*/
public ScaleTransform(Extent parent, double dx, double dy, double dz) { public ScaleTransform(Extent parent, double dx, double dy, double dz) {
super(parent); super(parent);
this.dx = dx; this.dx = dx;
this.dy = dy; this.dy = dy;
this.dz = dz; this.dz = dz;
this.maxy = parent.getMaximumPoint().getBlockY(); this.minY = parent.getMinY();
this.maxy = parent.getMaxY();
} }
@Override @Override
public ResettableExtent setExtent(Extent extent) { public ResettableExtent setExtent(Extent extent) {
min = null; min = null;
maxy = extent.getMaximumPoint().getBlockY(); mutable = new MutableVector3();
mutable = new MutableBlockVector3(); this.minY = extent.getMinY();
this.maxy = extent.getMaxY();
return super.setExtent(extent); return super.setExtent(extent);
} }
private void getPos(BlockVector3 pos) { private MutableVector3 getPos(BlockVector3 pos) {
if (min == null) { if (min == null) {
min = pos; min = pos;
} }
mutable.mutX(min.getX() + (pos.getX() - min.getX()) * dx); mutable.mutX(min.getX() + (pos.getX() - min.getX()) * dx);
mutable.mutY(min.getY() + (pos.getY() - min.getY()) * dy); mutable.mutY(min.getY() + (pos.getY() - min.getY()) * dy);
mutable.mutZ(min.getZ() + (pos.getZ() - min.getZ()) * dz); mutable.mutZ(min.getZ() + (pos.getZ() - min.getZ()) * dz);
return new MutableVector3(mutable);
} }
private void getPos(int x, int y, int z) { private MutableVector3 getPos(int x, int y, int z) {
if (min == null) { if (min == null) {
min = BlockVector3.at(x, y, z); min = BlockVector3.at(x, y, z);
} }
mutable.mutX(min.getX() + (x - min.getX()) * dx); mutable.mutX(min.getX() + (x - min.getX()) * dx);
mutable.mutY(min.getY() + (y - min.getY()) * dy); mutable.mutY(min.getY() + (y - min.getY()) * dy);
mutable.mutZ(min.getZ() + (z - min.getZ()) * dz); mutable.mutZ(min.getZ() + (z - min.getZ()) * dz);
return new MutableVector3(mutable);
} }
@Override @Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block)
throws WorldEditException { throws WorldEditException {
boolean result = false; boolean result = false;
getPos(location); MutableVector3 vector3 = getPos(location);
double sx = mutable.getX(); MutableBlockVector3 pos = new MutableBlockVector3();
double sy = mutable.getY(); double sx = vector3.getX();
double sz = mutable.getZ(); double sy = vector3.getY();
double sz = vector3.getZ();
double ex = sx + dx; double ex = sx + dx;
double ey = Math.min(maxy, sy + dy); double ey = Math.max(minY, Math.min(maxy, sy + dy));
double ez = sz + dz; double ez = sz + dz;
for (mutable.mutY(sy); mutable.getY() < ey; mutable.mutY(mutable.getY() + 1)) { for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) {
for (mutable.mutZ(sz); mutable.getZ() < ez; mutable.mutZ(mutable.getZ() + 1)) { for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) {
for (mutable.mutX(sx); mutable.getX() < ex; mutable.mutX(mutable.getX() + 1)) { for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) {
result |= super.setBlock(mutable, block); if (!getExtent().contains(pos)) {
continue;
}
result |= super.setBlock(pos, block);
} }
} }
} }
@ -82,17 +98,21 @@ public class ScaleTransform extends ResettableExtent {
@Override @Override
public boolean setBiome(BlockVector3 position, BiomeType biome) { public boolean setBiome(BlockVector3 position, BiomeType biome) {
boolean result = false; boolean result = false;
getPos(position); MutableVector3 vector3 = getPos(position);
double sx = mutable.getX(); MutableBlockVector3 pos = new MutableBlockVector3();
double sy = mutable.getY(); double sx = vector3.getX();
double sz = mutable.getZ(); double sy = vector3.getY();
double sz = vector3.getZ();
double ex = sx + dx; double ex = sx + dx;
double ey = Math.min(maxy, sy + dy); double ey = Math.max(minY, Math.min(maxy, sy + dy));
double ez = sz + dz; double ez = sz + dz;
for (mutable.mutY(sy); mutable.getY() < ey; mutable.mutY(mutable.getY() + 1)) { for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) {
for (mutable.mutZ(sz); mutable.getZ() < ez; mutable.mutZ(mutable.getZ() + 1)) { for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) {
for (mutable.mutX(sx); mutable.getX() < ex; mutable.mutX(mutable.getX() + 1)) { for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) {
result |= super.setBiome(mutable, biome); if (!getExtent().contains(pos)) {
continue;
}
result |= super.setBiome(pos, biome);
} }
} }
} }
@ -103,17 +123,45 @@ public class ScaleTransform extends ResettableExtent {
public <B extends BlockStateHolder<B>> boolean setBlock(int x1, int y1, int z1, B block) public <B extends BlockStateHolder<B>> boolean setBlock(int x1, int y1, int z1, B block)
throws WorldEditException { throws WorldEditException {
boolean result = false; boolean result = false;
getPos(x1, y1, z1); MutableVector3 vector3 = getPos(x1, y1, z1);
double sx = mutable.getX(); MutableBlockVector3 pos = new MutableBlockVector3();
double sy = mutable.getY(); double sx = vector3.getX();
double sz = mutable.getZ(); double sy = vector3.getY();
double ex = mutable.getX() + dx; double sz = vector3.getZ();
double ex = vector3.getX() + dx;
double ey = Math.min(maxy, sy + dy); double ey = Math.min(maxy, sy + dy);
double ez = mutable.getZ() + dz; double ez = vector3.getZ() + dz;
for (mutable.mutY(sy); mutable.getY() < ey; mutable.mutY(mutable.getY() + 1)) { for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) {
for (mutable.mutZ(sz); mutable.getZ() < ez; mutable.mutZ(mutable.getZ() + 1)) { for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) {
for (mutable.mutX(sx); mutable.getX() < ex; mutable.mutX(mutable.getX() + 1)) { for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) {
result |= super.setBlock(mutable, block); if (!getExtent().contains(pos)) {
continue;
}
result |= super.setBlock(pos, block);
}
}
}
return result;
}
@Override
public boolean setBiome(int x1, int y1, int z1, BiomeType biome) {
boolean result = false;
MutableVector3 vector3 = getPos(x1, y1, z1);
MutableBlockVector3 pos = new MutableBlockVector3();
double sx = vector3.getX();
double sy = vector3.getY();
double sz = vector3.getZ();
double ex = sx + dx;
double ey = Math.max(minY, Math.min(maxy, sy + dy));
double ez = sz + dz;
for (pos.mutY(sy); pos.getY() < ey; pos.mutY(pos.getY() + 1)) {
for (pos.mutZ(sz); pos.getZ() < ez; pos.mutZ(pos.getZ() + 1)) {
for (pos.mutX(sx); pos.getX() < ex; pos.mutX(pos.getX() + 1)) {
if (!getExtent().contains(pos)) {
continue;
}
result |= super.setBiome(pos, biome);
} }
} }
} }
@ -123,11 +171,13 @@ public class ScaleTransform extends ResettableExtent {
@Nullable @Nullable
@Override @Override
public Entity createEntity(Location location, BaseEntity entity) { public Entity createEntity(Location location, BaseEntity entity) {
getPos(location.getBlockX(), location.getBlockY(), location.getBlockZ());
Location newLoc = new Location(location.getExtent(), Location newLoc = new Location(location.getExtent(),
mutable.toVector3(), getPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()),
location.getYaw(), location.getPitch() location.getYaw(), location.getPitch()
); );
if (!getExtent().contains(newLoc.toBlockPoint())) {
return null;
}
return super.createEntity(newLoc, entity); return super.createEntity(newLoc, entity);
} }

Datei anzeigen

@ -57,4 +57,9 @@ public abstract class SelectTransform extends ResettableExtent {
return getExtent(position).setBiome(position, biome); return getExtent(position).setBiome(position, biome);
} }
@Override
public boolean setBiome(int x, int y, int z, BiomeType biome) {
return getExtent(x, y, z).setBiome(x, y, z, biome);
}
} }

Datei anzeigen

@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.registry.state.PropertyKey;
import com.fastasyncworldedit.core.registry.state.PropertyKeySet; import com.fastasyncworldedit.core.registry.state.PropertyKeySet;
import com.fastasyncworldedit.core.util.MutableCharSequence; import com.fastasyncworldedit.core.util.MutableCharSequence;
import com.fastasyncworldedit.core.util.StringMan; import com.fastasyncworldedit.core.util.StringMan;
import com.fastasyncworldedit.core.world.block.BlanketBaseBlock;
import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.BlockMask;
@ -423,6 +424,9 @@ public class BlockMaskBuilder {
public <T extends BlockStateHolder<T>> BlockMaskBuilder add(BlockStateHolder<T> state) { public <T extends BlockStateHolder<T>> BlockMaskBuilder add(BlockStateHolder<T> state) {
BlockType type = state.getBlockType(); BlockType type = state.getBlockType();
if (state instanceof BlanketBaseBlock) {
return add(type);
}
int i = type.getInternalId(); int i = type.getInternalId();
long[] states = bitSets[i]; long[] states = bitSets[i];
if (states != ALL) { if (states != ALL) {

Datei anzeigen

@ -3,22 +3,31 @@ package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.util.TextureHolder; import com.fastasyncworldedit.core.util.TextureHolder;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
public class AngleColorPattern extends DataAnglePattern { public class AngleColorPattern extends AnglePattern {
protected transient TextureHolder holder; protected transient TextureHolder holder;
/**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param holder {@link TextureHolder} to use to get textures
* @param distance distance to use to calculate angle
*/
public AngleColorPattern(Extent extent, TextureHolder holder, int distance) { public AngleColorPattern(Extent extent, TextureHolder holder, int distance) {
super(extent, distance); super(extent, distance);
this.holder = holder.getTextureUtil(); this.holder = holder.getTextureUtil();
} }
public int getColor(int color, int slope) { private int getColor(int color, int slope) {
if (slope == 0) { if (slope == 0) {
return color; return color;
} }
@ -54,7 +63,13 @@ public class AngleColorPattern extends DataAnglePattern {
if (slope == -1) { if (slope == -1) {
return block; return block;
} }
int color = holder.getTextureUtil().getColor(block.getBlockType()); BlockType type = block.getBlockType();
int color;
if (type == BlockTypes.GRASS_BLOCK) {
color = holder.getTextureUtil().getColor(extent.getBiome(position));
} else {
color = holder.getTextureUtil().getColor(type);
}
if (color == 0) { if (color == 0) {
return block; return block;
} }
@ -69,7 +84,13 @@ public class AngleColorPattern extends DataAnglePattern {
if (slope == -1) { if (slope == -1) {
return false; return false;
} }
int color = holder.getTextureUtil().getColor(block.getBlockType()); BlockType type = block.getBlockType();
int color;
if (type == BlockTypes.GRASS_BLOCK) {
color = holder.getTextureUtil().getColor(extent.getBiome(get));
} else {
color = holder.getTextureUtil().getColor(type);
}
if (color == 0) { if (color == 0) {
return false; return false;
} }

Datei anzeigen

@ -1,22 +1,27 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.extent.ExtentHeightCacher; import com.fastasyncworldedit.core.extent.ExtentHeightCacher;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockStateHolder;
public class DataAnglePattern extends AbstractPattern { public abstract class AnglePattern extends AbstractPattern {
public final double factor; public final double factor;
public final Extent extent; public final Extent extent;
public final int maxY; public final int maxY;
public final int distance; public final int distance;
public DataAnglePattern(Extent extent, int distance) { /**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param distance distance to calculate angle with
*/
public AnglePattern(Extent extent, int distance) {
this.extent = new ExtentHeightCacher(extent); this.extent = new ExtentHeightCacher(extent);
this.maxY = extent.getMaximumPoint().getBlockY(); this.maxY = extent.getMaximumPoint().getBlockY();
this.distance = distance; this.distance = distance;
@ -58,25 +63,9 @@ public class DataAnglePattern extends AbstractPattern {
} }
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public abstract BaseBlock applyBlock(BlockVector3 position);
BlockState block = extent.getBlock(position);
int slope = getSlope(block, position, extent);
if (slope == -1) {
return block.toBaseBlock();
}
int data = Math.min(slope, 255) >> 4;
return block.withPropertyId(data).toBaseBlock();
}
@Override @Override
public boolean apply(Extent extent, BlockVector3 setPosition, BlockVector3 getPosition) throws WorldEditException { public abstract boolean apply(Extent extent, BlockVector3 setPosition, BlockVector3 getPosition);
BlockState block = extent.getBlock(getPosition);
int slope = getSlope(block, getPosition, extent);
if (slope == -1) {
return false;
}
int data = Math.min(slope, 255) >> 4;
return extent.setBlock(setPosition, block.withPropertyId(data));
}
} }

Datei anzeigen

@ -1,12 +1,15 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TextureHolder; import com.fastasyncworldedit.core.util.TextureHolder;
import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.util.TextureUtil;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.awt.Color; import java.awt.Color;
@ -15,18 +18,35 @@ public class AverageColorPattern extends AbstractExtentPattern {
private final transient TextureHolder holder; private final transient TextureHolder holder;
private final int color; private final int color;
public AverageColorPattern(Extent extent, int color, TextureHolder util) { /**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param holder {@link TextureHolder} to use to get textures
* @param r red channel, clamped 0 -> 255
* @param g green channel, clamped 0 -> 255
* @param b blue channel, clamped 0 -> 255
* @param a alpha channel, clamped 0 -> 255
*/
public AverageColorPattern(Extent extent, TextureHolder holder, int r, int g, int b, int a) {
super(extent); super(extent);
this.holder = util; this.holder = holder;
this.color = new Color(color).getRGB(); this.color = new Color(MathMan.clamp(r, 0, 255), MathMan.clamp(g, 0, 255), MathMan.clamp(b, 0, 255), MathMan.clamp(a, 0
, 255)).getRGB();
} }
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
BaseBlock block = getExtent().getFullBlock(position); BaseBlock block = getExtent().getFullBlock(position);
TextureUtil util = holder.getTextureUtil(); TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block.getBlockType()); BlockType type = block.getBlockType();
int newColor = util.averageColor(currentColor, color); int currentColor;
if (type == BlockTypes.GRASS_BLOCK) {
currentColor = holder.getTextureUtil().getColor(getExtent().getBiome(position));
} else {
currentColor = holder.getTextureUtil().getColor(type);
}
int newColor = TextureUtil.averageColor(currentColor, color);
return util.getNearestBlock(newColor).getDefaultState().toBaseBlock(); return util.getNearestBlock(newColor).getDefaultState().toBaseBlock();
} }
@ -34,11 +54,16 @@ public class AverageColorPattern extends AbstractExtentPattern {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
BlockType blockType = get.getBlock(extent).getBlockType(); BlockType blockType = get.getBlock(extent).getBlockType();
TextureUtil util = holder.getTextureUtil(); TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(blockType); int currentColor;
if (blockType == BlockTypes.GRASS_BLOCK) {
currentColor = holder.getTextureUtil().getColor(extent.getBiome(get));
} else {
currentColor = holder.getTextureUtil().getColor(blockType);
}
if (currentColor == 0) { if (currentColor == 0) {
return false; return false;
} }
int newColor = util.averageColor(currentColor, color); int newColor = TextureUtil.averageColor(currentColor, color);
BlockType newBlock = util.getNearestBlock(newColor); BlockType newBlock = util.getNearestBlock(newColor);
if (newBlock == blockType) { if (newBlock == blockType) {
return false; return false;

Datei anzeigen

@ -2,6 +2,7 @@ package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
@ -10,6 +11,12 @@ public class BiomeApplyingPattern extends AbstractExtentPattern {
private final BiomeType biomeType; private final BiomeType biomeType;
/**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param biomeType biome type to set
*/
public BiomeApplyingPattern(Extent extent, BiomeType biomeType) { public BiomeApplyingPattern(Extent extent, BiomeType biomeType) {
super(extent); super(extent);
this.biomeType = biomeType; this.biomeType = biomeType;

Datei anzeigen

@ -11,8 +11,6 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import java.util.UUID;
public class BufferedPattern extends AbstractPattern implements ResettablePattern { public class BufferedPattern extends AbstractPattern implements ResettablePattern {
protected final LocalBlockVectorSet set = new LocalBlockVectorSet(); protected final LocalBlockVectorSet set = new LocalBlockVectorSet();
@ -20,10 +18,14 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter
protected final long[] actionTime; protected final long[] actionTime;
protected final Pattern pattern; protected final Pattern pattern;
protected final UUID uuid;
/**
* Create a new {@link Pattern} instance
*
* @param actor actor associated with the pattern
* @param parent pattern to set
*/
public BufferedPattern(Actor actor, Pattern parent) { public BufferedPattern(Actor actor, Pattern parent) {
this.uuid = actor.getUniqueId();
long[] tmp = actor.getMeta("lastActionTime"); long[] tmp = actor.getMeta("lastActionTime");
if (tmp == null) { if (tmp == null) {
actor.setMeta("lastActionTime", tmp = new long[2]); actor.setMeta("lastActionTime", tmp = new long[2]);

Datei anzeigen

@ -6,6 +6,12 @@ import com.sk89q.worldedit.math.BlockVector3;
public class BufferedPattern2D extends BufferedPattern { public class BufferedPattern2D extends BufferedPattern {
/**
* Create a new {@link Pattern} instance
*
* @param actor actor associated with the pattern
* @param parent pattern to set
*/
public BufferedPattern2D(Actor actor, Pattern parent) { public BufferedPattern2D(Actor actor, Pattern parent) {
super(actor, parent); super(actor, parent);
} }

Datei anzeigen

@ -1,47 +0,0 @@
package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import static com.google.common.base.Preconditions.checkNotNull;
public class DataPattern extends AbstractExtentPattern {
private final Pattern pattern;
public DataPattern(Extent extent, Pattern parent) {
super(extent);
checkNotNull(parent);
this.pattern = parent;
}
@Override
public BaseBlock applyBlock(BlockVector3 position) {
BaseBlock oldBlock = getExtent().getFullBlock(position);
BaseBlock newBlock = pattern.applyBlock(position);
return oldBlock.toBlockState().withProperties(newBlock.toBlockState()).toBaseBlock(newBlock.getNbtData());
}
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
BaseBlock oldBlock = get.getFullBlock(extent);
BaseBlock newBlock = pattern.applyBlock(get);
BlockState oldState = oldBlock.toBlockState();
BlockState newState = oldState.withProperties(newBlock.toBlockState());
if (newState != oldState) {
if (oldBlock.hasNbtData()) {
set.setFullBlock(extent, newState.toBaseBlock(oldBlock.getNbtData()));
} else {
set.setBlock(extent, newState);
}
return true;
}
return false;
}
}

Datei anzeigen

@ -5,9 +5,11 @@ import com.fastasyncworldedit.core.util.TextureUtil;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
public class DesaturatePattern extends AbstractPattern { public class DesaturatePattern extends AbstractPattern {
@ -15,21 +17,33 @@ public class DesaturatePattern extends AbstractPattern {
private final Extent extent; private final Extent extent;
private final double value; private final double value;
public DesaturatePattern(Extent extent, double value, TextureHolder util) { /**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param holder {@link TextureHolder} to use for textures
* @param value decimal percent to desaturate by (0 -> 1)
*/
public DesaturatePattern(Extent extent, TextureHolder holder, double value) {
this.extent = extent; this.extent = extent;
this.holder = util; this.holder = holder;
this.value = Math.max(0, Math.min(1, value)); this.value = Math.max(0, Math.min(1, value));
} }
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
BlockType block = extent.getBlock(position).getBlockType(); BlockType type = extent.getBlock(position).getBlockType();
TextureUtil util = holder.getTextureUtil(); TextureUtil util = holder.getTextureUtil();
int color = getColor(util.getColor(block)); int color;
if (type == BlockTypes.GRASS_BLOCK) {
color = holder.getTextureUtil().getColor(extent.getBiome(position));
} else {
color = holder.getTextureUtil().getColor(type);
}
return util.getNearestBlock(color).getDefaultState().toBaseBlock(); return util.getNearestBlock(color).getDefaultState().toBaseBlock();
} }
public int getColor(int color) { private int getColor(int color) {
int r = (color >> 16) & 0xFF; int r = (color >> 16) & 0xFF;
int g = (color >> 8) & 0xFF; int g = (color >> 8) & 0xFF;
int b = (color >> 0) & 0xFF; int b = (color >> 0) & 0xFF;
@ -45,7 +59,12 @@ public class DesaturatePattern extends AbstractPattern {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
BlockType type = get.getBlock(extent).getBlockType(); BlockType type = get.getBlock(extent).getBlockType();
TextureUtil util = holder.getTextureUtil(); TextureUtil util = holder.getTextureUtil();
int color = util.getColor(type); int color;
if (type == BlockTypes.GRASS_BLOCK) {
color = holder.getTextureUtil().getColor(extent.getBiome(get));
} else {
color = holder.getTextureUtil().getColor(type);
}
int newColor = getColor(color); int newColor = getColor(color);
if (newColor == color) { if (newColor == color) {
return false; return false;

Datei anzeigen

@ -2,11 +2,17 @@ package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
public class ExistingPattern extends AbstractExtentPattern { public class ExistingPattern extends AbstractExtentPattern {
/**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
*/
public ExistingPattern(Extent extent) { public ExistingPattern(Extent extent) {
super(extent); super(extent);
} }

Datei anzeigen

@ -1,28 +0,0 @@
package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
public class IdDataMaskPattern extends AbstractExtentPattern {
private final Pattern pattern;
private final int bitMask;
public IdDataMaskPattern(Extent extent, Pattern parent, int bitMask) {
super(extent);
this.pattern = parent;
this.bitMask = bitMask;
}
@Override
public BaseBlock applyBlock(BlockVector3 position) {
BaseBlock oldBlock = getExtent().getFullBlock(position);
BaseBlock newBlock = pattern.applyBlock(position);
int oldData = oldBlock.getInternalPropertiesId();
int newData = newBlock.getInternalPropertiesId() + oldData - (oldData & bitMask);
return newBlock.withPropertyId(newData).toBaseBlock();
}
}

Datei anzeigen

@ -1,27 +0,0 @@
package com.fastasyncworldedit.core.function.pattern;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import static com.google.common.base.Preconditions.checkNotNull;
public class IdPattern extends AbstractExtentPattern {
private final Pattern pattern;
public IdPattern(Extent extent, Pattern parent) {
super(extent);
checkNotNull(parent);
this.pattern = parent;
}
@Override
public BaseBlock applyBlock(BlockVector3 position) {
BaseBlock oldBlock = getExtent().getFullBlock(position);
BaseBlock newBlock = pattern.applyBlock(position);
return newBlock.withPropertyId(oldBlock.getInternalPropertiesId()).toBaseBlock();
}
}

Datei anzeigen

@ -13,6 +13,13 @@ public class Linear2DBlockPattern extends AbstractPattern {
private final int xScale; private final int xScale;
private final int zScale; private final int zScale;
/**
* Create a new {@link Pattern} instance
*
* @param patterns array of patterns to linearly choose from based on x/z coordinates
* @param xScale x-axis scale
* @param zScale z-axis scale
*/
public Linear2DBlockPattern(Pattern[] patterns, int xScale, int zScale) { public Linear2DBlockPattern(Pattern[] patterns, int xScale, int zScale) {
this.patternsArray = patterns; this.patternsArray = patterns;
this.xScale = xScale; this.xScale = xScale;

Datei anzeigen

@ -14,6 +14,14 @@ public class Linear3DBlockPattern extends AbstractPattern {
private final int yScale; private final int yScale;
private final int zScale; private final int zScale;
/**
* Create a new {@link Pattern} instance
*
* @param patterns array of patterns to linearly choose from based on x/y/z coordinates
* @param xScale x-axis scale
* @param yScale y-axis scale
* @param zScale z-axis scale
*/
public Linear3DBlockPattern(Pattern[] patterns, int xScale, int yScale, int zScale) { public Linear3DBlockPattern(Pattern[] patterns, int xScale, int yScale, int zScale) {
this.patternsArray = patterns; this.patternsArray = patterns;
this.xScale = xScale; this.xScale = xScale;

Datei anzeigen

@ -12,6 +12,11 @@ public class LinearBlockPattern extends AbstractPattern implements ResettablePat
private final Pattern[] patternsArray; private final Pattern[] patternsArray;
private transient int index; private transient int index;
/**
* Create a new {@link Pattern} instance
*
* @param patterns array of patterns to linearly choose from based on x/z coordinates
*/
public LinearBlockPattern(Pattern[] patterns) { public LinearBlockPattern(Pattern[] patterns) {
this.patternsArray = patterns; this.patternsArray = patterns;
} }

Datei anzeigen

@ -14,6 +14,13 @@ public class MaskedPattern extends AbstractPattern {
private final Pattern secondary; private final Pattern secondary;
private final Mask mask; private final Mask mask;
/**
* Create a new {@link Pattern} instance
*
* @param mask mask to use
* @param primary pattern if mask true
* @param secondary pattern if mask false
*/
public MaskedPattern(Mask mask, Pattern primary, Pattern secondary) { public MaskedPattern(Mask mask, Pattern primary, Pattern secondary) {
this.mask = mask; this.mask = mask;
this.primary = primary; this.primary = primary;

Datei anzeigen

@ -13,6 +13,11 @@ public class NoXPattern extends AbstractPattern {
private final Pattern pattern; private final Pattern pattern;
private final MutableBlockVector3 mutable = new MutableBlockVector3(); private final MutableBlockVector3 mutable = new MutableBlockVector3();
/**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
*/
public NoXPattern(Pattern pattern) { public NoXPattern(Pattern pattern) {
this.pattern = pattern; this.pattern = pattern;
} }

Datei anzeigen

@ -13,6 +13,11 @@ public class NoYPattern extends AbstractPattern {
private final Pattern pattern; private final Pattern pattern;
private final MutableBlockVector3 mutable = new MutableBlockVector3(); private final MutableBlockVector3 mutable = new MutableBlockVector3();
/**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
*/
public NoYPattern(Pattern pattern) { public NoYPattern(Pattern pattern) {
this.pattern = pattern; this.pattern = pattern;
} }

Datei anzeigen

@ -11,13 +11,17 @@ import com.sk89q.worldedit.world.block.BaseBlock;
public class NoZPattern extends AbstractPattern { public class NoZPattern extends AbstractPattern {
private final Pattern pattern; private final Pattern pattern;
private final MutableBlockVector3 mutable = new MutableBlockVector3();
/**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
*/
public NoZPattern(Pattern pattern) { public NoZPattern(Pattern pattern) {
this.pattern = pattern; this.pattern = pattern;
} }
private final transient MutableBlockVector3 mutable = new MutableBlockVector3();
@Override @Override
public BaseBlock applyBlock(BlockVector3 pos) { public BaseBlock applyBlock(BlockVector3 pos) {
mutable.mutX(pos.getX()); mutable.mutX(pos.getX());

Datei anzeigen

@ -13,13 +13,27 @@ public class OffsetPattern extends AbstractPattern {
private final int dx; private final int dx;
private final int dy; private final int dy;
private final int dz; private final int dz;
private final int minY;
private final int maxY;
private final transient MutableBlockVector3 mutable = new MutableBlockVector3(); private final transient MutableBlockVector3 mutable = new MutableBlockVector3();
private final Pattern pattern; private final Pattern pattern;
public OffsetPattern(Pattern pattern, int dx, int dy, int dz) { /**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
* @param dx offset x
* @param dy offset y
* @param dz offset z
* @param minY min applicable y (inclusive
* @param maxY max applicable y (inclusive
*/
public OffsetPattern(Pattern pattern, int dx, int dy, int dz, int minY, int maxY) {
this.dx = dx; this.dx = dx;
this.dy = dy; this.dy = dy;
this.dz = dz; this.dz = dz;
this.minY = minY;
this.maxY = maxY;
this.pattern = pattern; this.pattern = pattern;
} }
@ -35,6 +49,9 @@ public class OffsetPattern extends AbstractPattern {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
mutable.mutX(get.getX() + dx); mutable.mutX(get.getX() + dx);
mutable.mutY(get.getY() + dy); mutable.mutY(get.getY() + dy);
if (mutable.getY() < minY || mutable.getY() > maxY) {
return false;
}
mutable.mutZ(get.getZ() + dz); mutable.mutZ(get.getZ() + dz);
return pattern.apply(extent, get, mutable); return pattern.apply(extent, get, mutable);
} }

Datei anzeigen

@ -1,259 +0,0 @@
package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.registry.state.PropertyKey;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.MutableCharSequence;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.AbstractProperty;
import com.sk89q.worldedit.registry.state.IntegerProperty;
import com.sk89q.worldedit.registry.state.Property;
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 com.sk89q.worldedit.world.block.BlockTypesCache;
import java.util.ArrayList;
import java.util.List;
public class PropertyPattern extends AbstractExtentPattern {
private final int[] transformed;
public PropertyPattern(Extent extent, String[] properties) {
this(extent);
addRegex(".*[" + StringMan.join(properties, ",") + "]");
}
public PropertyPattern(Extent extent) {
super(extent);
this.transformed = new int[BlockTypesCache.states.length];
for (int i = 0; i < transformed.length; i++) {
transformed[i] = i;
}
}
private static final Operator EQUAL = (length, value, index) -> value;
private static final Operator PLUS = (length, value, index) -> index + value;
private static final Operator MINUS = (length, value, index) -> index - value;
private static final Operator MODULO = (length, value, index) -> index % value;
private static final Operator AND = (length, value, index) -> index & value;
private static final Operator OR = (length, value, index) -> index | value;
private static final Operator XOR = (length, value, index) -> index ^ value;
private interface Operator {
int apply(int length, int value, int index);
}
private Operator getOp(char c) {
switch (c) {
case '=':
return EQUAL;
case '+':
return PLUS;
case '-':
return MINUS;
case '%':
return MODULO;
case '&':
return AND;
case '|':
return OR;
case '^':
return XOR;
default:
return null;
}
}
private void add(BlockType type, PropertyKey key, Operator operator, MutableCharSequence value, boolean wrap) {
if (!type.hasProperty(key)) {
return;
}
AbstractProperty property = (AbstractProperty) type.getProperty(key);
BlockState defaultState = type.getDefaultState();
int valueInt;
if (value.length() == 0) {
valueInt = property.getIndex(defaultState.getInternalId());
} else if (!(property instanceof IntegerProperty) && MathMan.isInteger(value)) {
valueInt = StringMan.parseInt(value);
} else {
valueInt = property.getIndexFor(value);
}
List values = property.getValues();
int length = values.size();
for (int i = 0; i < values.size(); i++) {
int result = operator.apply(length, valueInt, i);
if (wrap) {
result = MathMan.wrap(result, 0, length - 1);
} else {
result = Math.max(Math.min(result, length - 1), 0);
}
if (result == i) {
continue;
}
int internalId = valueInt + i;
int state = property.modifyIndex(0, i);
if (type.getProperties().size() > 1) {
ArrayList<Property> properties = new ArrayList<>(type.getProperties().size() - 1);
for (Property current : type.getProperties()) {
if (current == property) {
continue;
}
properties.add(current);
}
applyRecursive(type, property, properties, 0, state, result);
} else {
int ordinal = type.withStateId(internalId).getOrdinal();
transformed[ordinal] = type.withStateId(result).getOrdinal();
}
}
}
private void applyRecursive(
BlockType type,
AbstractProperty property,
List<Property> properties,
int propertiesIndex,
int stateId,
int index
) {
AbstractProperty current = (AbstractProperty) properties.get(propertiesIndex);
List values = current.getValues();
if (propertiesIndex + 1 < properties.size()) {
for (int i = 0; i < values.size(); i++) {
int newState = current.modifyIndex(stateId, i);
applyRecursive(type, property, properties, propertiesIndex + 1, newState, index);
}
} else {
for (int i = 0; i < values.size(); i++) {
int statesIndex = current.modifyIndex(stateId, i) >> BlockTypesCache.BIT_OFFSET;
BlockState state = type.withPropertyId(statesIndex);
int existingOrdinal = transformed[state.getOrdinal()];
int existing = BlockTypesCache.states[existingOrdinal].getInternalId();
//states[statesIndex] << BlockTypesCache.BIT_OFFSET;
BlockState newState = state.withPropertyId(property.modifyIndex(existing, index) >> BlockTypesCache.BIT_OFFSET);
transformed[state.getOrdinal()] = newState.getOrdinal();
}
}
}
public PropertyPattern addRegex(String input) {
if (input.charAt(input.length() - 1) == ']') {
int propStart = StringMan.findMatchingBracket(input, input.length() - 1);
if (propStart == -1) {
return this;
}
MutableCharSequence charSequence = MutableCharSequence.getTemporal();
charSequence.setString(input);
charSequence.setSubstring(0, propStart);
BlockType type = null;
List<BlockType> blockTypeList = null;
if (StringMan.isAlphanumericUnd(charSequence)) {
type = BlockTypes.get(charSequence);
} else {
String regex = charSequence.toString();
blockTypeList = new ArrayList<>();
for (BlockType myType : BlockTypesCache.values) {
if (myType.getId().matches(regex)) {
blockTypeList.add(myType);
}
}
if (blockTypeList.size() == 1) {
type = blockTypeList.get(0);
}
}
PropertyKey key = null;
int length = input.length();
int last = propStart + 1;
Operator operator = null;
boolean wrap = false;
for (int i = last; i < length; i++) {
char c = input.charAt(i);
switch (c) {
case '[':
case '{':
case '(':
int next = StringMan.findMatchingBracket(input, i);
if (next != -1) {
i = next;
}
break;
case ']':
case ',': {
charSequence.setSubstring(last, i);
char firstChar = input.charAt(last + 1);
if (type != null) {
add(type, key, operator, charSequence, wrap);
} else {
for (BlockType myType : blockTypeList) {
add(myType, key, operator, charSequence, wrap);
}
}
last = i + 1;
break;
}
default:
Operator tmp = getOp(c);
if (tmp != null) {
operator = tmp;
charSequence.setSubstring(last, i);
char cp = input.charAt(i + 1);
boolean extra = cp == '=';
wrap = cp == '~';
if (extra || wrap) {
i++;
}
if (charSequence.length() > 0) {
key = PropertyKey.getByName(charSequence);
}
last = i + 1;
}
break;
}
}
}
return this;
}
@Override
public BaseBlock applyBlock(BlockVector3 position) {
BaseBlock block = getExtent().getFullBlock(position);
return apply(block, block);
}
public BaseBlock apply(BaseBlock block, BaseBlock orDefault) {
int ordinal = block.getOrdinal();
int newOrdinal = transformed[ordinal];
if (newOrdinal != ordinal) {
CompoundTag nbt = block.getNbtData();
BlockState newState = BlockState.getFromOrdinal(newOrdinal);
return newState.toBaseBlock(nbt);
}
return orDefault;
}
@Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
int ordinal = get.getOrdinal(extent);
int newOrdinal = transformed[ordinal];
if (newOrdinal != ordinal) {
set.setOrdinal(extent, newOrdinal);
}
return false;
}
}

Datei anzeigen

@ -4,6 +4,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
@ -18,16 +19,21 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class RandomFullClipboardPattern extends AbstractPattern { public class RandomFullClipboardPattern extends AbstractPattern {
private final Extent extent;
private final List<ClipboardHolder> clipboards; private final List<ClipboardHolder> clipboards;
private final boolean randomRotate; private final boolean randomRotate;
private final boolean randomFlip; private final boolean randomFlip;
private final Vector3 flipVector = Vector3.at(1, 0, 0).multiply(-2).add(1, 1, 1); private final Vector3 flipVector = Vector3.at(1, 0, 0).multiply(-2).add(1, 1, 1);
public RandomFullClipboardPattern(Extent extent, List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) { /**
* Create a new {@link Pattern} instance
*
* @param clipboards list of clipboards to choose from. Does not paste air
* @param randomRotate if the clipboard should be randomly rotated (through multiples of 90)
* @param randomFlip if the clipboard should be randomly flipped
*/
public RandomFullClipboardPattern(List<ClipboardHolder> clipboards, boolean randomRotate, boolean randomFlip) {
checkNotNull(clipboards); checkNotNull(clipboards);
this.clipboards = clipboards; this.clipboards = clipboards;
this.extent = extent;
this.randomRotate = randomRotate; this.randomRotate = randomRotate;
this.randomFlip = randomFlip; this.randomFlip = randomFlip;
} }
@ -40,7 +46,7 @@ public class RandomFullClipboardPattern extends AbstractPattern {
transform = transform.rotateY(ThreadLocalRandom.current().nextInt(4) * 90); transform = transform.rotateY(ThreadLocalRandom.current().nextInt(4) * 90);
holder.setTransform(new AffineTransform().rotateY(ThreadLocalRandom.current().nextInt(4) * 90)); holder.setTransform(new AffineTransform().rotateY(ThreadLocalRandom.current().nextInt(4) * 90));
} }
if (randomFlip) { if (randomFlip && ThreadLocalRandom.current().nextBoolean()) {
transform = transform.scale(flipVector); transform = transform.scale(flipVector);
} }
if (!transform.isIdentity()) { if (!transform.isIdentity()) {

Datei anzeigen

@ -15,6 +15,8 @@ public class RandomOffsetPattern extends AbstractPattern {
private final int dx; private final int dx;
private final int dy; private final int dy;
private final int dz; private final int dz;
private final int minY;
private final int maxY;
private final Pattern pattern; private final Pattern pattern;
private final transient int dx2; private final transient int dx2;
@ -23,7 +25,17 @@ public class RandomOffsetPattern extends AbstractPattern {
private final transient MutableBlockVector3 mutable = new MutableBlockVector3(); private final transient MutableBlockVector3 mutable = new MutableBlockVector3();
private final transient SplittableRandom r; private final transient SplittableRandom r;
public RandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) { /**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
* @param dx offset x
* @param dy offset y
* @param dz offset z
* @param minY min applicable y (inclusive
* @param maxY max applicable y (inclusive
*/
public RandomOffsetPattern(Pattern pattern, int dx, int dy, int dz, int minY, int maxY) {
this.pattern = pattern; this.pattern = pattern;
this.dx = dx; this.dx = dx;
this.dy = dy; this.dy = dy;
@ -32,6 +44,8 @@ public class RandomOffsetPattern extends AbstractPattern {
this.dy2 = dy * 2 + 1; this.dy2 = dy * 2 + 1;
this.dz2 = dz * 2 + 1; this.dz2 = dz * 2 + 1;
this.r = new SplittableRandom(); this.r = new SplittableRandom();
this.minY = minY;
this.maxY = maxY;
} }
@ -48,6 +62,9 @@ public class RandomOffsetPattern extends AbstractPattern {
mutable.mutX((set.getX() + r.nextInt(dx2) - dx)); mutable.mutX((set.getX() + r.nextInt(dx2) - dx));
mutable.mutY((set.getY() + r.nextInt(dy2) - dy)); mutable.mutY((set.getY() + r.nextInt(dy2) - dy));
mutable.mutZ((set.getZ() + r.nextInt(dz2) - dz)); mutable.mutZ((set.getZ() + r.nextInt(dz2) - dz));
if (mutable.getY() < minY || mutable.getY() > maxY) {
return false;
}
return pattern.apply(extent, get, mutable); return pattern.apply(extent, get, mutable);
} }

Datei anzeigen

@ -11,11 +11,22 @@ import com.sk89q.worldedit.world.block.BaseBlock;
public class RelativePattern extends AbstractPattern implements ResettablePattern { public class RelativePattern extends AbstractPattern implements ResettablePattern {
private final Pattern pattern; private final Pattern pattern;
private BlockVector3 origin; private final int minY;
private final int maxY;
private final MutableBlockVector3 mutable = new MutableBlockVector3(); private final MutableBlockVector3 mutable = new MutableBlockVector3();
private BlockVector3 origin;
public RelativePattern(Pattern pattern) { /**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
* @param minY min applicable y (inclusive
* @param maxY max applicable y (inclusive
*/
public RelativePattern(Pattern pattern, int minY, int maxY) {
this.pattern = pattern; this.pattern = pattern;
this.minY = minY;
this.maxY = maxY;
} }
@Override @Override
@ -36,6 +47,9 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter
} }
mutable.mutX(set.getX() - origin.getX()); mutable.mutX(set.getX() - origin.getX());
mutable.mutY(set.getY() - origin.getY()); mutable.mutY(set.getY() - origin.getY());
if (mutable.getY() < minY || mutable.getY() > maxY) {
return false;
}
mutable.mutZ(set.getZ() - origin.getZ()); mutable.mutZ(set.getZ() - origin.getZ());
return pattern.apply(extent, get, mutable); return pattern.apply(extent, get, mutable);
} }

Datei anzeigen

@ -1,13 +1,16 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.TextureHolder; import com.fastasyncworldedit.core.util.TextureHolder;
import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.util.TextureUtil;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.awt.Color; import java.awt.Color;
@ -17,33 +20,53 @@ public class SaturatePattern extends AbstractPattern {
private final int color; private final int color;
private final Extent extent; private final Extent extent;
/**
public SaturatePattern(Extent extent, int color, TextureHolder texture) { * Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param holder {@link TextureHolder} to use to get textures
* @param r red channel, clamped 0 -> 255
* @param g green channel, clamped 0 -> 255
* @param b blue channel, clamped 0 -> 255
* @param a alpha channel, clamped 0 -> 255
*/
public SaturatePattern(Extent extent, TextureHolder holder, int r, int g, int b, int a) {
this.extent = extent; this.extent = extent;
this.holder = texture; this.holder = holder;
this.color = new Color(color).getRGB(); this.color = new Color(MathMan.clamp(r, 0, 255), MathMan.clamp(g, 0, 255), MathMan.clamp(b, 0, 255), MathMan.clamp(a, 0
, 255)).getRGB();
} }
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
BlockType block = extent.getBlock(position).getBlockType(); BlockType type = extent.getBlock(position).getBlockType();
TextureUtil util = holder.getTextureUtil(); TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block); int currentColor;
int newColor = util.multiplyColor(currentColor, color); if (type == BlockTypes.GRASS_BLOCK) {
currentColor = holder.getTextureUtil().getColor(extent.getBiome(position));
} else {
currentColor = holder.getTextureUtil().getColor(type);
}
int newColor = TextureUtil.multiplyColor(currentColor, color);
return util.getNearestBlock(newColor).getDefaultState().toBaseBlock(); return util.getNearestBlock(newColor).getDefaultState().toBaseBlock();
} }
@Override @Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
BlockType block = get.getBlock(extent).getBlockType(); BlockType type = get.getBlock(extent).getBlockType();
TextureUtil util = holder.getTextureUtil(); TextureUtil util = holder.getTextureUtil();
int currentColor = util.getColor(block); int currentColor;
if (type == BlockTypes.GRASS_BLOCK) {
currentColor = holder.getTextureUtil().getColor(extent.getBiome(get));
} else {
currentColor = holder.getTextureUtil().getColor(type);
}
if (currentColor == 0) { if (currentColor == 0) {
return false; return false;
} }
int newColor = util.multiplyColor(currentColor, color); int newColor = TextureUtil.multiplyColor(currentColor, color);
BlockType newBlock = util.getNearestBlock(newColor); BlockType newBlock = util.getNearestBlock(newColor);
if (newBlock.equals(block)) { if (newBlock.equals(type)) {
return false; return false;
} }
return set.setBlock(extent, newBlock.getDefaultState()); return set.setBlock(extent, newBlock.getDefaultState());

Datei anzeigen

@ -1,12 +1,15 @@
package com.fastasyncworldedit.core.function.pattern; package com.fastasyncworldedit.core.function.pattern;
import com.fastasyncworldedit.core.util.TextureHolder;
import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.util.TextureUtil;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -16,23 +19,43 @@ public class ShadePattern extends AbstractPattern {
private final Extent extent; private final Extent extent;
private final boolean darken; private final boolean darken;
public ShadePattern(Extent extent, boolean darken, TextureUtil util) { /**
* Create a new {@link Pattern} instance
*
* @param extent extent to set to
* @param holder {@link TextureHolder} to use for textures
* @param darken if the shade should darken or lighten colours
*/
public ShadePattern(Extent extent, TextureHolder holder, boolean darken) {
checkNotNull(extent); checkNotNull(extent);
this.extent = extent; this.extent = extent;
this.util = util; this.util = holder.getTextureUtil();
this.darken = darken; this.darken = darken;
} }
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
BlockType block = extent.getBlock(position).getBlockType(); BlockType block = extent.getBlock(position).getBlockType();
return (darken ? util.getDarkerBlock(block) : util.getLighterBlock(block)).getDefaultState().toBaseBlock(); BlockType type;
if (block == BlockTypes.GRASS_BLOCK) {
int color = util.getColor(extent.getBiome(position));
type = (darken ? util.getDarkerBlock(color) : util.getLighterBlock(color));
} else {
type = (darken ? util.getDarkerBlock(block) : util.getLighterBlock(block));
}
return type.getDefaultState().toBaseBlock();
} }
@Override @Override
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
BlockType type = get.getBlock(extent).getBlockType(); BlockType type = get.getBlock(extent).getBlockType();
BlockType newType = (darken ? util.getDarkerBlock(type) : util.getLighterBlock(type)); BlockType newType;
if (type == BlockTypes.GRASS_BLOCK) {
int color = util.getColor(extent.getBiome(get));
newType = (darken ? util.getDarkerBlock(color) : util.getLighterBlock(color));
} else {
newType = (darken ? util.getDarkerBlock(type) : util.getLighterBlock(type));
}
if (type != newType) { if (type != newType) {
return set.setBlock(extent, newType.getDefaultState()); return set.setBlock(extent, newType.getDefaultState());
} }

Datei anzeigen

@ -18,6 +18,8 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
private final int dx; private final int dx;
private final int dy; private final int dy;
private final int dz; private final int dz;
private final int minY;
private final int maxY;
private final Pattern pattern; private final Pattern pattern;
private final int dx2; private final int dx2;
@ -26,19 +28,23 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
private final MutableBlockVector3 mutable; private final MutableBlockVector3 mutable;
private final SplittableRandom r; private final SplittableRandom r;
public static boolean[] getTypes() { /**
boolean[] types = new boolean[BlockTypes.size()]; * Create a new {@link Pattern} instance
for (BlockType type : BlockTypesCache.values) { *
types[type.getInternalId()] = type.getMaterial().isSolid(); * @param pattern pattern to apply
} * @param dx offset x
return types; * @param dy offset y
} * @param dz offset z
* @param minY min applicable y (inclusive
public SolidRandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) { * @param maxY max applicable y (inclusive
*/
public SolidRandomOffsetPattern(Pattern pattern, int dx, int dy, int dz, int minY, int maxY) {
this.pattern = pattern; this.pattern = pattern;
this.dx = dx; this.dx = dx;
this.dy = dy; this.dy = dy;
this.dz = dz; this.dz = dz;
this.minY = minY;
this.maxY = maxY;
this.dx2 = dx * 2 + 1; this.dx2 = dx * 2 + 1;
this.dy2 = dy * 2 + 1; this.dy2 = dy * 2 + 1;
@ -47,6 +53,14 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
this.mutable = new MutableBlockVector3(); this.mutable = new MutableBlockVector3();
} }
public static boolean[] getTypes() {
boolean[] types = new boolean[BlockTypes.size()];
for (BlockType type : BlockTypesCache.values) {
types[type.getInternalId()] = type.getMaterial().isSolid();
}
return types;
}
@Override @Override
public BaseBlock applyBlock(BlockVector3 position) { public BaseBlock applyBlock(BlockVector3 position) {
mutable.mutX(position.getX() + r.nextInt(dx2) - dx); mutable.mutX(position.getX() + r.nextInt(dx2) - dx);
@ -63,6 +77,9 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException {
mutable.mutX(set.getX() + r.nextInt(dx2) - dx); mutable.mutX(set.getX() + r.nextInt(dx2) - dx);
mutable.mutY(set.getY() + r.nextInt(dy2) - dy); mutable.mutY(set.getY() + r.nextInt(dy2) - dy);
if (mutable.getY() < minY || mutable.getY() > maxY) {
return false;
}
mutable.mutZ(set.getZ() + r.nextInt(dz2) - dz); mutable.mutZ(set.getZ() + r.nextInt(dz2) - dz);
BaseBlock block = pattern.applyBlock(mutable); BaseBlock block = pattern.applyBlock(mutable);
if (block.getMaterial().isSolid()) { if (block.getMaterial().isSolid()) {

Datei anzeigen

@ -13,13 +13,25 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern {
private final Pattern pattern; private final Pattern pattern;
private final int moves; private final int moves;
private final int minY;
private final int maxY;
private final MutableBlockVector3 cur; private final MutableBlockVector3 cur;
private final MutableBlockVector3[] buffer; private final MutableBlockVector3[] buffer;
private final MutableBlockVector3[] allowed; private final MutableBlockVector3[] allowed;
public SurfaceRandomOffsetPattern(Pattern pattern, int distance) { /**
* Create a new {@link Pattern} instance
*
* @param pattern pattern to apply
* @param distance number of "spreads" to make
* @param minY min applicable y (inclusive
* @param maxY max applicable y (inclusive
*/
public SurfaceRandomOffsetPattern(Pattern pattern, int distance, int minY, int maxY) {
this.pattern = pattern; this.pattern = pattern;
this.minY = minY;
this.maxY = maxY;
this.moves = Math.min(255, distance); this.moves = Math.min(255, distance);
cur = new MutableBlockVector3(); cur = new MutableBlockVector3();
this.buffer = new MutableBlockVector3[BreadthFirstSearch.DIAGONAL_DIRECTIONS.length]; this.buffer = new MutableBlockVector3[BreadthFirstSearch.DIAGONAL_DIRECTIONS.length];
@ -70,12 +82,12 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern {
int y = v.getBlockY(); int y = v.getBlockY();
int z = v.getBlockZ(); int z = v.getBlockZ();
v.mutY(y + 1); v.mutY(y + 1);
if (canPassthrough(v)) { if (y < maxY && canPassthrough(v)) {
v.mutY(y); v.mutY(y);
return true; return true;
} }
v.mutY(y - 1); v.mutY(y - 1);
if (canPassthrough(v)) { if (y > minY && canPassthrough(v)) {
v.mutY(y); v.mutY(y);
return true; return true;
} }

Datei anzeigen

@ -1,6 +1,7 @@
package com.fastasyncworldedit.core.util; package com.fastasyncworldedit.core.util;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
@ -22,11 +23,6 @@ public class DelegateTextureUtil extends TextureUtil {
return parent.getNearestBlock(color); return parent.getNearestBlock(color);
} }
@Override
public BlockType getNearestBlock(BlockType block) {
return parent.getNearestBlock(block);
}
@Override @Override
public BlockType getNextNearestBlock(int color) { public BlockType getNextNearestBlock(int color) {
return parent.getNextNearestBlock(color); return parent.getNextNearestBlock(color);
@ -47,11 +43,26 @@ public class DelegateTextureUtil extends TextureUtil {
return parent.getDarkerBlock(block); return parent.getDarkerBlock(block);
} }
@Override
public BlockType getLighterBlock(final int color) {
return parent.getLighterBlock(color);
}
@Override
public BlockType getDarkerBlock(final int color) {
return parent.getDarkerBlock(color);
}
@Override @Override
public int getColor(BlockType block) { public int getColor(BlockType block) {
return parent.getColor(block); return parent.getColor(block);
} }
@Override
public int getColor(final BiomeType biome) {
return parent.getColor(biome);
}
@Override @Override
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) { public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) {
return parent.getIsBlockCloserThanBiome(blockAndBiomeIdOutput, color, biomePriority); return parent.getIsBlockCloserThanBiome(blockAndBiomeIdOutput, color, biomePriority);
@ -77,11 +88,6 @@ public class DelegateTextureUtil extends TextureUtil {
return parent.getFolder(); return parent.getFolder();
} }
@Override
public int combineTransparency(int top, int bottom) {
return parent.combineTransparency(top, bottom);
}
@Override @Override
public void calculateLayerArrays() { public void calculateLayerArrays() {
parent.calculateLayerArrays(); parent.calculateLayerArrays();
@ -92,11 +98,6 @@ public class DelegateTextureUtil extends TextureUtil {
parent.loadModTextures(); parent.loadModTextures();
} }
@Override
public int multiplyColor(int c1, int c2) {
return parent.multiplyColor(c1, c2);
}
@Override @Override
public BlockType getNearestBlock(BlockType block, boolean darker) { public BlockType getNearestBlock(BlockType block, boolean darker) {
return parent.getNearestBlock(block, darker); return parent.getNearestBlock(block, darker);
@ -112,19 +113,4 @@ public class DelegateTextureUtil extends TextureUtil {
return parent.hasAlpha(color); return parent.hasAlpha(color);
} }
@Override
public long colorDistance(int c1, int c2) {
return parent.colorDistance(c1, c2);
}
@Override
public long colorDistance(int red1, int green1, int blue1, int c2) {
return parent.colorDistance(red1, green1, blue1, c2);
}
@Override
public long getDistance(BufferedImage image, int c1) {
return parent.getDistance(image, c1);
}
} }

Datei anzeigen

@ -11,15 +11,16 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockType; import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.block.BlockTypesCache; import com.sk89q.worldedit.world.block.BlockTypesCache;
import com.sk89q.worldedit.world.registry.BlockMaterial;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArraySet; import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
@ -32,24 +33,18 @@ import java.io.InputStreamReader;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
import static org.apache.logging.log4j.LogManager.getLogger;
// TODO FIXME
public class TextureUtil implements TextureHolder { public class TextureUtil implements TextureHolder {
private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final Logger LOGGER = LogManagerCompat.getLogger();
@ -63,20 +58,7 @@ public class TextureUtil implements TextureHolder {
} }
private final File folder; private final File folder;
protected int[] blockColors = new int[BlockTypes.size()]; private final BiomeColor[] biomes = new BiomeColor[]{
protected long[] blockDistance = new long[BlockTypes.size()];
protected long[] distances;
protected int[] validColors;
protected int[] validBlockIds;
protected int[] validLayerColors;
protected int[][] validLayerBlocks;
protected int[] validMixBiomeColors;
protected long[] validMixBiomeIds;
/**
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
*/
protected BiomeColor[] validBiomes;
private final BiomeColor[] biomes = new BiomeColor[] {
// ID Name Temperature, rainfall, grass, foliage colors // ID Name Temperature, rainfall, grass, foliage colors
// - note: the colors here are just placeholders, they are computed in the program // - note: the colors here are just placeholders, they are computed in the program
new BiomeColor(0, "ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F), new BiomeColor(0, "ocean", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
@ -122,17 +104,17 @@ public class TextureUtil implements TextureHolder {
new BiomeColor(37, "badlands", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(37, "badlands", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(38, "wooded_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(38, "wooded_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(39, "badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(39, "badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(40, "small_end_islands", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(40, "small_end_islands", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(41, "end_midlands", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(41, "end_midlands", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(42, "end_highlands", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(42, "end_highlands", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(43, "end_barrens", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(43, "end_barrens", 0.5f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(44, "warm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(44, "warm_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(45, "lukewarm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(45, "lukewarm_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(46, "cold_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(46, "cold_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(47, "deep_warm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(47, "deep_warm_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(48, "deep_lukewarm_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(48, "deep_lukewarm_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(49, "deep_cold_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(49, "deep_cold_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(50, "deep_frozen_ocean", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(50, "deep_frozen_ocean", 0.8f, 0.5f, 0x92BD59, 0x77AB2F),
new BiomeColor(51, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(51, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(52, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(52, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(53, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(53, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
@ -242,22 +224,22 @@ public class TextureUtil implements TextureHolder {
new BiomeColor(156, "tall_birch_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F), new BiomeColor(156, "tall_birch_hills", 0.6f, 0.6f, 0x92BD59, 0x77AB2F),
new BiomeColor(157, "dark_forest_hills", 0.7f, 0.8f, 0x92BD59, 0x77AB2F), new BiomeColor(157, "dark_forest_hills", 0.7f, 0.8f, 0x92BD59, 0x77AB2F),
new BiomeColor(158, "snowy_taiga_mountains", -0.5f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(158, "snowy_taiga_mountains", -0.5f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(159, "Unknown", -0.5f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(159, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(160, "giant_spruce_taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F), new BiomeColor(160, "giant_spruce_taiga", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
// special exception, temperature not 0.3 // special exception, temperature not 0.3
new BiomeColor(161, "giant_spruce_taiga_hills", 0.25f, 0.8f, 0x92BD59, 0x77AB2F), new BiomeColor(161, "giant_spruce_taiga_hills", 0.25f, 0.8f, 0x92BD59, 0x77AB2F),
new BiomeColor(162, "modified_gravelly_mountains", 0.2f, 0.3f, 0x92BD59, 0x77AB2F), new BiomeColor(162, "gravelly_mountains+", 0.2f, 0.3f, 0x92BD59, 0x77AB2F),
new BiomeColor(163, "shattered_savanna", 1.1f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(163, "shattered_savanna", 1.1f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(164, "shattered_savanna_plateau", 1.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(164, "shattered_savanna_plateau", 1.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(165, "eroded_badlands", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(165, "eroded_badlands", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(166, "modified_wooded_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(166, "modified_wooded_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(167, "modified_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(167, "modified_badlands_plateau", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(168, "bamboo_jungle", 0.95f, 0.9f, 0x92BD59, 0x77AB2F), new BiomeColor(168, "bamboo_jungle", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
new BiomeColor(169, "bamboo_jungle_hills", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(168, "bamboo_jungle_hills", 0.95f, 0.9f, 0x92BD59, 0x77AB2F),
new BiomeColor(170, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(170, "soul_sand_valley", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(171, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(171, "crimson_forest", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(172, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(172, "warped_forest", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(173, "Unknown Biome", 2.0f, 0.0f, 0x92BD59, 0x77AB2F), new BiomeColor(173, "basalt_deltas", 2.0f, 0.0f, 0x92BD59, 0x77AB2F),
new BiomeColor(174, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(174, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(175, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(175, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(176, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(176, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
@ -341,24 +323,41 @@ public class TextureUtil implements TextureHolder {
new BiomeColor(254, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F), new BiomeColor(254, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F),
new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F)}; new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F)};
private final BlockType[] layerBuffer = new BlockType[2]; private final BlockType[] layerBuffer = new BlockType[2];
protected int[] blockColors = new int[BlockTypes.size()];
protected long[] blockDistance = new long[BlockTypes.size()];
protected long[] distances;
protected int[] validColors;
protected int[] validBlockIds;
protected int[] validLayerColors;
protected int[][] validLayerBlocks;
protected int[] validMixBiomeColors;
protected long[] validMixBiomeIds;
/**
* https://github.com/erich666/Mineways/blob/master/Win/biomes.cpp
*/
protected BiomeColor[] validBiomes;
/**
* Do not use. Use {@link Fawe#getTextureUtil()}
*/
public TextureUtil() throws FileNotFoundException { public TextureUtil() throws FileNotFoundException {
this(MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TEXTURES)); this(MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.TEXTURES));
} }
/**
* Do not use. Use {@link Fawe#getTextureUtil()}
*/
public TextureUtil(File folder) throws FileNotFoundException { public TextureUtil(File folder) throws FileNotFoundException {
this.folder = folder; this.folder = folder;
if (!folder.exists()) { if (!folder.exists()) {
try { try {
LOGGER.info("Downloading asset jar from Mojang, please wait..."); LOGGER.info("Downloading asset jar from Mojang, please wait...");
new File(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" + "/.minecraft/versions/") new File(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/").mkdirs();
.mkdirs();
try (BufferedInputStream in = new BufferedInputStream( try (BufferedInputStream in = new BufferedInputStream(
new URL("https://launcher.mojang.com/v1/objects/8d9b65467c7913fcf6f5b2e729d44a1e00fde150/client.jar") new URL("https://launcher.mojang.com/v1/objects/8d9b65467c7913fcf6f5b2e729d44a1e00fde150/client.jar")
.openStream()); .openStream());
FileOutputStream fileOutputStream = new FileOutputStream( FileOutputStream fileOutputStream = new FileOutputStream(
Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/1.17.1.jar")) {
+ "/.minecraft/versions/1.17.1.jar")) {
byte[] dataBuffer = new byte[1024]; byte[] dataBuffer = new byte[1024];
int bytesRead; int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) { while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
@ -367,14 +366,16 @@ public class TextureUtil implements TextureHolder {
LOGGER.info("Asset jar down has been downloaded successfully."); LOGGER.info("Asset jar down has been downloaded successfully.");
} catch (IOException e) { } catch (IOException e) {
LOGGER.error( LOGGER.error(
"Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar in it."); "Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` " +
"folder with a `.minecraft/versions` jar in it.");
LOGGER.error("If the file exists, please make sure the server has read access to the directory."); LOGGER.error("If the file exists, please make sure the server has read access to the directory.");
} }
} catch (AccessControlException e) { } catch (AccessControlException e) {
LOGGER.error( LOGGER.error(
"Could not download asset jar. It's likely your file permission are setup improperly and do not allow fetching data from the Mojang servers."); "Could not download asset jar. It's likely your file permission are setup improperly and do not allow fetching data from the Mojang servers.");
LOGGER.error( LOGGER.error(
"Please create the following folder manually: `FastAsyncWorldEdit/textures` with `.minecraft/versions` jar in it."); "Please create the following folder manually: `FastAsyncWorldEdit/textures` with a `" +
".minecraft/versions` jar in it.");
} }
} }
@ -423,22 +424,155 @@ public class TextureUtil implements TextureHolder {
} }
int factor1 = FACTORS[total1]; int factor1 = FACTORS[total1];
int factor2 = FACTORS[total2]; int factor2 = FACTORS[total2];
long r = (512 * (red1 * factor1 - red2 * factor2)) >> 10; long r = (512 * ((long) red1 * factor1 - (long) red2 * factor2)) >> 10;
long g = (green1 * factor1 - green2 * factor2); long g = ((long) green1 * factor1 - (long) green2 * factor2);
long b = (767 * (blue1 * factor1 - blue2 * factor2)) >> 10; long b = (767 * ((long) blue1 * factor1 - (long) blue2 * factor2)) >> 10;
return (int) ((r * r + g * g + b * b) >> 25); return (int) ((r * r + g * g + b * b) >> 25);
} }
@Override public TextureUtil getTextureUtil() { protected static long colorDistance(int c1, int c2) {
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1) & 0xFF;
return colorDistance(red1, green1, blue1, c2);
}
private static long colorDistance(int red1, int green1, int blue1, int c2) {
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2) & 0xFF;
int rmean = (red1 + red2) >> 1;
int r = red1 - red2;
int g = green1 - green2;
int b = blue1 - blue2;
int hd = hueDistance(red1, green1, blue1, red2, green2, blue2);
return (((long) (512 + rmean) * r * r) >> 8) + 4L * g * g + (((long) (767 - rmean) * b * b) >> 8) + ((long) hd * hd);
}
/**
* Combine two colors by multipling
*
* @param c1 color 1
* @param c2 color 2
* @return new color
*/
public static int multiplyColor(int c1, int c2) {
int alpha1 = (c1 >> 24) & 0xFF;
int alpha2 = (c2 >> 24) & 0xFF;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1) & 0xFF;
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2) & 0xFF;
int red = ((red1 * red2)) / 255;
int green = ((green1 * green2)) / 255;
int blue = ((blue1 * blue2)) / 255;
int alpha = ((alpha1 * alpha2)) / 255;
return (alpha << 24) + (red << 16) + (green << 8) + (blue);
}
/**
* Combine two colors by averaging
*
* @param c1 color 1
* @param c2 color 2
* @return new color
*/
public static int averageColor(int c1, int c2) {
int alpha1 = (c1 >> 24) & 0xFF;
int alpha2 = (c2 >> 24) & 0xFF;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1) & 0xFF;
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2) & 0xFF;
int red = ((red1 + red2)) >> 1;
int green = ((green1 + green2)) >> 1;
int blue = ((blue1 + blue2)) >> 1;
int alpha = ((alpha1 + alpha2)) >> 1;
return (alpha << 24) + (red << 16) + (green << 8) + (blue);
}
/**
* Combine multiple colors by multipling
*
* @param colors colors
* @return new color
*/
public static int averageColor(int... colors) {
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
for (int c : colors) {
alpha += (c >> 24) & 0xFF;
red += (c >> 16) & 0xFF;
green += (c >> 8) & 0xFF;
blue += (c) & 0xFF;
}
int num = colors.length;
alpha /= num;
red /= num;
green /= num;
blue /= num;
return (alpha << 24) + (red << 16) + (green << 8) + (blue);
}
/**
* Assumes the top layer is a transparent color and the bottom is opaque
*/
public static int combineTransparency(int top, int bottom) {
int alpha1 = (top >> 24) & 0xFF;
int alpha2 = 255 - alpha1;
int red1 = (top >> 16) & 0xFF;
int green1 = (top >> 8) & 0xFF;
int blue1 = (top) & 0xFF;
int red2 = (bottom >> 16) & 0xFF;
int green2 = (bottom >> 8) & 0xFF;
int blue2 = (bottom) & 0xFF;
int red = ((red1 * alpha1) + (red2 * alpha2)) / 255;
int green = ((green1 * alpha1) + (green2 * alpha2)) / 255;
int blue = ((blue1 * alpha1) + (blue2 * alpha2)) / 255;
return (red << 16) + (green << 8) + (blue) + (255 << 24);
}
private static long getDistance(BufferedImage image, int c1) {
long totalDistSqr = 0;
int width = image.getWidth();
int height = image.getHeight();
int area = width * height;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1) & 0xFF;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int c2 = image.getRGB(x, y);
long distance = colorDistance(red1, green1, blue1, c2);
totalDistSqr += distance * distance;
}
}
return totalDistSqr / area;
}
@Override
public TextureUtil getTextureUtil() {
return this; return this;
} }
/**
* Get the block most closely matching a color based on the block's average color
*
* @param color color to match
* @return matching block
*/
public BlockType getNearestBlock(int color) { public BlockType getNearestBlock(int color) {
long min = Long.MAX_VALUE; long min = Long.MAX_VALUE;
int closest = 0; int closest = 0;
int red1 = (color >> 16) & 0xFF; int red1 = (color >> 16) & 0xFF;
int green1 = (color >> 8) & 0xFF; int green1 = (color >> 8) & 0xFF;
int blue1 = (color >> 0) & 0xFF; int blue1 = (color) & 0xFF;
int alpha = (color >> 24) & 0xFF; int alpha = (color >> 24) & 0xFF;
for (int i = 0; i < validColors.length; i++) { for (int i = 0; i < validColors.length; i++) {
int other = validColors[i]; int other = validColors[i];
@ -456,20 +590,18 @@ public class TextureUtil implements TextureHolder {
return BlockTypes.get(closest); return BlockTypes.get(closest);
} }
public BlockType getNearestBlock(BlockType block) { /**
int color = getColor(block); * Get the block most closely matching a color, without matching the color, based on the block's average color
if (color == 0) { *
return null; * @param color color to match
} * @return matching block
return getNextNearestBlock(color); */
}
public BlockType getNextNearestBlock(int color) { public BlockType getNextNearestBlock(int color) {
long min = Long.MAX_VALUE; long min = Long.MAX_VALUE;
int closest = 0; int closest = 0;
int red1 = (color >> 16) & 0xFF; int red1 = (color >> 16) & 0xFF;
int green1 = (color >> 8) & 0xFF; int green1 = (color >> 8) & 0xFF;
int blue1 = (color >> 0) & 0xFF; int blue1 = (color) & 0xFF;
int alpha = (color >> 24) & 0xFF; int alpha = (color >> 24) & 0xFF;
for (int i = 0; i < validColors.length; i++) { for (int i = 0; i < validColors.length; i++) {
int other = validColors[i]; int other = validColors[i];
@ -495,7 +627,7 @@ public class TextureUtil implements TextureHolder {
long min = Long.MAX_VALUE; long min = Long.MAX_VALUE;
int red1 = (color >> 16) & 0xFF; int red1 = (color >> 16) & 0xFF;
int green1 = (color >> 8) & 0xFF; int green1 = (color >> 8) & 0xFF;
int blue1 = (color >> 0) & 0xFF; int blue1 = (color) & 0xFF;
int alpha = (color >> 24) & 0xFF; int alpha = (color >> 24) & 0xFF;
for (int i = 0; i < validLayerColors.length; i++) { for (int i = 0; i < validLayerColors.length; i++) {
int other = validLayerColors[i]; int other = validLayerColors[i];
@ -512,23 +644,80 @@ public class TextureUtil implements TextureHolder {
return layerBuffer; return layerBuffer;
} }
/**
* Get the next lightest block
*
* @param block input block
* @return next lightest block
*/
public BlockType getLighterBlock(BlockType block) { public BlockType getLighterBlock(BlockType block) {
return getNearestBlock(block, false); return getNearestBlock(block, false);
} }
/**
* Get the next darkest block
*
* @param block input block
* @return next darkest block
*/
public BlockType getDarkerBlock(BlockType block) { public BlockType getDarkerBlock(BlockType block) {
return getNearestBlock(block, true); return getNearestBlock(block, true);
} }
/**
* Get the next lightest block
*
* @param color input color
* @return next lightest block
*/
public BlockType getLighterBlock(int color) {
return getNearestBlock(color, false);
}
/**
* Get the next darkest block
*
* @param color input color
* @return next darkest block
*/
public BlockType getDarkerBlock(int color) {
return getNearestBlock(color, true);
}
/**
* Get the integer representation of a block's RGBA color.
*
* @param block input block
* @return integer RGBA color
*/
public int getColor(BlockType block) { public int getColor(BlockType block) {
if (block == BlockTypes.GRASS_BLOCK) {
return validBiomes[0].grassCombined;
}
return blockColors[block.getInternalId()]; return blockColors[block.getInternalId()];
} }
/**
* Get the integer representation of a biomes's RGBA color when applied to grass.
*
* @param biome input biome
* @return integer RGBA color
*/
public int getColor(BiomeType biome) {
return validBiomes[biome.getInternalId()].grassCombined;
}
/**
* Get the {@link BiomeColor} entry from a biome's ID
*
* @param biome biome id
* @return the {@link BiomeColor} entry
*/
public BiomeColor getBiome(int biome) { public BiomeColor getBiome(int biome) {
return biomes[biome]; return biomes[biome];
} }
public boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) { protected boolean getIsBlockCloserThanBiome(char[] blockAndBiomeIdOutput, int color, int biomePriority) {
BlockType block = getNearestBlock(color); BlockType block = getNearestBlock(color);
TextureUtil.BiomeColor biome = getNearestBiome(color); TextureUtil.BiomeColor biome = getNearestBiome(color);
int blockColor = getColor(block); int blockColor = getColor(block);
@ -537,13 +726,13 @@ public class TextureUtil implements TextureHolder {
return colorDistance(biome.grassCombined, color) - biomePriority > colorDistance(blockColor, color); return colorDistance(biome.grassCombined, color) - biomePriority > colorDistance(blockColor, color);
} }
public int getBiomeMix(int[] biomeIdsOutput, int color) { protected int getBiomeMix(int[] biomeIdsOutput, int color) {
long closest = Long.MAX_VALUE; long closest = Long.MAX_VALUE;
int closestAverage = Integer.MAX_VALUE; int closestAverage = Integer.MAX_VALUE;
long min = Long.MAX_VALUE; long min = Long.MAX_VALUE;
int red1 = (color >> 16) & 0xFF; int red1 = (color >> 16) & 0xFF;
int green1 = (color >> 8) & 0xFF; int green1 = (color >> 8) & 0xFF;
int blue1 = (color >> 0) & 0xFF; int blue1 = (color) & 0xFF;
int alpha = (color >> 24) & 0xFF; int alpha = (color >> 24) & 0xFF;
for (int i = 0; i < validMixBiomeColors.length; i++) { for (int i = 0; i < validMixBiomeColors.length; i++) {
int other = validMixBiomeColors[i]; int other = validMixBiomeColors[i];
@ -556,12 +745,18 @@ public class TextureUtil implements TextureHolder {
} }
} }
} }
biomeIdsOutput[0] = (int) ((closest >> 0) & 0xFF); biomeIdsOutput[0] = (int) ((closest) & 0xFF);
biomeIdsOutput[1] = (int) ((closest >> 8) & 0xFF); biomeIdsOutput[1] = (int) ((closest >> 8) & 0xFF);
biomeIdsOutput[2] = (int) ((closest >> 16) & 0xFF); biomeIdsOutput[2] = (int) ((closest >> 16) & 0xFF);
return closestAverage; return closestAverage;
} }
/**
* Get the biome most closely matching a color based on the block's average color
*
* @param color color to match
* @return matching block
*/
public BiomeColor getNearestBiome(int color) { public BiomeColor getNearestBiome(int color) {
int grass = blockColors[BlockTypes.GRASS_BLOCK.getInternalId()]; int grass = blockColors[BlockTypes.GRASS_BLOCK.getInternalId()];
if (grass == 0) { if (grass == 0) {
@ -571,7 +766,7 @@ public class TextureUtil implements TextureHolder {
long min = Long.MAX_VALUE; long min = Long.MAX_VALUE;
int red = (color >> 16) & 0xFF; int red = (color >> 16) & 0xFF;
int green = (color >> 8) & 0xFF; int green = (color >> 8) & 0xFF;
int blue = (color >> 0) & 0xFF; int blue = (color) & 0xFF;
for (BiomeColor biome : validBiomes) { for (BiomeColor biome : validBiomes) {
long distance = colorDistance(red, green, blue, biome.grassCombined); long distance = colorDistance(red, green, blue, biome.grassCombined);
if (distance < min) { if (distance < min) {
@ -582,17 +777,10 @@ public class TextureUtil implements TextureHolder {
return closest; return closest;
} }
public File getFolder() { protected File getFolder() {
return folder; return folder;
} }
public long colorDistance(int c1, int c2) {
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
return colorDistance(red1, green1, blue1, c2);
}
private BufferedImage readImage(ZipFile zipFile, String name) throws IOException { private BufferedImage readImage(ZipFile zipFile, String name) throws IOException {
ZipEntry entry = getEntry(zipFile, name); ZipEntry entry = getEntry(zipFile, name);
if (entry != null) { if (entry != null) {
@ -619,56 +807,35 @@ public class TextureUtil implements TextureHolder {
if (folder.exists()) { if (folder.exists()) {
// Get all the jar files // Get all the jar files
File[] files = folder.listFiles((dir, name) -> name.endsWith(".jar")); File[] files = folder.listFiles((dir, name) -> name.endsWith(".jar"));
for (BlockType blockType : BlockTypesCache.values) {
BlockMaterial material = blockType.getMaterial();
if (!material.isSolid() || !material.isFullCube()) {
continue;
}
int color = material.getMapColor();
if (color != 0) {
colorMap.put(blockType.getInternalId(), (Integer) color);
}
}
if (files.length == 0) { if (files.length == 0) {
new File(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" + "/.minecraft/versions/") new File(Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/")
.mkdirs(); .mkdirs();
try (BufferedInputStream in = new BufferedInputStream( try (BufferedInputStream in = new BufferedInputStream(
new URL("https://launcher.mojang.com/v1/objects/8d9b65467c7913fcf6f5b2e729d44a1e00fde150/client.jar") new URL("https://launcher.mojang.com/v1/objects/8d9b65467c7913fcf6f5b2e729d44a1e00fde150/client.jar")
.openStream()); .openStream());
FileOutputStream fileOutputStream = new FileOutputStream( FileOutputStream fileOutputStream = new FileOutputStream(
Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/" Fawe.imp().getDirectory() + "/" + Settings.IMP.PATHS.TEXTURES + "/1.17.1.jar")) {
+ "/.minecraft/versions/1.17.1.jar")) {
byte[] dataBuffer = new byte[1024]; byte[] dataBuffer = new byte[1024];
int bytesRead; int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) { while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead); fileOutputStream.write(dataBuffer, 0, bytesRead);
} }
fileOutputStream.close();
files = folder.listFiles((dir, name) -> name.endsWith(".jar"));
} catch (IOException e) { } catch (IOException e) {
LOGGER.error( LOGGER.error(
"Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` folder with `.minecraft/versions` jar or mods in it."); "Could not download version jar. Please do so manually by creating a `FastAsyncWorldEdit/textures` " +
"folder with a `.minecraft/versions` jar or mods in it.");
LOGGER.error("If the file exists, please make sure the server has read access to the directory."); LOGGER.error("If the file exists, please make sure the server has read access to the directory.");
} }
} else { }
if ((files.length > 0)) {
for (File file : files) { for (File file : files) {
ZipFile zipFile = new ZipFile(file); ZipFile zipFile = new ZipFile(file);
// Get all the groups in the current jar // Get all the groups in the current jar
// The vanilla textures are in `assets/minecraft` // The vanilla textures are in `assets/minecraft`
// A jar may contain textures for multiple mods // A jar may contain textures for multiple mods
Enumeration<? extends ZipEntry> entries = zipFile.entries();
Set<String> mods = new HashSet<>();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
String name = entry.getName();
Path path = Paths.get(name);
if (path.startsWith("assets" + File.separator)) {
String[] split = path.toString().split(Pattern.quote(File.separator));
if (split.length > 1) {
String modId = split[1];
mods.add(modId);
}
}
}
String modelsDir = "assets/%1$s/models/block/%2$s.json"; String modelsDir = "assets/%1$s/models/block/%2$s.json";
String texturesDir = "assets/%1$s/textures/%2$s.png"; String texturesDir = "assets/%1$s/textures/%2$s.png";
@ -679,18 +846,24 @@ public class TextureUtil implements TextureHolder {
if (!blockType.getMaterial().isFullCube() || blockType.getId().toLowerCase().contains("shulker")) { if (!blockType.getMaterial().isFullCube() || blockType.getId().toLowerCase().contains("shulker")) {
continue; continue;
} }
switch (blockType.getId().toLowerCase(Locale.ROOT)) {
case "slime_block":
case "honey_block":
case "mob_spawner":
case "spawner":
continue;
}
int combined = blockType.getInternalId(); int combined = blockType.getInternalId();
String id = blockType.getId(); String id = blockType.getId();
String[] split = id.split(":", 2); String[] split = id.split(":", 2);
String name = split.length == 1 ? id : split[1]; String name = split.length == 1 ? id : split[1];
String nameSpace = split.length == 1 ? "" : split[0]; String nameSpace = split.length == 1 ? "" : split[0];
Map<String, String> texturesMap = new ConcurrentHashMap<>();
// Read models // Read models
String modelFileName = String.format(modelsDir, nameSpace, name); String modelFileName = String.format(modelsDir, nameSpace, name);
ZipEntry entry = getEntry(zipFile, modelFileName); ZipEntry entry = getEntry(zipFile, modelFileName);
if (entry == null) { if (entry == null) {
getLogger(TextureUtil.class).error("Cannot find {} in {}", modelFileName, file); LOGGER.error("Cannot find {} in {}", modelFileName, file);
continue; continue;
} }
@ -728,7 +901,7 @@ public class TextureUtil implements TextureHolder {
BufferedImage image = readImage(zipFile, textureFileName); BufferedImage image = readImage(zipFile, textureFileName);
if (image == null) { if (image == null) {
getLogger(TextureUtil.class).error("Cannot find {}", textureFileName); LOGGER.error("Cannot find {}", textureFileName);
continue; continue;
} }
int color = ImageUtil.getColor(image); int color = ImageUtil.getColor(image);
@ -738,15 +911,16 @@ public class TextureUtil implements TextureHolder {
} }
Integer grass = null; Integer grass = null;
{ {
String grassFileName = String.format(texturesDir, "minecraft", "grass_block_top"); String grassFileName = String.format(texturesDir, "minecraft", "block/grass_block_top");
BufferedImage image = readImage(zipFile, grassFileName); BufferedImage image = readImage(zipFile, grassFileName);
if (image != null) { if (image != null) {
grass = ImageUtil.getColor(image); grass = ImageUtil.getColor(image);
} }
} }
if (grass != null) { if (grass != null) {
colorMap.put(BlockTypes.GRASS_BLOCK.getInternalId(), grass);
// assets\minecraft\textures\colormap // assets\minecraft\textures\colormap
ZipEntry grassEntry = getEntry(zipFile, "assets/minecraft/textures/colormap/grass_block.png"); ZipEntry grassEntry = getEntry(zipFile, "assets/minecraft/textures/colormap/grass.png");
if (grassEntry != null) { if (grassEntry != null) {
try (InputStream is = zipFile.getInputStream(grassEntry)) { try (InputStream is = zipFile.getInputStream(grassEntry)) {
BufferedImage image = ImageIO.read(is); BufferedImage image = ImageIO.read(is);
@ -774,7 +948,7 @@ public class TextureUtil implements TextureHolder {
biomes[167].grass = 0x90814D + (255 << 24); biomes[167].grass = 0x90814D + (255 << 24);
List<BiomeColor> valid = new ArrayList<>(); List<BiomeColor> valid = new ArrayList<>();
for (BiomeColor biome : biomes) { for (BiomeColor biome : biomes) {
// biome.grass = multiplyColor(biome.grass, grass); //biome.grass = multiplyColor(biome.grass, grass);
if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) { if (biome.grass != 0 && !biome.name.equalsIgnoreCase("Unknown Biome")) {
valid.add(biome); valid.add(biome);
} }
@ -789,8 +963,6 @@ public class TextureUtil implements TextureHolder {
uniqueColors.add(color); uniqueColors.add(color);
} }
} }
int count = 0;
int count2 = 0;
uniqueBiomesColors.clear(); uniqueBiomesColors.clear();
LongArrayList layerIds = new LongArrayList(); LongArrayList layerIds = new LongArrayList();
@ -803,9 +975,8 @@ public class TextureUtil implements TextureHolder {
BiomeColor c3 = uniqueColors.get(k); BiomeColor c3 = uniqueColors.get(k);
int average = averageColor(c1.grass, c2.grass, c3.grass); int average = averageColor(c1.grass, c2.grass, c3.grass);
if (uniqueBiomesColors.add(average)) { if (uniqueBiomesColors.add(average)) {
count++;
layerColors.add(average); layerColors.add(average);
layerIds.add((c1.id) + (c2.id << 8) + (c3.id << 16)); layerIds.add((c1.id) + ((long) c2.id << 8) + ((long) c3.id << 16));
} }
} }
} }
@ -848,75 +1019,6 @@ public class TextureUtil implements TextureHolder {
calculateLayerArrays(); calculateLayerArrays();
} }
public int multiplyColor(int c1, int c2) {
int alpha1 = (c1 >> 24) & 0xFF;
int alpha2 = (c2 >> 24) & 0xFF;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2 >> 0) & 0xFF;
int red = ((red1 * red2)) / 255;
int green = ((green1 * green2)) / 255;
int blue = ((blue1 * blue2)) / 255;
int alpha = ((alpha1 * alpha2)) / 255;
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
}
public int averageColor(int c1, int c2) {
int alpha1 = (c1 >> 24) & 0xFF;
int alpha2 = (c2 >> 24) & 0xFF;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2 >> 0) & 0xFF;
int red = ((red1 + red2)) >> 1;
int green = ((green1 + green2)) >> 1;
int blue = ((blue1 + blue2)) >> 1;
int alpha = ((alpha1 + alpha2)) >> 1;
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
}
public int averageColor(int... colors) {
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
for (int c : colors) {
alpha += (c >> 24) & 0xFF;
red += (c >> 16) & 0xFF;
green += (c >> 8) & 0xFF;
blue += (c >> 0) & 0xFF;
}
int num = colors.length;
alpha /= num;
red /= num;
green /= num;
blue /= num;
return (alpha << 24) + (red << 16) + (green << 8) + (blue << 0);
}
/**
* Assumes the top layer is a transparent color and the bottom is opaque
*/
public int combineTransparency(int top, int bottom) {
int alpha1 = (top >> 24) & 0xFF;
int alpha2 = 255 - alpha1;
int red1 = (top >> 16) & 0xFF;
int green1 = (top >> 8) & 0xFF;
int blue1 = (top >> 0) & 0xFF;
int red2 = (bottom >> 16) & 0xFF;
int green2 = (bottom >> 8) & 0xFF;
int blue2 = (bottom >> 0) & 0xFF;
int red = ((red1 * alpha1) + (red2 * alpha2)) / 255;
int green = ((green1 * alpha1) + (green2 * alpha2)) / 255;
int blue = ((blue1 * alpha1) + (blue2 * alpha2)) / 255;
return (red << 16) + (green << 8) + (blue << 0) + (255 << 24);
}
protected void calculateLayerArrays() { protected void calculateLayerArrays() {
Int2ObjectOpenHashMap<int[]> colorLayerMap = new Int2ObjectOpenHashMap<>(); Int2ObjectOpenHashMap<int[]> colorLayerMap = new Int2ObjectOpenHashMap<>();
for (int i = 0; i < validBlockIds.length; i++) { for (int i = 0; i < validBlockIds.length; i++) {
@ -928,7 +1030,7 @@ public class TextureUtil implements TextureHolder {
if (!hasAlpha(colorOther)) { if (!hasAlpha(colorOther)) {
int combinedOther = validBlockIds[j]; int combinedOther = validBlockIds[j];
int combinedColor = combineTransparency(color, colorOther); int combinedColor = combineTransparency(color, colorOther);
colorLayerMap.put(combinedColor, new int[] {combined, combinedOther}); colorLayerMap.put(combinedColor, new int[]{combined, combinedOther});
} }
} }
} }
@ -956,7 +1058,7 @@ public class TextureUtil implements TextureHolder {
int closest = 0; int closest = 0;
int red1 = (color >> 16) & 0xFF; int red1 = (color >> 16) & 0xFF;
int green1 = (color >> 8) & 0xFF; int green1 = (color >> 8) & 0xFF;
int blue1 = (color >> 0) & 0xFF; int blue1 = (color) & 0xFF;
int alpha = (color >> 24) & 0xFF; int alpha = (color >> 24) & 0xFF;
int intensity1 = 2 * red1 + 4 * green1 + 3 * blue1; int intensity1 = 2 * red1 + 4 * green1 + 3 * blue1;
for (int i = 0; i < validColors.length; i++) { for (int i = 0; i < validColors.length; i++) {
@ -964,7 +1066,7 @@ public class TextureUtil implements TextureHolder {
if (other != color && ((other >> 24) & 0xFF) == alpha) { if (other != color && ((other >> 24) & 0xFF) == alpha) {
int red2 = (other >> 16) & 0xFF; int red2 = (other >> 16) & 0xFF;
int green2 = (other >> 8) & 0xFF; int green2 = (other >> 8) & 0xFF;
int blue2 = (other >> 0) & 0xFF; int blue2 = (other) & 0xFF;
int intensity2 = 2 * red2 + 4 * green2 + 3 * blue2; int intensity2 = 2 * red2 + 4 * green2 + 3 * blue2;
if (darker ? intensity2 >= intensity1 : intensity1 >= intensity2) { if (darker ? intensity2 >= intensity1 : intensity1 >= intensity2) {
continue; continue;
@ -1003,36 +1105,6 @@ public class TextureUtil implements TextureHolder {
return alpha != 255; return alpha != 255;
} }
protected long colorDistance(int red1, int green1, int blue1, int c2) {
int red2 = (c2 >> 16) & 0xFF;
int green2 = (c2 >> 8) & 0xFF;
int blue2 = (c2 >> 0) & 0xFF;
int rmean = (red1 + red2) >> 1;
int r = red1 - red2;
int g = green1 - green2;
int b = blue1 - blue2;
int hd = hueDistance(red1, green1, blue1, red2, green2, blue2);
return (((512 + rmean) * r * r) >> 8) + 4 * g * g + (((767 - rmean) * b * b) >> 8) + (hd * hd);
}
public long getDistance(BufferedImage image, int c1) {
long totalDistSqr = 0;
int width = image.getWidth();
int height = image.getHeight();
int area = width * height;
int red1 = (c1 >> 16) & 0xFF;
int green1 = (c1 >> 8) & 0xFF;
int blue1 = (c1 >> 0) & 0xFF;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int c2 = image.getRGB(x, y);
long distance = colorDistance(red1, green1, blue1, c2);
totalDistSqr += distance * distance;
}
}
return totalDistSqr / area;
}
public int[] getValidBlockIds() { public int[] getValidBlockIds() {
return validBlockIds.clone(); return validBlockIds.clone();
} }

Datei anzeigen

@ -350,7 +350,7 @@ public final class StringUtil {
*/ */
public static List<String> split(String input, char delimiter, char open, char close) { public static List<String> split(String input, char delimiter, char open, char close) {
if (input.indexOf(open) == -1 && input.indexOf(close) == -1) { if (input.indexOf(open) == -1 && input.indexOf(close) == -1) {
return Arrays.asList(input.split(String.valueOf(delimiter))); return Arrays.asList(input.split(String.valueOf(delimiter), -1));
} }
int level = 0; int level = 0;
int begin = 0; int begin = 0;
@ -366,7 +366,7 @@ public final class StringUtil {
level--; level--;
} }
} }
if (begin < input.length()) { if (begin <= input.length()) {
split.add(input.substring(begin)); split.add(input.substring(begin));
} }
return split; return split;

Datei anzeigen

@ -20,6 +20,7 @@
package com.sk89q.worldedit; package com.sk89q.worldedit;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -37,6 +38,7 @@ import com.sk89q.worldedit.extension.factory.BlockFactory;
import com.sk89q.worldedit.extension.factory.ItemFactory; import com.sk89q.worldedit.extension.factory.ItemFactory;
import com.sk89q.worldedit.extension.factory.MaskFactory; import com.sk89q.worldedit.extension.factory.MaskFactory;
import com.sk89q.worldedit.extension.factory.PatternFactory; import com.sk89q.worldedit.extension.factory.PatternFactory;
import com.fastasyncworldedit.core.extension.factory.TransformFactory;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extension.platform.Platform;
@ -138,6 +140,7 @@ public final class WorldEdit {
private final ItemFactory itemFactory = new ItemFactory(this); private final ItemFactory itemFactory = new ItemFactory(this);
private final MaskFactory maskFactory = new MaskFactory(this); private final MaskFactory maskFactory = new MaskFactory(this);
private final PatternFactory patternFactory = new PatternFactory(this); private final PatternFactory patternFactory = new PatternFactory(this);
private final TransformFactory transformFactory = new TransformFactory(this);
static { static {
getVersion(); getVersion();
@ -240,6 +243,16 @@ public final class WorldEdit {
return patternFactory; return patternFactory;
} }
/**
* Get the transform factory from which new {@link ResettableExtent}s
* can be constructed.
*
* @return the transform factory
*/
public TransformFactory getTransformFactory() {
return transformFactory;
}
/** /**
* Return the session manager. * Return the session manager.
* *

Datei anzeigen

@ -86,6 +86,18 @@ import static com.google.common.base.Preconditions.checkNotNull;
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class) @CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class GeneralCommands { public class GeneralCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public GeneralCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
public static void register( public static void register(
CommandRegistrationHandler registration, CommandRegistrationHandler registration,
CommandManager commandManager, CommandManager commandManager,
@ -149,18 +161,6 @@ public class GeneralCommands {
return CommandUtil.createNewCommandReplacementText("//perf " + flipped); return CommandUtil.createNewCommandReplacementText("//perf " + flipped);
} }
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public GeneralCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command( @Command(
name = "/limit", name = "/limit",
desc = "Modify block change limit" desc = "Modify block change limit"
@ -451,50 +451,6 @@ public class GeneralCommands {
); );
} }
private static class ItemSearcher implements Callable<Component> {
private final boolean blocksOnly;
private final boolean itemsOnly;
private final String search;
private final int page;
ItemSearcher(String search, boolean blocksOnly, boolean itemsOnly, int page) {
this.blocksOnly = blocksOnly;
this.itemsOnly = itemsOnly;
this.search = search;
this.page = page;
}
@Override
public Component call() throws Exception {
String command = "/searchitem " + (blocksOnly ? "-b " : "") + (itemsOnly ? "-i " : "") + "-p %page% " + search;
Map<String, Component> results = new TreeMap<>();
String idMatch = search.replace(' ', '_');
String nameMatch = search.toLowerCase(Locale.ROOT);
for (ItemType searchType : ItemType.REGISTRY) {
if (blocksOnly && !searchType.hasBlockType()) {
continue;
}
if (itemsOnly && searchType.hasBlockType()) {
continue;
}
final String id = searchType.getId();
if (id.contains(idMatch)) {
Component name = searchType.getRichName();
results.put(id, TextComponent.builder()
.append(name)
.append(" (" + id + ")")
.build());
}
}
List<Component> list = new ArrayList<>(results.values());
return PaginationBox.fromComponents("Search results for '" + search + "'", command, list)
.create(page);
}
}
//FAWE start //FAWE start
@Command( @Command(
name = "/gtexture", name = "/gtexture",
@ -592,15 +548,18 @@ public class GeneralCommands {
} }
} }
@Command( @Command(
name = "/gtransform", name = "/gtransform",
aliases = {"gtransform"}, aliases = {"gtransform"},
desc = "Set the global transform" desc = "Set the global transform"
) )
@CommandPermissions({"worldedit.global-transform", "worldedit.transform.global"}) @CommandPermissions({"worldedit.global-transform", "worldedit.transform.global"})
public void gtransform(Player player, EditSession editSession, LocalSession session, ResettableExtent transform) throws public void gtransform(
WorldEditException { Player player,
EditSession editSession,
LocalSession session,
@Arg(desc = "The transform to set", def = "") ResettableExtent transform
) throws WorldEditException {
session.setTransform(transform); session.setTransform(transform);
if (transform == null) { if (transform == null) {
player.print(Caption.of("fawe.worldedit.general.transform.disabled")); player.print(Caption.of("fawe.worldedit.general.transform.disabled"));
@ -648,5 +607,49 @@ public class GeneralCommands {
actor.print(Caption.of("worldedit.fast.enabled")); actor.print(Caption.of("worldedit.fast.enabled"));
} }
} }
private static class ItemSearcher implements Callable<Component> {
private final boolean blocksOnly;
private final boolean itemsOnly;
private final String search;
private final int page;
ItemSearcher(String search, boolean blocksOnly, boolean itemsOnly, int page) {
this.blocksOnly = blocksOnly;
this.itemsOnly = itemsOnly;
this.search = search;
this.page = page;
}
@Override
public Component call() throws Exception {
String command = "/searchitem " + (blocksOnly ? "-b " : "") + (itemsOnly ? "-i " : "") + "-p %page% " + search;
Map<String, Component> results = new TreeMap<>();
String idMatch = search.replace(' ', '_');
String nameMatch = search.toLowerCase(Locale.ROOT);
for (ItemType searchType : ItemType.REGISTRY) {
if (blocksOnly && !searchType.hasBlockType()) {
continue;
}
if (itemsOnly && searchType.hasBlockType()) {
continue;
}
final String id = searchType.getId();
if (id.contains(idMatch)) {
Component name = searchType.getRichName();
results.put(id, TextComponent.builder()
.append(name)
.append(" (" + id + ")")
.build());
}
}
List<Component> list = new ArrayList<>(results.values());
return PaginationBox.fromComponents("Search results for '" + search + "'", command, list)
.create(page);
}
}
//FAWE end //FAWE end
} }

Datei anzeigen

@ -23,6 +23,7 @@ import com.fastasyncworldedit.core.command.tool.TargetMode;
import com.fastasyncworldedit.core.command.tool.brush.BrushSettings; import com.fastasyncworldedit.core.command.tool.brush.BrushSettings;
import com.fastasyncworldedit.core.command.tool.scroll.Scroll; import com.fastasyncworldedit.core.command.tool.scroll.Scroll;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.StringMan; import com.fastasyncworldedit.core.util.StringMan;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
@ -360,33 +361,33 @@ public class ToolUtilCommands {
player.print(Caption.of("fawe.worldedit.brush.brush.source.mask")); player.print(Caption.of("fawe.worldedit.brush.brush.source.mask"));
} }
// TODO: Ping @MattBDev to reimplement 2020-02-04 @Command(
// @Command( name = "transform",
// name = "transform", aliases = {"/transform"},
// desc = "Set the brush transform" desc = "Set the brush transform"
// ) )
// @CommandPermissions({"worldedit.brush.options.transform", "worldedit.transform.brush"}) @CommandPermissions({"worldedit.brush.options.transform", "worldedit.transform.brush"})
// public void transform(Player player, LocalSession session, EditSession editSession, public void transform(Player player, LocalSession session, EditSession editSession,
// @Arg(desc = "The transform", def = "") ResettableExtent transform, @Arg(desc = "The transform", def = "") ResettableExtent transform,
// @Switch(name = 'h', desc = "Whether the offhand should be considered or not") @Switch(name = 'h', desc = "Whether the offhand should be considered or not")
// boolean offHand, boolean offHand,
// Arguments arguments) throws WorldEditException { Arguments arguments) throws WorldEditException {
// BrushTool tool = session.getBrushTool(player, false); BrushTool tool = session.getBrushTool(player, false);
// if (tool == null) { if (tool == null) {
// player.print(TranslatableComponent.of("fawe.worldedit.brush.brush.none")); player.print(Caption.of("fawe.worldedit.brush.brush.none"));
// return; return;
// } }
// if (transform == null) { if (transform == null) {
// player.print(TranslatableComponent.of("fawe.worldedit.brush.brush.transform.disabled")); player.print(Caption.of("fawe.worldedit.brush.brush.transform.disabled"));
// tool.setTransform(null); tool.setTransform(null);
// return; return;
// } }
// BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext(); BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
// String lastArg = Iterables.getLast(CommandArgParser.spaceSplit(arguments.get())).getSubstring(); String lastArg = Iterables.getLast(CommandArgParser.spaceSplit(arguments.get())).getSubstring();
// settings.addSetting(BrushSettings.SettingType.TRANSFORM, lastArg); settings.addSetting(BrushSettings.SettingType.TRANSFORM, lastArg);
// settings.setTransform(transform); settings.setTransform(transform);
// tool.update(); tool.update();
// player.print(TranslatableComponent.of("fawe.worldedit.brush.brush.transform")); player.print(Caption.of("fawe.worldedit.brush.brush.transform"));
// } }
//FAWE end //FAWE end
} }

Datei anzeigen

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command.argument; package com.sk89q.worldedit.command.argument;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.SupplyingExtent; import com.fastasyncworldedit.core.extent.SupplyingExtent;
import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
@ -54,6 +55,23 @@ import java.util.function.Function;
public class FactoryConverter<T> implements ArgumentConverter<T> { public class FactoryConverter<T> implements ArgumentConverter<T> {
private final WorldEdit worldEdit;
private final Function<WorldEdit, AbstractFactory<T>> factoryExtractor;
private final String description;
@Nullable
private final Consumer<ParserContext> contextTweaker;
private FactoryConverter(
WorldEdit worldEdit,
Function<WorldEdit, AbstractFactory<T>> factoryExtractor,
String description,
@Nullable Consumer<ParserContext> contextTweaker
) {
this.worldEdit = worldEdit;
this.factoryExtractor = factoryExtractor;
this.description = description;
this.contextTweaker = contextTweaker;
}
public static void register(WorldEdit worldEdit, CommandManager commandManager) { public static void register(WorldEdit worldEdit, CommandManager commandManager) {
commandManager.registerConverter( commandManager.registerConverter(
Key.of(Pattern.class), Key.of(Pattern.class),
@ -67,6 +85,10 @@ public class FactoryConverter<T> implements ArgumentConverter<T> {
Key.of(BaseItem.class), Key.of(BaseItem.class),
new FactoryConverter<>(worldEdit, WorldEdit::getItemFactory, "item", null) new FactoryConverter<>(worldEdit, WorldEdit::getItemFactory, "item", null)
); );
commandManager.registerConverter(
Key.of(ResettableExtent.class),
new FactoryConverter<>(worldEdit, WorldEdit::getTransformFactory, "transform", null)
);
commandManager.registerConverter( commandManager.registerConverter(
Key.of(Mask.class, ClipboardMask.class), Key.of(Mask.class, ClipboardMask.class),
@ -90,24 +112,6 @@ public class FactoryConverter<T> implements ArgumentConverter<T> {
); );
} }
private final WorldEdit worldEdit;
private final Function<WorldEdit, AbstractFactory<T>> factoryExtractor;
private final String description;
@Nullable
private final Consumer<ParserContext> contextTweaker;
private FactoryConverter(
WorldEdit worldEdit,
Function<WorldEdit, AbstractFactory<T>> factoryExtractor,
String description,
@Nullable Consumer<ParserContext> contextTweaker
) {
this.worldEdit = worldEdit;
this.factoryExtractor = factoryExtractor;
this.description = description;
this.contextTweaker = contextTweaker;
}
@Override @Override
public ConversionResult<T> convert(String argument, InjectedValueAccess context) { public ConversionResult<T> convert(String argument, InjectedValueAccess context) {
Actor actor = context.injectedValue(Key.of(Actor.class)) Actor actor = context.injectedValue(Key.of(Actor.class))

Datei anzeigen

@ -234,6 +234,27 @@ public final class SuggestionHelper {
return Stream.empty(); return Stream.empty();
} }
//FAWE start
/**
* Returns a stream of suggestions for booleans.
*
* @param argumentInput the given input to filter with.
* @return a stream of suggestions.
*/
public static Stream<String> suggestBoolean(String argumentInput) {
if (argumentInput.isEmpty()) {
return Stream.of("true", "false");
}
if ("true".startsWith(argumentInput)) {
return Stream.of("true");
} else if ("false".startsWith(argumentInput)) {
return Stream.of("false");
}
// no valid input anymore
return Stream.empty();
}
//FAWE end
private static boolean isDouble(String input) { private static boolean isDouble(String input) {
boolean point = false; boolean point = false;
for (char c : input.toCharArray()) { for (char c : input.toCharArray()) {

Datei anzeigen

@ -22,6 +22,7 @@ package com.sk89q.worldedit.extension.factory;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.mask.AdjacentMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.AdjacentMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.AngleMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.AngleMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.RichMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.ExtremaMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.ExtremaMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.FalseMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.FalseMaskParser;
import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParser; import com.fastasyncworldedit.core.extension.factory.parser.mask.LiquidMaskParser;
@ -71,6 +72,10 @@ import java.util.stream.Collectors;
*/ */
public final class MaskFactory extends AbstractFactory<Mask> { public final class MaskFactory extends AbstractFactory<Mask> {
//FAWE start - rich mask parsing
private final RichMaskParser richMaskParser;
//FAWE end
/** /**
* Create a new mask registry. * Create a new mask registry.
* *
@ -79,6 +84,10 @@ public final class MaskFactory extends AbstractFactory<Mask> {
public MaskFactory(WorldEdit worldEdit) { public MaskFactory(WorldEdit worldEdit) {
super(worldEdit, new BlocksMaskParser(worldEdit)); super(worldEdit, new BlocksMaskParser(worldEdit));
//FAWE start - rich mask parsing
richMaskParser = new RichMaskParser(worldEdit);
//FAWE end
register(new ExistingMaskParser(worldEdit)); register(new ExistingMaskParser(worldEdit));
register(new AirMaskParser(worldEdit)); register(new AirMaskParser(worldEdit));
register(new SolidMaskParser(worldEdit)); register(new SolidMaskParser(worldEdit));
@ -133,6 +142,25 @@ public final class MaskFactory extends AbstractFactory<Mask> {
continue; continue;
} }
//FAWE start - rich mask parsing
Mask match = richMaskParser.parseFromInput(component, context);
if (match != null) {
masks.add(match);
continue;
}
parseFromParsers(context, masks, component);
//FAWE end
}
return getMask(input, masks);
}
//FAWE start - rich mask parsing
private void parseFromParsers(
final ParserContext context,
final List<Mask> masks,
final String component
) {
Mask match = null; Mask match = null;
for (InputParser<Mask> parser : getParsers()) { for (InputParser<Mask> parser : getParsers()) {
match = parser.parseFromInput(component, context); match = parser.parseFromInput(component, context);
@ -147,6 +175,30 @@ public final class MaskFactory extends AbstractFactory<Mask> {
masks.add(match); masks.add(match);
} }
/**
* Parses a mask without considering parsing through the {@link RichMaskParser}, therefore not accepting
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
*
* @param input input string
* @param context input context
* @return parsed result
* @throws InputParseException if no result found
*/
public Mask parseWithoutRich(String input, ParserContext context) throws InputParseException {
List<Mask> masks = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
parseFromParsers(context, masks, component);
}
return getMask(input, masks);
}
private Mask getMask(final String input, final List<Mask> masks) {
switch (masks.size()) { switch (masks.size()) {
case 0: case 0:
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input))); throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
@ -156,5 +208,6 @@ public final class MaskFactory extends AbstractFactory<Mask> {
return new MaskIntersection(masks).optimize(); return new MaskIntersection(masks).optimize();
} }
} }
//FAWE end
} }

Datei anzeigen

@ -19,24 +19,56 @@
package com.sk89q.worldedit.extension.factory; package com.sk89q.worldedit.extension.factory;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AngleColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.AverageColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.BiomePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BufferedPattern2DParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.BufferedPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.BufferedPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ColorPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.DarkenPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.DesaturatePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExistingPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExistingPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.ExpressionPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.LightenPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear2DPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear2DPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear3DPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.Linear3DPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.LinearPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.MaskedPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.NoXPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.NoYPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.NoZPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.OffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.PerlinPatternParser; 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.RandomPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RandomPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RelativePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RichPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.RidgedMultiFractalPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.RidgedMultiFractalPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SaturatePatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SimplexPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.SimplexPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SolidRandomOffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.SurfaceRandomOffsetPatternParser;
import com.fastasyncworldedit.core.extension.factory.parser.pattern.VoronoiPatternParser; import com.fastasyncworldedit.core.extension.factory.parser.pattern.VoronoiPatternParser;
import com.fastasyncworldedit.core.math.random.TrueRandom;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.BlockCategoryPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.ClipboardPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.RandomStatePatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.SingleBlockPatternParser;
import com.sk89q.worldedit.extension.factory.parser.pattern.TypeOrStateApplyingPatternParser; import com.sk89q.worldedit.extension.factory.parser.pattern.TypeOrStateApplyingPatternParser;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.NoMatchException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.RandomPattern;
import com.sk89q.worldedit.internal.registry.AbstractFactory; import com.sk89q.worldedit.internal.registry.AbstractFactory;
import com.sk89q.worldedit.internal.registry.InputParser;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import java.util.ArrayList;
import java.util.List;
/** /**
* A registry of known {@link Pattern}s. Provides methods to instantiate * A registry of known {@link Pattern}s. Provides methods to instantiate
@ -47,6 +79,10 @@ import com.sk89q.worldedit.internal.registry.AbstractFactory;
*/ */
public final class PatternFactory extends AbstractFactory<Pattern> { public final class PatternFactory extends AbstractFactory<Pattern> {
//FAWE start - rich pattern parsing
private final RichPatternParser richPatternParser;
//FAWE end
/** /**
* Create a new instance. * Create a new instance.
* *
@ -55,6 +91,10 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
public PatternFactory(WorldEdit worldEdit) { public PatternFactory(WorldEdit worldEdit) {
super(worldEdit, new SingleBlockPatternParser(worldEdit)); super(worldEdit, new SingleBlockPatternParser(worldEdit));
//FAWE start - rich pattern parsing
richPatternParser = new RichPatternParser(worldEdit);
//FAWE end
// split and parse each sub-pattern // split and parse each sub-pattern
register(new RandomPatternParser(worldEdit)); register(new RandomPatternParser(worldEdit));
@ -65,16 +105,117 @@ public final class PatternFactory extends AbstractFactory<Pattern> {
register(new BlockCategoryPatternParser(worldEdit)); register(new BlockCategoryPatternParser(worldEdit));
//FAWE start //FAWE start
register(new SimplexPatternParser(worldEdit)); register(new AngleColorPatternParser(worldEdit));
register(new VoronoiPatternParser(worldEdit)); register(new AverageColorPatternParser(worldEdit));
register(new PerlinPatternParser(worldEdit));
register(new RidgedMultiFractalPatternParser(worldEdit));
register(new BiomePatternParser(worldEdit)); register(new BiomePatternParser(worldEdit));
register(new BufferedPatternParser(worldEdit));
register(new BufferedPattern2DParser(worldEdit));
register(new ColorPatternParser(worldEdit));
register(new DarkenPatternParser(worldEdit));
register(new DesaturatePatternParser(worldEdit));
register(new ExistingPatternParser(worldEdit));
register(new ExpressionPatternParser(worldEdit));
register(new LightenPatternParser(worldEdit));
register(new Linear2DPatternParser(worldEdit)); register(new Linear2DPatternParser(worldEdit));
register(new Linear3DPatternParser(worldEdit)); register(new Linear3DPatternParser(worldEdit));
register(new BufferedPatternParser(worldEdit)); register(new LinearPatternParser(worldEdit));
register(new ExistingPatternParser(worldEdit)); register(new MaskedPatternParser(worldEdit));
register(new NoXPatternParser(worldEdit));
register(new NoYPatternParser(worldEdit));
register(new NoZPatternParser(worldEdit));
register(new OffsetPatternParser(worldEdit));
register(new PerlinPatternParser(worldEdit));
register(new RandomFullClipboardPatternParser(worldEdit));
register(new RandomOffsetPatternParser(worldEdit));
register(new RelativePatternParser(worldEdit));
register(new RidgedMultiFractalPatternParser(worldEdit));
register(new SaturatePatternParser(worldEdit));
register(new SimplexPatternParser(worldEdit));
register(new SolidRandomOffsetPatternParser(worldEdit));
register(new SurfaceRandomOffsetPatternParser(worldEdit));
register(new VoronoiPatternParser(worldEdit));
//FAWE end //FAWE end
} }
@Override
public Pattern parseFromInput(String input, ParserContext context) throws InputParseException {
List<Pattern> patterns = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
//FAWE start - rich pattern parsing
Pattern match = richPatternParser.parseFromInput(component, context);
if (match != null) {
patterns.add(match);
continue;
}
parseFromParsers(context, patterns, component);
//FAWE end
}
return getPattern(input, patterns);
}
//FAWE start - rich pattern parsing
private void parseFromParsers(
final ParserContext context,
final List<Pattern> patterns,
final String component
) {
Pattern match = null;
for (InputParser<Pattern> parser : getParsers()) {
match = parser.parseFromInput(component, context);
if (match != null) {
break;
}
}
if (match == null) {
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(component)));
}
patterns.add(match);
}
/**
* Parses a pattern without considering parsing through the {@link RichPatternParser}, therefore not accepting
* "richer" parsing where & and , are used. Exists to prevent stack overflows.
*
* @param input input string
* @param context input context
* @return parsed result
* @throws InputParseException if no result found
*/
public Pattern parseWithoutRich(String input, ParserContext context) throws InputParseException {
List<Pattern> patterns = new ArrayList<>();
for (String component : input.split(" ")) {
if (component.isEmpty()) {
continue;
}
parseFromParsers(context, patterns, component);
}
return getPattern(input, patterns);
}
private Pattern getPattern(final String input, final List<Pattern> patterns) {
switch (patterns.size()) {
case 0:
throw new NoMatchException(Caption.of("worldedit.error.no-match", TextComponent.of(input)));
case 1:
return patterns.get(0);
default:
RandomPattern randomPattern = new RandomPattern(new TrueRandom());
for (Pattern pattern : patterns) {
randomPattern.add(pattern, 1d);
}
return randomPattern;
}
}
//FAWE end
} }

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen