From ccad0bced924aae7ad0bc3b909b51ec12518feb5 Mon Sep 17 00:00:00 2001 From: sauilitired Date: Tue, 18 Dec 2018 20:54:20 +0100 Subject: [PATCH 1/4] Progress. --- .../plotsquared/bukkit/BukkitMain.java | 11 ++- .../bukkit/util/BukkitBlockRegistry.java | 19 ++++ .../bukkit/util/LegacyMappings.java | 55 ++++++++++- .../plotsquared/plot/IPlotMain.java | 5 +- .../plot/object/BlockRegistry.java | 31 ++++++ .../plotsquared/plot/object/BlockWrapper.java | 40 ++++++++ .../plot/object/BlockWrapperFactory.java | 97 +++++++++++++++++++ .../plotsquared/plot/object/PlotBlock.java | 19 ++++ 8 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitBlockRegistry.java create mode 100644 Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java create mode 100644 Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java create mode 100644 Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java index e3535231b..e1be65cd6 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/BukkitMain.java @@ -19,6 +19,7 @@ import com.github.intellectualsites.plotsquared.bukkit.listeners.PlotPlusListene import com.github.intellectualsites.plotsquared.bukkit.listeners.SingleWorldListener; import com.github.intellectualsites.plotsquared.bukkit.listeners.WorldEvents; import com.github.intellectualsites.plotsquared.bukkit.titles.DefaultTitle_111; +import com.github.intellectualsites.plotsquared.bukkit.util.BukkitBlockRegistry; import com.github.intellectualsites.plotsquared.bukkit.util.BukkitChatManager; import com.github.intellectualsites.plotsquared.bukkit.util.BukkitChunkManager; import com.github.intellectualsites.plotsquared.bukkit.util.BukkitCommand; @@ -51,6 +52,7 @@ import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper; import com.github.intellectualsites.plotsquared.plot.generator.HybridGen; import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils; import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator; +import com.github.intellectualsites.plotsquared.plot.object.BlockRegistry; import com.github.intellectualsites.plotsquared.plot.object.Plot; import com.github.intellectualsites.plotsquared.plot.object.PlotArea; import com.github.intellectualsites.plotsquared.plot.object.PlotId; @@ -98,6 +100,7 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.command.PluginCommand; @@ -112,7 +115,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; -public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain { +public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain { @Getter private static WorldEdit worldEdit; private static Map pluginMap; @@ -168,6 +171,7 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain @Getter private SingleWorldListener singleWorldListener; private Method methodUnloadChunk0; private boolean methodUnloadSetup = false; + private final BlockRegistry blockRegistry = new BukkitBlockRegistry(Material.values()); @Override public int[] getServerVersion() { if (this.version == null) { @@ -920,4 +924,9 @@ public final class BukkitMain extends JavaPlugin implements Listener, IPlotMain } return names; } + + @Override + public BlockRegistry getBlockRegistry() { + return this.blockRegistry; + } } diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitBlockRegistry.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitBlockRegistry.java new file mode 100644 index 000000000..1d416f6bf --- /dev/null +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/BukkitBlockRegistry.java @@ -0,0 +1,19 @@ +package com.github.intellectualsites.plotsquared.bukkit.util; + +import com.github.intellectualsites.plotsquared.plot.object.BlockRegistry; +import com.github.intellectualsites.plotsquared.plot.object.PlotBlock; +import lombok.NonNull; +import org.bukkit.Material; + +public class BukkitBlockRegistry extends BlockRegistry { + + public BukkitBlockRegistry(final Material... preInitializedItems) { + super(Material.class, preInitializedItems); + } + + @Override + public PlotBlock getPlotBlock(@NonNull final Material item) { + return PlotBlock.get(item.name()); + } + +} diff --git a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/LegacyMappings.java b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/LegacyMappings.java index f23752d5a..b38ea9e0e 100644 --- a/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/LegacyMappings.java +++ b/Bukkit/src/main/java/com/github/intellectualsites/plotsquared/bukkit/util/LegacyMappings.java @@ -1,11 +1,15 @@ package com.github.intellectualsites.plotsquared.bukkit.util; -import lombok.*; -import org.bukkit.Material; - import java.util.HashMap; import java.util.Locale; import java.util.Map; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.ToString; +import org.bukkit.Material; /** * Borrowed from https://github.com/Phoenix616/IDConverter/blob/master/mappings/src/main/java/de/themoep/idconverter/IdMappings.java @@ -849,6 +853,51 @@ public class LegacyMappings { } } + /** + * Try to find a legacy plot block by any means possible. + * Strategy: + * - Check if the name contains a namespace, if so, strip it + * - Check if there's a (new) material matching the name + * - Check if there's a legacy material matching the name + * - Check if there's a numerical ID matching the name + * - Return null if everything else fails + * + * @param string String ID + * @return LegacyBlock if found, else null + */ + public static LegacyBlock fromAny(@NonNull final String string) { + String workingString = string; + String[] parts = null; + if (string.contains(":")) { + parts = string.split(":"); + if (parts.length > 1) { + if (parts[0].equalsIgnoreCase("minecraft")) { + workingString = parts[1]; + } else { + workingString = parts[0]; + } + } + } + LegacyBlock plotBlock = fromNewName(workingString); + if (plotBlock != null) { + return plotBlock; + } else if ((plotBlock = fromLegacyName(workingString)) != null) { + return plotBlock; + } else { + try { + if (parts != null && parts.length > 1) { + final int id = Integer.parseInt(parts[0]); + final int data = Integer.parseInt(parts[1]); + return fromIdAndData(id, data); + } else { + return fromLegacyId(Integer.parseInt(workingString)); + } + } catch (final Throwable exception) { + return null; + } + } + } + public static LegacyBlock fromLegacyId(final int id) { return NUMERICAL_MAP.get(id); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java index c797a76f3..972c7396f 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/IPlotMain.java @@ -4,6 +4,7 @@ import com.github.intellectualsites.plotsquared.plot.generator.GeneratorWrapper; import com.github.intellectualsites.plotsquared.plot.generator.HybridUtils; import com.github.intellectualsites.plotsquared.plot.generator.IndependentPlotGenerator; import com.github.intellectualsites.plotsquared.plot.logger.ILogger; +import com.github.intellectualsites.plotsquared.plot.object.BlockRegistry; import com.github.intellectualsites.plotsquared.plot.object.PlotPlayer; import com.github.intellectualsites.plotsquared.plot.util.*; import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider; @@ -11,7 +12,7 @@ import com.github.intellectualsites.plotsquared.plot.util.block.QueueProvider; import java.io.File; import java.util.List; -public interface IPlotMain extends ILogger { +public interface IPlotMain extends ILogger { /** * Log a message to console. @@ -272,4 +273,6 @@ public interface IPlotMain extends ILogger { AbstractTitle initTitleManager(); List getPluginIds(); + + BlockRegistry getBlockRegistry(); } diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java new file mode 100644 index 000000000..f8be06c45 --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java @@ -0,0 +1,31 @@ +package com.github.intellectualsites.plotsquared.plot.object; + +import java.util.HashMap; +import java.util.Map; +import lombok.Getter; +import lombok.NonNull; + +public abstract class BlockRegistry { + + @Getter + private final Class type; + private final Map map = new HashMap<>(); + + public BlockRegistry(@NonNull final Class type, final T... preInitializedItems) { + this.type = type; + } + + public final void addMapping(@NonNull final PlotBlock plotBlock, @NonNull final T t) { + if (map.containsKey(plotBlock)) { + return; + } + this.map.put(plotBlock, t); + } + + public abstract PlotBlock getPlotBlock(final T item); + + public final T getItem(final PlotBlock plotBlock) { + return this.map.get(plotBlock); + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java new file mode 100644 index 000000000..b63de816a --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java @@ -0,0 +1,40 @@ +package com.github.intellectualsites.plotsquared.plot.object; + +import java.util.Collections; +import java.util.Map; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.ToString; + +@ToString +@EqualsAndHashCode +@RequiredArgsConstructor +public final class BlockWrapper { + + @Getter + private final PlotBlock type; + private final Map blockStates; + + public T getState(@NonNull final Class stateType, @NonNull final Class valueType, @NonNull final T defaultValue) { + if (!blockStates.containsKey(stateType)) { + return defaultValue; + } + final Object rawValue = blockStates.get(stateType); + if (!rawValue.getClass().equals(valueType)) { + throw new ClassCastException(String.format("State type %s has a value of type %s but %s was requested", + stateType.getSimpleName(), rawValue.getClass().getSimpleName(), valueType.getSimpleName())); + } + return valueType.cast(rawValue); + } + + public void setState(@NonNull final Class stateType, @NonNull final T value) { + this.blockStates.put(stateType, value); + } + + public Map getAllStates() { + return Collections.unmodifiableMap(this.blockStates); + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java new file mode 100644 index 000000000..9e8ce873c --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java @@ -0,0 +1,97 @@ +package com.github.intellectualsites.plotsquared.plot.object; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +public final class BlockWrapperFactory { + + @RequiredArgsConstructor + public static final class StateEntry { + + @Getter + private final StateType stateType; + @Getter + private final ObjectType value; + + } + + public interface BlockStateDeserializer { + StateEntry deserialize(PlotBlock type, String serialized); + boolean isOfType(String serializedString); + } + + @FunctionalInterface + public interface BlockStateSerializer { + String serialize(PlotBlock type, StateEntry entry); + } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + public static final class StateSerializationMapping { + @Getter + private final StateType type; + @Getter + private final ObjectType objectType; + @Getter + private final BlockStateSerializer serializer; + @Getter + private final BlockStateDeserializer deserializer; + } + + private final Map stateSerializationMappings = new HashMap<>(); + + public StateSerializationMapping + addStateMapping(@NonNull final StateType type, @NonNull final ObjectType objectType, @NonNull final BlockStateSerializer serializer, @NonNull final BlockStateDeserializer deserializer) { + final StateSerializationMapping stateSerializationMapping = new StateSerializationMapping<>(type, objectType, serializer, deserializer); + this.stateSerializationMappings.put(type, stateSerializationMapping); + return stateSerializationMapping; + } + + public StateSerializationMapping + getStateMapping(@NonNull final StateType type) { + return this.stateSerializationMappings.get(type); + } + + public Collection serializeStates(@NonNull final BlockWrapper blockWrapper) { + final List serializedStates = new ArrayList<>(); + blockWrapper.getAllStates().entrySet().stream().map(entry -> new StateEntry(entry.getKey(), entry.getValue())) + .forEach(entry -> { + final StateSerializationMapping stateSerializationMapping = getStateMapping(entry.getStateType()); + final BlockStateSerializer blockStateSerializer = stateSerializationMapping.getSerializer(); + final String serialized = blockStateSerializer.serialize(blockWrapper.getType(), entry); + serializedStates.add(serialized); + }); + return serializedStates; + } + + public BlockStateDeserializer getDeserializerRaw(@NonNull final String serializedString) { + for (final StateSerializationMapping stateSerializationMapping : this.stateSerializationMappings.values()) { + if (stateSerializationMapping.getDeserializer().isOfType(serializedString)) { + return stateSerializationMapping.getDeserializer(); + } + } + return null; + } + + public Collection deserializeStates(@NonNull final PlotBlock plotBlock, @NonNull final Collection serializedStates) { + final Collection stateEntries = new ArrayList<>(serializedStates.size()); + for (final String serializedState : serializedStates) { + if (serializedState == null || serializedState.isEmpty()) { + continue; + } + final BlockStateDeserializer blockStateDeserializer = getDeserializerRaw(serializedState); + if (blockStateDeserializer == null) { + throw new IllegalStateException(String.format("No deserializer available for %s", serializedState)); + } + stateEntries.add(blockStateDeserializer.deserialize(plotBlock, serializedState)); + } + return stateEntries; + } + +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java index 17bbccc39..c73a0ccbb 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java @@ -1,5 +1,6 @@ package com.github.intellectualsites.plotsquared.plot.object; +import com.github.intellectualsites.plotsquared.plot.PlotSquared; import com.github.intellectualsites.plotsquared.plot.config.Settings; import lombok.NonNull; @@ -7,6 +8,9 @@ import java.util.Collection; public abstract class PlotBlock { + private static Class conversionType; + private static BlockRegistry blockRegistry; + public static boolean isEverything(@NonNull final PlotBlock block) { return block.equals(LegacyPlotBlock.EVERYTHING) || block.equals(StringPlotBlock.EVERYTHING); } @@ -56,6 +60,21 @@ public abstract class PlotBlock { return get(((LegacyPlotBlock) plotBlock).getId(), (byte) 0); } + public static PlotBlock get(@NonNull final Object type) { + if (blockRegistry == null) { + blockRegistry = PlotSquared.imp().getBlockRegistry(); + if (blockRegistry == null) { + throw new UnsupportedOperationException("The PlotSquared implementation has not registered a custom block registry." + + " This method can't be used."); + } + conversionType = blockRegistry.getType(); + } + if (!type.getClass().equals(blockRegistry.getClass())) { + throw new UnsupportedOperationException("The PlotSquared implementation has not registered a block registry for this object type"); + } + return blockRegistry.getPlotBlock(type); + } + public final boolean equalsAny(final int id, @NonNull final String stringId) { if (this instanceof StringPlotBlock) { final StringPlotBlock stringPlotBlock = (StringPlotBlock) this; From 10b87f572832cf3e379ce2ed037df05129658729 Mon Sep 17 00:00:00 2001 From: sauilitired Date: Tue, 18 Dec 2018 20:56:55 +0100 Subject: [PATCH 2/4] Add mappings for pre initialized items --- .../plotsquared/plot/object/BlockRegistry.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java index f8be06c45..49c6ab0b4 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockRegistry.java @@ -13,6 +13,9 @@ public abstract class BlockRegistry { public BlockRegistry(@NonNull final Class type, final T... preInitializedItems) { this.type = type; + for (final T preInitializedItem : preInitializedItems) { + this.addMapping(getPlotBlock(preInitializedItem), preInitializedItem); + } } public final void addMapping(@NonNull final PlotBlock plotBlock, @NonNull final T t) { From af9418552a6f1cd3f960e9413452085affcab083 Mon Sep 17 00:00:00 2001 From: sauilitired Date: Tue, 18 Dec 2018 20:58:52 +0100 Subject: [PATCH 3/4] Whoops. --- .../intellectualsites/plotsquared/plot/object/PlotBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java index c73a0ccbb..4599c0d14 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/PlotBlock.java @@ -69,7 +69,7 @@ public abstract class PlotBlock { } conversionType = blockRegistry.getType(); } - if (!type.getClass().equals(blockRegistry.getClass())) { + if (!type.getClass().equals(conversionType)) { throw new UnsupportedOperationException("The PlotSquared implementation has not registered a block registry for this object type"); } return blockRegistry.getPlotBlock(type); From 1d3270d8694b34dd9f7f7b84232681aebbd8e4a6 Mon Sep 17 00:00:00 2001 From: sauilitired Date: Wed, 19 Dec 2018 00:01:13 +0100 Subject: [PATCH 4/4] BlockBuckets r cool :cow: --- .../plotsquared/plot/config/C.java | 6 +- .../plotsquared/plot/object/BlockBucket.java | 154 ++++++++++++++++++ .../plotsquared/plot/object/BlockWrapper.java | 40 ----- .../plot/object/BlockWrapperFactory.java | 97 ----------- 4 files changed, 159 insertions(+), 138 deletions(-) create mode 100644 Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockBucket.java delete mode 100644 Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java delete mode 100644 Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/C.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/C.java index 7df62a6d0..517678835 100644 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/C.java +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/config/C.java @@ -831,7 +831,11 @@ public enum C { HELP_FOOTER("$3&m---------&r $1Plot\u00B2 Help $3&m---------", "Help"), HELP_INFO_ITEM("$1/plot help %category% $3- $2%category_desc%", "Help"), HELP_ITEM( - "$1%usage% [%alias%]&- $3- $2%desc%&-", "Help"), /* + "$1%usage% [%alias%]&- $3- $2%desc%&-", "Help"), + + BUCKET_ENTRIES_IGNORED("$2Total bucket values add up to 1 or more. Blocks without a spcified chance will be ignored", "Generator_Bucket"), + + /* * Direction */ diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockBucket.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockBucket.java new file mode 100644 index 000000000..49d921ad8 --- /dev/null +++ b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockBucket.java @@ -0,0 +1,154 @@ +package com.github.intellectualsites.plotsquared.plot.object; + +import com.github.intellectualsites.plotsquared.plot.config.C; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Random; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +/** + * A block bucket is a container of block types, where each block + * has a specified chance of being randomly picked + */ +@SuppressWarnings({"unused", "WeakerAccess"}) +public final class BlockBucket implements Iterable { + + private final Random random = new Random(); + private final Map ranges = new HashMap<>(); + private final Map blocks; + private final BucketIterator bucketIterator = new BucketIterator(); + private boolean compiled; + + public BlockBucket() { + this.blocks = new HashMap<>(); + } + + public void addBlock(@NonNull final PlotBlock block) { + this.addBlock(block, -1); + } + + public void addBlock(@NonNull final PlotBlock block, final int chance) { + this.blocks.put(block, chance); + this.compiled = false; + } + + public void compile() { + if (isCompiled()) { + return; + } + final Map temp = new HashMap<>(blocks.size()); + final List unassigned = new ArrayList<>(blocks.size()); + + int sum = 0; + for (final Map.Entry entry : blocks.entrySet()) { + if (entry.getValue() == -1) { + unassigned.add(entry.getKey()); + } else { + sum += entry.getValue(); + } + } + // + // If this doesn't amount to 100 add it up to exactly 100. + // + if (sum < 100) { + final int remaining = 100 - sum; + final int perUnassigned = remaining / unassigned.size(); + for (final PlotBlock block : unassigned) { + temp.put(block, perUnassigned); + sum += perUnassigned; + } + // Make sure there isn't a tiny difference remaining + if (sum < 100) { + final int difference = 100 - sum; + temp.put(unassigned.get(0), perUnassigned + difference); + sum = 100; + } + } else if (!unassigned.isEmpty()) { + C.BUCKET_ENTRIES_IGNORED.send(ConsolePlayer.getConsole()); + } + // + // If the sum adds up to more than 100, divide all values + // + if (sum > 100) { + final double ratio = 100D / sum; + for (final Map.Entry entry : blocks.entrySet()) { + if (entry.getValue() == -1) { + continue; + } + temp.put(entry.getKey(), (int)(entry.getValue() * ratio)); + } + } else { + temp.forEach(temp::put); + } + int start = 0; + for (final Map.Entry entry : temp.entrySet()) { + final int rangeStart = start; + final int rangeEnd = rangeStart + entry.getValue(); + start = rangeEnd + 1; + final Range range = new Range(rangeStart, rangeEnd); + this.ranges.put(range, entry.getKey()); + } + this.blocks.clear(); + this.compiled = true; + } + + @Override + public Iterator iterator() { + return this.bucketIterator; + } + + public boolean isCompiled() { + return this.compiled; + } + + /** + * Get a random block out of the bucket + * + * @return Randomly picked block (cased on specified rates) + */ + public PlotBlock getBlock() { + if (!isCompiled()) { + this.compile(); + } + final int number = random.nextInt(101); + for (final Map.Entry entry : ranges.entrySet()) { + if (entry.getKey().isInRange(number)) { + return entry.getValue(); + } + } + // Didn't find a block? Try again + return getBlock(); + } + + private final class BucketIterator implements Iterator { + + @Override + public boolean hasNext() { + return true; + } + + @Override + public PlotBlock next() { + return getBlock(); + } + } + + @Getter + @EqualsAndHashCode + @RequiredArgsConstructor + private final static class Range { + + private final int min; + private final int max; + + public boolean isInRange(final int num) { + return num <= max && num >= min; + } + } +} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java deleted file mode 100644 index b63de816a..000000000 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapper.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.github.intellectualsites.plotsquared.plot.object; - -import java.util.Collections; -import java.util.Map; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.ToString; - -@ToString -@EqualsAndHashCode -@RequiredArgsConstructor -public final class BlockWrapper { - - @Getter - private final PlotBlock type; - private final Map blockStates; - - public T getState(@NonNull final Class stateType, @NonNull final Class valueType, @NonNull final T defaultValue) { - if (!blockStates.containsKey(stateType)) { - return defaultValue; - } - final Object rawValue = blockStates.get(stateType); - if (!rawValue.getClass().equals(valueType)) { - throw new ClassCastException(String.format("State type %s has a value of type %s but %s was requested", - stateType.getSimpleName(), rawValue.getClass().getSimpleName(), valueType.getSimpleName())); - } - return valueType.cast(rawValue); - } - - public void setState(@NonNull final Class stateType, @NonNull final T value) { - this.blockStates.put(stateType, value); - } - - public Map getAllStates() { - return Collections.unmodifiableMap(this.blockStates); - } - -} diff --git a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java b/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java deleted file mode 100644 index 9e8ce873c..000000000 --- a/Core/src/main/java/com/github/intellectualsites/plotsquared/plot/object/BlockWrapperFactory.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.github.intellectualsites.plotsquared.plot.object; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -public final class BlockWrapperFactory { - - @RequiredArgsConstructor - public static final class StateEntry { - - @Getter - private final StateType stateType; - @Getter - private final ObjectType value; - - } - - public interface BlockStateDeserializer { - StateEntry deserialize(PlotBlock type, String serialized); - boolean isOfType(String serializedString); - } - - @FunctionalInterface - public interface BlockStateSerializer { - String serialize(PlotBlock type, StateEntry entry); - } - - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - public static final class StateSerializationMapping { - @Getter - private final StateType type; - @Getter - private final ObjectType objectType; - @Getter - private final BlockStateSerializer serializer; - @Getter - private final BlockStateDeserializer deserializer; - } - - private final Map stateSerializationMappings = new HashMap<>(); - - public StateSerializationMapping - addStateMapping(@NonNull final StateType type, @NonNull final ObjectType objectType, @NonNull final BlockStateSerializer serializer, @NonNull final BlockStateDeserializer deserializer) { - final StateSerializationMapping stateSerializationMapping = new StateSerializationMapping<>(type, objectType, serializer, deserializer); - this.stateSerializationMappings.put(type, stateSerializationMapping); - return stateSerializationMapping; - } - - public StateSerializationMapping - getStateMapping(@NonNull final StateType type) { - return this.stateSerializationMappings.get(type); - } - - public Collection serializeStates(@NonNull final BlockWrapper blockWrapper) { - final List serializedStates = new ArrayList<>(); - blockWrapper.getAllStates().entrySet().stream().map(entry -> new StateEntry(entry.getKey(), entry.getValue())) - .forEach(entry -> { - final StateSerializationMapping stateSerializationMapping = getStateMapping(entry.getStateType()); - final BlockStateSerializer blockStateSerializer = stateSerializationMapping.getSerializer(); - final String serialized = blockStateSerializer.serialize(blockWrapper.getType(), entry); - serializedStates.add(serialized); - }); - return serializedStates; - } - - public BlockStateDeserializer getDeserializerRaw(@NonNull final String serializedString) { - for (final StateSerializationMapping stateSerializationMapping : this.stateSerializationMappings.values()) { - if (stateSerializationMapping.getDeserializer().isOfType(serializedString)) { - return stateSerializationMapping.getDeserializer(); - } - } - return null; - } - - public Collection deserializeStates(@NonNull final PlotBlock plotBlock, @NonNull final Collection serializedStates) { - final Collection stateEntries = new ArrayList<>(serializedStates.size()); - for (final String serializedState : serializedStates) { - if (serializedState == null || serializedState.isEmpty()) { - continue; - } - final BlockStateDeserializer blockStateDeserializer = getDeserializerRaw(serializedState); - if (blockStateDeserializer == null) { - throw new IllegalStateException(String.format("No deserializer available for %s", serializedState)); - } - stateEntries.add(blockStateDeserializer.deserialize(plotBlock, serializedState)); - } - return stateEntries; - } - -}