diff --git a/src/main/java/com/gtnewhorizon/structurelib/ClientProxy.java b/src/main/java/com/gtnewhorizon/structurelib/ClientProxy.java index 088faab8..3ff4af93 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/ClientProxy.java +++ b/src/main/java/com/gtnewhorizon/structurelib/ClientProxy.java @@ -2,10 +2,12 @@ package com.gtnewhorizon.structurelib; import static com.gtnewhorizon.structurelib.StructureLib.RANDOM; +import java.lang.ref.WeakReference; import java.util.*; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityClientPlayerMP; import net.minecraft.client.gui.GuiNewChat; import net.minecraft.client.particle.EntityFX; import net.minecraft.client.renderer.Tessellator; @@ -23,18 +25,25 @@ import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.entity.EntityJoinWorldEvent; import net.minecraftforge.event.world.WorldEvent; +import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.opengl.GL11; import com.gtnewhorizon.structurelib.entity.fx.WeightlessParticleFX; +import com.gtnewhorizon.structurelib.net.RegistryOrderSyncMessage; import com.gtnewhorizon.structurelib.net.SetChannelDataMessage; +import cpw.mods.fml.client.event.ConfigChangedEvent; import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.event.FMLLoadCompleteEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.eventhandler.EventPriority; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent; import cpw.mods.fml.common.gameevent.TickEvent.Phase; +import cpw.mods.fml.common.network.FMLNetworkEvent; public class ClientProxy extends CommonProxy { @@ -239,6 +248,7 @@ public class ClientProxy extends CommonProxy { public void preInit(FMLPreInitializationEvent e) { FMLCommonHandler.instance().bus().register(new FMLEventHandler()); MinecraftForge.EVENT_BUS.register(new ForgeEventHandler()); + DebugHelper.addDebug(); } static void markTextureUsed(IIcon icon) { @@ -246,6 +256,31 @@ public class ClientProxy extends CommonProxy { ((IStructureCompat) StructureLib.COMPAT).markTextureUsed(icon); } + static void sendRegistryOrderToServer() { + if (FMLEventHandler.configSent) return; + FMLEventHandler.configSent = true; + for (String s : SortedRegistry.ALL_REGISTRIES.keySet()) { + Pair, List> registryOrder = ConfigurationHandler.INSTANCE.getRegistryOrder(s); + if (registryOrder == null || registryOrder.getKey().isEmpty() && registryOrder.getValue().isEmpty()) continue; + StructureLib.net.sendToServer(new RegistryOrderSyncMessage(s, registryOrder.getKey(), registryOrder.getValue())); + } + } + + @Override + public void loadComplete(FMLLoadCompleteEvent evt) { + super.loadComplete(evt); + for (Map.Entry>> e : SortedRegistry.ALL_REGISTRIES.entrySet()) { + SortedRegistry r = e.getValue().get(); + if (r == null) continue; + Pair, List> p = ConfigurationHandler.INSTANCE.getRegistryOrder(e.getKey()); + r.registerOrdering(getSPPlayerUUID(), p.getKey(), p.getValue()); + } + } + + public UUID getSPPlayerUUID() { + return EntityPlayer.func_146094_a(Minecraft.getMinecraft().getSession().func_148256_e()); + } + private static class HintGroup { private final List hints = new LinkedList<>(); @@ -434,12 +469,34 @@ public class ClientProxy extends CommonProxy { public static class FMLEventHandler { + static boolean connected = false; + static boolean configSent = false; + private void resetPlayerLocation() { lastPlayerPos.xCoord = Minecraft.getMinecraft().thePlayer.posX; lastPlayerPos.yCoord = Minecraft.getMinecraft().thePlayer.posY; lastPlayerPos.zCoord = Minecraft.getMinecraft().thePlayer.posZ; } + @SubscribeEvent + public void onPlayerLogIn(FMLNetworkEvent.ClientConnectedToServerEvent e) { + connected = true; + configSent = false; + } + + @SubscribeEvent + public void onPlayerLogOut(FMLNetworkEvent.ClientDisconnectionFromServerEvent e) { + connected = false; + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public void onConfigChange(ConfigChangedEvent.PostConfigChangedEvent e) { + if (connected && e.modID.equals(StructureLibAPI.MOD_ID)) { + configSent = false; + sendRegistryOrderToServer(); + } + } + @SubscribeEvent public void onClientTick(ClientTickEvent e) { if (e.phase == Phase.END && Minecraft.getMinecraft().thePlayer != null) { @@ -483,6 +540,13 @@ public class ClientProxy extends CommonProxy { public static class ForgeEventHandler { + @SubscribeEvent + public void onEntityJoinWorld(EntityJoinWorldEvent e) { + if (e.world.isRemote && e.entity instanceof EntityClientPlayerMP) { + sendRegistryOrderToServer(); + } + } + @SubscribeEvent public void onWorldLoad(WorldEvent.Load e) { if (e.world.isRemote) { diff --git a/src/main/java/com/gtnewhorizon/structurelib/CommonProxy.java b/src/main/java/com/gtnewhorizon/structurelib/CommonProxy.java index 6f542b55..3759da0e 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/CommonProxy.java +++ b/src/main/java/com/gtnewhorizon/structurelib/CommonProxy.java @@ -15,7 +15,7 @@ import net.minecraft.world.World; import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage; import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage; - +import cpw.mods.fml.common.event.FMLLoadCompleteEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; public class CommonProxy { @@ -70,6 +70,10 @@ public class CommonProxy { } } + public void loadComplete(FMLLoadCompleteEvent e) { + ConfigurationHandler.INSTANCE.loadRegistryOrder(); + } + private final Map> throttleMap = new WeakHashMap<>(); public void addThrottledChat(Object throttleKey, EntityPlayer player, IChatComponent text, short intervalRequired, diff --git a/src/main/java/com/gtnewhorizon/structurelib/ConfigurationHandler.java b/src/main/java/com/gtnewhorizon/structurelib/ConfigurationHandler.java index e96b5aad..5fa1d03c 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/ConfigurationHandler.java +++ b/src/main/java/com/gtnewhorizon/structurelib/ConfigurationHandler.java @@ -1,15 +1,24 @@ package com.gtnewhorizon.structurelib; import java.io.File; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; import java.util.Map; import net.minecraftforge.common.config.ConfigCategory; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + import cpw.mods.fml.client.event.ConfigChangedEvent; import cpw.mods.fml.common.FMLCommonHandler; import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import org.apache.commons.lang3.tuple.Pair; public enum ConfigurationHandler { @@ -22,6 +31,7 @@ public enum ConfigurationHandler { private int hintTransparency; private int autoPlaceBudget; private int autoPlaceInterval; + private Map, List>> registryOrders; ConfigurationHandler() { FMLCommonHandler.instance().bus().register(this); @@ -86,8 +96,36 @@ public enum ConfigurationHandler { + "Note this relates to the wall clock, not in game ticks.\n" + "Value smaller than default is likely to be perceived as no minimal interval whatsoever."); + loadRegistryOrder(); + + saveConfig(); + } + + void loadRegistryOrder() { + registryOrders = new HashMap<>(); + for (Map.Entry>> e : SortedRegistry.ALL_REGISTRIES.entrySet()) { + SortedRegistry r = e.getValue().get(); + if (r == null) continue; + Property pOrder = config + .get("registries." + e.getKey(), "ordering", Iterables.toArray(r.getCurrentOrdering(), String.class), "stuff not in this list will be automatically available after all entries listed here in their natural order, unless explicitly disabled in disabled config below."); + Property pDisable = config.get("registries." + e.getKey(), "disabled", new String[0], "stuff in this list will be disabled"); + List all = Lists.newArrayList(r.getCurrentOrdering()); + List curVal = new ArrayList<>(Arrays.asList(pOrder.getStringList())); + List disabled = new ArrayList<>(Arrays.asList(pDisable.getStringList())); + curVal.removeAll(disabled); + all.removeAll(disabled); + curVal.removeIf(s -> !all.remove(s)); + curVal.addAll(all); + pOrder.set(curVal.toArray(new String[0])); + registryOrders.put(e.getKey(), Pair.of(curVal, disabled)); + } + saveConfig(); + } + + private void saveConfig() { if (config.hasChanged()) { config.save(); + config.load(); } } @@ -122,6 +160,10 @@ public enum ConfigurationHandler { return autoPlaceInterval; } + public Pair, List> getRegistryOrder(String name) { + return registryOrders.get(name); + } + Configuration getConfig() { return config; } diff --git a/src/main/java/com/gtnewhorizon/structurelib/SortedRegistry.java b/src/main/java/com/gtnewhorizon/structurelib/SortedRegistry.java new file mode 100644 index 00000000..6ad47919 --- /dev/null +++ b/src/main/java/com/gtnewhorizon/structurelib/SortedRegistry.java @@ -0,0 +1,151 @@ +package com.gtnewhorizon.structurelib; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.NavigableMap; +import java.util.Spliterator; +import java.util.TreeMap; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Consumer; + +import javax.annotation.Nullable; + +import net.minecraft.entity.player.EntityPlayerMP; + +import com.gtnewhorizon.structurelib.net.RegistryOrderSyncMessage; + +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; +import org.apache.commons.lang3.tuple.Pair; + +public class SortedRegistry implements Iterable { + + static final ConcurrentHashMap>> ALL_REGISTRIES = new ConcurrentHashMap<>(); + static { + RegistryOrderSyncMessage.Handler.setAllRegistries(ALL_REGISTRIES); + } + private final NavigableMap store = new TreeMap<>(); + /** + * Store stuff in an array for faster iteration access than a red black tree + */ + private List baked = Collections.emptyList(); + + private final Map, List>> playerOrdering = new HashMap<>(); + private final Map> playerBaked = new HashMap<>(); + + /** + * Construct an unsynchronized registry + */ + public SortedRegistry() { + } + + /** + * Construct a synchronized registry whose ordering will be synced to the server + * + * @param name network name + */ + + public SortedRegistry(String name) { + WeakReference> oldValue = ALL_REGISTRIES.put(name, new WeakReference<>(this)); + if (oldValue != null && oldValue.get() != null) { + throw new IllegalArgumentException("duplicate name"); + } + FMLCommonHandler.instance().bus().register(this); + } + + @SubscribeEvent + public void onPlayerLogOut(PlayerEvent.PlayerLoggedOutEvent e) { + playerOrdering.remove(e.player.getUniqueID()); + playerBaked.remove(e.player.getUniqueID()); + } + + public void register(String key, V val) { + if (key == null || val == null) throw new NullPointerException(); + V old = store.putIfAbsent(key, val); + if (old != null) { + throw new IllegalArgumentException("Duplicate key: " + key); + } + baked = new ArrayList<>(store.values()); + for (Map.Entry, List>> e : playerOrdering.entrySet()) { + makePlayerBaked(e.getKey(), e.getValue().getKey(), e.getValue().getValue()); + } + } + + public void registerOrdering(EntityPlayerMP player, List ordering, List disabled) { + registerOrdering(player.getUniqueID(), ordering, disabled); + } + + public void registerOrdering(UUID playerID, List ordering, List disabled) { + playerOrdering.put(playerID, Pair.of(ordering, disabled)); + makePlayerBaked(playerID, ordering, disabled); + } + + private void makePlayerBaked(UUID player, List ordering, List disabled) { + TreeMap copy = new TreeMap<>(store); + for (String s : disabled) { + copy.remove(s); + } + List b = new ArrayList<>(); + for (String k : ordering) { + V v = copy.remove(k); + if (v != null) { + b.add(v); + } + } + b.addAll(copy.values()); + playerBaked.put(player, b); + } + + public int size() { + return store.size(); + } + + public boolean isEmpty() { + return store.isEmpty(); + } + + public boolean containsKey(String key) { + return store.containsKey(key); + } + + public boolean containsValue(V value) { + return store.containsValue(value); + } + + public V get(String key) { + return store.get(key); + } + + public Iterable getPlayerOrdering(@Nullable EntityPlayerMP player) { + if (player == null) return baked; + List playerPreference = playerBaked.get(player.getUniqueID()); + if (playerPreference == null) return baked; + return playerPreference; + } + + Iterable getCurrentOrdering() { + return store.keySet(); + } + + @Override + public Iterator iterator() { + return baked.iterator(); + } + + @Override + public void forEach(Consumer action) { + baked.forEach(action); + } + + @Override + public Spliterator spliterator() { + return baked.spliterator(); + } +} diff --git a/src/main/java/com/gtnewhorizon/structurelib/StructureLib.java b/src/main/java/com/gtnewhorizon/structurelib/StructureLib.java index 2269a7db..404e087b 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/StructureLib.java +++ b/src/main/java/com/gtnewhorizon/structurelib/StructureLib.java @@ -17,13 +17,16 @@ import com.gtnewhorizon.structurelib.item.ItemConstructableTrigger; import com.gtnewhorizon.structurelib.item.ItemFrontRotationTool; import com.gtnewhorizon.structurelib.net.AlignmentMessage; import com.gtnewhorizon.structurelib.net.ErrorHintParticleMessage; +import com.gtnewhorizon.structurelib.net.RegistryOrderSyncMessage; import com.gtnewhorizon.structurelib.net.SetChannelDataMessage; import com.gtnewhorizon.structurelib.net.UpdateHintParticleMessage; +import com.gtnewhorizon.structurelib.util.InventoryUtility; import com.gtnewhorizon.structurelib.util.XSTR; import cpw.mods.fml.common.Loader; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.SidedProxy; +import cpw.mods.fml.common.event.FMLLoadCompleteEvent; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.event.FMLServerStartingEvent; import cpw.mods.fml.common.network.NetworkRegistry; @@ -65,6 +68,7 @@ public class StructureLib { net.registerMessage(UpdateHintParticleMessage.Handler.class, UpdateHintParticleMessage.class, 2, Side.CLIENT); net.registerMessage(SetChannelDataMessage.Handler.class, SetChannelDataMessage.class, 3, Side.SERVER); net.registerMessage(ErrorHintParticleMessage.Handler.class, ErrorHintParticleMessage.class, 4, Side.CLIENT); + net.registerMessage(RegistryOrderSyncMessage.Handler.class, RegistryOrderSyncMessage.class, 5, Side.SERVER); try { DEBUG_MODE = Boolean.parseBoolean(System.getProperty("structurelib.debug")); @@ -109,11 +113,17 @@ public class StructureLib { proxy.preInit(e); NetworkRegistry.INSTANCE.registerGuiHandler(instance(), new GuiHandler()); + InventoryUtility.init(); if (Loader.isModLoaded(STRUCTURECOMPAT_MODID)) { COMPAT = Loader.instance().getIndexedModList().get(STRUCTURECOMPAT_MODID).getMod(); } } + @Mod.EventHandler + public void loadComplete(FMLLoadCompleteEvent e) { + proxy.loadComplete(e); + } + @Mod.EventHandler public void serverStarting(FMLServerStartingEvent e) { e.registerServerCommand(new CommandConfigureChannels()); diff --git a/src/main/java/com/gtnewhorizon/structurelib/net/RegistryOrderSyncMessage.java b/src/main/java/com/gtnewhorizon/structurelib/net/RegistryOrderSyncMessage.java new file mode 100644 index 00000000..311a2cf6 --- /dev/null +++ b/src/main/java/com/gtnewhorizon/structurelib/net/RegistryOrderSyncMessage.java @@ -0,0 +1,77 @@ +package com.gtnewhorizon.structurelib.net; + +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +import com.gtnewhorizon.structurelib.SortedRegistry; + +import cpw.mods.fml.common.network.ByteBufUtils; +import cpw.mods.fml.common.network.simpleimpl.IMessage; +import cpw.mods.fml.common.network.simpleimpl.IMessageHandler; +import cpw.mods.fml.common.network.simpleimpl.MessageContext; +import io.netty.buffer.ByteBuf; + +public class RegistryOrderSyncMessage implements IMessage { + + private String name; + private List order; + private List disabled; + + public RegistryOrderSyncMessage() {} + + public RegistryOrderSyncMessage(String name, List order, List disabled) { + this.name = name; + this.order = order; + this.disabled = disabled; + } + + @Override + public void fromBytes(ByteBuf buf) { + name = ByteBufUtils.readUTF8String(buf); + int size = ByteBufUtils.readVarInt(buf, 2); + order = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + order.add(ByteBufUtils.readUTF8String(buf)); + } + size = ByteBufUtils.readVarInt(buf, 2); + disabled = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + disabled.add(ByteBufUtils.readUTF8String(buf)); + } + } + + @Override + public void toBytes(ByteBuf buf) { + ByteBufUtils.writeUTF8String(buf, name); + ByteBufUtils.writeVarInt(buf, order.size(), 2); + for (String s : order) { + ByteBufUtils.writeUTF8String(buf, s); + } + ByteBufUtils.writeVarInt(buf, disabled.size(), 2); + for (String s : disabled) { + ByteBufUtils.writeUTF8String(buf, s); + } + } + + public static class Handler implements IMessageHandler { + + private static ConcurrentHashMap>> ALL_REGISTRIES; + + public static void setAllRegistries(ConcurrentHashMap>> r) { + if (ALL_REGISTRIES == null) ALL_REGISTRIES = r; + } + + @Override + public IMessage onMessage(RegistryOrderSyncMessage message, MessageContext ctx) { + if (ALL_REGISTRIES == null) return null; + WeakReference> ref = ALL_REGISTRIES.get(message.name); + if (ref == null) return null; + SortedRegistry r = ref.get(); + if (r == null) return null; + r.registerOrdering(ctx.getServerHandler().playerEntity, message.order, message.disabled); + return null; + } + } +} diff --git a/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java b/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java index b735e3d1..4300f83a 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java +++ b/src/main/java/com/gtnewhorizon/structurelib/structure/StructureUtility.java @@ -623,8 +623,8 @@ public class StructureUtility { * * * @param tierExtractor a function to extract tier info from a block. This function can return null and will never - * be passed a null block or an invalid block meta. If this function returns null, then the block - * would be considered invalid. + * be passed a null block or an invalid block meta. If this function returns null, then the + * block would be considered invalid. * @param allKnownTiers A list of all known tiers as of calling. Can be empty or null. No hint will be spawned if * empty or null. Cannot have null elements. First element denotes the most primitive tier. * Last element denotes the most advanced tier. If not all tiers are available at definition diff --git a/src/main/java/com/gtnewhorizon/structurelib/util/InventoryUtility.java b/src/main/java/com/gtnewhorizon/structurelib/util/InventoryUtility.java index 770043b2..6e9940b6 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/util/InventoryUtility.java +++ b/src/main/java/com/gtnewhorizon/structurelib/util/InventoryUtility.java @@ -30,6 +30,7 @@ import net.minecraft.inventory.InventoryEnderChest; import net.minecraft.item.ItemStack; import com.gtnewhorizon.gtnhlib.util.map.ItemStackMap; +import com.gtnewhorizon.structurelib.SortedRegistry; import com.gtnewhorizon.structurelib.util.InventoryUtility.ItemStackExtractor.APIType; import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode; @@ -38,12 +39,13 @@ import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode; */ public class InventoryUtility { - private static final SortedRegistry stackExtractors = new SortedRegistry<>(); + private static final SortedRegistry stackExtractors = new SortedRegistry<>("stackExtractors"); private static final List> enableEnder = new CopyOnWriteArrayList<>(); /** * The remove() of the Iterable returned must be implemented! */ - private static final SortedRegistry> inventoryProviders = new SortedRegistry<>(); + private static final SortedRegistry> inventoryProviders = new SortedRegistry<>( + "inventoryProviders"); static { inventoryProviders.register("5000-main-inventory", new InventoryProvider>() { @@ -102,8 +104,8 @@ public class InventoryUtility { registerInventoryProvider(key, newInventoryProvider(extractor)); } - public static Iterator getStackExtractors() { - return stackExtractors.iterator(); + public static Iterator getStackExtractors(EntityPlayerMP player) { + return stackExtractors.getPlayerOrdering(player).iterator(); } public static InventoryProvider> newInventoryProvider( @@ -165,7 +167,7 @@ public class InventoryUtility { boolean simulate, int count) { ItemStackCounterImpl store = new ItemStackCounterImpl(); int sum = 0; - for (InventoryProvider provider : inventoryProviders) { + for (InventoryProvider provider : inventoryProviders.getPlayerOrdering(player)) { sum += takeFromPlayer(player, predicate, simulate, count - sum, store, provider, null); if (sum >= count) return store.getStore(); } @@ -186,7 +188,7 @@ public class InventoryUtility { int count = filter.stackSize; ItemStackPredicate predicate = ItemStackPredicate.from(filter, NBTMode.EXACT); ItemStackCounterImpl store = new ItemStackCounterImpl(); - for (InventoryProvider provider : inventoryProviders) { + for (InventoryProvider provider : inventoryProviders.getPlayerOrdering(player)) { sum += takeFromPlayer(player, predicate, simulate, count - sum, store, provider, filter); if (sum >= count) return sum; } @@ -212,7 +214,7 @@ public class InventoryUtility { * @param predicate item stack filter * @param simulate whether to do removal * @param count let's hope int size is enough... - * @param recursive do recursive lookup using {@link #getStackExtractors() stack extractors} + * @param recursive do recursive lookup using {@link #getStackExtractors(EntityPlayerMP) stack extractors} * @return amount taken. never negative nor bigger than count... */ public static Map takeFromInventory(Iterable inv, Predicate predicate, @@ -252,7 +254,7 @@ public class InventoryUtility { if (found == count) return count; } if (!recursive) continue; - for (ItemStackExtractor f : stackExtractors) { + for (ItemStackExtractor f : stackExtractors.getPlayerOrdering(player)) { boolean end = f.isAPIImplemented(APIType.IS_VALID_SOURCE); if (!f.isValidSource(stack, player)) continue; if (filter != null && f.isAPIImplemented(APIType.EXTRACT_ONE_STACK)) { @@ -268,6 +270,10 @@ public class InventoryUtility { return found; } + public static void init() { + // dummy method to init static final fields + } + public interface OptimizedExtractor { /** diff --git a/src/main/java/com/gtnewhorizon/structurelib/util/SortedRegistry.java b/src/main/java/com/gtnewhorizon/structurelib/util/SortedRegistry.java deleted file mode 100644 index 90253c70..00000000 --- a/src/main/java/com/gtnewhorizon/structurelib/util/SortedRegistry.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.gtnewhorizon.structurelib.util; - -import java.util.*; -import java.util.function.Consumer; - -public class SortedRegistry implements Iterable { - - private final NavigableMap store = new TreeMap<>(); - /** - * Store stuff in an array for faster iteration access than a red black tree - */ - private List baked = Collections.emptyList(); - - public void register(String key, V val) { - if (key == null || val == null) throw new NullPointerException(); - V old = store.putIfAbsent(key, val); - if (old != null) { - throw new IllegalArgumentException("Duplicate key: " + key); - } - // TODO allow a user to edit the order with a configuration file - baked = new ArrayList<>(store.values()); - } - - public int size() { - return store.size(); - } - - public boolean isEmpty() { - return store.isEmpty(); - } - - public boolean containsKey(String key) { - return store.containsKey(key); - } - - public boolean containsValue(V value) { - return store.containsValue(value); - } - - public V get(String key) { - return store.get(key); - } - - @Override - public Iterator iterator() { - return baked.iterator(); - } - - @Override - public void forEach(Consumer action) { - baked.forEach(action); - } - - @Override - public Spliterator spliterator() { - return baked.spliterator(); - } -}