From 76b4bb4857ead10acecbbeea8de85878595a3ab6 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Wed, 28 Sep 2016 22:48:20 +1000 Subject: [PATCH] I forgot to commit everything --- core/src/main/java/com/boydti/fawe/Fawe.java | 2 + .../fawe/object/pattern/MaskedPattern.java | 33 +++++ .../fawe/object/pattern/PatternExtent.java | 95 +++++++++++++ .../fawe/object/pattern/PatternTraverser.java | 12 +- .../object/pattern/RandomOffsetPattern.java | 33 +++++ .../extension/factory/DefaultMaskParser.java | 2 +- .../factory/HashTagPatternParser.java | 71 +++++++++- .../worldedit/session/request/Request.java | 132 ++++++++++++++++++ 8 files changed, 372 insertions(+), 8 deletions(-) create mode 100644 core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java create mode 100644 core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java create mode 100644 core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java create mode 100644 core/src/main/java/com/sk89q/worldedit/session/request/Request.java diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index 378a7d66..1003a933 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -76,6 +76,7 @@ import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.selector.CuboidRegionSelector; import com.sk89q.worldedit.session.SessionManager; +import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.world.registry.BundledBlockData; import java.io.File; @@ -336,6 +337,7 @@ public class Fawe { EditSessionEvent.inject(); // Add EditSession to event LocalSession.inject(); // Add remember order / queue flushing SessionManager.inject(); // Custom session saving + Request.inject(); // Custom pattern extent // Commands BrushCommands.inject(); // Translations + heightmap ToolCommands.inject(); // Translations + inspect diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java new file mode 100644 index 00000000..536bdff3 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java @@ -0,0 +1,33 @@ +package com.boydti.fawe.object.pattern; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.pattern.AbstractPattern; +import com.sk89q.worldedit.function.pattern.Pattern; +import java.util.Arrays; +import java.util.List; + +public class MaskedPattern extends AbstractPattern { + + private final PatternExtent patternExtent; + private final Pattern secondaryPattern; + private final List patterns; + private Mask mask; + + public MaskedPattern(Mask mask, PatternExtent primary, Pattern secondary) { + this.mask = mask; + this.patternExtent = primary; + this.secondaryPattern = secondary; + this.patterns = Arrays.asList(primary, secondary); + } + + + @Override + public BaseBlock apply(Vector position) { + if (mask.test(position)) { + return patternExtent.apply(position); + } + return secondaryPattern.apply(position); + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java b/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java new file mode 100644 index 00000000..9a6da188 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java @@ -0,0 +1,95 @@ +package com.boydti.fawe.object.pattern; + +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.operation.Operation; +import com.sk89q.worldedit.function.pattern.AbstractPattern; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.biome.BaseBiome; +import java.util.ArrayList; +import java.util.List; +import javax.annotation.Nullable; + +public class PatternExtent extends AbstractPattern implements Extent { + private final Pattern pattern; + private BaseBlock block; + + public PatternExtent(Pattern pattern) { + this.pattern = pattern; + } + + @Override + public Vector getMinimumPoint() { + return new Vector(Integer.MIN_VALUE,0,Integer.MIN_VALUE); + } + + @Override + public Vector getMaximumPoint() { + return new Vector(Integer.MAX_VALUE,255,Integer.MAX_VALUE); + } + + @Override + public List getEntities(Region region) { + return new ArrayList<>(); + } + + @Override + public List getEntities() { + return new ArrayList<>(); + } + + @Nullable + @Override + public Entity createEntity(Location location, BaseEntity entity) { + return null; + } + + @Override + public BaseBlock getBlock(Vector position) { + return block = pattern.apply(position); + } + + public BaseBlock getAndResetBlock() { + BaseBlock result = block; + block = null; + return result; + } + + @Override + public BaseBlock getLazyBlock(Vector position) { + return getBlock(position); + } + + @Override + public BaseBiome getBiome(Vector2D position) { + return new BaseBiome(0); + } + + @Override + public boolean setBlock(Vector position, BaseBlock block) throws WorldEditException { + return false; + } + + @Override + public boolean setBiome(Vector2D position, BaseBiome biome) { + return false; + } + + @Nullable + @Override + public Operation commit() { + return null; + } + + @Override + public BaseBlock apply(Vector position) { + return pattern.apply(position); + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/PatternTraverser.java b/core/src/main/java/com/boydti/fawe/object/pattern/PatternTraverser.java index 76a8fa6a..3d985177 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/PatternTraverser.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/PatternTraverser.java @@ -1,5 +1,6 @@ package com.boydti.fawe.object.pattern; +import com.boydti.fawe.object.mask.ResettableMask; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.Pattern; import java.lang.reflect.Field; @@ -23,6 +24,9 @@ public class PatternTraverser { if (pattern instanceof ResettablePattern) { ((ResettablePattern) pattern).reset(); } + if (pattern instanceof ResettableMask) { + ((ResettableMask) pattern).reset(); + } Class current = pattern.getClass(); while(current.getSuperclass() != null) { if (newExtent != null) { @@ -35,7 +39,13 @@ public class PatternTraverser { try { Field field = current.getDeclaredField("pattern"); field.setAccessible(true); - Pattern next = (Pattern) field.get(pattern); + Object next = field.get(pattern); + reset(next, newExtent); + } catch (NoSuchFieldException | IllegalAccessException ignore) {} + try { + Field field = current.getDeclaredField("mask"); + field.setAccessible(true); + Object next = field.get(pattern); reset(next, newExtent); } catch (NoSuchFieldException | IllegalAccessException ignore) {} try { diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java new file mode 100644 index 00000000..9ceb6b7c --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java @@ -0,0 +1,33 @@ +package com.boydti.fawe.object.pattern; + +import com.boydti.fawe.object.PseudoRandom; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.function.pattern.AbstractPattern; +import com.sk89q.worldedit.function.pattern.Pattern; + +public class RandomOffsetPattern extends AbstractPattern { + private final PseudoRandom r = new PseudoRandom(); + private final int dx, dy, dz, dx2, dy2, dz2; + private final Pattern pattern; + private final Vector mutable = new Vector(); + + public RandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) { + this.pattern = pattern; + this.dx = dx; + this.dy = dy; + this.dz = dz; + this.dx2 = dx * 2 + 1; + this.dy2 = dy * 2 + 1; + this.dz2 = dz * 2 + 1; + + } + + @Override + public BaseBlock apply(Vector position) { + mutable.x = position.x + r.nextInt(dx2) - dx; + mutable.y = position.y + r.nextInt(dy2) - dy; + mutable.z = position.z + r.nextInt(dz2) - dz; + return pattern.apply(mutable); + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java index 4ea5ce99..21b8c781 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/DefaultMaskParser.java @@ -97,7 +97,7 @@ public class DefaultMaskParser extends InputParser { } private Mask getBlockMaskComponent(List masks, String component, ParserContext context) throws InputParseException { - Extent extent = Request.request().getEditSession(); + Extent extent = Request.request().getExtent(); final char firstChar = component.charAt(0); switch (firstChar) { diff --git a/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java b/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java index 4287d7da..f5a4a1e8 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/factory/HashTagPatternParser.java @@ -3,9 +3,12 @@ package com.sk89q.worldedit.extension.factory; import com.boydti.fawe.object.pattern.ExistingPattern; 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.PatternExtent; +import com.boydti.fawe.object.pattern.RandomOffsetPattern; import com.boydti.fawe.object.pattern.RelativePattern; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.LocalSession; @@ -13,13 +16,16 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.input.ParserContext; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.BlockPattern; 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.registry.InputParser; import com.sk89q.worldedit.session.ClipboardHolder; +import com.sk89q.worldedit.session.request.Request; import java.util.ArrayList; +import java.util.List; public class HashTagPatternParser extends InputParser { @@ -27,6 +33,26 @@ public class HashTagPatternParser extends InputParser { super(worldEdit); } + private List split(String input, char delim) { + List result = new ArrayList(); + int start = 0; + boolean inQuotes = false; + for (int current = 0; current < input.length(); current++) { + if (input.charAt(current) == '\"') inQuotes = !inQuotes; // toggle state + boolean atLastChar = (current == input.length() - 1); + if(atLastChar) result.add(input.substring(start)); + else if (input.charAt(current) == delim && !inQuotes) { + String toAdd = input.substring(start, current); + if (toAdd.startsWith("\"")) { + toAdd = toAdd.substring(1, toAdd.length() - 1); + } + result.add(toAdd); + start = current + 1; + } + } + return result; + } + @Override public Pattern parseFromInput(String input, ParserContext context) throws InputParseException { switch (input.toLowerCase().charAt(0)) { @@ -77,10 +103,43 @@ public class HashTagPatternParser extends InputParser { case "#noz": { return new NoZPattern(parseFromInput(rest, context)); } + case "#mask": { + List split3 = split(rest, ':'); + if (split3.size() != 3) { + throw new InputParseException("The correct format is #mask:::"); + } + Pattern primary = parseFromInput(split3.get(1), context); + Pattern secondary = parseFromInput(split3.get(2), context); + PatternExtent extent = new PatternExtent(primary); + Request request = Request.request(); + request.setExtent(extent); + request.setSession(context.getSession()); + request.setWorld(context.getWorld()); + context.setExtent(extent); + MaskFactory factory = worldEdit.getMaskFactory(); + Mask mask = factory.parseFromInput(split3.get(0), context); + if (mask == null | primary == null || secondary == null) { + throw new InputParseException("The correct format is #mask:;; (null provided)"); + } + return new MaskedPattern(mask, extent, secondary); + } + case "#randomoffset": + case "#spread": { + try { + int x = Math.abs(Integer.parseInt(split2[1])); + int y = Math.abs(Integer.parseInt(split2[2])); + int z = Math.abs(Integer.parseInt(split2[3])); + rest = rest.substring(split2[1].length() + split2[2].length() + split2[3].length() + 3); + Pattern pattern = parseFromInput(rest, context); + return new RandomOffsetPattern(pattern, x, y, z); + } catch (NumberFormatException e) { + + } + } case "#l": case "#linear": { ArrayList patterns = new ArrayList<>(); - for (String token : rest.split(",")) { + for (String token : split(rest, ',')) { patterns.add(parseFromInput(token, context)); } if (patterns.isEmpty()) { @@ -91,7 +150,7 @@ public class HashTagPatternParser extends InputParser { case "#l3d": case "#linear3D": { ArrayList patterns = new ArrayList<>(); - for (String token : rest.split(",")) { + for (String token : split(rest, ',')) { patterns.add(parseFromInput(token, context)); } if (patterns.isEmpty()) { @@ -104,13 +163,13 @@ public class HashTagPatternParser extends InputParser { throw new InputParseException("Invalid, see: https://github.com/boy0001/FastAsyncWorldedit/wiki/WorldEdit-and-FAWE-patterns"); } default: - String[] items = input.split(","); - if (items.length == 1) { - return new BlockPattern(worldEdit.getBlockFactory().parseFromInput(items[0], context)); + List items = split(input, ','); + if (items.size() == 1) { + return new BlockPattern(worldEdit.getBlockFactory().parseFromInput(items.get(0), context)); } BlockFactory blockRegistry = worldEdit.getBlockFactory(); RandomPattern randomPattern = new RandomPattern(); - for (String token : input.split(",")) { + for (String token : items) { Pattern pattern; double chance; // Parse special percentage syntax diff --git a/core/src/main/java/com/sk89q/worldedit/session/request/Request.java b/core/src/main/java/com/sk89q/worldedit/session/request/Request.java new file mode 100644 index 00000000..afa81a49 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/session/request/Request.java @@ -0,0 +1,132 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.session.request; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.World; +import javax.annotation.Nullable; + +/** + * Describes the current request using a {@link ThreadLocal}. + */ +public final class Request { + + private static final ThreadLocal threadLocal = + new ThreadLocal() { + @Override protected Request initialValue() { + return new Request(); + } + }; + + private @Nullable World world; + private @Nullable LocalSession session; + private @Nullable EditSession editSession; + private @Nullable Extent extent; + + private Request() { + } + + /** + * Get the request world. + * + * @return the world, which may be null + */ + public @Nullable World getWorld() { + return world; + } + + /** + * Set the request world. + * + * @param world the world, which may be null + */ + public void setWorld(@Nullable World world) { + this.world = world; + } + + public void setExtent(@Nullable Extent extent) { + this.extent = extent; + } + + public @Nullable Extent getExtent() { + if (extent != null) return extent; + if (editSession != null) return editSession; + if (world != null) return world; + return null; + } + + /** + * Get the request session. + * + * @return the session, which may be null + */ + public @Nullable LocalSession getSession() { + return session; + } + + /** + * Get the request session. + * + * @param session the session, which may be null + */ + public void setSession(@Nullable LocalSession session) { + this.session = session; + } + + /** + * Get the {@link EditSession}. + * + * @return the edit session, which may be null + */ + public @Nullable EditSession getEditSession() { + return editSession; + } + + /** + * Set the {@link EditSession}. + * + * @param editSession the edit session, which may be null + */ + public void setEditSession(@Nullable EditSession editSession) { + this.editSession = editSession; + } + + /** + * Get the current request, which is specific to the current thread. + * + * @return the current request + */ + public static Request request() { + return threadLocal.get(); + } + + /** + * Reset the current request and clear all fields. + */ + public static void reset() { + threadLocal.remove(); + } + + public static Class inject() { + return Request.class; + } +}