Add list support to ForgeConfigSpec.
Fix incorrect Supplier used in ForgeConfigSpec. Port ForgeChunkManager config to new system. Delete old Configuration classes. It's finally gone!
This commit is contained in:
parent
5238eca241
commit
eb42614288
|
@ -20,12 +20,9 @@
|
||||||
package net.minecraftforge.common;
|
package net.minecraftforge.common;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ -53,9 +50,6 @@ import net.minecraft.world.chunk.Chunk;
|
||||||
import net.minecraft.world.chunk.IChunk;
|
import net.minecraft.world.chunk.IChunk;
|
||||||
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
||||||
import net.minecraft.world.storage.ThreadedFileIOBase;
|
import net.minecraft.world.storage.ThreadedFileIOBase;
|
||||||
import net.minecraftforge.common.config.ConfigCategory;
|
|
||||||
import net.minecraftforge.common.config.Configuration;
|
|
||||||
import net.minecraftforge.common.config.Property;
|
|
||||||
import net.minecraftforge.common.util.Constants;
|
import net.minecraftforge.common.util.Constants;
|
||||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||||
import net.minecraftforge.fml.ModContainer;
|
import net.minecraftforge.fml.ModContainer;
|
||||||
|
@ -98,13 +92,8 @@ public class ForgeChunkManager
|
||||||
{
|
{
|
||||||
public static Marker CHUNK_MANAGER = MarkerManager.getMarker("CHUNKMANAGER");
|
public static Marker CHUNK_MANAGER = MarkerManager.getMarker("CHUNKMANAGER");
|
||||||
private static Logger LOGGER = LogManager.getLogger();
|
private static Logger LOGGER = LogManager.getLogger();
|
||||||
private static int defaultMaxCount;
|
|
||||||
private static int defaultMaxChunks;
|
|
||||||
private static boolean overridesEnabled;
|
|
||||||
|
|
||||||
private static Map<World, Multimap<String, Ticket>> tickets = new MapMaker().weakKeys().makeMap();
|
private static Map<World, Multimap<String, Ticket>> tickets = new MapMaker().weakKeys().makeMap();
|
||||||
private static Map<String, Integer> ticketConstraints = Maps.newHashMap();
|
|
||||||
private static Map<String, Integer> chunkConstraints = Maps.newHashMap();
|
|
||||||
|
|
||||||
private static SetMultimap<String, Ticket> playerTickets = HashMultimap.create();
|
private static SetMultimap<String, Ticket> playerTickets = HashMultimap.create();
|
||||||
|
|
||||||
|
@ -115,23 +104,10 @@ public class ForgeChunkManager
|
||||||
|
|
||||||
private static Map<World,Cache<Long, ChunkEntry>> dormantChunkCache = new MapMaker().weakKeys().makeMap();
|
private static Map<World,Cache<Long, ChunkEntry>> dormantChunkCache = new MapMaker().weakKeys().makeMap();
|
||||||
|
|
||||||
private static File cfgFile;
|
|
||||||
private static Configuration config;
|
|
||||||
private static int playerTicketLength;
|
|
||||||
private static int dormantChunkCacheSize;
|
|
||||||
|
|
||||||
public static boolean asyncChunkLoading;
|
public static boolean asyncChunkLoading;
|
||||||
|
|
||||||
public static final List<String> MOD_PROP_ORDER = new ArrayList<String>(2);
|
|
||||||
|
|
||||||
private static Set<String> warnedMods = Sets.newHashSet();
|
private static Set<String> warnedMods = Sets.newHashSet();
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
MOD_PROP_ORDER.add("maximumTicketCount");
|
|
||||||
MOD_PROP_ORDER.add("maximumChunksPerTicket");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ChunkEntry
|
private static class ChunkEntry
|
||||||
{
|
{
|
||||||
public final Chunk chunk;
|
public final Chunk chunk;
|
||||||
|
@ -246,7 +222,7 @@ public class ForgeChunkManager
|
||||||
this.modId = modId;
|
this.modId = modId;
|
||||||
this.ticketType = type;
|
this.ticketType = type;
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.maxDepth = getMaxChunkDepthFor(modId);
|
this.maxDepth = ForgeConfig.CHUNK.chunksPerTicket(modId);
|
||||||
this.requestedChunks = Sets.newLinkedHashSet();
|
this.requestedChunks = Sets.newLinkedHashSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,9 +247,10 @@ public class ForgeChunkManager
|
||||||
*/
|
*/
|
||||||
public void setChunkListDepth(int depth)
|
public void setChunkListDepth(int depth)
|
||||||
{
|
{
|
||||||
if (depth > getMaxChunkDepthFor(modId) || (depth <= 0 && getMaxChunkDepthFor(modId) > 0))
|
|
||||||
|
if (depth > maxDepth || (depth <= 0 && maxDepth > 0))
|
||||||
{
|
{
|
||||||
LOGGER.warn(CHUNK_MANAGER, "The mod {} tried to modify the chunk ticket depth to: {}, its allowed maximum is: {}", modId, depth, getMaxChunkDepthFor(modId));
|
LOGGER.warn(CHUNK_MANAGER, "The mod {} tried to modify the chunk ticket depth to: {}, its allowed maximum is: {}", modId, depth, maxDepth);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -300,7 +277,7 @@ public class ForgeChunkManager
|
||||||
*/
|
*/
|
||||||
public int getMaxChunkListDepth()
|
public int getMaxChunkListDepth()
|
||||||
{
|
{
|
||||||
return getMaxChunkDepthFor(modId);
|
return maxDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -471,9 +448,9 @@ public class ForgeChunkManager
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dormantChunkCacheSize != 0)
|
if (ForgeConfig.CHUNK.dormantChunkCacheSize() != 0)
|
||||||
{ // only put into cache if we're using dormant chunk caching
|
{ // only put into cache if we're using dormant chunk caching
|
||||||
dormantChunkCache.put(world, CacheBuilder.newBuilder().maximumSize(dormantChunkCacheSize).build());
|
dormantChunkCache.put(world, CacheBuilder.newBuilder().maximumSize(ForgeConfig.CHUNK.dormantChunkCacheSize()).build());
|
||||||
}
|
}
|
||||||
WorldServer worldServer = (WorldServer) world;
|
WorldServer worldServer = (WorldServer) world;
|
||||||
File chunkDir = worldServer.getChunkSaveLocation();
|
File chunkDir = worldServer.getChunkSaveLocation();
|
||||||
|
@ -575,7 +552,7 @@ public class ForgeChunkManager
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int maxTicketLength = getMaxTicketLengthFor(modId);
|
int maxTicketLength = ForgeConfig.CHUNK.maxTickets(modId);
|
||||||
List<Ticket> tickets = loadedTickets.get(modId);
|
List<Ticket> tickets = loadedTickets.get(modId);
|
||||||
if (loadingCallback instanceof OrderedLoadingCallback)
|
if (loadingCallback instanceof OrderedLoadingCallback)
|
||||||
{
|
{
|
||||||
|
@ -621,7 +598,7 @@ public class ForgeChunkManager
|
||||||
}
|
}
|
||||||
|
|
||||||
forcedChunks.remove(world);
|
forcedChunks.remove(world);
|
||||||
if (dormantChunkCacheSize != 0) // only if in use
|
if (ForgeConfig.CHUNK.dormantChunkCacheSize() != 0) // only if in use
|
||||||
{
|
{
|
||||||
dormantChunkCache.remove(world);
|
dormantChunkCache.remove(world);
|
||||||
}
|
}
|
||||||
|
@ -664,7 +641,7 @@ public class ForgeChunkManager
|
||||||
if (container!=null)
|
if (container!=null)
|
||||||
{
|
{
|
||||||
String modId = container.getModId();
|
String modId = container.getModId();
|
||||||
int allowedCount = getMaxTicketLengthFor(modId);
|
int allowedCount = ForgeConfig.CHUNK.maxTickets(modId);
|
||||||
return allowedCount - tickets.get(world).get(modId).size();
|
return allowedCount - tickets.get(world).get(modId).size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -679,21 +656,9 @@ public class ForgeChunkManager
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getMaxTicketLengthFor(String modId)
|
|
||||||
{
|
|
||||||
int allowedCount = ticketConstraints.containsKey(modId) && overridesEnabled ? ticketConstraints.get(modId) : defaultMaxCount;
|
|
||||||
return allowedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getMaxChunkDepthFor(String modId)
|
|
||||||
{
|
|
||||||
int allowedCount = chunkConstraints.containsKey(modId) && overridesEnabled ? chunkConstraints.get(modId) : defaultMaxChunks;
|
|
||||||
return allowedCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int ticketCountAvailableFor(String username)
|
public static int ticketCountAvailableFor(String username)
|
||||||
{
|
{
|
||||||
return playerTicketLength - playerTickets.get(username).size();
|
return ForgeConfig.CHUNK.playerTicketCount() - playerTickets.get(username).size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -705,7 +670,7 @@ public class ForgeChunkManager
|
||||||
LOGGER.error(CHUNK_MANAGER, "Failed to locate the container for mod instance {} ({} : {})", mod, mod.getClass().getName(), Integer.toHexString(System.identityHashCode(mod)));
|
LOGGER.error(CHUNK_MANAGER, "Failed to locate the container for mod instance {} ({} : {})", mod, mod.getClass().getName(), Integer.toHexString(System.identityHashCode(mod)));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (playerTickets.get(player).size()>playerTicketLength)
|
if (playerTickets.get(player).size() > ForgeConfig.CHUNK.playerTicketCount())
|
||||||
{
|
{
|
||||||
LOGGER.warn(CHUNK_MANAGER, "Unable to assign further chunkloading tickets to player {} (on behalf of mod {})", player, mc.getModId());
|
LOGGER.warn(CHUNK_MANAGER, "Unable to assign further chunkloading tickets to player {} (on behalf of mod {})", player, mc.getModId());
|
||||||
return null;
|
return null;
|
||||||
|
@ -739,7 +704,7 @@ public class ForgeChunkManager
|
||||||
throw new RuntimeException("Invalid ticket request");
|
throw new RuntimeException("Invalid ticket request");
|
||||||
}
|
}
|
||||||
|
|
||||||
int allowedCount = getMaxTicketLengthFor(modId);
|
int allowedCount = ForgeConfig.CHUNK.maxTickets(modId);
|
||||||
|
|
||||||
if (tickets.get(world).get(modId).size() >= allowedCount)
|
if (tickets.get(world).get(modId).size() >= allowedCount)
|
||||||
{
|
{
|
||||||
|
@ -861,27 +826,6 @@ public class ForgeChunkManager
|
||||||
forcedChunks.put(ticket.world,newMap);
|
forcedChunks.put(ticket.world,newMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void loadConfiguration()
|
|
||||||
{
|
|
||||||
ticketConstraints.clear();
|
|
||||||
chunkConstraints.clear();
|
|
||||||
for (String mod : config.getCategoryNames())
|
|
||||||
{
|
|
||||||
if (mod.equals(ForgeVersion.MOD_ID) || mod.equals("defaults"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Property modTC = config.get(mod, "maximumTicketCount", 200);
|
|
||||||
Property modCPT = config.get(mod, "maximumChunksPerTicket", 25);
|
|
||||||
ticketConstraints.put(mod, modTC.getInt(200));
|
|
||||||
chunkConstraints.put(mod, modCPT.getInt(25));
|
|
||||||
}
|
|
||||||
if (config.hasChanged())
|
|
||||||
{
|
|
||||||
config.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of persistent chunks in the world. This set is immutable.
|
* The list of persistent chunks in the world. This set is immutable.
|
||||||
* @param world
|
* @param world
|
||||||
|
@ -975,7 +919,7 @@ public class ForgeChunkManager
|
||||||
|
|
||||||
public static void putDormantChunk(long coords, Chunk chunk)
|
public static void putDormantChunk(long coords, Chunk chunk)
|
||||||
{
|
{
|
||||||
if (dormantChunkCacheSize == 0) return; // Skip if we're not dormant caching chunks
|
if (ForgeConfig.CHUNK.dormantChunkCacheSize() == 0) return; // Skip if we're not dormant caching chunks
|
||||||
Cache<Long, ChunkEntry> cache = dormantChunkCache.get(chunk.getWorld());
|
Cache<Long, ChunkEntry> cache = dormantChunkCache.get(chunk.getWorld());
|
||||||
if (cache != null)
|
if (cache != null)
|
||||||
{
|
{
|
||||||
|
@ -985,7 +929,7 @@ public class ForgeChunkManager
|
||||||
|
|
||||||
public static void storeChunkNBT(World world, IChunk ichunk, NBTTagCompound nbt)
|
public static void storeChunkNBT(World world, IChunk ichunk, NBTTagCompound nbt)
|
||||||
{
|
{
|
||||||
if (dormantChunkCacheSize == 0) return;
|
if (ForgeConfig.CHUNK.dormantChunkCacheSize() == 0) return;
|
||||||
|
|
||||||
Cache<Long, ChunkEntry> cache = dormantChunkCache.get(world);
|
Cache<Long, ChunkEntry> cache = dormantChunkCache.get(world);
|
||||||
if (cache == null) return;
|
if (cache == null) return;
|
||||||
|
@ -1012,7 +956,7 @@ public class ForgeChunkManager
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Chunk fetchDormantChunk(long coords, World world)
|
public static Chunk fetchDormantChunk(long coords, World world)
|
||||||
{
|
{
|
||||||
if (dormantChunkCacheSize == 0) return null; // Don't bother with maps at all if its never gonna get a response
|
if (ForgeConfig.CHUNK.dormantChunkCacheSize() == 0) return null; // Don't bother with maps at all if its never gonna get a response
|
||||||
|
|
||||||
Cache<Long, ChunkEntry> cache = dormantChunkCache.get(world);
|
Cache<Long, ChunkEntry> cache = dormantChunkCache.get(world);
|
||||||
if (cache == null) return null;
|
if (cache == null) return null;
|
||||||
|
@ -1042,160 +986,4 @@ public class ForgeChunkManager
|
||||||
if (tileEntity != null) chunk.addTileEntity(tileEntity);
|
if (tileEntity != null) chunk.addTileEntity(tileEntity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void captureConfig(File configDir)
|
|
||||||
{
|
|
||||||
cfgFile = new File(configDir,"forgeChunkLoading.cfg");
|
|
||||||
config = new Configuration(cfgFile, true);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
config.load();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
File dest = new File(cfgFile.getParentFile(),"forgeChunkLoading.cfg.bak");
|
|
||||||
if (dest.exists())
|
|
||||||
{
|
|
||||||
dest.delete();
|
|
||||||
}
|
|
||||||
cfgFile.renameTo(dest);
|
|
||||||
LOGGER.error(CHUNK_MANAGER, "A critical error occurred reading the forgeChunkLoading.cfg file, defaults will be used - the invalid file is backed up at forgeChunkLoading.cfg.bak", e);
|
|
||||||
}
|
|
||||||
syncConfigDefaults();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronizes the local fields with the values in the Configuration object.
|
|
||||||
*/
|
|
||||||
public static void syncConfigDefaults()
|
|
||||||
{
|
|
||||||
// By adding a property order list we are defining the order that the properties will appear both in the config file and on the GUIs.
|
|
||||||
// Property order lists are defined per-ConfigCategory.
|
|
||||||
List<String> propOrder = new ArrayList<String>();
|
|
||||||
|
|
||||||
config.setCategoryComment("defaults", "Default configuration for forge chunk loading control")
|
|
||||||
.setCategoryRequiresWorldRestart("defaults", true);
|
|
||||||
|
|
||||||
Property temp = config.get("defaults", "enabled", true);
|
|
||||||
temp.setComment("Are mod overrides enabled?");
|
|
||||||
temp.setLanguageKey("forge.configgui.enableModOverrides");
|
|
||||||
overridesEnabled = temp.getBoolean(true);
|
|
||||||
propOrder.add("enabled");
|
|
||||||
|
|
||||||
temp = config.get("defaults", "maximumChunksPerTicket", 25);
|
|
||||||
temp.setComment("The default maximum number of chunks a mod can force, per ticket, \n" +
|
|
||||||
"for a mod without an override. This is the maximum number of chunks a single ticket can force.");
|
|
||||||
temp.setLanguageKey("forge.configgui.maximumChunksPerTicket");
|
|
||||||
temp.setMinValue(0);
|
|
||||||
defaultMaxChunks = temp.getInt(25);
|
|
||||||
propOrder.add("maximumChunksPerTicket");
|
|
||||||
|
|
||||||
temp = config.get("defaults", "maximumTicketCount", 200);
|
|
||||||
temp.setComment("The default maximum ticket count for a mod which does not have an override\n" +
|
|
||||||
"in this file. This is the number of chunk loading requests a mod is allowed to make.");
|
|
||||||
temp.setLanguageKey("forge.configgui.maximumTicketCount");
|
|
||||||
temp.setMinValue(0);
|
|
||||||
defaultMaxCount = temp.getInt(200);
|
|
||||||
propOrder.add("maximumTicketCount");
|
|
||||||
|
|
||||||
temp = config.get("defaults", "playerTicketCount", 500);
|
|
||||||
temp.setComment("The number of tickets a player can be assigned instead of a mod. This is shared across all mods and it is up to the mods to use it.");
|
|
||||||
temp.setLanguageKey("forge.configgui.playerTicketCount");
|
|
||||||
temp.setMinValue(0);
|
|
||||||
playerTicketLength = temp.getInt(500);
|
|
||||||
propOrder.add("playerTicketCount");
|
|
||||||
|
|
||||||
temp = config.get("defaults", "dormantChunkCacheSize", 0);
|
|
||||||
temp.setComment("Unloaded chunks can first be kept in a dormant cache for quicker\n" +
|
|
||||||
"loading times. Specify the size (in chunks) of that cache here");
|
|
||||||
temp.setLanguageKey("forge.configgui.dormantChunkCacheSize");
|
|
||||||
temp.setMinValue(0);
|
|
||||||
dormantChunkCacheSize = temp.getInt(0);
|
|
||||||
propOrder.add("dormantChunkCacheSize");
|
|
||||||
LOGGER.info(CHUNK_MANAGER, "Configured a dormant chunk cache size of {}", temp.getInt(0));
|
|
||||||
|
|
||||||
temp = config.get("defaults", "asyncChunkLoading", true);
|
|
||||||
temp.setComment("Load chunks asynchronously for players, reducing load on the server thread.\n" +
|
|
||||||
"Can be disabled to help troubleshoot chunk loading issues.");
|
|
||||||
temp.setLanguageKey("forge.configgui.asyncChunkLoading");
|
|
||||||
asyncChunkLoading = temp.getBoolean(true);
|
|
||||||
propOrder.add("asyncChunkLoading");
|
|
||||||
|
|
||||||
config.setCategoryPropertyOrder("defaults", propOrder);
|
|
||||||
|
|
||||||
config.addCustomCategoryComment(ForgeVersion.MOD_ID, "Sample mod specific control section.\n" +
|
|
||||||
"Copy this section and rename the with the modid for the mod you wish to override.\n" +
|
|
||||||
"A value of zero in either entry effectively disables any chunkloading capabilities\n" +
|
|
||||||
"for that mod");
|
|
||||||
|
|
||||||
temp = config.get(ForgeVersion.MOD_ID, "maximumTicketCount", 200);
|
|
||||||
temp.setComment("Maximum ticket count for the mod. Zero disables chunkloading capabilities.");
|
|
||||||
temp = config.get(ForgeVersion.MOD_ID, "maximumChunksPerTicket", 25);
|
|
||||||
temp.setComment("Maximum chunks per ticket for the mod.");
|
|
||||||
for (String mod : config.getCategoryNames())
|
|
||||||
{
|
|
||||||
if (mod.equals(ForgeVersion.MOD_ID) || mod.equals("defaults"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
config.get(mod, "maximumTicketCount", 200).setLanguageKey("forge.configgui.maximumTicketCount").setMinValue(0);
|
|
||||||
config.get(mod, "maximumChunksPerTicket", 25).setLanguageKey("forge.configgui.maximumChunksPerTicket").setMinValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.hasChanged())
|
|
||||||
{
|
|
||||||
config.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Configuration getConfig()
|
|
||||||
{
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigCategory getDefaultsCategory()
|
|
||||||
{
|
|
||||||
return config.getCategory("defaults");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<ConfigCategory> getModCategories()
|
|
||||||
{
|
|
||||||
List<ConfigCategory> list = new ArrayList<ConfigCategory>();
|
|
||||||
for (String mod : config.getCategoryNames())
|
|
||||||
{
|
|
||||||
if (mod.equals(ForgeVersion.MOD_ID) || mod.equals("defaults"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
list.add(config.getCategory(mod));
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static ConfigCategory getConfigFor(Object mod)
|
|
||||||
{
|
|
||||||
ModContainer container = getContainer(mod);
|
|
||||||
if (container != null)
|
|
||||||
{
|
|
||||||
return config.getCategory(container.getModId());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addConfigProperty(Object mod, String propertyName, String value, Property.Type type)
|
|
||||||
{
|
|
||||||
ModContainer container = getContainer(mod);
|
|
||||||
if (container != null)
|
|
||||||
{
|
|
||||||
ConfigCategory cat = config.getCategory(container.getModId());
|
|
||||||
Property prop = new Property(propertyName, value, type).setLanguageKey("forge.configgui." + propertyName);
|
|
||||||
if (type == Property.Type.INTEGER)
|
|
||||||
{
|
|
||||||
prop.setMinValue(0);
|
|
||||||
}
|
|
||||||
cat.put(propertyName, prop);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,13 +23,23 @@ import static net.minecraftforge.fml.Logging.CORE;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||||
|
|
||||||
import net.minecraftforge.common.config.ForgeConfigSpec;
|
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||||
|
|
||||||
public class ForgeConfig
|
public class ForgeConfig
|
||||||
{
|
{
|
||||||
|
@ -118,9 +128,71 @@ public class ForgeConfig
|
||||||
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
private static ForgeConfigSpec chunk_spec = new ForgeConfigSpec.Builder()
|
||||||
|
.comment("Default configuration for Forge chunk loading control")
|
||||||
|
.push("defaults")
|
||||||
|
.comment("Allow mod overrides, false will use default for everything.")
|
||||||
|
.translation("forge.configgui.enableModOverrides")
|
||||||
|
.define("enable", true)
|
||||||
|
|
||||||
|
.comment("The default maximum number of chunks a mod can force, per ticket,",
|
||||||
|
"for a mod without an override. This is the maximum number of chunks a single ticket can force.")
|
||||||
|
.translation("forge.configgui.maximumChunksPerTicket")
|
||||||
|
.defineInRange("chunksPerTicket", 25, 0, Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
.comment("The default maximum ticket count for a mod which does not have an override",
|
||||||
|
"in this file. This is the number of chunk loading requests a mod is allowed to make.")
|
||||||
|
.translation("forge.configgui.maximumTicketCount")
|
||||||
|
.defineInRange("maxTickets", 200, 0, Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
.comment("The number of tickets a player can be assigned instead of a mod. This is shared across all mods and it is up to the mods to use it.")
|
||||||
|
.translation("forge.configgui.playerTicketCount")
|
||||||
|
.defineInRange("playerTicketCount", 500, 0, Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
.comment("Unloaded chunks can first be kept in a dormant cache for quicker loading times. Specify the size (in chunks) of that cache here")
|
||||||
|
.translation("forge.configgui.dormantChunkCacheSize")
|
||||||
|
.defineInRange("dormantChunkCacheSize", 0, 0, Integer.MAX_VALUE)
|
||||||
|
|
||||||
|
.comment("Load chunks asynchronously for players, reducing load on the server thread.",
|
||||||
|
"Can be disabled to help troubleshoot chunk loading issues.")
|
||||||
|
.translation("forge.configgui.asyncChunkLoading")
|
||||||
|
.define("asyncChunkLoading", true)
|
||||||
|
.pop()
|
||||||
|
|
||||||
|
//Not sure how to do unlimited nested config objects, so doing this for now as it works.
|
||||||
|
.comment("Per Mod settings. If a mod is missing a entry, or value the default will be used.")
|
||||||
|
.defineList("mods", () -> {
|
||||||
|
Map<String, Object> ret = new HashMap<>();
|
||||||
|
ret.put("modid", ForgeVersion.MOD_ID);
|
||||||
|
ret.put("maxTickets", 200);
|
||||||
|
ret.put("chunksPerTicket", 25);
|
||||||
|
return Arrays.asList(ret);
|
||||||
|
}, (o) -> {
|
||||||
|
if (!(o instanceof Map)) return false;
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<Object, Object> map = (Map<Object, Object>)o;
|
||||||
|
for (Entry<Object, Object> e : map.entrySet()) {
|
||||||
|
if ("modid".equals(e.getKey())) {
|
||||||
|
if (!(e.getValue() instanceof String))
|
||||||
|
return false;
|
||||||
|
} else if ("maxTickets".equals(e.getKey())) {
|
||||||
|
if (!(e.getValue() instanceof Integer))
|
||||||
|
return false;
|
||||||
|
} else if ("chunksPerTicket".equals(e.getKey())) {
|
||||||
|
if (!(e.getValue() instanceof Integer))
|
||||||
|
return false;
|
||||||
|
} else { //Unknown entry
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
private CommentedFileConfig configData;
|
private CommentedFileConfig configData;
|
||||||
private void loadFrom(final Path configFile)
|
private CommentedFileConfig chunkData;
|
||||||
{
|
private void loadFrom(final Path configRoot) {
|
||||||
|
Path configFile = configRoot.resolve("forge.toml");
|
||||||
configData = CommentedFileConfig.builder(configFile).sync()
|
configData = CommentedFileConfig.builder(configFile).sync()
|
||||||
.autosave()
|
.autosave()
|
||||||
//.autoreload()
|
//.autoreload()
|
||||||
|
@ -128,18 +200,32 @@ public class ForgeConfig
|
||||||
.build();
|
.build();
|
||||||
configData.load();
|
configData.load();
|
||||||
if (!spec.isCorrect(configData)) {
|
if (!spec.isCorrect(configData)) {
|
||||||
LogManager.getLogger().warn(CORE, "Configuration file {} is not correct. Correcting", configFile);
|
LogManager.getLogger().warn(CORE, "Configuration file {} is not correct. Correcting", configRoot);
|
||||||
spec.correct(configData, (action, path, incorrectValue, correctedValue) ->
|
spec.correct(configData, (action, path, incorrectValue, correctedValue) ->
|
||||||
LogManager.getLogger().warn(CORE, "Incorrect key {} was corrected from {} to {}", path, incorrectValue, correctedValue));
|
LogManager.getLogger().warn(CORE, "Incorrect key {} was corrected from {} to {}", path, incorrectValue, correctedValue));
|
||||||
configData.save();
|
configData.save();
|
||||||
}
|
}
|
||||||
|
LogManager.getLogger().debug(CORE, "Loaded Forge config from {}", configFile);
|
||||||
|
|
||||||
|
|
||||||
|
configFile = configRoot.resolve("forge_chunks.toml");
|
||||||
|
chunkData = CommentedFileConfig.builder(configFile).sync()
|
||||||
|
.autosave()
|
||||||
|
//.autoreload()
|
||||||
|
.writingMode(WritingMode.REPLACE)
|
||||||
|
.build();
|
||||||
|
chunkData.load();
|
||||||
|
if (!chunk_spec.isCorrect(chunkData)) {
|
||||||
|
LogManager.getLogger().warn(CORE, "Configuration file {} is not correct. Correcting", configRoot);
|
||||||
|
chunk_spec.correct(chunkData, (action, path, incorrectValue, correctedValue) ->
|
||||||
|
LogManager.getLogger().warn(CORE, "Incorrect key {} was corrected from {} to {}", path, incorrectValue, correctedValue));
|
||||||
|
chunkData.save();
|
||||||
|
}
|
||||||
|
LogManager.getLogger().debug(CORE, "Loaded Forge Chunk config from {}", configFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void load()
|
public static void load() {
|
||||||
{
|
INSTANCE.loadFrom(Paths.get("config"));
|
||||||
Path configFile = Paths.get("config").resolve("forge.toml");
|
|
||||||
INSTANCE.loadFrom(configFile);
|
|
||||||
LogManager.getLogger().debug(CORE, "Loaded FML config from {}", configFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Make this less duplciate? Maybe static CfgEntry<T> zombieBaseSummonChance = create((spec, name) -> spec.comment().translation().define(name), "zombieBaseSummonChance")
|
//TODO: Make this less duplciate? Maybe static CfgEntry<T> zombieBaseSummonChance = create((spec, name) -> spec.comment().translation().define(name), "zombieBaseSummonChance")
|
||||||
|
@ -173,6 +259,40 @@ public class ForgeConfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class CHUNK {
|
||||||
|
public static boolean enableModOverrides() {
|
||||||
|
return ForgeConfig.INSTANCE.chunkData.<Boolean>getOrElse("defaults.enable", true);
|
||||||
|
}
|
||||||
|
public static int playerTicketCount() {
|
||||||
|
return ForgeConfig.INSTANCE.chunkData.<Integer>getOrElse("defaults.playerTicketCount", 500);
|
||||||
|
}
|
||||||
|
public static int dormantChunkCacheSize() {
|
||||||
|
return ForgeConfig.INSTANCE.chunkData.<Integer>getOrElse("defaults.dormantChunkCacheSize", 0);
|
||||||
|
}
|
||||||
|
private static int maxTickets() {
|
||||||
|
return ForgeConfig.INSTANCE.chunkData.<Integer>getOrElse("defaults.maxTickets", 200);
|
||||||
|
}
|
||||||
|
public static int chunksPerTicket() {
|
||||||
|
return ForgeConfig.INSTANCE.chunkData.<Integer>getOrElse("defaults.chunksPerTicket", 0);
|
||||||
|
}
|
||||||
|
public static int maxTickets(@Nullable String modid) {
|
||||||
|
if (!enableModOverrides() || modid == null)
|
||||||
|
return maxTickets();
|
||||||
|
Map<Object,Object> data = ForgeConfig.INSTANCE.chunkData.<List<Map<Object, Object>>>getOrElse("mods", Collections.emptyList())
|
||||||
|
.stream().filter(e -> modid.equals(e.get("modid"))).findFirst().orElse(null);
|
||||||
|
Integer ret = data == null ? null : (Integer)data.get("maxTickets");
|
||||||
|
return ret == null ? maxTickets() : ret;
|
||||||
|
}
|
||||||
|
public static int chunksPerTicket(@Nullable String modid) {
|
||||||
|
if (!enableModOverrides() || modid == null)
|
||||||
|
return chunksPerTicket();
|
||||||
|
Map<Object,Object> data = ForgeConfig.INSTANCE.chunkData.<List<Map<Object, Object>>>getOrElse("mods", Collections.emptyList())
|
||||||
|
.stream().filter(e -> modid.equals(e.get("modid"))).findFirst().orElse(null);
|
||||||
|
Integer ret = data == null ? null : (Integer)data.get("chunksPerTicket");
|
||||||
|
return ret == null ? chunksPerTicket() : ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//General
|
//General
|
||||||
//public static boolean disableVersionCheck = false;
|
//public static boolean disableVersionCheck = false;
|
||||||
//public static boolean logCascadingWorldGeneration = true; // see Chunk#logCascadingWorldGeneration()
|
//public static boolean logCascadingWorldGeneration = true; // see Chunk#logCascadingWorldGeneration()
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package net.minecraftforge.common.config;
|
package net.minecraftforge.common;
|
||||||
|
|
||||||
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.ADD;
|
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.ADD;
|
||||||
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.REMOVE;
|
import static com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction.REMOVE;
|
||||||
|
@ -33,20 +33,17 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import com.electronwill.nightconfig.core.CommentedConfig;
|
import com.electronwill.nightconfig.core.CommentedConfig;
|
||||||
import com.electronwill.nightconfig.core.Config;
|
import com.electronwill.nightconfig.core.Config;
|
||||||
import com.electronwill.nightconfig.core.ConfigFormat;
|
|
||||||
import com.electronwill.nightconfig.core.InMemoryFormat;
|
import com.electronwill.nightconfig.core.InMemoryFormat;
|
||||||
import com.electronwill.nightconfig.core.UnmodifiableConfig;
|
|
||||||
import com.electronwill.nightconfig.core.utils.UnmodifiableConfigWrapper;
|
import com.electronwill.nightconfig.core.utils.UnmodifiableConfigWrapper;
|
||||||
import com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction;
|
import com.electronwill.nightconfig.core.ConfigSpec.CorrectionAction;
|
||||||
import com.electronwill.nightconfig.core.ConfigSpec.CorrectionListener;
|
import com.electronwill.nightconfig.core.ConfigSpec.CorrectionListener;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Supplier;
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -219,8 +216,7 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<Config>
|
||||||
public <V extends Comparable<? super V>> Builder defineInRange(String path, Supplier<V> defaultSupplier, V min, V max, Class<V> clazz) {
|
public <V extends Comparable<? super V>> Builder defineInRange(String path, Supplier<V> defaultSupplier, V min, V max, Class<V> clazz) {
|
||||||
return defineInRange(split(path), defaultSupplier, min, max, clazz);
|
return defineInRange(split(path), defaultSupplier, min, max, clazz);
|
||||||
}
|
}
|
||||||
public <V extends Comparable<? super V>> Builder defineInRange(List<String> path, Supplier<V> defaultSupplier, V min, V max, Class<V> clazz)
|
public <V extends Comparable<? super V>> Builder defineInRange(List<String> path, Supplier<V> defaultSupplier, V min, V max, Class<V> clazz) {
|
||||||
{
|
|
||||||
Range<V> range = new Range<>(clazz, min, max);
|
Range<V> range = new Range<>(clazz, min, max);
|
||||||
context.setRange(range);
|
context.setRange(range);
|
||||||
if (min.compareTo(max) > 0)
|
if (min.compareTo(max) > 0)
|
||||||
|
@ -228,17 +224,32 @@ public class ForgeConfigSpec extends UnmodifiableConfigWrapper<Config>
|
||||||
define(path, defaultSupplier, range);
|
define(path, defaultSupplier, range);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
public void defineInList(String path, Object defaultValue, Collection<?> acceptableValues) {
|
public Builder defineInList(String path, Object defaultValue, Collection<?> acceptableValues) {
|
||||||
defineInList(split(path), defaultValue, acceptableValues);
|
return defineInList(split(path), defaultValue, acceptableValues);
|
||||||
}
|
}
|
||||||
public void defineInList(String path, Supplier<?> defaultSupplier, Collection<?> acceptableValues) {
|
public Builder defineInList(String path, Supplier<?> defaultSupplier, Collection<?> acceptableValues) {
|
||||||
defineInList(split(path), defaultSupplier, acceptableValues);
|
return defineInList(split(path), defaultSupplier, acceptableValues);
|
||||||
}
|
}
|
||||||
public void defineInList(List<String> path, Object defaultValue, Collection<?> acceptableValues) {
|
public Builder defineInList(List<String> path, Object defaultValue, Collection<?> acceptableValues) {
|
||||||
defineInList(path, () -> defaultValue, acceptableValues);
|
return defineInList(path, () -> defaultValue, acceptableValues);
|
||||||
}
|
}
|
||||||
public void defineInList(List<String> path, Supplier<?> defaultSupplier, Collection<?> acceptableValues) {
|
public Builder defineInList(List<String> path, Supplier<?> defaultSupplier, Collection<?> acceptableValues) {
|
||||||
define(path, defaultSupplier, acceptableValues::contains);
|
return define(path, defaultSupplier, acceptableValues::contains);
|
||||||
|
}
|
||||||
|
public Builder defineList(String path, List<?> defaultValue, Predicate<Object> elementValidator) {
|
||||||
|
return defineList(split(path), defaultValue, elementValidator);
|
||||||
|
}
|
||||||
|
public Builder defineList(String path, Supplier<List<?>> defaultSupplier, Predicate<Object> elementValidator) {
|
||||||
|
return defineList(split(path), defaultSupplier, elementValidator);
|
||||||
|
}
|
||||||
|
public Builder defineList(List<String> path, List<?> defaultValue, Predicate<Object> elementValidator) {
|
||||||
|
return defineList(path, () -> defaultValue, elementValidator);
|
||||||
|
}
|
||||||
|
public Builder defineList(List<String> path, Supplier<List<?>> defaultSupplier, Predicate<Object> elementValidator) {
|
||||||
|
return define(path, defaultSupplier, (Object o) -> {
|
||||||
|
if (!(o instanceof List)) return false;
|
||||||
|
return ((List<?>)o).stream().allMatch(elementValidator);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Enum
|
//Enum
|
|
@ -114,7 +114,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
||||||
CapabilityAnimation.register();
|
CapabilityAnimation.register();
|
||||||
CapabilityEnergy.register();
|
CapabilityEnergy.register();
|
||||||
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
|
MinecraftForge.EVENT_BUS.register(MinecraftForge.INTERNAL_HANDLER);
|
||||||
// ForgeChunkManager.captureConfig(evt.getModConfigurationDirectory());
|
|
||||||
MinecraftForge.EVENT_BUS.register(this);
|
MinecraftForge.EVENT_BUS.register(this);
|
||||||
|
|
||||||
if (!ForgeMod.disableVersionCheck)
|
if (!ForgeMod.disableVersionCheck)
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library 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 version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library 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 library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.common.config;
|
|
||||||
|
|
||||||
import java.lang.annotation.ElementType;
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
import java.lang.annotation.Target;
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.TYPE)
|
|
||||||
public @interface Config
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The mod id that this configuration is associated with.
|
|
||||||
*/
|
|
||||||
String modid();
|
|
||||||
/**
|
|
||||||
* A user friendly name for the config file,
|
|
||||||
* the default will be modid
|
|
||||||
*/
|
|
||||||
String name() default "";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The type this is, right now the only value is INSTANCE.
|
|
||||||
* This is intended to be expanded upon later for more Forge controlled
|
|
||||||
* configs.
|
|
||||||
*/
|
|
||||||
Type type() default Type.INSTANCE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Root element category, defaults to "general", if this is an empty string then the root category is disabled.
|
|
||||||
* Any primitive fields will cause an error, and you must specify sub-category objects
|
|
||||||
*/
|
|
||||||
String category() default "general";
|
|
||||||
|
|
||||||
public static enum Type
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Loaded once, directly after mod construction. Before pre-init.
|
|
||||||
* This class must have static fields.
|
|
||||||
*/
|
|
||||||
INSTANCE(true);
|
|
||||||
|
|
||||||
|
|
||||||
private boolean isStatic = true;
|
|
||||||
private Type(boolean isStatic) { this.isStatic = isStatic; }
|
|
||||||
public boolean isStatic(){ return this.isStatic; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
|
||||||
@interface LangKey
|
|
||||||
{
|
|
||||||
String value();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
@interface Comment
|
|
||||||
{
|
|
||||||
String[] value();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
@interface Ignore
|
|
||||||
{}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
@interface RangeInt
|
|
||||||
{
|
|
||||||
int min() default Integer.MIN_VALUE;
|
|
||||||
int max() default Integer.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
@interface RangeDouble
|
|
||||||
{
|
|
||||||
double min() default Double.MIN_VALUE;
|
|
||||||
double max() default Double.MAX_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target(ElementType.FIELD)
|
|
||||||
@interface Name
|
|
||||||
{
|
|
||||||
String value();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
|
||||||
@interface RequiresMcRestart
|
|
||||||
{}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Target({ElementType.FIELD, ElementType.TYPE})
|
|
||||||
@interface RequiresWorldRestart
|
|
||||||
{}
|
|
||||||
}
|
|
|
@ -1,442 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library 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 version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library 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 library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.common.config;
|
|
||||||
|
|
||||||
import static net.minecraftforge.common.config.Configuration.COMMENT_SEPARATOR;
|
|
||||||
import static net.minecraftforge.common.config.Configuration.NEW_LINE;
|
|
||||||
import static net.minecraftforge.common.config.Configuration.allowedProperties;
|
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.client.config.IConfigEntry;
|
|
||||||
|
|
||||||
public class ConfigCategory implements Map<String, Property>
|
|
||||||
{
|
|
||||||
private String name;
|
|
||||||
private String comment;
|
|
||||||
private String languagekey;
|
|
||||||
private ArrayList<ConfigCategory> children = new ArrayList<ConfigCategory>();
|
|
||||||
private Map<String, Property> properties = new TreeMap<String, Property>();
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private int propNumber = 0;
|
|
||||||
public final ConfigCategory parent;
|
|
||||||
private boolean changed = false;
|
|
||||||
private boolean requiresWorldRestart = false;
|
|
||||||
private boolean showInGui = true;
|
|
||||||
private boolean requiresMcRestart = false;
|
|
||||||
private Class<? extends IConfigEntry> customEntryClass = null;
|
|
||||||
private List<String> propertyOrder = null;
|
|
||||||
|
|
||||||
public ConfigCategory(String name)
|
|
||||||
{
|
|
||||||
this(name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigCategory(String name, ConfigCategory parent)
|
|
||||||
{
|
|
||||||
this.name = name;
|
|
||||||
this.parent = parent;
|
|
||||||
if (parent != null)
|
|
||||||
{
|
|
||||||
parent.children.add(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj)
|
|
||||||
{
|
|
||||||
if (obj instanceof ConfigCategory)
|
|
||||||
{
|
|
||||||
ConfigCategory cat = (ConfigCategory)obj;
|
|
||||||
return name.equals(cat.name) && children.equals(cat.children);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getQualifiedName()
|
|
||||||
{
|
|
||||||
return getQualifiedName(name, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getQualifiedName(String name, ConfigCategory parent)
|
|
||||||
{
|
|
||||||
return (parent == null ? name : parent.getQualifiedName() + Configuration.CATEGORY_SPLITTER + name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigCategory getFirstParent()
|
|
||||||
{
|
|
||||||
return (parent == null ? this : parent.getFirstParent());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChild()
|
|
||||||
{
|
|
||||||
return parent != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, Property> getValues()
|
|
||||||
{
|
|
||||||
return ImmutableMap.copyOf(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Property> getOrderedValues()
|
|
||||||
{
|
|
||||||
if (this.propertyOrder != null)
|
|
||||||
{
|
|
||||||
ArrayList<Property> set = new ArrayList<Property>();
|
|
||||||
for (String key : this.propertyOrder)
|
|
||||||
if (properties.containsKey(key))
|
|
||||||
set.add(properties.get(key));
|
|
||||||
|
|
||||||
return ImmutableList.copyOf(set);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return ImmutableList.copyOf(properties.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigCategory setConfigEntryClass(Class<? extends IConfigEntry> clazz)
|
|
||||||
{
|
|
||||||
this.customEntryClass = clazz;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<? extends IConfigEntry> getConfigEntryClass()
|
|
||||||
{
|
|
||||||
return this.customEntryClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigCategory setLanguageKey(String languagekey)
|
|
||||||
{
|
|
||||||
this.languagekey = languagekey;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLanguagekey()
|
|
||||||
{
|
|
||||||
if (this.languagekey != null)
|
|
||||||
return this.languagekey;
|
|
||||||
else
|
|
||||||
return getQualifiedName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setComment(String comment)
|
|
||||||
{
|
|
||||||
this.comment = comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getComment()
|
|
||||||
{
|
|
||||||
return this.comment;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the flag for whether or not this category can be edited while a world is running. Care should be taken to ensure
|
|
||||||
* that only properties that are truly dynamic can be changed from the in-game options menu. Only set this flag to
|
|
||||||
* true if all child properties/categories are unable to be modified while a world is running.
|
|
||||||
*/
|
|
||||||
public ConfigCategory setRequiresWorldRestart(boolean requiresWorldRestart)
|
|
||||||
{
|
|
||||||
this.requiresWorldRestart = requiresWorldRestart;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not this category is able to be edited while a world is running using the in-game Mod Options screen
|
|
||||||
* as well as the Mods list screen, or only from the Mods list screen.
|
|
||||||
*/
|
|
||||||
public boolean requiresWorldRestart()
|
|
||||||
{
|
|
||||||
return this.requiresWorldRestart;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether or not this ConfigCategory should be allowed to show on config GUIs.
|
|
||||||
* Defaults to true.
|
|
||||||
*/
|
|
||||||
public ConfigCategory setShowInGui(boolean showInGui)
|
|
||||||
{
|
|
||||||
this.showInGui = showInGui;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether or not this ConfigCategory should be allowed to show on config GUIs.
|
|
||||||
* Defaults to true unless set to false.
|
|
||||||
*/
|
|
||||||
public boolean showInGui()
|
|
||||||
{
|
|
||||||
return showInGui;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets whether or not this ConfigCategory requires Minecraft to be restarted when changed.
|
|
||||||
* Defaults to false. Only set this flag to true if ALL child properties/categories require
|
|
||||||
* Minecraft to be restarted when changed. Setting this flag will also prevent modification
|
|
||||||
* of the child properties/categories while a world is running.
|
|
||||||
*/
|
|
||||||
public ConfigCategory setRequiresMcRestart(boolean requiresMcRestart)
|
|
||||||
{
|
|
||||||
this.requiresMcRestart = this.requiresWorldRestart = requiresMcRestart;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets whether or not this ConfigCategory requires Minecraft to be restarted when changed.
|
|
||||||
* Defaults to false unless set to true.
|
|
||||||
*/
|
|
||||||
public boolean requiresMcRestart()
|
|
||||||
{
|
|
||||||
return this.requiresMcRestart;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigCategory setPropertyOrder(List<String> propertyOrder)
|
|
||||||
{
|
|
||||||
this.propertyOrder = propertyOrder;
|
|
||||||
for (String s : properties.keySet())
|
|
||||||
if (!propertyOrder.contains(s))
|
|
||||||
propertyOrder.add(s);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> getPropertyOrder()
|
|
||||||
{
|
|
||||||
if (this.propertyOrder != null)
|
|
||||||
return ImmutableList.copyOf(this.propertyOrder);
|
|
||||||
else
|
|
||||||
return ImmutableList.copyOf(properties.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean containsKey(String key)
|
|
||||||
{
|
|
||||||
return properties.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Property get(String key)
|
|
||||||
{
|
|
||||||
return properties.get(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void write(BufferedWriter out, String... data) throws IOException
|
|
||||||
{
|
|
||||||
write(out, true, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void write(BufferedWriter out, boolean new_line, String... data) throws IOException
|
|
||||||
{
|
|
||||||
for (int x = 0; x < data.length; x++)
|
|
||||||
{
|
|
||||||
out.write(data[x]);
|
|
||||||
}
|
|
||||||
if (new_line) out.write(NEW_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void write(BufferedWriter out, int indent) throws IOException
|
|
||||||
{
|
|
||||||
String pad0 = getIndent(indent);
|
|
||||||
String pad1 = getIndent(indent + 1);
|
|
||||||
String pad2 = getIndent(indent + 2);
|
|
||||||
|
|
||||||
if (comment != null && !comment.isEmpty())
|
|
||||||
{
|
|
||||||
write(out, pad0, COMMENT_SEPARATOR);
|
|
||||||
write(out, pad0, "# ", name);
|
|
||||||
write(out, pad0, "#--------------------------------------------------------------------------------------------------------#");
|
|
||||||
Splitter splitter = Splitter.onPattern("\r?\n");
|
|
||||||
|
|
||||||
for (String line : splitter.split(comment))
|
|
||||||
{
|
|
||||||
write(out, pad0, "# ", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
write(out, pad0, COMMENT_SEPARATOR, NEW_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
String displayName = name;
|
|
||||||
|
|
||||||
if (!allowedProperties.matchesAllOf(name))
|
|
||||||
{
|
|
||||||
displayName = '"' + name + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
write(out, pad0, displayName, " {");
|
|
||||||
|
|
||||||
Property[] props = getOrderedValues().toArray(new Property[] {});
|
|
||||||
|
|
||||||
for (int x = 0; x < props.length; x++)
|
|
||||||
{
|
|
||||||
Property prop = props[x];
|
|
||||||
|
|
||||||
if (prop.getComment() != null && !prop.getComment().isEmpty())
|
|
||||||
{
|
|
||||||
if (x != 0)
|
|
||||||
{
|
|
||||||
out.newLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
Splitter splitter = Splitter.onPattern("\r?\n");
|
|
||||||
for (String commentLine : splitter.split(prop.getComment()))
|
|
||||||
{
|
|
||||||
write(out, pad1, "# ", commentLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String propName = prop.getName();
|
|
||||||
|
|
||||||
if (!allowedProperties.matchesAllOf(propName))
|
|
||||||
{
|
|
||||||
propName = '"' + propName + '"';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prop.isList())
|
|
||||||
{
|
|
||||||
char type = prop.getType().getID();
|
|
||||||
|
|
||||||
write(out, pad1, String.valueOf(type), ":", propName, " <");
|
|
||||||
|
|
||||||
for (String line : prop.getStringList())
|
|
||||||
{
|
|
||||||
write(out, pad2, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
write(out, pad1, " >");
|
|
||||||
}
|
|
||||||
else if (prop.getType() == null)
|
|
||||||
{
|
|
||||||
write(out, pad1, propName, "=", prop.getString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char type = prop.getType().getID();
|
|
||||||
write(out, pad1, String.valueOf(type), ":", propName, "=", prop.getString());
|
|
||||||
}
|
|
||||||
|
|
||||||
prop.resetChangedState();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (children.size() > 0)
|
|
||||||
out.newLine();
|
|
||||||
|
|
||||||
for (ConfigCategory child : children)
|
|
||||||
{
|
|
||||||
child.write(out, indent + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
write(out, pad0, "}", NEW_LINE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getIndent(int indent)
|
|
||||||
{
|
|
||||||
StringBuilder buf = new StringBuilder("");
|
|
||||||
for (int x = 0; x < indent; x++)
|
|
||||||
{
|
|
||||||
buf.append(" ");
|
|
||||||
}
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasChanged()
|
|
||||||
{
|
|
||||||
if (changed) return true;
|
|
||||||
for (Property prop : properties.values())
|
|
||||||
{
|
|
||||||
if (prop.hasChanged()) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void resetChangedState()
|
|
||||||
{
|
|
||||||
changed = false;
|
|
||||||
for (Property prop : properties.values())
|
|
||||||
{
|
|
||||||
prop.resetChangedState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Map bouncer functions for compatibility with older mods, to be removed once all mods stop using it.
|
|
||||||
@Override public int size(){ return properties.size(); }
|
|
||||||
@Override public boolean isEmpty() { return properties.isEmpty(); }
|
|
||||||
@Override public boolean containsKey(Object key) { return properties.containsKey(key); }
|
|
||||||
@Override public boolean containsValue(Object value){ return properties.containsValue(value); }
|
|
||||||
@Override public Property get(Object key) { return properties.get(key); }
|
|
||||||
@Override public Property put(String key, Property value)
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
if (this.propertyOrder != null && !this.propertyOrder.contains(key))
|
|
||||||
this.propertyOrder.add(key);
|
|
||||||
return properties.put(key, value);
|
|
||||||
}
|
|
||||||
@Override public Property remove(Object key)
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
return properties.remove(key);
|
|
||||||
}
|
|
||||||
@Override public void putAll(Map<? extends String, ? extends Property> m)
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
if (this.propertyOrder != null)
|
|
||||||
for (String key : m.keySet())
|
|
||||||
if (!this.propertyOrder.contains(key))
|
|
||||||
this.propertyOrder.add(key);
|
|
||||||
properties.putAll(m);
|
|
||||||
}
|
|
||||||
@Override public void clear()
|
|
||||||
{
|
|
||||||
changed = true;
|
|
||||||
properties.clear();
|
|
||||||
}
|
|
||||||
@Override public Set<String> keySet() { return properties.keySet(); }
|
|
||||||
@Override public Collection<Property> values() { return properties.values(); }
|
|
||||||
|
|
||||||
@Override //Immutable copy, changes will NOT be reflected in this category
|
|
||||||
public Set<java.util.Map.Entry<String, Property>> entrySet()
|
|
||||||
{
|
|
||||||
return ImmutableSet.copyOf(properties.entrySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<ConfigCategory> getChildren(){ return ImmutableSet.copyOf(children); }
|
|
||||||
|
|
||||||
public void removeChild(ConfigCategory child)
|
|
||||||
{
|
|
||||||
if (children.contains(child))
|
|
||||||
{
|
|
||||||
children.remove(child);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,363 +0,0 @@
|
||||||
/*
|
|
||||||
* Minecraft Forge
|
|
||||||
* Copyright (c) 2016-2018.
|
|
||||||
*
|
|
||||||
* This library 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 version 2.1
|
|
||||||
* of the License.
|
|
||||||
*
|
|
||||||
* This library 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 library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.minecraftforge.common.config;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
import net.minecraftforge.fml.client.config.ConfigGuiType;
|
|
||||||
import net.minecraftforge.fml.client.config.DummyConfigElement.DummyCategoryElement;
|
|
||||||
import net.minecraftforge.fml.client.config.IConfigEntry;
|
|
||||||
import net.minecraftforge.fml.client.config.IArrayEntry;
|
|
||||||
import net.minecraftforge.fml.client.config.IConfigElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class bridges the gap between the FML config GUI classes and the Forge Configuration classes.
|
|
||||||
*/
|
|
||||||
public class ConfigElement implements IConfigElement
|
|
||||||
{
|
|
||||||
private Property prop;
|
|
||||||
private Property.Type type;
|
|
||||||
private boolean isProperty;
|
|
||||||
private ConfigCategory category;
|
|
||||||
private boolean categoriesFirst = true;
|
|
||||||
|
|
||||||
public ConfigElement(ConfigCategory category)
|
|
||||||
{
|
|
||||||
this.category = category;
|
|
||||||
isProperty = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigElement(Property prop)
|
|
||||||
{
|
|
||||||
this.prop = prop;
|
|
||||||
this.type = prop.getType();
|
|
||||||
this.isProperty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigElement listCategoriesFirst(boolean categoriesFirst)
|
|
||||||
{
|
|
||||||
this.categoriesFirst = categoriesFirst;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<IConfigElement> getChildElements()
|
|
||||||
{
|
|
||||||
if (!isProperty)
|
|
||||||
{
|
|
||||||
List<IConfigElement> elements = new ArrayList<IConfigElement>();
|
|
||||||
Iterator<ConfigCategory> ccI = category.getChildren().iterator();
|
|
||||||
Iterator<Property> pI = category.getOrderedValues().iterator();
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
if (categoriesFirst)
|
|
||||||
while (ccI.hasNext())
|
|
||||||
{
|
|
||||||
ConfigElement temp = new ConfigElement(ccI.next());
|
|
||||||
if (temp.showInGui()) // don't bother adding elements that shouldn't show
|
|
||||||
elements.add(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (pI.hasNext())
|
|
||||||
{
|
|
||||||
ConfigElement temp = new ConfigElement(pI.next());
|
|
||||||
if (temp.showInGui())
|
|
||||||
elements.add(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!categoriesFirst)
|
|
||||||
while (ccI.hasNext())
|
|
||||||
{
|
|
||||||
ConfigElement temp = new ConfigElement(ccI.next());
|
|
||||||
if (temp.showInGui())
|
|
||||||
elements.add(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getName() : category.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isProperty()
|
|
||||||
{
|
|
||||||
return isProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends IConfigEntry> getConfigEntryClass()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getConfigEntryClass() : category.getConfigEntryClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<? extends IArrayEntry> getArrayEntryClass()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getArrayEntryClass() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getQualifiedName()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getName() : category.getQualifiedName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ConfigGuiType getType()
|
|
||||||
{
|
|
||||||
return isProperty ? getType(this.prop) : ConfigGuiType.CONFIG_CATEGORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ConfigGuiType getType(Property prop)
|
|
||||||
{
|
|
||||||
return prop.getType() == Property.Type.BOOLEAN ? ConfigGuiType.BOOLEAN : prop.getType() == Property.Type.DOUBLE ? ConfigGuiType.DOUBLE :
|
|
||||||
prop.getType() == Property.Type.INTEGER ? ConfigGuiType.INTEGER : prop.getType() == Property.Type.COLOR ? ConfigGuiType.COLOR :
|
|
||||||
prop.getType() == Property.Type.MOD_ID ? ConfigGuiType.MOD_ID : ConfigGuiType.STRING;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isList()
|
|
||||||
{
|
|
||||||
return isProperty && prop.isList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isListLengthFixed()
|
|
||||||
{
|
|
||||||
return isProperty && prop.isListLengthFixed();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getMaxListLength()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getMaxListLength() : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getComment()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getComment() : category.getComment();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDefault()
|
|
||||||
{
|
|
||||||
return !isProperty || prop.isDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setToDefault()
|
|
||||||
{
|
|
||||||
if (isProperty)
|
|
||||||
prop.setToDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requiresWorldRestart()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.requiresWorldRestart() : category.requiresWorldRestart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showInGui()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.showInGui() : category.showInGui();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requiresMcRestart()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.requiresMcRestart() : category.requiresMcRestart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] getValidValues()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getValidValues() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLanguageKey()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getLanguageKey() : category.getLanguagekey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getDefault()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getDefault() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] getDefaults()
|
|
||||||
{
|
|
||||||
if (isProperty)
|
|
||||||
{
|
|
||||||
String[] aVal = prop.getDefaults();
|
|
||||||
if (type == Property.Type.BOOLEAN)
|
|
||||||
{
|
|
||||||
Boolean[] ba = new Boolean[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
ba[i] = Boolean.valueOf(aVal[i]);
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
else if (type == Property.Type.DOUBLE)
|
|
||||||
{
|
|
||||||
Double[] da = new Double[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
da[i] = Double.valueOf(aVal[i].toString());
|
|
||||||
return da;
|
|
||||||
}
|
|
||||||
else if (type == Property.Type.INTEGER)
|
|
||||||
{
|
|
||||||
Integer[] ia = new Integer[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
ia[i] = Integer.valueOf(aVal[i].toString());
|
|
||||||
return ia;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return aVal;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pattern getValidationPattern()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getValidationPattern() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object get()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getString() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] getList()
|
|
||||||
{
|
|
||||||
if (isProperty)
|
|
||||||
{
|
|
||||||
String[] aVal = prop.getStringList();
|
|
||||||
if (type == Property.Type.BOOLEAN)
|
|
||||||
{
|
|
||||||
Boolean[] ba = new Boolean[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
ba[i] = Boolean.valueOf(aVal[i]);
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
else if (type == Property.Type.DOUBLE)
|
|
||||||
{
|
|
||||||
Double[] da = new Double[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
da[i] = Double.valueOf(aVal[i].toString());
|
|
||||||
return da;
|
|
||||||
}
|
|
||||||
else if (type == Property.Type.INTEGER)
|
|
||||||
{
|
|
||||||
Integer[] ia = new Integer[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
ia[i] = Integer.valueOf(aVal[i].toString());
|
|
||||||
return ia;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return aVal;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(Object value)
|
|
||||||
{
|
|
||||||
if (isProperty)
|
|
||||||
{
|
|
||||||
if (type == Property.Type.BOOLEAN)
|
|
||||||
prop.set(Boolean.parseBoolean(value.toString()));
|
|
||||||
else if (type == Property.Type.DOUBLE)
|
|
||||||
prop.set(Double.parseDouble(value.toString()));
|
|
||||||
else if (type == Property.Type.INTEGER)
|
|
||||||
prop.set(Integer.parseInt(value.toString()));
|
|
||||||
else
|
|
||||||
prop.set(value.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(Object[] aVal)
|
|
||||||
{
|
|
||||||
if (isProperty)
|
|
||||||
{
|
|
||||||
if (type == Property.Type.BOOLEAN)
|
|
||||||
{
|
|
||||||
boolean[] ba = new boolean[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
ba[i] = Boolean.valueOf(aVal[i].toString());
|
|
||||||
prop.set(ba);
|
|
||||||
}
|
|
||||||
else if (type == Property.Type.DOUBLE)
|
|
||||||
{
|
|
||||||
double[] da = new double[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
da[i] = Double.valueOf(aVal[i].toString());
|
|
||||||
prop.set(da);
|
|
||||||
}
|
|
||||||
else if (type == Property.Type.INTEGER)
|
|
||||||
{
|
|
||||||
int[] ia = new int[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
ia[i] = Integer.valueOf(aVal[i].toString());
|
|
||||||
prop.set(ia);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String[] is = new String[aVal.length];
|
|
||||||
for(int i = 0; i < aVal.length; i++)
|
|
||||||
is[i] = aVal[i].toString();
|
|
||||||
prop.set(is);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getMinValue()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getMinValue() : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getMaxValue()
|
|
||||||
{
|
|
||||||
return isProperty ? prop.getMaxValue() : null;
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue