diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java index 9f2becf76a..0ddd6ad49e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AngleColorPattern.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.core.function.pattern; import com.fastasyncworldedit.core.util.TextureHolder; +import com.fastasyncworldedit.core.util.TextureUtil; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.Pattern; @@ -13,7 +14,7 @@ public class AngleColorPattern extends AnglePattern { - protected transient TextureHolder holder; + protected transient TextureUtil util; /** * Create a new {@link Pattern} instance @@ -24,7 +25,20 @@ public class AngleColorPattern extends AnglePattern { */ public AngleColorPattern(Extent extent, TextureHolder holder, int distance) { super(extent, distance); - this.holder = holder.getTextureUtil(); + this.util = holder.getTextureUtil(); + } + + /** + * Create a new {@link Pattern} instance + * + * @param extent extent to set to + * @param distance distance to use to calculate angle + * @param util {@link TextureUtil} to use to get textures + * @since TODO + */ + private AngleColorPattern(Extent extent, int distance, TextureUtil util) { + super(extent, distance); + this.util = util; } private int getColor(int color, int slope) { @@ -66,15 +80,15 @@ public BaseBlock applyBlock(BlockVector3 position) { BlockType type = block.getBlockType(); int color; if (type == BlockTypes.GRASS_BLOCK) { - color = holder.getTextureUtil().getColor(extent.getBiome(position)); + color = util.getColor(extent.getBiome(position)); } else { - color = holder.getTextureUtil().getColor(type); + color = util.getColor(type); } if (color == 0) { return block; } int newColor = getColor(color, slope); - return holder.getTextureUtil().getNearestBlock(newColor).getDefaultState().toBaseBlock(); + return util.getNearestBlock(newColor).getDefaultState().toBaseBlock(); } @Override @@ -87,19 +101,24 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W BlockType type = block.getBlockType(); int color; if (type == BlockTypes.GRASS_BLOCK) { - color = holder.getTextureUtil().getColor(extent.getBiome(get)); + color = util.getColor(extent.getBiome(get)); } else { - color = holder.getTextureUtil().getColor(type); + color = util.getColor(type); } if (color == 0) { return false; } int newColor = getColor(color, slope); - BlockType newBlock = holder.getTextureUtil().getNearestBlock(newColor); + BlockType newBlock = util.getNearestBlock(newColor); if (newBlock == null) { return false; } return set.setBlock(extent, newBlock.getDefaultState()); } + @Override + public Pattern fork() { + return new AngleColorPattern(extent, distance, util.fork()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AverageColorPattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AverageColorPattern.java index af08889fa1..2107bbc0cf 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AverageColorPattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/AverageColorPattern.java @@ -15,7 +15,7 @@ public class AverageColorPattern extends AbstractExtentPattern { - private final transient TextureHolder holder; + private final transient TextureUtil util; private final int color; /** @@ -30,21 +30,34 @@ public class AverageColorPattern extends AbstractExtentPattern { */ public AverageColorPattern(Extent extent, TextureHolder holder, int r, int g, int b, int a) { super(extent); - this.holder = holder; + this.util = holder.getTextureUtil(); 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(); } + /** + * Create a new {@link Pattern} instance + * + * @param extent extent to set to + * @param util {@link TextureUtil} to use to get textures + * @param color color to saturate to + * @since TODO + */ + private AverageColorPattern(Extent extent, TextureUtil util, int color) { + super(extent); + this.util = util; + this.color = color; + } + @Override public BaseBlock applyBlock(BlockVector3 position) { BaseBlock block = getExtent().getFullBlock(position); - TextureUtil util = holder.getTextureUtil(); BlockType type = block.getBlockType(); int currentColor; if (type == BlockTypes.GRASS_BLOCK) { - currentColor = holder.getTextureUtil().getColor(getExtent().getBiome(position)); + currentColor = util.getColor(getExtent().getBiome(position)); } else { - currentColor = holder.getTextureUtil().getColor(type); + currentColor = util.getColor(type); } int newColor = TextureUtil.averageColor(currentColor, color); return util.getNearestBlock(newColor).getDefaultState().toBaseBlock(); @@ -53,12 +66,11 @@ public BaseBlock applyBlock(BlockVector3 position) { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { BlockType blockType = get.getBlock(extent).getBlockType(); - TextureUtil util = holder.getTextureUtil(); int currentColor; if (blockType == BlockTypes.GRASS_BLOCK) { - currentColor = holder.getTextureUtil().getColor(extent.getBiome(get)); + currentColor = util.getColor(extent.getBiome(get)); } else { - currentColor = holder.getTextureUtil().getColor(blockType); + currentColor = util.getColor(blockType); } if (currentColor == 0) { return false; @@ -71,4 +83,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W return set.setBlock(extent, newBlock.getDefaultState()); } + @Override + public Pattern fork() { + return new AverageColorPattern(getExtent(), util, color); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/DesaturatePattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/DesaturatePattern.java index 49eff45314..f573e32dcc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/DesaturatePattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/DesaturatePattern.java @@ -13,8 +13,8 @@ public class DesaturatePattern extends AbstractPattern { - private final TextureHolder holder; - private final Extent extent; + private final transient TextureUtil util; + private final transient Extent extent; private final double value; /** @@ -26,19 +26,32 @@ public class DesaturatePattern extends AbstractPattern { */ public DesaturatePattern(Extent extent, TextureHolder holder, double value) { this.extent = extent; - this.holder = holder; + this.util = holder.getTextureUtil(); + this.value = Math.max(0, Math.min(1, value)); + } + + /** + * Create a new {@link Pattern} instance + * + * @param extent extent to set to + * @param value decimal percent to desaturate by (0 -> 1) + * @param util {@link TextureUtil} to use for textures + * @since TODO + */ + private DesaturatePattern(Extent extent, double value, TextureUtil util) { + this.extent = extent; + this.util = util; this.value = Math.max(0, Math.min(1, value)); } @Override public BaseBlock applyBlock(BlockVector3 position) { BlockType type = extent.getBlock(position).getBlockType(); - TextureUtil util = holder.getTextureUtil(); int color; if (type == BlockTypes.GRASS_BLOCK) { - color = holder.getTextureUtil().getColor(extent.getBiome(position)); + color = util.getColor(extent.getBiome(position)); } else { - color = holder.getTextureUtil().getColor(type); + color = util.getColor(type); } return util.getNearestBlock(color).getDefaultState().toBaseBlock(); } @@ -58,12 +71,11 @@ private int getColor(int color) { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { BlockType type = get.getBlock(extent).getBlockType(); - TextureUtil util = holder.getTextureUtil(); int color; if (type == BlockTypes.GRASS_BLOCK) { - color = holder.getTextureUtil().getColor(extent.getBiome(get)); + color = util.getColor(extent.getBiome(get)); } else { - color = holder.getTextureUtil().getColor(type); + color = util.getColor(type); } int newColor = getColor(color); if (newColor == color) { @@ -76,4 +88,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W return set.setBlock(extent, newType.getDefaultState()); } + @Override + public Pattern fork() { + return new DesaturatePattern(extent, value, util); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SaturatePattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SaturatePattern.java index 0c42c814a1..9f3161dfc2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SaturatePattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/SaturatePattern.java @@ -16,9 +16,9 @@ public class SaturatePattern extends AbstractPattern { - private final TextureHolder holder; + private final transient TextureUtil util; + private final transient Extent extent; private final int color; - private final Extent extent; /** * Create a new {@link Pattern} instance @@ -32,20 +32,33 @@ public class SaturatePattern extends AbstractPattern { */ public SaturatePattern(Extent extent, TextureHolder holder, int r, int g, int b, int a) { this.extent = extent; - this.holder = holder; + this.util = holder.getTextureUtil(); 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(); } + /** + * Create a new {@link Pattern} instance + * + * @param extent extent to set to + * @param util {@link TextureUtil} to use to get textures + * @param color color to saturate to + * @since TODO + */ + private SaturatePattern(Extent extent, TextureUtil util, int color) { + this.extent = extent; + this.util = util; + this.color = color; + } + @Override public BaseBlock applyBlock(BlockVector3 position) { BlockType type = extent.getBlock(position).getBlockType(); - TextureUtil util = holder.getTextureUtil(); int currentColor; if (type == BlockTypes.GRASS_BLOCK) { - currentColor = holder.getTextureUtil().getColor(extent.getBiome(position)); + currentColor = util.getColor(extent.getBiome(position)); } else { - currentColor = holder.getTextureUtil().getColor(type); + currentColor = util.getColor(type); } int newColor = TextureUtil.multiplyColor(currentColor, color); return util.getNearestBlock(newColor).getDefaultState().toBaseBlock(); @@ -54,12 +67,11 @@ public BaseBlock applyBlock(BlockVector3 position) { @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { BlockType type = get.getBlock(extent).getBlockType(); - TextureUtil util = holder.getTextureUtil(); int currentColor; if (type == BlockTypes.GRASS_BLOCK) { - currentColor = holder.getTextureUtil().getColor(extent.getBiome(get)); + currentColor = util.getColor(extent.getBiome(get)); } else { - currentColor = holder.getTextureUtil().getColor(type); + currentColor = util.getColor(type); } if (currentColor == 0) { return false; @@ -72,4 +84,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W return set.setBlock(extent, newBlock.getDefaultState()); } + @Override + public Pattern fork() { + return new SaturatePattern(extent, util.fork(), color); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ShadePattern.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ShadePattern.java index 386de836b8..f141ba6fdd 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ShadePattern.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/function/pattern/ShadePattern.java @@ -15,8 +15,8 @@ public class ShadePattern extends AbstractPattern { - private final TextureUtil util; - private final Extent extent; + private final transient TextureUtil util; + private final transient Extent extent; private final boolean darken; /** @@ -33,6 +33,21 @@ public ShadePattern(Extent extent, TextureHolder holder, boolean darken) { this.darken = darken; } + /** + * Create a new {@link Pattern} instance + * + * @param extent extent to set to + * @param darken if the shade should darken or lighten colours + * @param util {@link TextureUtil} to use for textures + * @since TODO + */ + private ShadePattern(Extent extent, boolean darken, TextureUtil util) { + checkNotNull(extent); + this.extent = extent; + this.util = util; + this.darken = darken; + } + @Override public BaseBlock applyBlock(BlockVector3 position) { BlockType block = extent.getBlock(position).getBlockType(); @@ -62,4 +77,9 @@ public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws W return false; } + @Override + public Pattern fork() { + return new ShadePattern(extent, darken, util.fork()); + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/CachedTextureUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/CachedTextureUtil.java index bafe8d7830..f0ef2d8f18 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/CachedTextureUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/CachedTextureUtil.java @@ -7,17 +7,50 @@ public class CachedTextureUtil extends DelegateTextureUtil { - private final TextureUtil parent; - private final transient Int2ObjectOpenHashMap colorBlockMap; - private final transient Int2ObjectOpenHashMap colorBiomeMap; - private final transient Int2ObjectOpenHashMap colorLayerMap; + protected final TextureUtil parent; + protected final transient Int2ObjectOpenHashMap colorBlockMap; + protected final transient Int2ObjectOpenHashMap colorBiomeMap; + protected final transient Int2ObjectOpenHashMap colorLayerMap; public CachedTextureUtil(TextureUtil parent) throws FileNotFoundException { super(parent); this.parent = parent; this.colorBlockMap = new Int2ObjectOpenHashMap<>(); - this.colorLayerMap = new Int2ObjectOpenHashMap<>(); this.colorBiomeMap = new Int2ObjectOpenHashMap<>(); + this.colorLayerMap = new Int2ObjectOpenHashMap<>(); + } + + /** + * Create a new instance + * + * @param parent parent {@link TextureUtil} + * @param colorBlockMap color block map to (copy and) use + * @param colorBiomeMap color biome map to (copy and) use + * @param colorLayerMap color layer map to (copy and) use + * @throws FileNotFoundException + * @since TODO + */ + protected CachedTextureUtil( + TextureUtil parent, + Int2ObjectOpenHashMap colorBlockMap, + Int2ObjectOpenHashMap colorBiomeMap, + Int2ObjectOpenHashMap colorLayerMap + ) throws FileNotFoundException { + super(parent); + this.parent = parent; + this.colorBlockMap = new Int2ObjectOpenHashMap<>(colorBlockMap); + this.colorBiomeMap = new Int2ObjectOpenHashMap<>(colorBiomeMap); + this.colorLayerMap = new Int2ObjectOpenHashMap<>(colorLayerMap); + } + + @Override + public TextureUtil fork() { + try { + return new CachedTextureUtil(parent.fork(), colorBlockMap, colorBiomeMap, colorLayerMap); + } catch (FileNotFoundException e) { + // This should never happen + throw new RuntimeException(e); + } } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/DelegateTextureUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/DelegateTextureUtil.java index 23fc05f4d5..bc56b91e75 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/DelegateTextureUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/DelegateTextureUtil.java @@ -17,6 +17,16 @@ public DelegateTextureUtil(TextureUtil parent) throws FileNotFoundException { this.parent = parent; } + @Override + public TextureUtil fork() { + try { + return new DelegateTextureUtil(parent.fork()); + } catch (FileNotFoundException e) { + // This should never happen + throw new RuntimeException(e); + } + } + @Override public BlockType getNearestBlock(int color) { return parent.getNearestBlock(color); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/RandomTextureUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/RandomTextureUtil.java index 2d313ecddc..3affdec7ea 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/RandomTextureUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/RandomTextureUtil.java @@ -8,15 +8,45 @@ public class RandomTextureUtil extends CachedTextureUtil { - public RandomTextureUtil(TextureUtil parent) throws FileNotFoundException { - super(parent); - } - private int index; private final int[] biomeMixBuffer = new int[3]; private final Int2ObjectOpenHashMap offsets = new Int2ObjectOpenHashMap<>(); private final Int2ObjectOpenHashMap biomeMixes = new Int2ObjectOpenHashMap<>(); + public RandomTextureUtil(TextureUtil parent) throws FileNotFoundException { + super(parent); + } + + /** + * Create a new instance + * + * @param parent parent {@link TextureUtil} + * @param colorBlockMap color block map to (copy and) use + * @param colorBiomeMap color biome map to (copy and) use + * @param colorLayerMap color layer map to (copy and) use + * @throws FileNotFoundException + * @since TODO + */ + private RandomTextureUtil( + TextureUtil parent, + Int2ObjectOpenHashMap colorBlockMap, + Int2ObjectOpenHashMap colorBiomeMap, + Int2ObjectOpenHashMap colorLayerMap + ) throws FileNotFoundException { + super(parent, colorBlockMap, colorBiomeMap, colorLayerMap); + } + + @Override + public TextureUtil fork() { + try { + // I don't think we should copy the "randomness" from this existing pattern? + return new RandomTextureUtil(parent, colorBlockMap, colorBiomeMap, colorLayerMap); + } catch (FileNotFoundException e) { + // This should never happen + throw new RuntimeException(e); + } + } + protected int addRandomColor(int c1, int c2) { int red1 = (c1 >> 16) & 0xFF; int green1 = (c1 >> 8) & 0xFF; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java index 2c140d86a2..a6a873c96f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TextureUtil.java @@ -333,7 +333,6 @@ public class TextureUtil implements TextureHolder { new BiomeColor(255, "Unknown Biome", 0.8f, 0.4f, 0x92BD59, 0x77AB2F)}; private static final String VERSION_MANIFEST = "https://piston-meta.mojang.com/mc/game/version_manifest.json"; - private final BlockType[] layerBuffer = new BlockType[2]; protected int[] blockColors = new int[BlockTypes.size()]; protected long[] blockDistance = new long[BlockTypes.size()]; protected long[] distances; @@ -658,6 +657,17 @@ public TextureUtil getTextureUtil() { return this; } + /** + * Create a copy of this {@link TextureUtil} instance if required for thread safety. + * + * @return either this {@link TextureUtil} instance if thread safe or a new copied instance. + * @since TODO + */ + public TextureUtil fork() { + // Default implementation should be thread safe (only array lookups) + return this; + } + /** * Get the block most closely matching a color based on the block's average color * @@ -736,9 +746,10 @@ public BlockType[] getNearestLayer(int color) { } } } - layerBuffer[0] = BlockTypesCache.values[closest[0]]; - layerBuffer[1] = BlockTypesCache.values[closest[1]]; - return layerBuffer; + BlockType[] result = new BlockType[2]; + result[0] = BlockTypesCache.values[closest[0]]; + result[1] = BlockTypesCache.values[closest[1]]; + return result; } /**