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 org.apache.commons.lang3.tuple.Pair; 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 cpw.mods.fml.relauncher.FMLLaunchHandler; public enum ConfigurationHandler { INSTANCE; private Configuration config; private int maxCoexistingHologram; private int maxRenderRadius; private int maxRenderCount; private boolean removeCollidingHologram; private boolean skipCorrectlyPlacedHints; private int hintLifespan; private int hintTransparency; private int autoPlaceBudget; private int autoPlaceInterval; private Map, List>> registryOrders; ConfigurationHandler() { FMLCommonHandler.instance().bus().register(this); } void init(File f) { config = new Configuration(f, ConfigurationVersion.latest().getVersionMarker()); ConfigurationVersion.migrateToLatest(config); loadConfig(); setLanguageKeys(); } private void setLanguageKeys() { for (String categoryName : config.getCategoryNames()) { ConfigCategory category = config.getCategory(categoryName); category.setLanguageKey("structurelib.config." + categoryName); for (Map.Entry entry : category.entrySet()) { entry.getValue().setLanguageKey(String.format("%s.%s", category.getLanguagekey(), entry.getKey())); } } } private void loadConfig() { maxCoexistingHologram = config.getInt( "maxCoexisting", "client.hologram", 1, 1, 100, "An attempt will be made to prune old holograms when a new hologram is about to be projected"); maxRenderRadius = config.getInt( "maxRenderRadius", "client.hologram", 512, 1, Integer.MAX_VALUE, "Maximum distance from the client player at which projected blocks are kept and rendered."); maxRenderCount = config.getInt( "maxRenderCount", "client.hologram", 1_000_000, 1, Integer.MAX_VALUE, "Maximum number of projected blocks kept for rendering across all holograms.\n" + "Blocks that are already placed correctly are not projected and do not count towards this.\n" + "When a hologram exceeds this, the blocks nearest to the player are the ones kept."); skipCorrectlyPlacedHints = config.getBoolean( "skipCorrectlyPlaced", "client.hologram", true, "Do not project a block that is already placed correctly, so the render budget is spent on the blocks\n" + "that are actually still missing.\n" + "This needs each structure element to be checked while the hologram is built. Elements are\n" + "not strictly required to have a side effect free check, so turn this off if a multiblock\n" + "misbehaves while being projected."); removeCollidingHologram = config.getBoolean( "removeColliding", "client.hologram", true, "An attempt will be made to remove an existing hologram if it collides with a new hologram."); hintLifespan = config .getInt("hintLifespan", "client.hologram", 400, 1, 20000, "Ticks before a hologram disappears."); hintTransparency = config.getInt( "hintTransparency", "client.hologram", 192, 1, 255, "Alpha value of hologram particles. Higher the value, the more \"ghostly\" the hologram will appear to be."); autoPlaceBudget = config.getInt( "autoPlaceBudget", "common.hologram", 25, 1, 200, "Max number of elements can be placed in one round of auto place.\n" + "As expected, server side settings will overrides client settings.\n" + "Certain larger multi might increase these values beyond this configured value."); autoPlaceInterval = config.getInt( "autoPlaceInterval", "common.hologram", 300, 0, 20000, "Unit: millisecond. Minimal interval between two auto place round.\n" + "As expected, server side settings will overrides client settings.\n" + "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() { loadRegistryOrderImpl(); setLanguageKeys(); saveConfig(); } private void loadRegistryOrderImpl() { registryOrders = new HashMap<>(); for (Map.Entry>> e : SortedRegistry.ALL_REGISTRIES.entrySet()) { SortedRegistry r = e.getValue().get(); if (r == null) continue; String category = "registries." + e.getKey(); if (FMLLaunchHandler.side().isClient()) { // only meaningful on client, and would crash on server config.setCategoryConfigEntryClass(category, RegistryOrderEntry.class); } Property pOrder = config.get( category, "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(category, "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(); } } @SubscribeEvent public void onConfigChange(ConfigChangedEvent.PostConfigChangedEvent e) { if (e.modID.equals(StructureLibAPI.MOD_ID)) { loadConfig(); } } public int getMaxCoexistingHologram() { return maxCoexistingHologram; } public int getMaxRenderRadius() { return maxRenderRadius; } public int getMaxRenderCount() { return maxRenderCount; } public boolean isRemoveCollidingHologram() { return removeCollidingHologram; } public boolean isSkipCorrectlyPlacedHints() { return skipCorrectlyPlacedHints; } public int getHintLifespan() { return hintLifespan; } public int getHintTransparency() { return hintTransparency; } public int getAutoPlaceBudget() { return autoPlaceBudget; } public int getAutoPlaceInterval() { return autoPlaceInterval; } public Pair, List> getRegistryOrder(String name) { return registryOrders.get(name); } Configuration getConfig() { return config; } }