Fix the rest of the "easy" compile errors (#5151)
* Add Entity.changeDimension patch and transitively required patches * Fix throws declaration on CommandSetDimension#execute * Fix rest of errors in fluid package * Add PLAYER_REACH attribute * Fix compile errors in fml.client.config and add GuiButton patch * Delete unnecessary client.config classes, fix all config errors * Comment some fluid errors in models * Fix all errors in common package root, except ForgeHooks * Mass comment network package * Experimental conversion of extended states to generic base class * Fix errors in common.util * Remove config annotation stuff cuz lex said so * Make extended state stuff compile fully
This commit is contained in:
parent
6814cbf0df
commit
c4cf950863
72 changed files with 610 additions and 5996 deletions
|
@ -0,0 +1,22 @@
|
|||
--- a/net/minecraft/client/gui/GuiButton.java
|
||||
+++ b/net/minecraft/client/gui/GuiButton.java
|
||||
@@ -22,6 +22,7 @@
|
||||
public boolean visible;
|
||||
protected boolean hovered;
|
||||
private boolean field_194832_o;
|
||||
+ public int packedFGColor; // FML
|
||||
|
||||
public GuiButton(int buttonId, int x, int y, String buttonText) {
|
||||
this(buttonId, x, y, 200, 20, buttonText);
|
||||
@@ -66,6 +67,11 @@
|
||||
this.drawTexturedModalRect(this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
|
||||
this.mouseDragged(minecraft, p_194828_1_, p_194828_2_);
|
||||
int j = 14737632;
|
||||
+ if (packedFGColor != 0)
|
||||
+ {
|
||||
+ j = packedFGColor;
|
||||
+ }
|
||||
+ else
|
||||
if (!this.enabled) {
|
||||
j = 10526880;
|
||||
} else if (this.hovered) {
|
|
@ -26,3 +26,60 @@
|
|||
}
|
||||
|
||||
public EntityType<?> func_200600_R() {
|
||||
@@ -2053,6 +2056,14 @@
|
||||
|
||||
@Nullable
|
||||
public Entity changeDimension(int dimensionIn) {
|
||||
+ if (this.world.isRemote || this.isDead) return null;
|
||||
+ return changeDimension(dimensionIn, this.getServer().getWorld(dimensionIn).getDefaultTeleporter());
|
||||
+ }
|
||||
+
|
||||
+ @Nullable // Forge: Entities that require custom handling should override this method, not the other
|
||||
+ public Entity changeDimension(int dimensionIn, net.minecraftforge.common.util.ITeleporter teleporter)
|
||||
+ {
|
||||
+ if (!net.minecraftforge.common.ForgeHooks.onTravelToDimension(this, dimensionIn)) return null;
|
||||
if (!this.world.isRemote && !this.isDead) {
|
||||
this.world.profiler.startSection("changeDimension");
|
||||
MinecraftServer minecraftserver = this.getServer();
|
||||
@@ -2060,7 +2071,7 @@
|
||||
WorldServer worldserver = minecraftserver.getWorld(i);
|
||||
WorldServer worldserver1 = minecraftserver.getWorld(dimensionIn);
|
||||
this.dimension = dimensionIn;
|
||||
- if (i == 1 && dimensionIn == 1) {
|
||||
+ if (i == 1 && dimensionIn == 1 && teleporter.isVanilla()) {
|
||||
worldserver1 = minecraftserver.func_200667_a(DimensionType.OVERWORLD);
|
||||
this.dimension = 0;
|
||||
}
|
||||
@@ -2069,16 +2080,17 @@
|
||||
this.isDead = false;
|
||||
this.world.profiler.startSection("reposition");
|
||||
BlockPos blockpos;
|
||||
- if (dimensionIn == 1) {
|
||||
+ if (dimensionIn == 1 && teleporter.isVanilla()) {
|
||||
blockpos = worldserver1.getSpawnCoordinate();
|
||||
} else {
|
||||
- double d0 = this.posX;
|
||||
- double d1 = this.posZ;
|
||||
+ double moveFactor = worldserver.provider.getMovementFactor() / worldserver1.provider.getMovementFactor();
|
||||
+ double d0 = MathHelper.clamp(this.posX * moveFactor, worldserver1.getWorldBorder().minX() + 16.0D, worldserver1.getWorldBorder().maxX() - 16.0D);
|
||||
+ double d1 = MathHelper.clamp(this.posZ * moveFactor, worldserver1.getWorldBorder().minZ() + 16.0D, worldserver1.getWorldBorder().maxZ() - 16.0D);
|
||||
double d2 = 8.0D;
|
||||
- if (dimensionIn == -1) {
|
||||
+ if (false && dimensionIn == -1) {
|
||||
d0 = MathHelper.clamp(d0 / 8.0D, worldserver1.getWorldBorder().minX() + 16.0D, worldserver1.getWorldBorder().maxX() - 16.0D);
|
||||
d1 = MathHelper.clamp(d1 / 8.0D, worldserver1.getWorldBorder().minZ() + 16.0D, worldserver1.getWorldBorder().maxZ() - 16.0D);
|
||||
- } else if (dimensionIn == 0) {
|
||||
+ } else if (false && dimensionIn == 0) {
|
||||
d0 = MathHelper.clamp(d0 * 8.0D, worldserver1.getWorldBorder().minX() + 16.0D, worldserver1.getWorldBorder().maxX() - 16.0D);
|
||||
d1 = MathHelper.clamp(d1 * 8.0D, worldserver1.getWorldBorder().minZ() + 16.0D, worldserver1.getWorldBorder().maxZ() - 16.0D);
|
||||
}
|
||||
@@ -2087,8 +2099,7 @@
|
||||
d1 = (double)MathHelper.clamp((int)d1, -29999872, 29999872);
|
||||
float f = this.rotationYaw;
|
||||
this.setLocationAndAngles(d0, this.posY, d1, 90.0F, 0.0F);
|
||||
- Teleporter teleporter = worldserver1.getDefaultTeleporter();
|
||||
- teleporter.placeInExistingPortal(this, f);
|
||||
+ teleporter.placeEntity(worldserver1, this, f);
|
||||
blockpos = new BlockPos(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/entity/player/EntityPlayer.java
|
||||
+++ b/net/minecraft/entity/player/EntityPlayer.java
|
||||
@@ -97,6 +97,8 @@
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
||||
public abstract class EntityPlayer extends EntityLivingBase {
|
||||
+ public static final net.minecraft.entity.ai.attributes.IAttribute REACH_DISTANCE = new net.minecraft.entity.ai.attributes.RangedAttribute(null, "generic.reachDistance", 5.0D, 0.0D, 1024.0D).setShouldWatch(true);
|
||||
+
|
||||
private static final DataParameter<Float> ABSORPTION = EntityDataManager.<Float>createKey(EntityPlayer.class, DataSerializers.FLOAT);
|
||||
private static final DataParameter<Integer> PLAYER_SCORE = EntityDataManager.<Integer>createKey(EntityPlayer.class, DataSerializers.VARINT);
|
||||
protected static final DataParameter<Byte> PLAYER_MODEL_FLAG = EntityDataManager.<Byte>createKey(EntityPlayer.class, DataSerializers.BYTE);
|
11
patches/minecraft/net/minecraft/item/ItemArmor.java.patch
Normal file
11
patches/minecraft/net/minecraft/item/ItemArmor.java.patch
Normal file
|
@ -0,0 +1,11 @@
|
|||
--- a/net/minecraft/item/ItemArmor.java
|
||||
+++ b/net/minecraft/item/ItemArmor.java
|
||||
@@ -105,4 +105,8 @@
|
||||
public int func_200881_e() {
|
||||
return this.damageReduceAmount;
|
||||
}
|
||||
+
|
||||
+ public float getToughness() {
|
||||
+ return this.toughness;
|
||||
+ }
|
||||
}
|
|
@ -1,6 +1,34 @@
|
|||
--- a/net/minecraft/server/MinecraftServer.java
|
||||
+++ b/net/minecraft/server/MinecraftServer.java
|
||||
@@ -523,6 +523,7 @@
|
||||
@@ -130,7 +130,7 @@
|
||||
private final DataFixer dataFixer;
|
||||
private String hostname;
|
||||
private int serverPort = -1;
|
||||
- public WorldServer[] worlds;
|
||||
+ public WorldServer[] worlds = new WorldServer[0];
|
||||
private PlayerList playerList;
|
||||
private boolean serverRunning = true;
|
||||
private boolean serverStopped;
|
||||
@@ -148,7 +148,8 @@
|
||||
private int buildLimit;
|
||||
private int maxPlayerIdleMinutes;
|
||||
public final long[] tickTimeArray = new long[100];
|
||||
- public long[][] timeOfLastDimensionTick;
|
||||
+ //public long[][] timeOfLastDimensionTick;
|
||||
+ public java.util.Hashtable<Integer, long[]> worldTickTimes = new java.util.Hashtable<Integer, long[]>();
|
||||
private KeyPair serverKeyPair;
|
||||
private String serverOwner;
|
||||
private String folderName;
|
||||
@@ -287,8 +288,6 @@
|
||||
public void loadAllWorlds(String saveName, String worldNameIn, long seed, WorldType type, JsonElement generatorOptions) {
|
||||
this.convertMapIfNeeded(saveName);
|
||||
this.func_200245_b(new TextComponentTranslation("menu.loadingLevel", new Object[0]));
|
||||
- this.worlds = new WorldServer[3];
|
||||
- this.timeOfLastDimensionTick = new long[this.worlds.length][100];
|
||||
ISaveHandler isavehandler = this.anvilConverterForAnvilFile.func_197715_a(saveName, this);
|
||||
this.setResourcePackFromWorld(this.getFolderName(), isavehandler);
|
||||
WorldInfo worldinfo = isavehandler.loadWorldInfo();
|
||||
@@ -523,6 +522,7 @@
|
||||
public void run() {
|
||||
try {
|
||||
if (this.init()) {
|
||||
|
@ -8,7 +36,7 @@
|
|||
this.field_211151_aa = Util.func_211177_b();
|
||||
this.statusResponse.setServerDescription(new TextComponentString(this.motd));
|
||||
this.statusResponse.setVersion(new ServerStatusResponse.Version("1.13", 393));
|
||||
@@ -546,7 +547,10 @@
|
||||
@@ -546,7 +546,10 @@
|
||||
|
||||
this.serverIsRunning = true;
|
||||
}
|
||||
|
@ -19,7 +47,7 @@
|
|||
this.finalTick((CrashReport)null);
|
||||
}
|
||||
} catch (Throwable throwable1) {
|
||||
@@ -565,6 +569,7 @@
|
||||
@@ -565,6 +568,7 @@
|
||||
LOGGER.error("We were unable to save this crash report to disk.");
|
||||
}
|
||||
|
||||
|
@ -27,7 +55,7 @@
|
|||
this.finalTick(crashreport);
|
||||
} finally {
|
||||
try {
|
||||
@@ -573,6 +578,7 @@
|
||||
@@ -573,6 +577,7 @@
|
||||
} catch (Throwable throwable) {
|
||||
LOGGER.error("Exception stopping the server", throwable);
|
||||
} finally {
|
||||
|
@ -35,3 +63,28 @@
|
|||
this.systemExitNow();
|
||||
}
|
||||
|
||||
@@ -686,10 +691,12 @@
|
||||
this.getFunctionManager().update();
|
||||
this.profiler.endStartSection("levels");
|
||||
|
||||
- for(int i = 0; i < this.worlds.length; ++i) {
|
||||
+ Integer[] ids = net.minecraftforge.common.DimensionManager.getIDs(this.tickCounter % 200 == 0);
|
||||
+ for(int x = 0; x < ids.length; ++x) {
|
||||
+ int id = ids[x];
|
||||
long j = Util.func_211178_c();
|
||||
- if (i == 0 || this.getAllowNether()) {
|
||||
- WorldServer worldserver = this.worlds[i];
|
||||
+ if (id == 0 || this.getAllowNether()) {
|
||||
+ WorldServer worldserver = net.minecraftforge.common.DimensionManager.getWorld(id);
|
||||
this.profiler.func_194340_a(() -> {
|
||||
return worldserver.getWorldInfo().getWorldName();
|
||||
});
|
||||
@@ -724,7 +731,7 @@
|
||||
this.profiler.endSection();
|
||||
}
|
||||
|
||||
- this.timeOfLastDimensionTick[i][this.tickCounter % 100] = Util.func_211178_c() - j;
|
||||
+ worldTickTimes.get(id)[this.tickCounter % 100] = Util.func_211178_c() - j;
|
||||
}
|
||||
|
||||
this.profiler.endStartSection("connection");
|
||||
|
|
25
patches/minecraft/net/minecraft/world/Teleporter.java.patch
Normal file
25
patches/minecraft/net/minecraft/world/Teleporter.java.patch
Normal file
|
@ -0,0 +1,25 @@
|
|||
--- a/net/minecraft/world/Teleporter.java
|
||||
+++ b/net/minecraft/world/Teleporter.java
|
||||
@@ -15,7 +15,7 @@
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
-public class Teleporter {
|
||||
+public class Teleporter implements net.minecraftforge.common.util.ITeleporter {
|
||||
private static final BlockPortal field_196236_a = (BlockPortal)Blocks.PORTAL;
|
||||
protected final WorldServer world;
|
||||
protected final Random random;
|
||||
@@ -334,4 +334,13 @@
|
||||
this.lastUpdateTime = lastUpdate;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ @Override
|
||||
+ public void placeEntity(World world, Entity entity, float yaw)
|
||||
+ {
|
||||
+ if (entity instanceof EntityPlayerMP)
|
||||
+ placeInPortal(entity, yaw);
|
||||
+ else
|
||||
+ placeInExistingPortal(entity, yaw);
|
||||
+ }
|
||||
}
|
|
@ -1,5 +1,14 @@
|
|||
--- a/net/minecraft/world/WorldServer.java
|
||||
+++ b/net/minecraft/world/WorldServer.java
|
||||
@@ -85,7 +85,7 @@
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
-public class WorldServer extends World implements IThreadListener {
|
||||
+public class WorldServer extends World implements IThreadListener, net.minecraftforge.common.extensions.IForgeWorldServer {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private final MinecraftServer server;
|
||||
private final EntityTracker entityTracker;
|
||||
@@ -150,6 +150,7 @@
|
||||
this.getWorldBorder().setTransition(this.worldInfo.getBorderSize());
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
--- a/net/minecraft/world/dimension/DimensionType.java
|
||||
+++ b/net/minecraft/world/dimension/DimensionType.java
|
||||
@@ -11,12 +11,19 @@
|
||||
private final String name;
|
||||
private final String suffix;
|
||||
private final Supplier<? extends Dimension> field_201038_g;
|
||||
+ private final boolean shouldLoadSpawn;
|
||||
|
||||
private DimensionType(int p_i48278_3_, String p_i48278_4_, String p_i48278_5_, Supplier<? extends Dimension> p_i48278_6_) {
|
||||
+ this(p_i48278_3_, p_i48278_4_, p_i48278_5_, p_i48278_6_, p_i48278_3_ == 0);
|
||||
+ }
|
||||
+
|
||||
+ private DimensionType(int p_i48278_3_, String p_i48278_4_, String p_i48278_5_, Supplier<? extends Dimension> p_i48278_6_, boolean shouldLoadSpawn)
|
||||
+ {
|
||||
this.id = p_i48278_3_;
|
||||
this.name = p_i48278_4_;
|
||||
this.suffix = p_i48278_5_;
|
||||
this.field_201038_g = p_i48278_6_;
|
||||
+ this.shouldLoadSpawn = shouldLoadSpawn;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
@@ -54,4 +61,11 @@
|
||||
|
||||
throw new IllegalArgumentException("Invalid dimension " + nameIn);
|
||||
}
|
||||
+
|
||||
+ public boolean shouldLoadSpawn(){ return this.shouldLoadSpawn; }
|
||||
+
|
||||
+ public static DimensionType create(int id, String name, String suffix, Supplier<? extends Dimension> provider, boolean shouldLoadSpawn)
|
||||
+ {
|
||||
+ return null;
|
||||
+ }
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
package net.minecraftforge.client.gui;
|
||||
|
||||
/*
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
@ -93,6 +93,7 @@ import static net.minecraftforge.common.ForgeMod.VERSION_CHECK_CAT;
|
|||
* ForgeChunkManager.syncConfigDefaults()
|
||||
* ForgeChunkManager.loadConfiguration()
|
||||
*/
|
||||
/* TODO Config gui
|
||||
public class ForgeGuiFactory implements IModGuiFactory
|
||||
{
|
||||
@Override
|
||||
|
@ -125,10 +126,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides the General Settings entry on the Minecraft Forge Configuration screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
*/
|
||||
*//*
|
||||
public static class GeneralEntry extends CategoryEntry
|
||||
{
|
||||
public GeneralEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -149,10 +150,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides the Client only Settings entry on the Minecraft Forge Configuration screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
*/
|
||||
*//*
|
||||
public static class ClientEntry extends CategoryEntry
|
||||
{
|
||||
public ClientEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -173,10 +174,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides the Forge Chunk Manager Config entry on the Minecraft Forge Configuration screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
*/
|
||||
*//*
|
||||
public static class ChunkLoaderEntry extends CategoryEntry
|
||||
{
|
||||
public ChunkLoaderEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -203,10 +204,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides the Forge Version Checking Config entry on the Minecraft Forge Configuration screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
*/
|
||||
*//*
|
||||
public static class VersionCheckEntry extends CategoryEntry
|
||||
{
|
||||
public VersionCheckEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -225,13 +226,13 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
|
||||
List<Property> props = new ArrayList<Property>();
|
||||
// TODO
|
||||
/*
|
||||
|
||||
for (ModContainer mod : ForgeVersion.gatherMods().keySet())
|
||||
{
|
||||
values.remove(mod.getModId());
|
||||
props.add(ForgeMod.getConfig().get(VERSION_CHECK_CAT, mod.getModId(), true)); //Get or make the value in the config
|
||||
}
|
||||
*/
|
||||
|
||||
props.addAll(values.values()); // Add any left overs from the config
|
||||
props.sort(Comparator.comparing(Property::getName));
|
||||
|
||||
|
@ -251,11 +252,11 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides the Mod Overrides entry on the Forge Chunk Loading config screen.
|
||||
* It extends the base Category entry class and defines the IConfigElement objects that will be used to build the child screen.
|
||||
* In this case it adds the custom entry for adding a new mod override and lists the existing mod overrides.
|
||||
*/
|
||||
*//*
|
||||
public static class ModOverridesEntry extends CategoryEntry
|
||||
{
|
||||
public ModOverridesEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -263,9 +264,9 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
super(owningScreen, owningEntryList, prop);
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This method is called in the constructor and is used to set the childScreen field.
|
||||
*/
|
||||
*//*
|
||||
@Override
|
||||
protected GuiScreen buildChildScreen()
|
||||
{
|
||||
|
@ -282,10 +283,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
I18n.format("forge.configgui.ctgy.forgeChunkLoadingModConfig"));
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* By overriding the enabled() method and checking the value of the "enabled" entry this entry is enabled/disabled based on the value of
|
||||
* the other entry.
|
||||
*/
|
||||
*//*
|
||||
@Override
|
||||
public boolean enabled()
|
||||
{
|
||||
|
@ -300,9 +301,9 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* Check to see if the child screen's entry list has changed.
|
||||
*/
|
||||
*//*
|
||||
@Override
|
||||
public boolean isChanged()
|
||||
{
|
||||
|
@ -314,10 +315,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* Since adding a new entry to the child screen is what constitutes a change here, reset the child
|
||||
* screen listEntries to the saved list.
|
||||
*/
|
||||
*//*
|
||||
@Override
|
||||
public void undoChanges()
|
||||
{
|
||||
|
@ -333,9 +334,9 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides a button that will open to a screen that will allow a user to define a new mod override.
|
||||
*/
|
||||
*//*
|
||||
public static class AddModOverrideEntry extends CategoryEntry
|
||||
{
|
||||
public AddModOverrideEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -365,10 +366,10 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* This custom list entry provides a Mod ID selector. The control is a button that opens a list of values to select from.
|
||||
* This entry also overrides onGuiClosed() to run code to save the data to a new ConfigCategory when the user is done.
|
||||
*/
|
||||
*//*
|
||||
public static class ModIDEntry extends SelectValueEntry
|
||||
{
|
||||
public ModIDEntry(GuiConfig owningScreen, GuiConfigEntries owningEntryList, IConfigElement prop)
|
||||
|
@ -382,21 +383,21 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
{
|
||||
Map<Object, String> selectableValues = new TreeMap<Object, String>();
|
||||
// TODO
|
||||
/*
|
||||
|
||||
|
||||
for (ModContainer mod : Loader.instance().getActiveModList())
|
||||
// only add mods to the list that have a non-immutable ModContainer
|
||||
if (!mod.isImmutable() && mod.getMod() != null)
|
||||
selectableValues.put(mod.getModId(), mod.getName());
|
||||
|
||||
*/
|
||||
|
||||
return selectableValues;
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* By overriding onGuiClosed() for this entry we can perform additional actions when the user is done such as saving
|
||||
* a new ConfigCategory object to the Configuration object.
|
||||
*/
|
||||
*//*
|
||||
@Override
|
||||
public void onGuiClosed()
|
||||
{
|
||||
|
@ -437,4 +438,4 @@ public class ForgeGuiFactory implements IModGuiFactory
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
|
|
@ -198,7 +198,7 @@ public final class ModelDynBucket implements IUnbakedModel
|
|||
public ModelDynBucket process(ImmutableMap<String, String> customData)
|
||||
{
|
||||
String fluidName = customData.get("fluid");
|
||||
Fluid fluid = FluidRegistry.getFluid(fluidName);
|
||||
Fluid fluid = null; // TODO fluids FluidRegistry.getFluid(fluidName);
|
||||
|
||||
if (fluid == null) fluid = this.fluid;
|
||||
|
||||
|
|
|
@ -49,7 +49,6 @@ import net.minecraftforge.common.ForgeVersion;
|
|||
import net.minecraftforge.common.model.IModelState;
|
||||
import net.minecraftforge.common.model.TRSRTransformation;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.fluids.BlockFluidBase;
|
||||
import net.minecraftforge.fluids.Fluid;
|
||||
import net.minecraftforge.fluids.FluidRegistry;
|
||||
|
||||
|
@ -69,8 +68,8 @@ import com.google.gson.JsonParser;
|
|||
public final class ModelFluid implements IUnbakedModel
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
public static final ModelFluid WATER = new ModelFluid(FluidRegistry.WATER);
|
||||
public static final ModelFluid LAVA = new ModelFluid(FluidRegistry.LAVA);
|
||||
public static final ModelFluid WATER = null; // TODO fluids new ModelFluid(FluidRegistry.WATER);
|
||||
public static final ModelFluid LAVA = null; // TODO fluids new ModelFluid(FluidRegistry.LAVA);
|
||||
|
||||
private final Fluid fluid;
|
||||
|
||||
|
@ -180,7 +179,7 @@ public final class ModelFluid implements IUnbakedModel
|
|||
IExtendedBlockState state = stateOption.get();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Float level = state.getValue(BlockFluidBase.LEVEL_CORNERS[i]);
|
||||
Float level = null; // TODO fluids state.getValue(BlockFluidBase.LEVEL_CORNERS[i]);
|
||||
cornerRound[i] = Math.round((level == null ? 8f / 9f : level) * 864);
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +198,7 @@ public final class ModelFluid implements IUnbakedModel
|
|||
Float flow = -1000f;
|
||||
if (stateOption.isPresent())
|
||||
{
|
||||
flow = stateOption.get().getValue(BlockFluidBase.FLOW_DIRECTION);
|
||||
flow = null; // TODO fluids stateOption.get().getValue(BlockFluidBase.FLOW_DIRECTION);
|
||||
if (flow == null) flow = -1000f;
|
||||
}
|
||||
int flowRound = (int) Math.round(Math.toDegrees(flow));
|
||||
|
@ -222,7 +221,7 @@ public final class ModelFluid implements IUnbakedModel
|
|||
IExtendedBlockState state = stateOption.get();
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Boolean overlay = state.getValue(BlockFluidBase.SIDE_OVERLAYS[i]);
|
||||
Boolean overlay = null; // TODO fluids state.getValue(BlockFluidBase.SIDE_OVERLAYS[i]);
|
||||
if (overlay != null) overlaySides[i] = overlay;
|
||||
}
|
||||
}
|
||||
|
@ -510,12 +509,13 @@ public final class ModelFluid implements IUnbakedModel
|
|||
|
||||
String fluidStr = customData.get("fluid");
|
||||
JsonElement e = new JsonParser().parse(fluidStr);
|
||||
String fluid = e.getAsString();
|
||||
String fluid = e.getAsString();/* TODO fluids
|
||||
if(!FluidRegistry.isFluidRegistered(fluid))
|
||||
{
|
||||
LOGGER.fatal("fluid '{}' not found", fluid);
|
||||
return WATER;
|
||||
}
|
||||
return new ModelFluid(FluidRegistry.getFluid(fluid));
|
||||
return new ModelFluid(FluidRegistry.getFluid(fluid));*/
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -523,7 +523,7 @@ public final class ModelLoader extends ModelBakery
|
|||
if(exState.getUnlistedNames().contains(Properties.AnimationProperty))
|
||||
{
|
||||
IModelState newState = exState.getValue(Properties.AnimationProperty);
|
||||
IExtendedBlockState newExState = exState.withProperty(Properties.AnimationProperty, null);
|
||||
IExtendedBlockState newExState = (IExtendedBlockState) exState.withProperty(Properties.AnimationProperty, null);
|
||||
if(newState != null)
|
||||
{
|
||||
return VanillaModelWrapper.this.bake(modelGetter, bakedTextureGetter, new ModelStateComposition(modelState, newState), uvlock, format).func_200117_a(newExState, side, rand);
|
||||
|
|
|
@ -77,7 +77,7 @@ public class AnimationTESR<T extends TileEntity> extends FastTESR<T> implements
|
|||
|
||||
// TODO: caching?
|
||||
IBakedModel model = blockRenderer.getBlockModelShapes().getModelForState(exState.getClean());
|
||||
IExtendedBlockState animState = exState.withProperty(Properties.AnimationProperty, pair.getLeft());
|
||||
IExtendedBlockState animState = (IExtendedBlockState) exState.withProperty(Properties.AnimationProperty, pair.getLeft());
|
||||
|
||||
renderer.setTranslation(x - pos.getX(), y - pos.getY(), z - pos.getZ());
|
||||
|
||||
|
|
|
@ -67,7 +67,6 @@ import net.minecraftforge.common.model.TRSRTransformation;
|
|||
import net.minecraftforge.common.model.animation.IClip;
|
||||
import net.minecraftforge.common.model.animation.IJoint;
|
||||
import net.minecraftforge.common.property.IExtendedBlockState;
|
||||
import net.minecraftforge.common.property.IUnlistedProperty;
|
||||
import net.minecraftforge.common.property.Properties;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
@ -81,7 +80,6 @@ import com.google.common.base.Objects;
|
|||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
|
|
|
@ -411,7 +411,7 @@ public class DimensionManager
|
|||
finally
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(w));
|
||||
w.flush();
|
||||
w.close();
|
||||
setWorld(id, null, w.getMinecraftServer());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ import net.minecraftforge.common.config.Property;
|
|||
import net.minecraftforge.common.util.Constants;
|
||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
import net.minecraftforge.fml.ModContainer;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
|
||||
import com.google.common.cache.Cache;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
|
@ -505,7 +506,7 @@ public class ForgeChunkManager
|
|||
String modId = ticketHolder.getString("Owner");
|
||||
boolean isPlayer = ForgeVersion.MOD_ID.equals(modId);
|
||||
|
||||
if (!isPlayer && !Loader.isModLoaded(modId))
|
||||
if (!isPlayer && !ModList.get().isLoaded(modId))
|
||||
{
|
||||
LOGGER.warn(CHUNK_MANAGER, "Found chunkloading data for mod {} which is currently not available or active - it will be removed from the world save", modId);
|
||||
continue;
|
||||
|
@ -678,7 +679,7 @@ public class ForgeChunkManager
|
|||
|
||||
private static ModContainer getContainer(Object mod)
|
||||
{
|
||||
ModContainer container = Loader.instance().getModObjectList().inverse().get(mod);
|
||||
ModContainer container = ModList.get().getModContainerByObject(mod).orElse(null);
|
||||
return container;
|
||||
}
|
||||
|
||||
|
@ -1036,7 +1037,7 @@ public class ForgeChunkManager
|
|||
NBTTagList tileEntities = nbt.getTagList("TileEntities", Constants.NBT.TAG_COMPOUND);
|
||||
for (int i = 0; i < tileEntities.size(); ++i)
|
||||
{
|
||||
TileEntity tileEntity = TileEntity.create(world, tileEntities.getCompoundTagAt(i));
|
||||
TileEntity tileEntity = TileEntity.func_203403_c(tileEntities.getCompoundTagAt(i));
|
||||
if (tileEntity != null) chunk.addTileEntity(tileEntity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ import net.minecraft.item.ItemMonsterPlacer;
|
|||
import net.minecraft.item.ItemPickaxe;
|
||||
import net.minecraft.item.ItemPotion;
|
||||
import net.minecraft.item.ItemSpade;
|
||||
import net.minecraft.item.ItemSpawnEgg;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemTippedArrow;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
|
@ -120,6 +121,7 @@ import net.minecraft.world.storage.loot.LootEntry;
|
|||
import net.minecraft.world.storage.loot.LootTable;
|
||||
import net.minecraft.world.storage.loot.LootTableManager;
|
||||
import net.minecraft.world.storage.loot.conditions.LootCondition;
|
||||
import net.minecraftforge.common.crafting.CraftingHelper;
|
||||
import net.minecraftforge.common.util.BlockSnapshot;
|
||||
import net.minecraftforge.event.AnvilUpdateEvent;
|
||||
import net.minecraftforge.event.DifficultyChangeEvent;
|
||||
|
@ -1283,21 +1285,6 @@ public class ForgeHooks
|
|||
MinecraftForge.EVENT_BUS.post(new BlockEvent.CropGrowEvent.Post(worldIn, pos, state, worldIn.getBlockState(pos)));
|
||||
}
|
||||
|
||||
private static final ClassValue<String> registryNames = new ClassValue<String>()
|
||||
{
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected String computeValue(Class<?> type)
|
||||
{
|
||||
return String.valueOf(TileEntity.getKey((Class<? extends TileEntity>) type));
|
||||
}
|
||||
};
|
||||
|
||||
public static String getRegistryName(Class<? extends TileEntity> type)
|
||||
{
|
||||
return registryNames.get(type);
|
||||
}
|
||||
|
||||
public static boolean loadAdvancements(Map<ResourceLocation, Advancement.Builder> map)
|
||||
{
|
||||
boolean errored = false;
|
||||
|
@ -1370,7 +1357,7 @@ public class ForgeHooks
|
|||
true, true
|
||||
);
|
||||
}
|
||||
|
||||
/* TODO this should be unnecessary now?
|
||||
public static void sendRecipeBook(NetHandlerPlayServer connection, State state, List<IRecipe> recipes, List<IRecipe> display, boolean isGuiOpen, boolean isFilteringCraftable)
|
||||
{
|
||||
NetworkDispatcher disp = NetworkDispatcher.get(connection.getNetworkManager());
|
||||
|
@ -1386,7 +1373,7 @@ public class ForgeHooks
|
|||
if (!recipes.isEmpty() || !display.isEmpty())
|
||||
connection.sendPacket(new SPacketRecipeBook(state, recipes, display, isGuiOpen, isFilteringCraftable));
|
||||
}
|
||||
|
||||
*/
|
||||
public static void onAdvancement(EntityPlayerMP player, Advancement advancement)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(new AdvancementEvent(player, advancement));
|
||||
|
@ -1406,7 +1393,7 @@ public class ForgeHooks
|
|||
if (item instanceof ItemEnchantedBook)
|
||||
{
|
||||
NBTTagList enchantmentsNbt = ItemEnchantedBook.getEnchantments(itemStack);
|
||||
if (enchantmentsNbt.tagCount() == 1)
|
||||
if (enchantmentsNbt.size() == 1)
|
||||
{
|
||||
NBTTagCompound nbttagcompound = enchantmentsNbt.getCompoundTagAt(0);
|
||||
Enchantment enchantment = Enchantment.getEnchantmentByID(nbttagcompound.getShort("id"));
|
||||
|
@ -1429,9 +1416,9 @@ public class ForgeHooks
|
|||
return resourceLocation.getNamespace();
|
||||
}
|
||||
}
|
||||
else if (item instanceof ItemMonsterPlacer)
|
||||
else if (item instanceof ItemSpawnEgg)
|
||||
{
|
||||
ResourceLocation resourceLocation = ItemMonsterPlacer.getNamedIdFrom(itemStack);
|
||||
ResourceLocation resourceLocation = ((ItemSpawnEgg)item).func_208076_b(null).getRegistryName();
|
||||
if (resourceLocation != null)
|
||||
{
|
||||
return resourceLocation.getNamespace();
|
||||
|
|
|
@ -428,7 +428,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
|||
NBTTagCompound forgeData = new NBTTagCompound();
|
||||
NBTTagCompound dimData = DimensionManager.saveDimensionDataMap();
|
||||
forgeData.setTag("DimensionData", dimData);
|
||||
FluidRegistry.writeDefaultFluidList(forgeData);
|
||||
// TODO fluids FluidRegistry.writeDefaultFluidList(forgeData);
|
||||
return forgeData;
|
||||
}
|
||||
|
||||
|
@ -436,7 +436,7 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook
|
|||
public void readData(SaveHandler handler, WorldInfo info, NBTTagCompound tag)
|
||||
{
|
||||
DimensionManager.loadDimensionDataMap(tag.hasKey("DimensionData") ? tag.getCompoundTag("DimensionData") : null);
|
||||
FluidRegistry.loadFluidDefaults(tag);
|
||||
// TODO fluids FluidRegistry.loadFluidDefaults(tag);
|
||||
}
|
||||
|
||||
public void mappingChanged(FMLModIdMappingEvent evt)
|
||||
|
|
|
@ -169,8 +169,8 @@ public interface ISpecialArmor
|
|||
{
|
||||
ItemArmor armor = (ItemArmor)stack.getItem();
|
||||
prop = new ArmorProperties(0, 0, Integer.MAX_VALUE);
|
||||
prop.Armor = armor.damageReduceAmount;
|
||||
prop.Toughness = armor.toughness;
|
||||
prop.Armor = armor.func_200881_e();
|
||||
prop.Toughness = armor.getToughness();
|
||||
}
|
||||
if (prop != null)
|
||||
{
|
||||
|
|
|
@ -85,7 +85,7 @@ public class MinecraftForge
|
|||
|
||||
UsernameCache.load();
|
||||
// Load before all the mods, so MC owns the MC fluids
|
||||
FluidRegistry.validateFluidRegistry();
|
||||
// TODO Fluids FluidRegistry.validateFluidRegistry();
|
||||
ForgeHooks.initTools();
|
||||
|
||||
//For all the normal CrashReport classes to be defined. We're in MC's classloader so this should all be fine
|
||||
|
|
|
@ -34,6 +34,7 @@ import net.minecraft.world.dimension.Dimension;
|
|||
import net.minecraft.world.gen.feature.template.TemplateManager;
|
||||
import net.minecraft.world.storage.IPlayerFileData;
|
||||
import net.minecraft.world.storage.ISaveHandler;
|
||||
import net.minecraft.world.storage.SessionLockException;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.world.storage.WorldInfo;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
@ -55,7 +56,7 @@ public class WorldSpecificSaveHandler implements ISaveHandler
|
|||
}
|
||||
|
||||
@Override public WorldInfo loadWorldInfo() { return parent.loadWorldInfo(); }
|
||||
@Override public void checkSessionLock() throws MinecraftException { parent.checkSessionLock(); }
|
||||
@Override public void checkSessionLock() throws SessionLockException { parent.checkSessionLock(); }
|
||||
@Override public IChunkLoader getChunkLoader(Dimension var1) { return parent.getChunkLoader(var1); }
|
||||
@Override public void saveWorldInfoWithPlayer(WorldInfo var1, NBTTagCompound var2) { parent.saveWorldInfoWithPlayer(var1, var2); }
|
||||
@Override public void saveWorldInfo(WorldInfo var1){ parent.saveWorldInfo(var1); }
|
||||
|
|
|
@ -37,7 +37,7 @@ import com.google.common.collect.ImmutableList;
|
|||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.IConfigEntry;
|
||||
|
||||
public class ConfigCategory implements Map<String, Property>
|
||||
{
|
||||
|
|
|
@ -30,8 +30,8 @@ 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.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.IArrayEntry;
|
||||
import net.minecraftforge.fml.client.config.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.IArrayEntry;
|
||||
import net.minecraftforge.fml.client.config.IConfigElement;
|
||||
|
||||
/**
|
||||
|
@ -360,59 +360,4 @@ public class ConfigElement implements IConfigElement
|
|||
{
|
||||
return isProperty ? prop.getMaxValue() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a ConfigElement derived from the annotation-based config system
|
||||
* @param configClass the class which contains the configuration
|
||||
* @return A ConfigElement based on the described category.
|
||||
*/
|
||||
public static IConfigElement from(Class<?> configClass)
|
||||
{
|
||||
Config annotation = configClass.getAnnotation(Config.class);
|
||||
if (annotation == null)
|
||||
throw new RuntimeException(String.format("The class '%s' has no @Config annotation!", configClass.getName()));
|
||||
|
||||
Configuration config = ConfigManager.getConfiguration(annotation.modid(), annotation.name());
|
||||
if (config == null)
|
||||
{
|
||||
String error = String.format("The configuration '%s' of mod '%s' isn't loaded with the ConfigManager!", annotation.name(), annotation.modid());
|
||||
throw new RuntimeException(error);
|
||||
}
|
||||
|
||||
String name = Strings.isNullOrEmpty(annotation.name()) ? annotation.modid() : annotation.name();
|
||||
String langKey = name;
|
||||
Config.LangKey langKeyAnnotation = configClass.getAnnotation(Config.LangKey.class);
|
||||
if (langKeyAnnotation != null)
|
||||
{
|
||||
langKey = langKeyAnnotation.value();
|
||||
}
|
||||
|
||||
if (annotation.category().isEmpty())
|
||||
{
|
||||
List<IConfigElement> elements = Lists.newArrayList();
|
||||
Set<String> catNames = config.getCategoryNames();
|
||||
for (String catName : catNames)
|
||||
{
|
||||
if (catName.isEmpty())
|
||||
continue;
|
||||
ConfigCategory category = config.getCategory(catName);
|
||||
if (category.isChild())
|
||||
continue;
|
||||
DummyCategoryElement element = new DummyCategoryElement(category.getName(), category.getLanguagekey(), new ConfigElement(category).getChildElements());
|
||||
element.setRequiresMcRestart(category.requiresMcRestart());
|
||||
element.setRequiresWorldRestart(category.requiresWorldRestart());
|
||||
elements.add(element);
|
||||
}
|
||||
|
||||
return new DummyCategoryElement(name, langKey, elements);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigCategory category = config.getCategory(annotation.category());
|
||||
DummyCategoryElement element = new DummyCategoryElement(name, langKey, new ConfigElement(category).getChildElements());
|
||||
element.setRequiresMcRestart(category.requiresMcRestart());
|
||||
element.setRequiresWorldRestart(category.requiresWorldRestart());
|
||||
return element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,383 +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.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import net.minecraftforge.common.config.Config.Comment;
|
||||
import net.minecraftforge.common.config.Config.LangKey;
|
||||
import net.minecraftforge.common.config.Config.Name;
|
||||
import net.minecraftforge.fml.common.FMLPaths;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.fml.common.LoaderException;
|
||||
import net.minecraftforge.fml.loading.moddiscovery.ModAnnotation.EnumHolder;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
public class ConfigManager
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private static Map<String, Multimap<Config.Type, ASMData>> asm_data = Maps.newHashMap();
|
||||
static Map<Class<?>, ITypeAdapter> ADAPTERS = Maps.newHashMap();
|
||||
static Map<Class<?>, Class<?>> ARRAY_REMAP = Maps.newHashMap();
|
||||
private static Map<String, Configuration> CONFIGS = Maps.newHashMap();
|
||||
private static Map<String, Set<Class<?>>> MOD_CONFIG_CLASSES = Maps.newHashMap();
|
||||
|
||||
static
|
||||
{
|
||||
register(boolean.class, TypeAdapters.bool);
|
||||
register(boolean[].class, TypeAdapters.boolA);
|
||||
register(Boolean.class, TypeAdapters.Bool);
|
||||
register(Boolean[].class, TypeAdapters.BoolA);
|
||||
register(float.class, TypeAdapters.flt);
|
||||
register(float[].class, TypeAdapters.fltA);
|
||||
register(Float.class, TypeAdapters.Flt);
|
||||
register(Float[].class, TypeAdapters.FltA);
|
||||
register(double.class, TypeAdapters.dbl);
|
||||
register(double[].class, TypeAdapters.dblA);
|
||||
register(Double.class, TypeAdapters.Dbl);
|
||||
register(Double[].class, TypeAdapters.DblA);
|
||||
register(byte.class, TypeAdapters.byt);
|
||||
register(byte[].class, TypeAdapters.bytA);
|
||||
register(Byte.class, TypeAdapters.Byt);
|
||||
register(Byte[].class, TypeAdapters.BytA);
|
||||
register(char.class, TypeAdapters.chr);
|
||||
register(char[].class, TypeAdapters.chrA);
|
||||
register(Character.class, TypeAdapters.Chr);
|
||||
register(Character[].class, TypeAdapters.ChrA);
|
||||
register(short.class, TypeAdapters.shrt);
|
||||
register(short[].class, TypeAdapters.shrtA);
|
||||
register(Short.class, TypeAdapters.Shrt);
|
||||
register(Short[].class, TypeAdapters.ShrtA);
|
||||
register(int.class, TypeAdapters.int_);
|
||||
register(int[].class, TypeAdapters.intA);
|
||||
register(Integer.class, TypeAdapters.Int);
|
||||
register(Integer[].class, TypeAdapters.IntA);
|
||||
register(String.class, TypeAdapters.Str);
|
||||
register(String[].class, TypeAdapters.StrA);
|
||||
|
||||
|
||||
ARRAY_REMAP.put(Boolean.class, Boolean[].class );
|
||||
ARRAY_REMAP.put(Float.class, Float[].class );
|
||||
ARRAY_REMAP.put(Double.class, Double[].class );
|
||||
ARRAY_REMAP.put(Byte.class, Byte[].class );
|
||||
ARRAY_REMAP.put(Character.class, Character[].class);
|
||||
ARRAY_REMAP.put(Short.class, Short[].class );
|
||||
ARRAY_REMAP.put(Integer.class, Integer[].class );
|
||||
ARRAY_REMAP.put(String.class, String[].class );
|
||||
}
|
||||
private static void register(Class<?> cls, ITypeAdapter adpt)
|
||||
{
|
||||
ADAPTERS.put(cls, adpt);
|
||||
}
|
||||
|
||||
public static void loadData(ASMDataTable data)
|
||||
{
|
||||
LOGGER.debug("Loading @Config anotation data");
|
||||
for (ASMData target : data.getAll(Config.class.getName()))
|
||||
{
|
||||
String modid = (String)target.getAnnotationInfo().get("modid");
|
||||
Multimap<Config.Type, ASMData> map = asm_data.computeIfAbsent(modid, k -> ArrayListMultimap.create());
|
||||
|
||||
EnumHolder tholder = (EnumHolder)target.getAnnotationInfo().get("type");
|
||||
Config.Type type = tholder == null ? Config.Type.INSTANCE : Config.Type.valueOf(tholder.getValue());
|
||||
|
||||
map.put(type, target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bounces to sync().
|
||||
* TODO: remove
|
||||
*/
|
||||
public static void load(String modid, Config.Type type)
|
||||
{
|
||||
sync(modid, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronizes configuration data between the file on disk, the {@code Configuration} object and the annotated
|
||||
* mod classes containing the configuration variables.
|
||||
*
|
||||
* When first called, this method will try to load the configuration from disk. If this fails, because the file
|
||||
* does not exist, it will be created with default values derived from the mods config classes variable default values
|
||||
* and comments and ranges, as well as configuration names based on the appropriate annotations found in {@code @Config}.
|
||||
*
|
||||
* Note, that this method is being called by the {@link FMLModContaier}, so the mod needn't call it in init().
|
||||
*
|
||||
* If this method is called after the initial load, it will check whether the values in the Configuration object differ
|
||||
* from the values in the corresponding variables. If they differ, it will either overwrite the variables if the Configuration
|
||||
* object is marked as changed (e.g. if it was changed with the ConfigGui) or otherwise overwrite the Configuration object's values.
|
||||
* It then proceeds to saving the changes to disk.
|
||||
* @param modid the mod's ID for which the configuration shall be loaded
|
||||
* @param type the configuration type, currently always {@code Config.Type.INSTANCE}
|
||||
*/
|
||||
public static void sync(String modid, Config.Type type)
|
||||
{
|
||||
LOGGER.debug("Attempting to inject @Config classes into {} for type {}", modid, type);
|
||||
ClassLoader mcl = Loader.instance().getModClassLoader();
|
||||
File configDir = FMLPaths.FMLCONFIG.get().toFile();
|
||||
Multimap<Config.Type, ASMData> map = asm_data.get(modid);
|
||||
|
||||
if (map == null)
|
||||
return;
|
||||
|
||||
for (ASMData targ : map.get(type))
|
||||
{
|
||||
try
|
||||
{
|
||||
Class<?> cls = Class.forName(targ.getClassName(), true, mcl);
|
||||
|
||||
Set<Class<?>> modConfigClasses = MOD_CONFIG_CLASSES.computeIfAbsent(modid, k -> Sets.<Class<?>>newHashSet());
|
||||
modConfigClasses.add(cls);
|
||||
|
||||
String name = (String)targ.getAnnotationInfo().get("name");
|
||||
if (name == null)
|
||||
name = modid;
|
||||
String category = (String)targ.getAnnotationInfo().get("category");
|
||||
if (category == null)
|
||||
category = "general";
|
||||
|
||||
File file = new File(configDir, name + ".cfg");
|
||||
|
||||
boolean loading = false;
|
||||
Configuration cfg = CONFIGS.get(file.getAbsolutePath());
|
||||
if (cfg == null)
|
||||
{
|
||||
cfg = new Configuration(file);
|
||||
cfg.load();
|
||||
CONFIGS.put(file.getAbsolutePath(), cfg);
|
||||
loading = true;
|
||||
}
|
||||
|
||||
sync(cfg, cls, modid, category, loading, null);
|
||||
|
||||
cfg.save();
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("An error occurred trying to load a config for {} into {}", targ.getClassName(), e);
|
||||
throw new LoaderException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static Class<?>[] getModConfigClasses(String modid)
|
||||
{
|
||||
return (MOD_CONFIG_CLASSES.containsKey(modid) ? MOD_CONFIG_CLASSES.get(modid).toArray(new Class<?>[0]) : new Class<?>[0]);
|
||||
}
|
||||
|
||||
public static boolean hasConfigForMod(String modid)
|
||||
{
|
||||
return asm_data.containsKey(modid);
|
||||
}
|
||||
|
||||
// =======================================================
|
||||
// INTERNAL
|
||||
// =======================================================
|
||||
static Configuration getConfiguration(String modid, String name) {
|
||||
if (Strings.isNullOrEmpty(name))
|
||||
name = modid;
|
||||
File configDir = FMLPaths.FMLCONFIG.get().toFile();
|
||||
File configFile = new File(configDir, name + ".cfg");
|
||||
return CONFIGS.get(configFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
private static void sync(Configuration cfg, Class<?> cls, String modid, String category, boolean loading, Object instance)
|
||||
{
|
||||
for (Field f : cls.getDeclaredFields())
|
||||
{
|
||||
if (!Modifier.isPublic(f.getModifiers()))
|
||||
continue;
|
||||
|
||||
//Only the root class may have static fields. Otherwise category tree nodes of the same type would share the
|
||||
//contained value messing up the sync
|
||||
if (Modifier.isStatic(f.getModifiers()) != (instance == null))
|
||||
continue;
|
||||
|
||||
if (f.isAnnotationPresent(Config.Ignore.class))
|
||||
continue;
|
||||
|
||||
String comment = null;
|
||||
Comment ca = f.getAnnotation(Comment.class);
|
||||
if (ca != null)
|
||||
comment = NEW_LINE.join(ca.value());
|
||||
|
||||
String langKey = modid + "." + (category.isEmpty() ? "" : category + Configuration.CATEGORY_SPLITTER) + f.getName().toLowerCase(Locale.ENGLISH);
|
||||
LangKey la = f.getAnnotation(LangKey.class);
|
||||
if (la != null)
|
||||
langKey = la.value();
|
||||
|
||||
boolean requiresMcRestart = f.isAnnotationPresent(Config.RequiresMcRestart.class);
|
||||
boolean requiresWorldRestart = f.isAnnotationPresent(Config.RequiresWorldRestart.class);
|
||||
|
||||
if (FieldWrapper.hasWrapperFor(f)) //Wrappers exist for primitives, enums, maps and arrays
|
||||
{
|
||||
if (Strings.isNullOrEmpty(category))
|
||||
throw new RuntimeException("An empty category may not contain anything but objects representing categories!");
|
||||
try
|
||||
{
|
||||
IFieldWrapper wrapper = FieldWrapper.get(instance, f, category);
|
||||
ITypeAdapter adapt = wrapper.getTypeAdapter();
|
||||
Property.Type propType = adapt.getType();
|
||||
|
||||
for (String key : wrapper.getKeys()) //Iterate the fully qualified property names the field provides
|
||||
{
|
||||
String suffix = StringUtils.replaceOnce(key, wrapper.getCategory() + Configuration.CATEGORY_SPLITTER, "");
|
||||
|
||||
boolean existed = exists(cfg, wrapper.getCategory(), suffix);
|
||||
if (!existed || loading) //Creates keys in category specified by the wrapper if new ones are programaticaly added
|
||||
{
|
||||
Property property = property(cfg, wrapper.getCategory(), suffix, propType, adapt.isArrayAdapter());
|
||||
|
||||
adapt.setDefaultValue(property, wrapper.getValue(key));
|
||||
if (!existed)
|
||||
adapt.setValue(property, wrapper.getValue(key));
|
||||
else
|
||||
wrapper.setValue(key, adapt.getValue(property));
|
||||
}
|
||||
else //If the key is not new, sync according to shouldReadFromVar()
|
||||
{
|
||||
Property property = property(cfg, wrapper.getCategory(), suffix, propType, adapt.isArrayAdapter());
|
||||
Object propVal = adapt.getValue(property);
|
||||
Object mapVal = wrapper.getValue(key);
|
||||
if (shouldReadFromVar(property, propVal, mapVal))
|
||||
adapt.setValue(property, mapVal);
|
||||
else
|
||||
wrapper.setValue(key, propVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ConfigCategory confCat = cfg.getCategory(wrapper.getCategory());
|
||||
|
||||
for (Property property : confCat.getOrderedValues()) //Iterate the properties to check for new data from the config side
|
||||
{
|
||||
String key = confCat.getQualifiedName() + Configuration.CATEGORY_SPLITTER + property.getName();
|
||||
if (!wrapper.handlesKey(key))
|
||||
continue;
|
||||
|
||||
if (loading || !wrapper.hasKey(key))
|
||||
{
|
||||
Object value = wrapper.getTypeAdapter().getValue(property);
|
||||
wrapper.setValue(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (loading)
|
||||
wrapper.setupConfiguration(cfg, comment, langKey, requiresMcRestart, requiresWorldRestart);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
String format = "Error syncing field '%s' of class '%s'!";
|
||||
String error = String.format(format, f.getName(), cls.getName());
|
||||
throw new RuntimeException(error, e);
|
||||
}
|
||||
}
|
||||
else if (f.getType().getSuperclass() != null && f.getType().getSuperclass().equals(Object.class))
|
||||
{ //If the field extends Object directly, descend the object tree and access the objects members
|
||||
Object newInstance = null;
|
||||
try
|
||||
{
|
||||
newInstance = f.get(instance);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
//Setup the sub category with its respective name, comment, language key, etc.
|
||||
String sub = (category.isEmpty() ? "" : category + Configuration.CATEGORY_SPLITTER) + getName(f).toLowerCase(Locale.ENGLISH);
|
||||
ConfigCategory confCat = cfg.getCategory(sub);
|
||||
confCat.setComment(comment);
|
||||
confCat.setLanguageKey(langKey);
|
||||
confCat.setRequiresMcRestart(requiresMcRestart);
|
||||
confCat.setRequiresWorldRestart(requiresWorldRestart);
|
||||
|
||||
sync(cfg, f.getType(), modid, sub, loading, newInstance);
|
||||
}
|
||||
else
|
||||
{
|
||||
String format = "Can't handle field '%s' of class '%s': Unknown type.";
|
||||
String error = String.format(format, f.getName(), cls.getCanonicalName());
|
||||
throw new RuntimeException(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static final Joiner NEW_LINE = Joiner.on('\n');
|
||||
static final Joiner PIPE = Joiner.on('|');
|
||||
|
||||
private static Property property(Configuration cfg, String category, String property, Property.Type type, boolean isList)
|
||||
{
|
||||
Property prop = cfg.getCategory(category).get(property);
|
||||
if (prop == null)
|
||||
{
|
||||
if (isList)
|
||||
prop = new Property(property, new String[0], type);
|
||||
else
|
||||
prop = new Property(property, (String)null, type);
|
||||
cfg.getCategory(category).put(property, prop);
|
||||
}
|
||||
return prop;
|
||||
}
|
||||
|
||||
private static boolean exists(Configuration cfg, String category, String property)
|
||||
{
|
||||
return cfg.hasCategory(category) && cfg.getCategory(category).containsKey(property);
|
||||
}
|
||||
|
||||
private static boolean shouldReadFromVar(Property property, Object propValue, Object fieldValue)
|
||||
{
|
||||
if (!propValue.equals(fieldValue))
|
||||
{
|
||||
if (property.hasChanged())
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getName(Field f)
|
||||
{
|
||||
if (f.isAnnotationPresent(Name.class))
|
||||
return f.getAnnotation(Name.class).value();
|
||||
return f.getName();
|
||||
}
|
||||
|
||||
}
|
|
@ -51,12 +51,7 @@ import com.google.common.base.CharMatcher;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import com.google.common.primitives.Floats;
|
||||
import net.minecraftforge.fml.client.config.GuiConfig;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.IConfigElement;
|
||||
import net.minecraftforge.fml.common.FMLPaths;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -143,16 +138,16 @@ public class Configuration
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
public Configuration(File file, String configVersion)
|
||||
{
|
||||
runConfiguration(file, configVersion);
|
||||
// runConfiguration(file, configVersion);
|
||||
}
|
||||
|
||||
public Configuration(File file, String configVersion, boolean caseSensitiveCustomCategories)
|
||||
{
|
||||
this.caseSensitiveCustomCategories = caseSensitiveCustomCategories;
|
||||
runConfiguration(file, configVersion);
|
||||
// runConfiguration(file, configVersion);
|
||||
}
|
||||
|
||||
public Configuration(File file, boolean caseSensitiveCustomCategories)
|
||||
|
@ -1239,7 +1234,7 @@ public class Configuration
|
|||
getCategory(category).setConfigEntryClass(clazz);
|
||||
return this;
|
||||
}
|
||||
|
||||
*/
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -1,432 +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.reflect.Field;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraftforge.common.config.Config.RangeDouble;
|
||||
import net.minecraftforge.common.config.Config.RangeInt;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static net.minecraftforge.common.config.ConfigManager.*;
|
||||
|
||||
public abstract class FieldWrapper implements IFieldWrapper
|
||||
{
|
||||
protected String category, name;
|
||||
|
||||
protected Field field;
|
||||
protected Object instance;
|
||||
|
||||
public FieldWrapper(String category, Field field, Object instance)
|
||||
{
|
||||
this.instance = instance;
|
||||
this.field = field;
|
||||
this.category = category;
|
||||
this.name = field.getName();
|
||||
|
||||
if (field.isAnnotationPresent(Config.Name.class))
|
||||
this.name = field.getAnnotation(Config.Name.class).value();
|
||||
|
||||
this.field.setAccessible(true); // Just in case
|
||||
}
|
||||
|
||||
public static IFieldWrapper get(Object instance, Field field, String category)
|
||||
{
|
||||
if (ADAPTERS.get(field.getType()) != null)
|
||||
return new PrimitiveWrapper(category, field, instance);
|
||||
else if (Enum.class.isAssignableFrom(field.getType()))
|
||||
return new EnumWrapper(category, field, instance);
|
||||
else if (Map.class.isAssignableFrom(field.getType()))
|
||||
return new MapWrapper(category, field, instance);
|
||||
else if (field.getType().getSuperclass().equals(Object.class))
|
||||
throw new RuntimeException("Objects should not be handled by field wrappers");
|
||||
else
|
||||
throw new IllegalArgumentException(String.format("Fields of type '%s' are not supported!", field.getType().getCanonicalName()));
|
||||
}
|
||||
|
||||
public static boolean hasWrapperFor(Field field)
|
||||
{
|
||||
if (ADAPTERS.get(field.getType()) != null)
|
||||
return true;
|
||||
else if (Enum.class.isAssignableFrom(field.getType()))
|
||||
return true;
|
||||
else if (Map.class.isAssignableFrom(field.getType()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class MapWrapper extends FieldWrapper
|
||||
{
|
||||
private Map<String, Object> theMap = null;
|
||||
private Type mType;
|
||||
private final String baseName;
|
||||
ITypeAdapter adapter;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private MapWrapper(String category, Field field, Object instance)
|
||||
{
|
||||
super(category, field, instance);
|
||||
|
||||
this.baseName = (this.category == null) ? "" : (this.category + ".") + this.name.toLowerCase(Locale.ENGLISH) + ".";
|
||||
|
||||
try
|
||||
{
|
||||
theMap = (Map<String, Object>) field.get(instance);
|
||||
}
|
||||
catch (ClassCastException cce)
|
||||
{
|
||||
throw new IllegalArgumentException(String.format("The map '%s' of class '%s' must have the key type String!", field.getName(),
|
||||
field.getDeclaringClass().getCanonicalName()), cce);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
ParameterizedType type = (ParameterizedType) field.getGenericType();
|
||||
mType = type.getActualTypeArguments()[1];
|
||||
|
||||
this.adapter = ADAPTERS.get(mType);
|
||||
if (this.adapter == null && mType instanceof GenericArrayType)
|
||||
{
|
||||
this.adapter = ADAPTERS.get(ARRAY_REMAP.get(((GenericArrayType)mType).getGenericComponentType())); //J6 seems to have issues, Need to find a better way to translate this. We don't have access to array depth.
|
||||
}
|
||||
|
||||
if (mType instanceof Class && Enum.class.isAssignableFrom((Class<?>)mType))
|
||||
{
|
||||
this.adapter = TypeAdapters.Str;
|
||||
}
|
||||
|
||||
if (this.adapter == null)
|
||||
throw new IllegalArgumentException(String.format("The map '%s' of class '%s' has target values which are neither primitive nor an enum!",
|
||||
field.getName(), field.getDeclaringClass().getCanonicalName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITypeAdapter getTypeAdapter()
|
||||
{
|
||||
return adapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getKeys()
|
||||
{
|
||||
Set<String> keys = theMap.keySet();
|
||||
String[] keyArray = new String[keys.size()];
|
||||
|
||||
Iterator<String> it = keys.iterator();
|
||||
for (int i = 0; i < keyArray.length; i++)
|
||||
{
|
||||
keyArray[i] = this.baseName + it.next();
|
||||
}
|
||||
|
||||
return keyArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(String key)
|
||||
{
|
||||
return theMap.get(getSuffix(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, Object value)
|
||||
{
|
||||
theMap.put(getSuffix(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(String key)
|
||||
{
|
||||
return theMap.containsKey(getSuffix(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesKey(String key)
|
||||
{
|
||||
if (key == null)
|
||||
return false;
|
||||
return key.startsWith(this.baseName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupConfiguration(Configuration cfg, String desc, String langKey, boolean reqMCRestart, boolean reqWorldRestart)
|
||||
{
|
||||
ConfigCategory confCat = cfg.getCategory(getCategory());
|
||||
confCat.setComment(desc);
|
||||
confCat.setLanguageKey(langKey);
|
||||
confCat.setRequiresMcRestart(reqMCRestart);
|
||||
confCat.setRequiresWorldRestart(reqWorldRestart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory()
|
||||
{
|
||||
return (this.category == null) ? "" : (this.category + ".") + this.name.toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the {@code this.baseName} prefix from the key
|
||||
* @param key the key to be edited
|
||||
* @return the keys suffix
|
||||
*/
|
||||
private String getSuffix(String key)
|
||||
{
|
||||
return StringUtils.replaceOnce(key, this.baseName, "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class EnumWrapper extends SingleValueFieldWrapper
|
||||
{
|
||||
|
||||
private EnumWrapper(String category, Field field, Object instance)
|
||||
{
|
||||
super(category, field, instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITypeAdapter getTypeAdapter()
|
||||
{
|
||||
return TypeAdapters.Str;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(String key)
|
||||
{
|
||||
if (!hasKey(key))
|
||||
throw new IllegalArgumentException("Unsupported Key!");
|
||||
|
||||
try
|
||||
{
|
||||
@SuppressWarnings("rawtypes")
|
||||
Enum enu = (Enum) field.get(instance);
|
||||
return enu.name();
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, Object value)
|
||||
{
|
||||
if (!hasKey(key))
|
||||
throw new IllegalArgumentException("Unsupported Key!");
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
Enum enu = Enum.valueOf((Class<? extends Enum>) field.getType(), (String) value);
|
||||
try
|
||||
{
|
||||
field.set(instance, enu);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public void setupConfiguration(Configuration cfg, String desc, String langKey, boolean reqMCRestart, boolean reqWorldRestart)
|
||||
{
|
||||
super.setupConfiguration(cfg, desc, langKey, reqMCRestart, reqWorldRestart);
|
||||
|
||||
Property prop = cfg.getCategory(this.category).get(this.name); // Will be setup in general by ConfigManager
|
||||
|
||||
List<String> lst = Lists.newArrayList();
|
||||
for (Enum e : ((Class<? extends Enum>) field.getType()).getEnumConstants())
|
||||
lst.add(e.name());
|
||||
|
||||
prop.setValidationPattern(Pattern.compile(PIPE.join(lst)));
|
||||
prop.setValidValues(lst.toArray(new String[0]));
|
||||
|
||||
String validValues = NEW_LINE.join(lst);
|
||||
|
||||
if (desc != null)
|
||||
prop.setComment(NEW_LINE.join(new String[] { desc, "Valid values:" }) + "\n" + validValues);
|
||||
else
|
||||
prop.setComment("Valid values:" + "\n" + validValues);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PrimitiveWrapper extends SingleValueFieldWrapper
|
||||
{
|
||||
|
||||
private PrimitiveWrapper(String category, Field field, Object instance)
|
||||
{
|
||||
super(category, field, instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITypeAdapter getTypeAdapter()
|
||||
{
|
||||
return ADAPTERS.get(field.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(String key)
|
||||
{
|
||||
if (!hasKey(key))
|
||||
throw new IllegalArgumentException("Unknown key!");
|
||||
try
|
||||
{
|
||||
return field.get(instance);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(String key, Object value)
|
||||
{
|
||||
if (!hasKey(key))
|
||||
throw new IllegalArgumentException("Unknown key: " + key);
|
||||
try
|
||||
{
|
||||
field.set(instance, value);
|
||||
}
|
||||
catch (IllegalAccessException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupConfiguration(Configuration cfg, String desc, String langKey, boolean reqMCRestart, boolean reqWorldRestart)
|
||||
{
|
||||
super.setupConfiguration(cfg, desc, langKey, reqMCRestart, reqWorldRestart);
|
||||
|
||||
Property prop = cfg.getCategory(this.category).get(this.name);
|
||||
|
||||
RangeInt ia = field.getAnnotation(RangeInt.class);
|
||||
if (ia != null)
|
||||
{
|
||||
prop.setMinValue(ia.min());
|
||||
prop.setMaxValue(ia.max());
|
||||
if (desc != null)
|
||||
prop.setComment(NEW_LINE.join(new String[] { desc, "Min: " + ia.min(), "Max: " + ia.max() }));
|
||||
else
|
||||
prop.setComment(NEW_LINE.join(new String[] { "Min: " + ia.min(), "Max: " + ia.max() }));
|
||||
}
|
||||
|
||||
RangeDouble da = field.getAnnotation(RangeDouble.class);
|
||||
if (da != null)
|
||||
{
|
||||
prop.setMinValue(da.min());
|
||||
prop.setMaxValue(da.max());
|
||||
if (desc != null)
|
||||
prop.setComment(NEW_LINE.join(new String[] { desc, "Min: " + da.min(), "Max: " + da.max() }));
|
||||
else
|
||||
prop.setComment(NEW_LINE.join(new String[] { "Min: " + da.min(), "Max: " + da.max() }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class SingleValueFieldWrapper extends FieldWrapper
|
||||
{
|
||||
private SingleValueFieldWrapper(String category, Field field, Object instance)
|
||||
{
|
||||
super(category, field, instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getKeys()
|
||||
{
|
||||
return asArray(this.category + "." + this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasKey(String key)
|
||||
{
|
||||
return (this.category + "." + this.name).equals(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlesKey(String key)
|
||||
{
|
||||
return hasKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupConfiguration(Configuration cfg, String desc, String langKey, boolean reqMCRestart, boolean reqWorldRestart)
|
||||
{
|
||||
Property prop = cfg.getCategory(this.category).get(this.name); // Will be setup in general by ConfigManager
|
||||
|
||||
prop.setComment(desc);
|
||||
prop.setLanguageKey(langKey);
|
||||
prop.setRequiresMcRestart(reqMCRestart);
|
||||
prop.setRequiresWorldRestart(reqWorldRestart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory()
|
||||
{
|
||||
return this.category;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static <T> T[] asArray(T... in)
|
||||
{
|
||||
return in;
|
||||
}
|
||||
|
||||
public static class BeanEntry<K, V> implements Entry<K, V>
|
||||
{
|
||||
private K key;
|
||||
private V value;
|
||||
|
||||
public BeanEntry(K key, V value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public K getKey()
|
||||
{
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V setValue(V value)
|
||||
{
|
||||
throw new UnsupportedOperationException("This is a static bean.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,78 +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;
|
||||
|
||||
/**
|
||||
* The objects are expected to get their wrapped field, the owning class, instance and category string on initialization.
|
||||
* In general: The key is the fully qualified property name, where each subcategory is appended with a dot.
|
||||
* i.e: general.map.isPresent
|
||||
*/
|
||||
public interface IFieldWrapper
|
||||
{
|
||||
|
||||
/**
|
||||
* @return The type adapter to serialize the values returned by getValue. Null if non-primitive.
|
||||
*/
|
||||
ITypeAdapter getTypeAdapter();
|
||||
|
||||
/**
|
||||
* @return a list of fully qualified property keys handled by this field
|
||||
*/
|
||||
String[] getKeys();
|
||||
|
||||
/**
|
||||
* @param key the fully qualified property key
|
||||
* @return the value the wrapped field associates with the given key
|
||||
*/
|
||||
Object getValue(String key);
|
||||
|
||||
/**
|
||||
* @param key the fully qualified property key
|
||||
* @param value the target value of the property associated with the key
|
||||
*/
|
||||
void setValue(String key, Object value);
|
||||
|
||||
/**
|
||||
* @param key a fully qualified property key
|
||||
* @return true if the wrapped field contains a property associated with the given key
|
||||
*/
|
||||
boolean hasKey(String key);
|
||||
|
||||
/**
|
||||
* @param key a fully qualified property key
|
||||
* @return true if the wrapped field can save information associated with the given key, false otherwise
|
||||
*/
|
||||
boolean handlesKey(String key);
|
||||
|
||||
/**
|
||||
* @param cfg The configuration object holding the properties
|
||||
* @param desc The properties description
|
||||
* @param langKey The languageKey of the property, used in GUI
|
||||
* @param reqMCRestart True, if a change in this property requires a restart of Minecraft
|
||||
* @param reqWorldRestart True, if the world needs to be reloaded after changes to this property
|
||||
*/
|
||||
void setupConfiguration(Configuration cfg, String desc, String langKey, boolean reqMCRestart, boolean reqWorldRestart);
|
||||
|
||||
/**
|
||||
* i.e. general.map in the example above
|
||||
* @return the category name in which the entries should be saved. This includes the parent categories
|
||||
*/
|
||||
String getCategory();
|
||||
}
|
|
@ -1,53 +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 net.minecraftforge.common.config.Property.Type;
|
||||
|
||||
/**
|
||||
* Abstracts the types of properties away. Higher level logic must prevent invalid data types.
|
||||
*/
|
||||
interface ITypeAdapter
|
||||
{
|
||||
/**
|
||||
* Assigns the default value to the property
|
||||
* @param property the property whose default value will be assigned
|
||||
* @param value the default value
|
||||
*/
|
||||
void setDefaultValue(Property property, Object value);
|
||||
|
||||
/**
|
||||
* Sets the properties value.
|
||||
* @param property the property whose value will be set
|
||||
* @param value the set value
|
||||
*/
|
||||
void setValue(Property property, Object value);
|
||||
|
||||
/**
|
||||
* Retrieves the properties value
|
||||
* @param prop the property whose value will be retrieved
|
||||
* @return the properties value
|
||||
*/
|
||||
Object getValue(Property prop);
|
||||
|
||||
Type getType();
|
||||
|
||||
boolean isArrayAdapter();
|
||||
}
|
|
@ -23,13 +23,9 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraftforge.fml.client.config.GuiConfig;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiEditArray;
|
||||
import net.minecraftforge.fml.client.config.GuiEditArrayEntries;
|
||||
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.IArrayEntry;
|
||||
import net.minecraftforge.fml.client.config.IArrayEntry;
|
||||
import net.minecraftforge.fml.client.config.IConfigElement;
|
||||
import net.minecraftforge.fml.client.config.IConfigEntry;
|
||||
|
||||
public class Property
|
||||
{
|
||||
|
|
|
@ -1,869 +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;
|
||||
|
||||
//=========================================================
|
||||
// Run away thar' be dragons!
|
||||
//=========================================================
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.google.common.primitives.Booleans;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import com.google.common.primitives.Doubles;
|
||||
import com.google.common.primitives.Floats;
|
||||
import com.google.common.primitives.Ints;
|
||||
import com.google.common.primitives.Shorts;
|
||||
|
||||
import net.minecraftforge.common.config.Property.Type;
|
||||
|
||||
class TypeAdapters
|
||||
{
|
||||
/*
|
||||
* boolean, boolean[], Boolean, Boolean[]
|
||||
* float, float[], Float, Float[]
|
||||
* double, double[], Double, Double[]
|
||||
* byte, byte[], Byte, Byte[]
|
||||
* char, char[], Character, Character[]
|
||||
* short, short[], Short, Short[]
|
||||
* int, int[], Integer, Integer[]
|
||||
* String, String[]
|
||||
*/
|
||||
static ITypeAdapter bool = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getBoolean();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Boolean)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Boolean)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.BOOLEAN;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter boolA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getBooleanList();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues((boolean[])value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues((boolean[])value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.BOOLEAN;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Bool = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Boolean.valueOf(prop.getBoolean());
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Boolean)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Boolean)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.BOOLEAN;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter BoolA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Booleans.asList(prop.getBooleanList()).toArray(new Boolean[prop.getBooleanList().length]);
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Booleans.toArray(Arrays.asList((Boolean[]) value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Booleans.toArray(Arrays.asList((Boolean[]) value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.BOOLEAN;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter flt = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return (float)prop.getDouble();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Float)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Float)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter fltA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Floats.toArray(Doubles.asList(prop.getDoubleList()));
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Doubles.toArray(Floats.asList((float[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Doubles.toArray(Floats.asList((float[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Flt = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Float.valueOf((float)prop.getDouble());
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Float)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Float)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter FltA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Floats.asList(Floats.toArray(Doubles.asList(prop.getDoubleList()))).toArray(new Float[prop.getDoubleList().length]);
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Doubles.toArray(Arrays.asList((Float[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Doubles.toArray(Arrays.asList((Float[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter dbl = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop)
|
||||
{
|
||||
return prop.getDouble();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Double)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Double)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter dblA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getDoubleList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues((double[])value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues((double[])value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Dbl = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Double.valueOf(prop.getDouble());
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Double)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Double) value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter DblA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Doubles.asList(prop.getDoubleList()).toArray(new Double[prop.getDoubleList().length]);
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Doubles.toArray(Arrays.asList((Double[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Doubles.toArray(Arrays.asList((Double[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.DOUBLE;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter byt = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop)
|
||||
{
|
||||
return (byte)prop.getInt();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Byte)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Byte)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter bytA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Bytes.toArray(Ints.asList(prop.getIntList()));
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Ints.toArray(Bytes.asList((byte[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Ints.toArray(Bytes.asList((byte[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Byt = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Byte.valueOf((byte)prop.getInt());
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Byte)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Byte)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter BytA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Bytes.asList(Bytes.toArray(Ints.asList(prop.getIntList()))).toArray(new Byte[prop.getIntList().length]);
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Ints.toArray(Arrays.asList((Byte[]) value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Ints.toArray(Arrays.asList((Byte[]) value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter chr = new ITypeAdapter() {
|
||||
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return (char)prop.getInt();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Character)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Character)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter chrA = new ITypeAdapter() {
|
||||
private int[] toPrim(char[] v) {
|
||||
if (v == null) return new int[0];
|
||||
int[] ret = new int[v.length];
|
||||
for (int x = 0; x < v.length; x++)
|
||||
ret[x] = v[x];
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
int[] v = prop.getIntList();
|
||||
char[] ret = new char[v.length];
|
||||
for (int x = 0; x < v.length; x++)
|
||||
ret[x] = (char)v[x];
|
||||
return ret;
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(toPrim((char[])value));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(toPrim((char[])value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Chr = new ITypeAdapter() {
|
||||
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Character.valueOf((char)prop.getInt());
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Character)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Character)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter ChrA = new ITypeAdapter() {
|
||||
private int[] toPrim(Character[] v) {
|
||||
if (v == null) return new int[0];
|
||||
int[] ret = new int[v.length];
|
||||
for (int x = 0; x < v.length; x++)
|
||||
ret[x] = v[x] == null ? 0 : v[x];
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
int[] v = prop.getIntList();
|
||||
Character[] ret = new Character[v.length];
|
||||
for (int x = 0; x < v.length; x++)
|
||||
ret[x] = Character.valueOf((char)v[x]);
|
||||
return ret;
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(toPrim((Character[])value));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(toPrim((Character[]) value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
static ITypeAdapter shrt = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return (short)prop.getInt();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Short)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Short)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter shrtA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Shorts.toArray(Ints.asList(prop.getIntList()));
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Ints.toArray(Shorts.asList((short[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Ints.toArray(Shorts.asList((short[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
static ITypeAdapter Shrt = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Short.valueOf((short)prop.getInt());
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Short)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Short)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter ShrtA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
int[] v = prop.getIntList();
|
||||
Short[] ret = new Short[v.length];
|
||||
for (int x = 0; x < ret.length; x++)
|
||||
ret[x] = Short.valueOf((short)v[x]);
|
||||
return ret;
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Ints.toArray(Arrays.asList((Short[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Ints.toArray(Arrays.asList((Short[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter int_ = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getInt();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Integer)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Integer)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter intA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getIntList();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues((int[])value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues((int[])value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Int = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return (Integer)prop.getInt();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((Integer)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((Integer)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter IntA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return Ints.asList(prop.getIntList()).toArray(new Integer[prop.getIntList().length]);
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues(Ints.toArray(Arrays.asList((Integer[])value)));
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues(Ints.toArray(Arrays.asList((Integer[])value)));
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.INTEGER;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter Str = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getString();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValue((String)value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValue((String)value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.STRING;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
static ITypeAdapter StrA = new ITypeAdapter() {
|
||||
@Override
|
||||
public Object getValue(Property prop) {
|
||||
return prop.getStringList();
|
||||
}
|
||||
@Override
|
||||
public void setDefaultValue(Property property, Object value)
|
||||
{
|
||||
property.setDefaultValues((String[])value);
|
||||
}
|
||||
@Override
|
||||
public void setValue(Property property, Object value)
|
||||
{
|
||||
property.setValues((String[])value);
|
||||
}
|
||||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
return Type.STRING;
|
||||
}
|
||||
@Override
|
||||
public boolean isArrayAdapter()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -3,12 +3,16 @@ package net.minecraftforge.common.extensions;
|
|||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.dimension.Dimension;
|
||||
import net.minecraft.world.dimension.NetherDimension;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import net.minecraftforge.client.IRenderHandler;
|
||||
|
||||
public interface IForgeDimension
|
||||
{
|
||||
default Dimension getDimension() { return (Dimension) this; }
|
||||
|
||||
/**
|
||||
* Called from {@link World#initCapabilities()}, to gather capabilities for this
|
||||
* world. It's safe to access world here since this is called after world is
|
||||
|
@ -26,6 +30,22 @@ public interface IForgeDimension
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The dimension's movement factor.
|
||||
* Whenever a player or entity changes dimension from world A to world B, their coordinates are multiplied by
|
||||
* worldA.provider.getMovementFactor() / worldB.provider.getMovementFactor()
|
||||
* Example: Overworld factor is 1, nether factor is 8. Traveling from overworld to nether multiplies coordinates by 1/8.
|
||||
* @return The movement factor
|
||||
*/
|
||||
default double getMovementFactor()
|
||||
{
|
||||
if (getDimension() instanceof NetherDimension)
|
||||
{
|
||||
return 8.0;
|
||||
}
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the providers current dimension ID, used in default getSaveFolder()
|
||||
* Added to allow default providers to be registered for multiple dimensions.
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
||||
|
||||
public interface IForgeWorldServer extends IForgeWorld
|
||||
{
|
||||
default WorldServer getWorldServer() { return (WorldServer) this; }
|
||||
|
||||
default File getChunkSaveLocation()
|
||||
{
|
||||
return ((AnvilChunkLoader) getWorldServer().getChunkProvider().chunkLoader).chunkSaveLocation;
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ import org.apache.logging.log4j.Logger;
|
|||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
|
||||
/* TODO fluids
|
||||
public class FluidIdRegistryMessageHandler extends SimpleChannelInboundHandler<ForgeMessage.FluidIdMapMessage> {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
|
@ -44,3 +44,4 @@ public class FluidIdRegistryMessageHandler extends SimpleChannelInboundHandler<F
|
|||
}
|
||||
|
||||
}
|
||||
*/
|
|
@ -70,7 +70,7 @@ public abstract class ForgeMessage {
|
|||
providerId = new String(data, StandardCharsets.UTF_8);
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO fluids
|
||||
public static class FluidIdMapMessage extends ForgeMessage {
|
||||
BiMap<Fluid, Integer> fluidIds = HashBiMap.create();
|
||||
Set<String> defaultFluids = Sets.newHashSet();
|
||||
|
@ -117,7 +117,7 @@ public abstract class ForgeMessage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
abstract void toBytes(ByteBuf bytes);
|
||||
abstract void fromBytes(ByteBuf bytes);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
package net.minecraftforge.common.network;
|
||||
|
||||
/* TODO handshake
|
||||
import java.util.EnumMap;
|
||||
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
|
@ -56,3 +56,4 @@ public class ForgeNetworkHandler
|
|||
clientChannel.pipeline().addAfter(handlerName, "FluidIdRegistryHandler", new FluidIdRegistryMessageHandler());
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
package net.minecraftforge.common.network;
|
||||
|
||||
/* TODO handshake
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import net.minecraftforge.fml.common.network.FMLIndexedMessageToMessageCodec;
|
||||
|
@ -41,3 +41,4 @@ public class ForgeRuntimeCodec extends FMLIndexedMessageToMessageCodec<ForgeMess
|
|||
msg.fromBytes(source);
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
package net.minecraftforge.common.network;
|
||||
|
||||
/* TODO handshake
|
||||
import net.minecraftforge.fml.common.network.NetworkHandshakeEstablished;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
|
@ -36,3 +36,4 @@ public class ServerToClientConnectionEstablishedHandler extends ChannelInboundHa
|
|||
ctx.fireUserEventTriggered(evt);
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -38,15 +38,16 @@ import net.minecraft.block.state.BlockState;
|
|||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.state.AbstractStateHolder;
|
||||
import net.minecraft.state.IProperty;
|
||||
import net.minecraft.state.IStateHolder;
|
||||
import net.minecraft.state.StateContainer;
|
||||
|
||||
public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
||||
// TODO Extended states gotta go, I doubt this works at all
|
||||
public class ExtendedStateContainer<O, S extends IExtendedState<S>> extends StateContainer<O, S>
|
||||
{
|
||||
private final ImmutableSet<IUnlistedProperty<?>> unlistedProperties;
|
||||
|
||||
public <A extends AbstractStateHolder<Block, IBlockState>> ExtendedBlockState(Block blockIn, StateContainer.IFactory<Block, IBlockState, ?> stateFactory, net.minecraft.state.IProperty<?>[] properties, IUnlistedProperty<?>[] unlistedProperties)
|
||||
public <A extends AbstractStateHolder<O, S>> ExtendedStateContainer(O blockIn, StateContainer.IFactory<O, S, A> stateFactory, net.minecraft.state.IProperty<?>[] properties, IUnlistedProperty<?>[] unlistedProperties)
|
||||
{
|
||||
super(blockIn, stateFactory, buildListedMap(properties));// TODO Unlisted properties?, buildUnlistedMap(unlistedProperties));
|
||||
super(blockIn, getProxyFactory(unlistedProperties, stateFactory), buildListedMap(properties));// TODO Unlisted properties?, buildUnlistedMap(unlistedProperties));
|
||||
ImmutableSet.Builder<IUnlistedProperty<?>> builder = ImmutableSet.builder();
|
||||
for(IUnlistedProperty<?> property : unlistedProperties)
|
||||
{
|
||||
|
@ -55,6 +56,15 @@ public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
|||
this.unlistedProperties = builder.build();
|
||||
}
|
||||
|
||||
private static <O, S extends IExtendedState<S>, A extends AbstractStateHolder<O, S>>
|
||||
StateContainer.IFactory<O, S, AbstractStateHolder<O,S>> getProxyFactory(IUnlistedProperty<?>[] unlistedProperties, StateContainer.IFactory<O, S, A> proxy)
|
||||
{
|
||||
return (o, props) -> {
|
||||
if (unlistedProperties == null || unlistedProperties.length == 0) return proxy.create(o, props);
|
||||
return new ExtendedStateHolder<O, S>(o, props, buildUnlistedMap(unlistedProperties), null);
|
||||
};
|
||||
}
|
||||
|
||||
public Collection<IUnlistedProperty<?>> getUnlistedProperties()
|
||||
{
|
||||
return unlistedProperties;
|
||||
|
@ -75,33 +85,25 @@ public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
|||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
protected StateImplementation createState(@Nonnull Block block, @Nonnull ImmutableMap<IProperty<?>, Comparable<?>> properties, @Nullable ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties)
|
||||
{
|
||||
if (unlistedProperties == null || unlistedProperties.isEmpty()) return super.createState(block, properties, unlistedProperties);
|
||||
return new ExtendedStateImplementation(block, properties, unlistedProperties, null, null);
|
||||
}
|
||||
|
||||
protected static class ExtendedStateImplementation extends StateImplementation implements IExtendedBlockState
|
||||
protected static class ExtendedStateHolder<O, S extends IExtendedState<S>> extends AbstractStateHolder<O, S> implements IExtendedState<S>
|
||||
{
|
||||
private final ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties;
|
||||
private IBlockState cleanState;
|
||||
private S cleanState;
|
||||
|
||||
protected ExtendedStateImplementation(Block block, ImmutableMap<IProperty<?>, Comparable<?>> properties, ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties, @Nullable ImmutableTable<IProperty<?>, Comparable<?>, IBlockState> table, IBlockState clean)
|
||||
protected ExtendedStateHolder(O block, ImmutableMap<IProperty<?>, Comparable<?>> properties, ImmutableMap<IUnlistedProperty<?>, Optional<?>> unlistedProperties, S clean)
|
||||
{
|
||||
super(block, properties, table);
|
||||
super(block, properties);
|
||||
this.unlistedProperties = unlistedProperties;
|
||||
this.cleanState = clean == null ? this : clean;
|
||||
this.cleanState = clean == null ? (S) this : clean;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public <T extends Comparable<T>, V extends T> IBlockState withProperty(@Nonnull IProperty<T> property, @Nonnull V value)
|
||||
public <T extends Comparable<T>, V extends T> S func_206870_a(@Nonnull IProperty<T> property, @Nonnull V value)
|
||||
{
|
||||
IBlockState clean = super.withProperty(property, value);
|
||||
S clean = super.func_206870_a(property, value);
|
||||
if (clean == this.cleanState) {
|
||||
return this;
|
||||
return (S) this;
|
||||
}
|
||||
|
||||
if (this == this.cleanState)
|
||||
|
@ -109,24 +111,24 @@ public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
|||
return clean;
|
||||
}
|
||||
|
||||
return new ExtendedStateImplementation(getBlock(), clean.getProperties(), unlistedProperties, ((StateImplementation)clean).getPropertyValueTable(), this.cleanState);
|
||||
return (S) new ExtendedStateHolder(field_206876_a, ((BlockState)clean).func_206871_b(), unlistedProperties, this.cleanState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> IExtendedBlockState withProperty(IUnlistedProperty<V> property, @Nullable V value)
|
||||
public <V> S withProperty(IUnlistedProperty<V> property, @Nullable V value)
|
||||
{
|
||||
Optional<?> oldValue = unlistedProperties.get(property);
|
||||
if (oldValue == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot set unlisted property " + property + " as it does not exist in " + getBlock().getBlockState());
|
||||
throw new IllegalArgumentException("Cannot set unlisted property " + property + " as it does not exist in " + this);
|
||||
}
|
||||
if (Objects.equals(oldValue.orElse(null), value))
|
||||
{
|
||||
return this;
|
||||
return (S) this;
|
||||
}
|
||||
if (!property.isValid(value))
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot set unlisted property " + property + " to " + value + " on block " + Block.REGISTRY.getNameForObject(getBlock()) + ", it is not an allowed value");
|
||||
throw new IllegalArgumentException("Cannot set unlisted property " + property + " to " + value + " on object " + field_206876_a + ", it is not an allowed value");
|
||||
}
|
||||
boolean clean = true;
|
||||
ImmutableMap.Builder<IUnlistedProperty<?>, Optional<?>> builder = ImmutableMap.builder();
|
||||
|
@ -139,9 +141,9 @@ public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
|||
}
|
||||
if (clean)
|
||||
{ // no dynamic properties, lookup normal state
|
||||
return (IExtendedBlockState) cleanState;
|
||||
return (S) cleanState;
|
||||
}
|
||||
return new ExtendedStateImplementation(getBlock(), getProperties(), builder.build(), propertyValueTable, this.cleanState);
|
||||
return (S) new ExtendedStateHolder(field_206876_a, func_206871_b(), builder.build(), this.cleanState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -157,7 +159,7 @@ public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
|||
Optional<?> value = unlistedProperties.get(property);
|
||||
if (value == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Cannot get unlisted property " + property + " as it does not exist in " + getBlock().getBlockState());
|
||||
throw new IllegalArgumentException("Cannot get unlisted property " + property + " as it does not exist in " + this);
|
||||
}
|
||||
return property.getType().cast(value.orElse(null));
|
||||
}
|
||||
|
@ -168,7 +170,7 @@ public class ExtendedBlockState extends StateContainer<Block, IBlockState>
|
|||
}
|
||||
|
||||
@Override
|
||||
public IBlockState getClean()
|
||||
public S getClean()
|
||||
{
|
||||
return cleanState;
|
||||
}
|
|
@ -1,40 +1,8 @@
|
|||
/*
|
||||
* 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.property;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
import java.util.Optional;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
public interface IExtendedBlockState extends IBlockState
|
||||
public interface IExtendedBlockState extends IExtendedState<IBlockState>, IBlockState
|
||||
{
|
||||
Collection<IUnlistedProperty<?>> getUnlistedNames();
|
||||
|
||||
<V>V getValue(IUnlistedProperty<V> property);
|
||||
|
||||
<V>IExtendedBlockState withProperty(IUnlistedProperty<V> property, V value);
|
||||
|
||||
ImmutableMap<IUnlistedProperty<?>, Optional<?>> getUnlistedProperties();
|
||||
|
||||
IBlockState getClean();
|
||||
}
|
||||
|
|
|
@ -17,11 +17,25 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.util;
|
||||
package net.minecraftforge.common.property;
|
||||
|
||||
import net.minecraft.util.datafix.IDataFixer;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface IDataFixerData extends IDataFixer
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.state.IStateHolder;
|
||||
|
||||
import java.util.Optional;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
public interface IExtendedState<C> extends IStateHolder<C>
|
||||
{
|
||||
int getVersion(String mod);
|
||||
Collection<IUnlistedProperty<?>> getUnlistedNames();
|
||||
|
||||
<V>V getValue(IUnlistedProperty<V> property);
|
||||
|
||||
<V>C withProperty(IUnlistedProperty<V> property, V value);
|
||||
|
||||
ImmutableMap<IUnlistedProperty<?>, Optional<?>> getUnlistedProperties();
|
||||
|
||||
C getClean();
|
||||
}
|
|
@ -28,7 +28,6 @@ import net.minecraft.tileentity.TileEntity;
|
|||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -54,7 +53,7 @@ public class BlockSnapshot
|
|||
@Nullable
|
||||
private WeakReference<World> world;
|
||||
private final ResourceLocation registryName;
|
||||
private final int meta;
|
||||
private final int meta = 0; // TODO BlockSnapshot needs a total refactor for the absence of metadata
|
||||
|
||||
public BlockSnapshot(World world, BlockPos pos, IBlockState state)
|
||||
{
|
||||
|
@ -68,7 +67,6 @@ public class BlockSnapshot
|
|||
this.pos = pos.toImmutable();
|
||||
this.setReplacedBlock(state);
|
||||
this.registryName = state.getBlock().getRegistryName();
|
||||
this.meta = state.getBlock().getMetaFromState(state);
|
||||
this.setFlag(3);
|
||||
this.nbt = nbt;
|
||||
if (DEBUG)
|
||||
|
@ -99,7 +97,6 @@ public class BlockSnapshot
|
|||
this.pos = pos.toImmutable();
|
||||
this.setFlag(flag);
|
||||
this.registryName = registryName;
|
||||
this.meta = meta;
|
||||
this.nbt = nbt;
|
||||
}
|
||||
|
||||
|
@ -143,7 +140,7 @@ public class BlockSnapshot
|
|||
World world = this.world != null ? this.world.get() : null;
|
||||
if (world == null)
|
||||
{
|
||||
world = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(getDimId());
|
||||
world = null; // TODO Server static access? FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(getDimId());
|
||||
this.world = new WeakReference<World>(world);
|
||||
}
|
||||
return world;
|
||||
|
@ -153,7 +150,7 @@ public class BlockSnapshot
|
|||
{
|
||||
if (this.replacedBlock == null)
|
||||
{
|
||||
this.replacedBlock = ForgeRegistries.BLOCKS.getValue(getRegistryName()).getStateFromMeta(getMeta());
|
||||
this.replacedBlock = ForgeRegistries.BLOCKS.getValue(getRegistryName()).func_196257_b(getMeta());
|
||||
}
|
||||
return this.replacedBlock;
|
||||
}
|
||||
|
@ -161,7 +158,7 @@ public class BlockSnapshot
|
|||
@Nullable
|
||||
public TileEntity getTileEntity()
|
||||
{
|
||||
return getNbt() != null ? TileEntity.create(getWorld(), getNbt()) : null;
|
||||
return getNbt() != null ? TileEntity.func_203403_c(getNbt()) : null;
|
||||
}
|
||||
|
||||
public boolean restore()
|
||||
|
@ -184,7 +181,7 @@ public class BlockSnapshot
|
|||
IBlockState current = getCurrentBlock();
|
||||
IBlockState replaced = getReplacedBlock();
|
||||
|
||||
if (current.getBlock() != replaced.getBlock() || current.getBlock().getMetaFromState(current) != replaced.getBlock().getMetaFromState(replaced))
|
||||
if (current != replaced)
|
||||
{
|
||||
if (force)
|
||||
{
|
||||
|
@ -212,15 +209,15 @@ public class BlockSnapshot
|
|||
|
||||
if (DEBUG)
|
||||
{
|
||||
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][Meta: %d ][Block: %s ][TileEntity: %s ][force: %s ][notifyNeighbors: %s]", world.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(), replaced.getBlock().getMetaFromState(replaced), replaced.getBlock().delegate.name(), te, force, notifyNeighbors);
|
||||
System.out.printf("Restored BlockSnapshot with data [World: %s ][Location: %d,%d,%d ][State: %s ][Block: %s ][TileEntity: %s ][force: %s ][notifyNeighbors: %s]", world.getWorldInfo().getWorldName(), pos.getX(), pos.getY(), pos.getZ(), replaced, replaced.getBlock().delegate.name(), te, force, notifyNeighbors);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void writeToNBT(NBTTagCompound compound)
|
||||
{
|
||||
compound.setString("blockMod", getRegistryName().getResourceDomain());
|
||||
compound.setString("blockName", getRegistryName().getResourcePath());
|
||||
compound.setString("blockMod", getRegistryName().getNamespace());
|
||||
compound.setString("blockName", getRegistryName().getPath());
|
||||
compound.setInteger("posX", getPos().getX());
|
||||
compound.setInteger("posY", getPos().getY());
|
||||
compound.setInteger("posZ", getPos().getZ());
|
||||
|
|
|
@ -1,185 +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.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.datafix.DataFixer;
|
||||
import net.minecraft.util.datafix.FixTypes;
|
||||
import net.minecraft.util.datafix.IDataWalker;
|
||||
import net.minecraft.util.datafix.IFixType;
|
||||
import net.minecraft.util.datafix.IFixableData;
|
||||
|
||||
public class CompoundDataFixer extends DataFixer
|
||||
{
|
||||
private final ModFixs vanilla;
|
||||
private final Map<String, ModFixs> modFixers = Maps.newHashMap();
|
||||
private final Map<IFixType, List<IDataWalker>> walkers = Maps.newHashMap();
|
||||
|
||||
public CompoundDataFixer(DataFixer vanilla)
|
||||
{
|
||||
super(0);
|
||||
this.vanilla = init("minecraft", vanilla.version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NBTTagCompound process(IFixType type, NBTTagCompound nbt)
|
||||
{
|
||||
final Map<String, Integer>versions = getVersions(nbt);
|
||||
final int mcversion = versions.get("minecraft") == null ? -1 : versions.get("minecraft");
|
||||
final IDataFixerData holder = new IDataFixerData()
|
||||
{
|
||||
@Override
|
||||
public NBTTagCompound process(IFixType type, NBTTagCompound nbt, int version)
|
||||
{
|
||||
for (Entry<String, ModFixs> e : modFixers.entrySet())
|
||||
{
|
||||
// This is a potential performance hot spot. As it walks all the data for all
|
||||
// of the fixers... But with the vanilla api there isn't a way to pass down
|
||||
// the mod specific version numbers, so redundant.. but not hacky...
|
||||
//Actually, this wont work as the data walkers take versions into account...
|
||||
ModFixs fixer = e.getValue();
|
||||
int ver = getVersion(e.getKey());
|
||||
if (ver < fixer.version)
|
||||
{
|
||||
for (IFixableData fix : fixer.getFixes(type))
|
||||
{
|
||||
if (fix.getFixVersion() > ver)
|
||||
nbt = fix.fixTagCompound(nbt);
|
||||
}
|
||||
|
||||
for (IDataWalker walker : getWalkers(type))
|
||||
nbt = walker.process(this, nbt, version); //We pass in the holder, in case a walker wants to know a mod version
|
||||
}
|
||||
}
|
||||
return nbt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion(String mod)
|
||||
{
|
||||
Integer ret = versions.get(mod);
|
||||
return ret == null ? -1 : ret;
|
||||
}
|
||||
};
|
||||
return holder.process(type, nbt, mcversion);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated //MODDERS DO NOT CALL DIRECTLY! Only use from DataWalker!
|
||||
public NBTTagCompound process(IFixType type, NBTTagCompound nbt, int mcversion)
|
||||
{
|
||||
if (type != FixTypes.OPTIONS) //Options are vanilla only
|
||||
throw new IllegalStateException("Do not call recursive process directly on DataFixer!");
|
||||
|
||||
for (IFixableData fix : vanilla.getFixes(type))
|
||||
{
|
||||
if (fix.getFixVersion() > mcversion)
|
||||
nbt = fix.fixTagCompound(nbt);
|
||||
}
|
||||
//Options is a hack, and doesn't have any nested components
|
||||
//for (IDataWalker walker : getWalkers(type))
|
||||
// nbt = walker.process(this, nbt, version);
|
||||
return nbt;
|
||||
}
|
||||
|
||||
private List<IDataWalker> getWalkers(IFixType type)
|
||||
{
|
||||
return walkers.computeIfAbsent(type, k -> Lists.newArrayList());
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated //Modders do not use this, this will register you as vanilla. Use the ModID version below.
|
||||
public void registerFix(IFixType type, IFixableData fixable)
|
||||
{
|
||||
vanilla.registerFix(type, fixable);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@Deprecated //Modders do not use this, use add below, To better allow custom fix types.
|
||||
public void registerWalker(FixTypes type, IDataWalker walker)
|
||||
{
|
||||
registerVanillaWalker(type, walker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerVanillaWalker(IFixType type, IDataWalker walker)
|
||||
{
|
||||
getWalkers(type).add(walker);
|
||||
}
|
||||
|
||||
private void validateModId(String mod)
|
||||
{
|
||||
//String current = Loader.instance().activeModContainer() == null ? "minecraft" : Loader.instance().activeModContainer().getModId();
|
||||
//Test active modid?
|
||||
if (!mod.equals(mod.toLowerCase(Locale.ENGLISH)))
|
||||
throw new IllegalArgumentException("Mod ID is not lower case: " + mod);
|
||||
if (mod.length() > 64)
|
||||
throw new IllegalArgumentException("Mod ID is to long: " + mod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize your mod specific data fixer.
|
||||
*
|
||||
* @param modid You mod id, must be lower case.
|
||||
* @param version The current data version of your mod
|
||||
*/
|
||||
public ModFixs init(String modid, int version)
|
||||
{
|
||||
validateModId(modid);
|
||||
if (modFixers.containsKey(modid))
|
||||
throw new IllegalStateException("Attempted to initalize DataFixer for " + modid + " twice");
|
||||
ModFixs ret = new ModFixs(modid, version);
|
||||
modFixers.put(modid, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
private Map<String, Integer> getVersions(NBTTagCompound nbt)
|
||||
{
|
||||
Map<String, Integer> ret = Maps.newHashMap();
|
||||
ret.put("minecraft", nbt.hasKey("DataVersion", 99) ? nbt.getInteger("DataVersion") : -1);
|
||||
if (nbt.hasKey("ForgeDataVersion", 10))
|
||||
{
|
||||
NBTTagCompound sub = nbt.getCompoundTag("ForgeDataVersion");
|
||||
for (String key : sub.getKeySet())
|
||||
{
|
||||
ret.put(key, sub.hasKey(key, 99) ? sub.getInteger(key) : -1);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void writeVersionData(NBTTagCompound nbt)
|
||||
{
|
||||
//nbt.setInteger("DataVersion", vanilla.version);
|
||||
NBTTagCompound sub = new NBTTagCompound();
|
||||
nbt.setTag("ForgeDataVersion", sub);
|
||||
for (ModFixs mod : modFixers.values())
|
||||
sub.setInteger(mod.mod, mod.version);
|
||||
}
|
||||
}
|
|
@ -1,85 +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.util;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import net.minecraftforge.fml.common.EnhancedRuntimeException;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class EnumHelper
|
||||
{
|
||||
/*
|
||||
* Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+
|
||||
* Also modified for use in decompiled code.
|
||||
* Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically
|
||||
*/
|
||||
|
||||
private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, @Nullable String value, int ordinal, Class<?>[] additionalTypes, @Nullable Object[] additionalValues) throws Exception
|
||||
{
|
||||
//new Enum(name, values.size() + 1, params)
|
||||
}
|
||||
|
||||
private static void blankField(Class<?> enumClass, String fieldName) throws Exception
|
||||
{
|
||||
for (Field field : Class.class.getDeclaredFields())
|
||||
{
|
||||
if (field.getName().contains(fieldName))
|
||||
{
|
||||
field.setAccessible(true);
|
||||
field.set(enumClass, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Class holds caches of the enum constants used for Enum.valueOf() and reflection magic. So we need to invalidate those caches when we add something new. They will automtically be re-built.
|
||||
public static void cleanEnumCache(Class<?> enumClass) throws Exception
|
||||
{
|
||||
blankField(enumClass, "enumConstantDirectory");
|
||||
blankField(enumClass, "enumConstants");
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "serial" })
|
||||
@Nullable
|
||||
private static <T extends Enum<?> & IExpandableEnum<?>> T addEnum(boolean test, final Class<T> enumType, T newValue)
|
||||
{
|
||||
try
|
||||
{
|
||||
T[] previousValues = enumType.getEnumConstants();
|
||||
T newValue = makeEnum(enumType, enumName, previousValues.length, paramTypes, paramValues);
|
||||
newValue.__set_values__(ArrayUtils.add(previousValues, newValue));
|
||||
cleanEnumCache(enumType);
|
||||
|
||||
return newValue;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,6 @@ package net.minecraftforge.common.util;
|
|||
import com.mojang.authlib.GameProfile;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraftforge.fml.common.FMLCommonHandler;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.play.client.CPacketClientSettings;
|
||||
|
@ -39,11 +38,10 @@ public class FakePlayer extends EntityPlayerMP
|
|||
{
|
||||
public FakePlayer(WorldServer world, GameProfile name)
|
||||
{
|
||||
super(FMLCommonHandler.instance().getMinecraftServerInstance(), world, name, new PlayerInteractionManager(world));
|
||||
super(world.getMinecraftServer(), world, name, new PlayerInteractionManager(world));
|
||||
}
|
||||
|
||||
@Override public Vec3d getPositionVector(){ return new Vec3d(0, 0, 0); }
|
||||
@Override public boolean canUseCommand(int i, String s){ return false; }
|
||||
@Override public void sendStatusMessage(ITextComponent chatComponent, boolean actionBar){}
|
||||
@Override public void sendMessage(ITextComponent component) {}
|
||||
@Override public void addStat(StatBase par1StatBase, int par2){}
|
||||
|
|
|
@ -22,7 +22,6 @@ package net.minecraftforge.common.util;
|
|||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.world.Teleporter;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldProvider;
|
||||
|
||||
/**
|
||||
* Interface for handling the placement of entities during dimension change.
|
||||
|
|
|
@ -36,8 +36,9 @@ import com.google.gson.JsonParseException;
|
|||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
|
||||
import net.minecraft.nbt.JsonToNBT;
|
||||
import net.minecraft.nbt.NBTException;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -103,7 +104,7 @@ public class JsonUtils
|
|||
try
|
||||
{
|
||||
return JsonToNBT.getTagFromJson(net.minecraft.util.JsonUtils.getString(json, key));
|
||||
} catch (NBTException e)
|
||||
} catch (CommandSyntaxException e)
|
||||
{
|
||||
throw new JsonSyntaxException("Malformed NBT tag", e);
|
||||
}
|
||||
|
|
|
@ -1,78 +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.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
|
||||
import net.minecraft.util.datafix.IFixType;
|
||||
import net.minecraft.util.datafix.IFixableData;
|
||||
|
||||
public class ModFixs
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
final String mod;
|
||||
final int version;
|
||||
private final Map<IFixType, List<IFixableData>> fixes = Maps.newHashMap();
|
||||
|
||||
ModFixs(String mod, int version)
|
||||
{
|
||||
this.mod = mod;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public List<IFixableData> getFixes(IFixType type)
|
||||
{
|
||||
return this.fixes.computeIfAbsent(type, k -> Lists.newArrayList());
|
||||
}
|
||||
|
||||
public void registerFix(IFixType type, IFixableData fixer)
|
||||
{
|
||||
List<IFixableData> list = getFixes(type);
|
||||
int ver = fixer.getFixVersion();
|
||||
|
||||
if (ver > this.version)
|
||||
{
|
||||
LOGGER.warn("[{}] Ignored fix registered for version: {} as the DataVersion of the game is: {}", mod, ver, this.version);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!list.isEmpty() && list.get(list.size()-1).getFixVersion() > ver)
|
||||
{
|
||||
for (int x = 0; x < list.size(); ++x)
|
||||
{
|
||||
if (list.get(x).getFixVersion() > ver)
|
||||
{
|
||||
list.add(x, fixer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
list.add(fixer);
|
||||
}
|
||||
|
||||
}
|
|
@ -45,7 +45,6 @@ public class PacketUtil
|
|||
{
|
||||
buffer.writeShort(Item.getIdFromItem(stack.getItem()));
|
||||
buffer.writeByte(stack.getCount());
|
||||
buffer.writeShort(stack.getMetadata());
|
||||
NBTTagCompound nbttagcompound = null;
|
||||
|
||||
if (stack.getItem().isDamageable() || stack.getItem().getShareTag())
|
||||
|
|
|
@ -67,7 +67,7 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem
|
|||
@Nonnull
|
||||
private ItemStack fillContainer(@Nonnull IBlockSource source, @Nonnull ItemStack stack)
|
||||
{
|
||||
World world = source.getWorld();
|
||||
World world = source.func_197524_h();
|
||||
EnumFacing dispenserFacing = source.getBlockState().getValue(BlockDispenser.FACING);
|
||||
BlockPos blockpos = source.getBlockPos().offset(dispenserFacing);
|
||||
|
||||
|
@ -101,7 +101,7 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem
|
|||
{
|
||||
ItemStack singleStack = stack.copy();
|
||||
singleStack.setCount(1);
|
||||
IFluidHandlerItem fluidHandler = FluidUtil.getFluidHandler(singleStack);
|
||||
IFluidHandlerItem fluidHandler = null; // TODO fluids FluidUtil.getFluidHandler(singleStack);
|
||||
if (fluidHandler == null)
|
||||
{
|
||||
return super.dispenseStack(source, stack);
|
||||
|
@ -110,7 +110,7 @@ public class DispenseFluidContainer extends BehaviorDefaultDispenseItem
|
|||
FluidStack fluidStack = fluidHandler.drain(Fluid.BUCKET_VOLUME, false);
|
||||
EnumFacing dispenserFacing = source.getBlockState().getValue(BlockDispenser.FACING);
|
||||
BlockPos blockpos = source.getBlockPos().offset(dispenserFacing);
|
||||
FluidActionResult result = fluidStack != null ? FluidUtil.tryPlaceFluid(null, source.getWorld(), blockpos, stack, fluidStack) : FluidActionResult.FAILURE;
|
||||
FluidActionResult result = fluidStack != null ? FluidUtil.tryPlaceFluid(null, source.func_197524_h(), blockpos, stack, fluidStack) : FluidActionResult.FAILURE;
|
||||
|
||||
if (result.isSuccess())
|
||||
{
|
||||
|
|
|
@ -29,10 +29,12 @@ import java.util.Locale;
|
|||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.material.Material;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Particles;
|
||||
import net.minecraft.init.SoundEvents;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.translation.LanguageMap;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.item.EnumRarity;
|
||||
|
@ -308,7 +310,7 @@ public class Fluid
|
|||
|
||||
for (int l = 0; l < 8; ++l)
|
||||
{
|
||||
worldIn.spawnParticle(EnumParticleTypes.SMOKE_LARGE, (double) pos.getX() + Math.random(), (double) pos.getY() + Math.random(), (double) pos.getZ() + Math.random(), 0.0D, 0.0D, 0.0D);
|
||||
worldIn.func_195589_b(Particles.field_197594_E, (double) pos.getX() + Math.random(), (double) pos.getY() + Math.random(), (double) pos.getZ() + Math.random(), 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,7 +320,7 @@ public class Fluid
|
|||
public String getLocalizedName(FluidStack stack)
|
||||
{
|
||||
String s = this.getUnlocalizedName();
|
||||
return s == null ? "" : I18n.translateToLocal(s);
|
||||
return s == null ? "" : LanguageMap.getInstance().translateKey(s); // TODO Server translation
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,6 +26,9 @@ import net.minecraftforge.registries.IRegistryDelegate;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
/**
|
||||
* ItemStack substitute for Fluids.
|
||||
*
|
||||
|
@ -36,6 +39,8 @@ import javax.annotation.Nullable;
|
|||
*/
|
||||
public class FluidStack
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
public int amount;
|
||||
public NBTTagCompound tag;
|
||||
private IRegistryDelegate<Fluid> fluidDelegate;
|
||||
|
@ -44,15 +49,15 @@ public class FluidStack
|
|||
{
|
||||
if (fluid == null)
|
||||
{
|
||||
FMLLog.bigWarning("Null fluid supplied to fluidstack. Did you try and create a stack for an unregistered fluid?");
|
||||
LOGGER.fatal("Null fluid supplied to fluidstack. Did you try and create a stack for an unregistered fluid?");
|
||||
throw new IllegalArgumentException("Cannot create a fluidstack from a null fluid");
|
||||
}
|
||||
}/* TODO fluids
|
||||
else if (!FluidRegistry.isFluidRegistered(fluid))
|
||||
{
|
||||
FMLLog.bigWarning("Failed attempt to create a FluidStack for an unregistered Fluid {} (type {})", fluid.getName(), fluid.getClass().getName());
|
||||
LOGGER.fatal("Failed attempt to create a FluidStack for an unregistered Fluid {} (type {})", fluid.getName(), fluid.getClass().getName());
|
||||
throw new IllegalArgumentException("Cannot create a fluidstack from an unregistered fluid");
|
||||
}
|
||||
this.fluidDelegate = FluidRegistry.makeDelegate(fluid);
|
||||
} */
|
||||
this.fluidDelegate = null; // TODO fluids FluidRegistry.makeDelegate(fluid);
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
|
@ -88,22 +93,22 @@ public class FluidStack
|
|||
}
|
||||
|
||||
String fluidName = nbt.getString("FluidName");
|
||||
if (FluidRegistry.getFluid(fluidName) == null)
|
||||
// TODO fluids if (FluidRegistry.getFluid(fluidName) == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}/*
|
||||
FluidStack stack = new FluidStack(FluidRegistry.getFluid(fluidName), nbt.getInteger("Amount"));
|
||||
|
||||
if (nbt.hasKey("Tag"))
|
||||
{
|
||||
stack.tag = nbt.getCompoundTag("Tag");
|
||||
}
|
||||
return stack;
|
||||
return stack;*/
|
||||
}
|
||||
|
||||
public NBTTagCompound writeToNBT(NBTTagCompound nbt)
|
||||
{
|
||||
nbt.setString("FluidName", FluidRegistry.getFluidName(getFluid()));
|
||||
// TODO fluids bt.setString("FluidName", FluidRegistry.getFluidName(getFluid()));
|
||||
nbt.setInteger("Amount", amount);
|
||||
|
||||
if (tag != null)
|
||||
|
@ -199,7 +204,7 @@ public class FluidStack
|
|||
return false;
|
||||
}
|
||||
|
||||
return isFluidEqual(FluidUtil.getFluidContained(other));
|
||||
return FluidUtil.getFluidContained(other).map(this::isFluidEqual).orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -704,7 +704,7 @@ public class FluidUtil
|
|||
*/
|
||||
@Nonnull
|
||||
public static ItemStack getFilledBucket(@Nonnull FluidStack fluidStack)
|
||||
{
|
||||
{/* TODO fluids
|
||||
Fluid fluid = fluidStack.getFluid();
|
||||
|
||||
if (fluidStack.tag == null || fluidStack.tag.isEmpty())
|
||||
|
@ -735,7 +735,7 @@ public class FluidUtil
|
|||
|
||||
return filledBucket;
|
||||
}
|
||||
|
||||
*/
|
||||
return ItemStack.EMPTY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
package net.minecraftforge.fluids;
|
||||
|
||||
import net.minecraft.block.BlockDispenser;
|
||||
import net.minecraft.creativetab.CreativeTabs;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemGroup;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.stats.StatList;
|
||||
|
@ -33,7 +33,9 @@ import net.minecraft.util.EnumHand;
|
|||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.text.translation.I18n;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentTranslation;
|
||||
import net.minecraft.util.text.translation.LanguageMap;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.ICapabilityProvider;
|
||||
import net.minecraftforge.event.entity.player.FillBucketEvent;
|
||||
|
@ -59,9 +61,9 @@ public class UniversalBucket extends Item
|
|||
private final ItemStack empty; // empty item to return and recognize when filling
|
||||
private final boolean nbtSensitive;
|
||||
|
||||
public UniversalBucket()
|
||||
public UniversalBucket(Builder builder)
|
||||
{
|
||||
this(Fluid.BUCKET_VOLUME, new ItemStack(Items.BUCKET), false);
|
||||
this(builder, Fluid.BUCKET_VOLUME, new ItemStack(Items.BUCKET), false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,17 +71,19 @@ public class UniversalBucket extends Item
|
|||
* @param empty Item used for filling with the bucket event and returned when emptied
|
||||
* @param nbtSensitive Whether the empty item is NBT sensitive (usually true if empty and full are the same items)
|
||||
*/
|
||||
public UniversalBucket(int capacity, @Nonnull ItemStack empty, boolean nbtSensitive)
|
||||
public UniversalBucket(Builder builder, int capacity, @Nonnull ItemStack empty, boolean nbtSensitive)
|
||||
{
|
||||
super(builder);
|
||||
this.capacity = capacity;
|
||||
this.empty = empty;
|
||||
this.nbtSensitive = nbtSensitive;
|
||||
|
||||
/* TODO move to builder construction
|
||||
this.setMaxStackSize(1);
|
||||
|
||||
this.setCreativeTab(CreativeTabs.MISC);
|
||||
|
||||
BlockDispenser.DISPENSE_BEHAVIOR_REGISTRY.putObject(this, DispenseFluidContainer.getInstance());
|
||||
*/
|
||||
BlockDispenser.func_199774_a(this, DispenseFluidContainer.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -101,10 +105,10 @@ public class UniversalBucket extends Item
|
|||
}
|
||||
|
||||
@Override
|
||||
public void getSubItems(@Nullable CreativeTabs tab, @Nonnull NonNullList<ItemStack> subItems)
|
||||
public void getSubItems(@Nullable ItemGroup tab, @Nonnull NonNullList<ItemStack> subItems)
|
||||
{
|
||||
if (!this.isInCreativeTab(tab))
|
||||
return;
|
||||
return;/* TODO fluids
|
||||
for (Fluid fluid : FluidRegistry.getRegisteredFluids().values())
|
||||
{
|
||||
if (fluid != FluidRegistry.WATER && fluid != FluidRegistry.LAVA && !fluid.getName().equals("milk"))
|
||||
|
@ -119,31 +123,32 @@ public class UniversalBucket extends Item
|
|||
subItems.add(filled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String getItemStackDisplayName(@Nonnull ItemStack stack)
|
||||
public ITextComponent func_200295_i(@Nonnull ItemStack stack)
|
||||
{
|
||||
FluidStack fluidStack = getFluid(stack);
|
||||
if (fluidStack == null)
|
||||
{
|
||||
if(!getEmpty().isEmpty())
|
||||
{
|
||||
return getEmpty().getDisplayName();
|
||||
return getEmpty().func_200301_q();
|
||||
}
|
||||
return super.getItemStackDisplayName(stack);
|
||||
return super.func_200295_i(stack);
|
||||
}
|
||||
|
||||
String unloc = this.getUnlocalizedNameInefficiently(stack);
|
||||
String unloc = this.getTranslationKey();
|
||||
|
||||
if (I18n.canTranslate(unloc + "." + fluidStack.getFluid().getName()))
|
||||
// TODO this is not reliable on the server
|
||||
if (LanguageMap.getInstance().func_210813_b(unloc + "." + fluidStack.getFluid().getName()))
|
||||
{
|
||||
return I18n.translateToLocal(unloc + "." + fluidStack.getFluid().getName());
|
||||
return new TextComponentTranslation(unloc + "." + fluidStack.getFluid().getName());
|
||||
}
|
||||
|
||||
return I18n.translateToLocalFormatted(unloc + ".name", fluidStack.getLocalizedName());
|
||||
return new TextComponentTranslation(unloc + ".name", fluidStack.getLocalizedName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -291,7 +296,7 @@ public class UniversalBucket extends Item
|
|||
public String getCreatorModId(@Nonnull ItemStack itemStack)
|
||||
{
|
||||
FluidStack fluidStack = getFluid(itemStack);
|
||||
String modId = FluidRegistry.getModId(fluidStack);
|
||||
String modId = null; // TODO fluids FluidRegistry.getModId(fluidStack);
|
||||
return modId != null ? modId : super.getCreatorModId(itemStack);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,18 +64,19 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide
|
|||
}
|
||||
|
||||
public boolean canFillFluidType(FluidStack fluid)
|
||||
{
|
||||
{/* TODO fluids
|
||||
if (fluid.getFluid() == FluidRegistry.WATER || fluid.getFluid() == FluidRegistry.LAVA || fluid.getFluid().getName().equals("milk"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return FluidRegistry.isUniversalBucketEnabled() && FluidRegistry.getBucketFluids().contains(fluid.getFluid());
|
||||
*/ return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FluidStack getFluid()
|
||||
{
|
||||
Item item = container.getItem();
|
||||
Item item = container.getItem();/* TODO fluids
|
||||
if (item == Items.WATER_BUCKET)
|
||||
{
|
||||
return new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME);
|
||||
|
@ -88,7 +89,7 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide
|
|||
{
|
||||
return FluidRegistry.getFluidStack("milk", Fluid.BUCKET_VOLUME);
|
||||
}
|
||||
else if (item == ForgeMod.getInstance().universalBucket)
|
||||
else*/ if (item == ForgeMod.getInstance().universalBucket)
|
||||
{
|
||||
return ForgeMod.getInstance().universalBucket.getFluid(container);
|
||||
}
|
||||
|
|
|
@ -127,6 +127,11 @@ public class ModList
|
|||
return Optional.ofNullable(this.indexedMods.get(modId));
|
||||
}
|
||||
|
||||
public Optional<? extends ModContainer> getModContainerByObject(Object obj)
|
||||
{
|
||||
return mods.stream().filter(mc -> mc.getMod() == obj).findFirst();
|
||||
}
|
||||
|
||||
public List<ModInfo> getMods()
|
||||
{
|
||||
return this.sortedList;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* TODO is this ded?
|
||||
package net.minecraftforge.fml.client;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -147,3 +147,4 @@ public class FMLConfigGuiFactory implements IModGuiFactory
|
|||
return fmlCategories;
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -24,12 +24,10 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.IArrayEntry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import net.minecraft.client.resources.I18n;
|
||||
|
||||
|
||||
/**
|
||||
* This class's main purpose is to provide the necessary objects for a sample Config GUI for FML, although
|
||||
|
|
|
@ -59,9 +59,9 @@ public class GuiButtonExt extends GuiButton
|
|||
this.mouseDragged(mc, mouseX, mouseY);
|
||||
int color = 14737632;
|
||||
|
||||
if (packedFGColour != 0)
|
||||
if (packedFGColor != 0)
|
||||
{
|
||||
color = packedFGColour;
|
||||
color = packedFGColor;
|
||||
}
|
||||
else if (!this.enabled)
|
||||
{
|
||||
|
|
|
@ -42,18 +42,19 @@ public class GuiCheckBox extends GuiButton
|
|||
}
|
||||
|
||||
@Override
|
||||
public void drawButton(Minecraft mc, int mouseX, int mouseY, float partial)
|
||||
public void func_194828_a(int mouseX, int mouseY, float partial)
|
||||
{
|
||||
if (this.visible)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.boxWidth && mouseY < this.y + this.height;
|
||||
GuiUtils.drawContinuousTexturedBox(BUTTON_TEXTURES, this.x, this.y, 0, 46, this.boxWidth, this.height, 200, 20, 2, 3, 2, 2, this.zLevel);
|
||||
this.mouseDragged(mc, mouseX, mouseY);
|
||||
int color = 14737632;
|
||||
|
||||
if (packedFGColour != 0)
|
||||
if (packedFGColor != 0)
|
||||
{
|
||||
color = packedFGColour;
|
||||
color = packedFGColor;
|
||||
}
|
||||
else if (!this.enabled)
|
||||
{
|
||||
|
@ -68,15 +69,9 @@ public class GuiCheckBox extends GuiButton
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean mousePressed(Minecraft mc, int mouseX, int mouseY)
|
||||
{
|
||||
if (this.enabled && this.visible && mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height)
|
||||
public void func_194829_a(double mouseX, double mouseY)
|
||||
{
|
||||
this.isChecked = !this.isChecked;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isChecked()
|
||||
|
|
|
@ -1,386 +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.fml.client.config;
|
||||
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.RESET_CHAR;
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.UNDO_CHAR;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
|
||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent.OnConfigChangedEvent;
|
||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent.PostConfigChangedEvent;
|
||||
import net.minecraftforge.fml.common.Loader;
|
||||
import net.minecraftforge.eventbus.api.Event.Result;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* This class is the base GuiScreen for all config GUI screens. It can be extended by mods to provide the top-level config screen
|
||||
* that will be called when the Config button is clicked from the Main Menu Mods list.
|
||||
*
|
||||
* @author bspkrs
|
||||
*/
|
||||
public class GuiConfig extends GuiScreen
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
/**
|
||||
* A reference to the screen object that created this. Used for navigating between screens.
|
||||
*/
|
||||
public final GuiScreen parentScreen;
|
||||
public String title = "Config GUI";
|
||||
@Nullable
|
||||
public String titleLine2;
|
||||
public final List<IConfigElement> configElements;
|
||||
public final List<IConfigEntry> initEntries;
|
||||
public GuiConfigEntries entryList;
|
||||
protected GuiButtonExt btnDefaultAll;
|
||||
protected GuiButtonExt btnUndoAll;
|
||||
protected GuiCheckBox chkApplyGlobally;
|
||||
public final String modID;
|
||||
/**
|
||||
* When set to a non-null value the OnConfigChanged and PostConfigChanged events will be posted when the Done button is pressed
|
||||
* if any configElements were changed (includes child screens). If not defined, the events will be posted if the parent gui is null
|
||||
* or if the parent gui is not an instance of GuiConfig.
|
||||
*/
|
||||
@Nullable
|
||||
public final String configID;
|
||||
public final boolean isWorldRunning;
|
||||
public final boolean allRequireWorldRestart;
|
||||
public final boolean allRequireMcRestart;
|
||||
public boolean needsRefresh = true;
|
||||
protected HoverChecker undoHoverChecker;
|
||||
protected HoverChecker resetHoverChecker;
|
||||
protected HoverChecker checkBoxHoverChecker;
|
||||
|
||||
/**
|
||||
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. If a non-null value is passed for configID,
|
||||
* the OnConfigChanged and PostConfigChanged events will be posted when the Done button is pressed if any configElements were changed
|
||||
* (includes child screens). If configID is not defined, the events will be posted if the parent gui is null or if the parent gui
|
||||
* is not an instance of GuiConfig.
|
||||
*
|
||||
* @param parentScreen the parent GuiScreen object
|
||||
* @param configElements a List of IConfigElement objects
|
||||
* @param modID the mod ID for the mod whose config settings will be edited
|
||||
* @param configID an identifier that will be passed to the OnConfigChanged and PostConfigChanged events. Setting this value will force
|
||||
* the save action to be called when the Done button is pressed on this screen if any configElements were changed.
|
||||
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
|
||||
* @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted
|
||||
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
|
||||
* edited.
|
||||
*/
|
||||
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID, String configID,
|
||||
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title)
|
||||
{
|
||||
this(parentScreen, configElements, modID, configID, allRequireWorldRestart, allRequireMcRestart, title, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. This constructor passes null for configID.
|
||||
* If configID is not defined, the events will be posted if the parent gui is null or if the parent gui is not an instance of GuiConfig.
|
||||
*
|
||||
* @param parentScreen the parent GuiScreen object
|
||||
* @param configElements a List of IConfigElement objects
|
||||
* @param modID the mod ID for the mod whose config settings will be edited
|
||||
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
|
||||
* @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted
|
||||
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
|
||||
* edited.
|
||||
*/
|
||||
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID,
|
||||
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title)
|
||||
{
|
||||
this(parentScreen, configElements, modID, null, allRequireWorldRestart, allRequireMcRestart, title, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. This constructor passes null for configID.
|
||||
* If configID is not defined, the events will be posted if the parent gui is null or if the parent gui is not an instance of GuiConfig.
|
||||
*
|
||||
* @param parentScreen the parent GuiScreen object
|
||||
* @param configElements a List of IConfigElement objects
|
||||
* @param modID the mod ID for the mod whose config settings will be edited
|
||||
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
|
||||
* @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted
|
||||
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
|
||||
* edited.
|
||||
* @param titleLine2 the desired title second line for this screen. Typically this is used to send the category name of the category
|
||||
* currently being edited.
|
||||
*/
|
||||
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID,
|
||||
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title, String titleLine2)
|
||||
{
|
||||
this(parentScreen, configElements, modID, null, allRequireWorldRestart, allRequireMcRestart, title, titleLine2);
|
||||
}
|
||||
|
||||
/**
|
||||
* GuiConfig constructor that will use ConfigChangedEvent when editing is concluded. titleLine2 is specified in this constructor.
|
||||
* If a non-null value is passed for configID, the OnConfigChanged and PostConfigChanged events will be posted when the Done button is
|
||||
* pressed if any configElements were changed (includes child screens). If configID is not defined, the events will be posted if the parent
|
||||
* gui is null or if the parent gui is not an instance of GuiConfig.
|
||||
*
|
||||
* @param parentScreen the parent GuiScreen object
|
||||
* @param configElements a List of IConfigElement objects
|
||||
* @param modID the mod ID for the mod whose config settings will be edited
|
||||
* @param configID an identifier that will be passed to the OnConfigChanged and PostConfigChanged events
|
||||
* @param allRequireWorldRestart send true if all configElements on this screen require a world restart
|
||||
* @param allRequireMcRestart send true if all configElements on this screen require MC to be restarted
|
||||
* @param title the desired title for this screen. For consistency it is recommended that you pass the path of the config file being
|
||||
* edited.
|
||||
* @param titleLine2 the desired title second line for this screen. Typically this is used to send the category name of the category
|
||||
* currently being edited.
|
||||
*/
|
||||
public GuiConfig(GuiScreen parentScreen, List<IConfigElement> configElements, String modID, @Nullable String configID,
|
||||
boolean allRequireWorldRestart, boolean allRequireMcRestart, String title, @Nullable String titleLine2)
|
||||
{
|
||||
this.mc = Minecraft.getMinecraft();
|
||||
this.parentScreen = parentScreen;
|
||||
this.configElements = configElements;
|
||||
this.entryList = new GuiConfigEntries(this, mc);
|
||||
this.initEntries = new ArrayList<>(entryList.listEntries);
|
||||
this.allRequireWorldRestart = allRequireWorldRestart;
|
||||
IF:if (!allRequireWorldRestart)
|
||||
{
|
||||
for (IConfigElement element : configElements)
|
||||
{
|
||||
if (!element.requiresWorldRestart());
|
||||
break IF;
|
||||
}
|
||||
allRequireWorldRestart = true;
|
||||
}
|
||||
this.allRequireMcRestart = allRequireMcRestart;
|
||||
IF:if (!allRequireMcRestart)
|
||||
{
|
||||
for (IConfigElement element : configElements)
|
||||
{
|
||||
if (!element.requiresMcRestart());
|
||||
break IF;
|
||||
}
|
||||
allRequireMcRestart = true;
|
||||
}
|
||||
this.modID = modID;
|
||||
this.configID = configID;
|
||||
this.isWorldRunning = mc.world != null;
|
||||
if (title != null)
|
||||
this.title = title;
|
||||
this.titleLine2 = titleLine2;
|
||||
if (this.titleLine2 != null && this.titleLine2.startsWith(" > "))
|
||||
this.titleLine2 = this.titleLine2.replaceFirst(" > ", "");
|
||||
}
|
||||
|
||||
public static String getAbridgedConfigPath(String path)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc.mcDataDir.getAbsolutePath().endsWith("."))
|
||||
return path.replace("\\", "/").replace(mc.mcDataDir.getAbsolutePath().replace("\\", "/").substring(0, mc.mcDataDir.getAbsolutePath().length() - 1), "/.minecraft/");
|
||||
else
|
||||
return path.replace("\\", "/").replace(mc.mcDataDir.getAbsolutePath().replace("\\", "/"), "/.minecraft");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui()
|
||||
{
|
||||
Keyboard.enableRepeatEvents(true);
|
||||
|
||||
if (this.entryList == null || this.needsRefresh)
|
||||
{
|
||||
this.entryList = new GuiConfigEntries(this, mc);
|
||||
this.needsRefresh = false;
|
||||
}
|
||||
|
||||
int undoGlyphWidth = mc.fontRenderer.getStringWidth(UNDO_CHAR) * 2;
|
||||
int resetGlyphWidth = mc.fontRenderer.getStringWidth(RESET_CHAR) * 2;
|
||||
int doneWidth = Math.max(mc.fontRenderer.getStringWidth(I18n.format("gui.done")) + 20, 100);
|
||||
int undoWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.undoChanges")) + undoGlyphWidth + 20;
|
||||
int resetWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.resetToDefault")) + resetGlyphWidth + 20;
|
||||
int checkWidth = mc.fontRenderer.getStringWidth(I18n.format("fml.configgui.applyGlobally")) + 13;
|
||||
int buttonWidthHalf = (doneWidth + 5 + undoWidth + 5 + resetWidth + 5 + checkWidth) / 2;
|
||||
this.buttonList.add(new GuiButtonExt(2000, this.width / 2 - buttonWidthHalf, this.height - 29, doneWidth, 20, I18n.format("gui.done")));
|
||||
this.buttonList.add(this.btnDefaultAll = new GuiUnicodeGlyphButton(2001, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5,
|
||||
this.height - 29, resetWidth, 20, " " + I18n.format("fml.configgui.tooltip.resetToDefault"), RESET_CHAR, 2.0F));
|
||||
this.buttonList.add(btnUndoAll = new GuiUnicodeGlyphButton(2002, this.width / 2 - buttonWidthHalf + doneWidth + 5,
|
||||
this.height - 29, undoWidth, 20, " " + I18n.format("fml.configgui.tooltip.undoChanges"), UNDO_CHAR, 2.0F));
|
||||
this.buttonList.add(chkApplyGlobally = new GuiCheckBox(2003, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5 + resetWidth + 5,
|
||||
this.height - 24, I18n.format("fml.configgui.applyGlobally"), false));
|
||||
|
||||
this.undoHoverChecker = new HoverChecker(this.btnUndoAll, 800);
|
||||
this.resetHoverChecker = new HoverChecker(this.btnDefaultAll, 800);
|
||||
this.checkBoxHoverChecker = new HoverChecker(chkApplyGlobally, 800);
|
||||
this.entryList.initGui();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGuiClosed()
|
||||
{
|
||||
this.entryList.onGuiClosed();
|
||||
|
||||
if (this.configID != null && this.parentScreen instanceof GuiConfig)
|
||||
{
|
||||
GuiConfig parentGuiConfig = (GuiConfig) this.parentScreen;
|
||||
parentGuiConfig.needsRefresh = true;
|
||||
parentGuiConfig.initGui();
|
||||
}
|
||||
|
||||
if (!(this.parentScreen instanceof GuiConfig))
|
||||
Keyboard.enableRepeatEvents(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button)
|
||||
{
|
||||
if (button.id == 2000)
|
||||
{
|
||||
boolean flag = true;
|
||||
try
|
||||
{
|
||||
if ((configID != null || this.parentScreen == null || !(this.parentScreen instanceof GuiConfig))
|
||||
&& (this.entryList.hasChangedEntry(true)))
|
||||
{
|
||||
boolean requiresMcRestart = this.entryList.saveConfigElements();
|
||||
|
||||
if (Loader.isModLoaded(modID))
|
||||
{
|
||||
ConfigChangedEvent event = new OnConfigChangedEvent(modID, configID, isWorldRunning, requiresMcRestart);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
if (!event.getResult().equals(Result.DENY))
|
||||
MinecraftForge.EVENT_BUS.post(new PostConfigChangedEvent(modID, configID, isWorldRunning, requiresMcRestart));
|
||||
|
||||
if (requiresMcRestart)
|
||||
{
|
||||
flag = false;
|
||||
mc.displayGuiScreen(new GuiMessageDialog(parentScreen, "fml.configgui.gameRestartTitle",
|
||||
new TextComponentString(I18n.format("fml.configgui.gameRestartRequired")), "fml.configgui.confirmRestartMessage"));
|
||||
}
|
||||
|
||||
if (this.parentScreen instanceof GuiConfig)
|
||||
((GuiConfig) this.parentScreen).needsRefresh = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOGGER.error("Error performing GuiConfig action:", e);
|
||||
}
|
||||
|
||||
if (flag)
|
||||
this.mc.displayGuiScreen(this.parentScreen);
|
||||
}
|
||||
else if (button.id == 2001)
|
||||
{
|
||||
this.entryList.setAllToDefault(this.chkApplyGlobally.isChecked());
|
||||
}
|
||||
else if (button.id == 2002)
|
||||
{
|
||||
this.entryList.undoAllChanges(this.chkApplyGlobally.isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException
|
||||
{
|
||||
super.handleMouseInput();
|
||||
this.entryList.handleMouseInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int x, int y, int mouseEvent) throws IOException
|
||||
{
|
||||
if (mouseEvent != 0 || !this.entryList.mouseClicked(x, y, mouseEvent))
|
||||
{
|
||||
this.entryList.mouseClickedPassThru(x, y, mouseEvent);
|
||||
super.mouseClicked(x, y, mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseReleased(int x, int y, int mouseEvent)
|
||||
{
|
||||
if (mouseEvent != 0 || !this.entryList.mouseReleased(x, y, mouseEvent))
|
||||
{
|
||||
super.mouseReleased(x, y, mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char eventChar, int eventKey)
|
||||
{
|
||||
if (eventKey == Keyboard.KEY_ESCAPE)
|
||||
this.mc.displayGuiScreen(parentScreen);
|
||||
else
|
||||
this.entryList.keyTyped(eventChar, eventKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen()
|
||||
{
|
||||
super.updateScreen();
|
||||
this.entryList.updateScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int mouseX, int mouseY, float partialTicks)
|
||||
{
|
||||
this.drawDefaultBackground();
|
||||
this.entryList.drawScreen(mouseX, mouseY, partialTicks);
|
||||
this.drawCenteredString(this.fontRenderer, this.title, this.width / 2, 8, 16777215);
|
||||
String title2 = this.titleLine2;
|
||||
|
||||
if (title2 != null)
|
||||
{
|
||||
int strWidth = mc.fontRenderer.getStringWidth(title2);
|
||||
int ellipsisWidth = mc.fontRenderer.getStringWidth("...");
|
||||
if (strWidth > width - 6 && strWidth > ellipsisWidth)
|
||||
title2 = mc.fontRenderer.trimStringToWidth(title2, width - 6 - ellipsisWidth).trim() + "...";
|
||||
this.drawCenteredString(this.fontRenderer, title2, this.width / 2, 18, 16777215);
|
||||
}
|
||||
|
||||
this.btnUndoAll.enabled = this.entryList.areAnyEntriesEnabled(this.chkApplyGlobally.isChecked()) && this.entryList.hasChangedEntry(this.chkApplyGlobally.isChecked());
|
||||
this.btnDefaultAll.enabled = this.entryList.areAnyEntriesEnabled(this.chkApplyGlobally.isChecked()) && !this.entryList.areAllEntriesDefault(this.chkApplyGlobally.isChecked());
|
||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||
this.entryList.drawScreenPost(mouseX, mouseY, partialTicks);
|
||||
if (this.undoHoverChecker.checkHover(mouseX, mouseY))
|
||||
this.drawToolTip(Arrays.asList(I18n.format("fml.configgui.tooltip.undoAll").split("\n")), mouseX, mouseY);
|
||||
if (this.resetHoverChecker.checkHover(mouseX, mouseY))
|
||||
this.drawToolTip(Arrays.asList(I18n.format("fml.configgui.tooltip.resetAll").split("\n")), mouseX, mouseY);
|
||||
if (this.checkBoxHoverChecker.checkHover(mouseX, mouseY))
|
||||
this.drawToolTip(Arrays.asList(I18n.format("fml.configgui.tooltip.applyGlobally").split("\n")), mouseX, mouseY);
|
||||
}
|
||||
|
||||
public void drawToolTip(List<String> stringList, int x, int y)
|
||||
{
|
||||
GuiUtils.drawHoveringText(stringList, x, y, width, height, 300, fontRenderer);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,225 +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.fml.client.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.RESET_CHAR;
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.UNDO_CHAR;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
/**
|
||||
* This class is the base screen used for editing an array-type property. It provides a list of array entries for the user to edit.
|
||||
* This screen is invoked from a GuiConfig screen by controls that use the EditListPropEntry IGuiConfigListEntry object.
|
||||
*
|
||||
* @author bspkrs
|
||||
*/
|
||||
public class GuiEditArray extends GuiScreen
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
protected GuiScreen parentScreen;
|
||||
protected IConfigElement configElement;
|
||||
protected GuiEditArrayEntries entryList;
|
||||
protected GuiButtonExt btnUndoChanges, btnDefault, btnDone;
|
||||
protected String title;
|
||||
protected String titleLine2;
|
||||
protected String titleLine3;
|
||||
protected int slotIndex;
|
||||
protected final Object[] beforeValues;
|
||||
protected Object[] currentValues;
|
||||
protected HoverChecker tooltipHoverChecker;
|
||||
protected List<String> toolTip;
|
||||
protected boolean enabled;
|
||||
|
||||
public GuiEditArray(GuiScreen parentScreen, IConfigElement configElement, int slotIndex, Object[] currentValues, boolean enabled)
|
||||
{
|
||||
this.mc = Minecraft.getMinecraft();
|
||||
this.parentScreen = parentScreen;
|
||||
this.configElement = configElement;
|
||||
this.slotIndex = slotIndex;
|
||||
this.beforeValues = currentValues;
|
||||
this.currentValues = currentValues;
|
||||
this.toolTip = new ArrayList<String>();
|
||||
this.enabled = enabled;
|
||||
String propName = I18n.format(configElement.getLanguageKey());
|
||||
String comment;
|
||||
|
||||
comment = I18n.format(configElement.getLanguageKey() + ".tooltip",
|
||||
"\n" + TextFormatting.AQUA, configElement.getDefault(), configElement.getMinValue(), configElement.getMaxValue());
|
||||
|
||||
if (!comment.equals(configElement.getLanguageKey() + ".tooltip"))
|
||||
Collections.addAll(toolTip, (TextFormatting.GREEN + propName + "\n" + TextFormatting.YELLOW + comment).split("\n"));
|
||||
else if (configElement.getComment() != null && !configElement.getComment().trim().isEmpty())
|
||||
Collections.addAll(toolTip, (TextFormatting.GREEN + propName + "\n" + TextFormatting.YELLOW + configElement.getComment()).split("\n"));
|
||||
else
|
||||
Collections.addAll(toolTip, (TextFormatting.GREEN + propName + "\n" + TextFormatting.RED + "No tooltip defined.").split("\n"));
|
||||
|
||||
if (parentScreen instanceof GuiConfig)
|
||||
{
|
||||
this.title = ((GuiConfig) parentScreen).title;
|
||||
if (((GuiConfig) parentScreen).titleLine2 != null)
|
||||
{
|
||||
this.titleLine2 = ((GuiConfig) parentScreen).titleLine2;
|
||||
this.titleLine3 = I18n.format(configElement.getLanguageKey());
|
||||
}
|
||||
else
|
||||
this.titleLine2 = I18n.format(configElement.getLanguageKey());
|
||||
this.tooltipHoverChecker = new HoverChecker(28, 37, 0, parentScreen.width, 800);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.title = I18n.format(configElement.getLanguageKey());
|
||||
this.tooltipHoverChecker = new HoverChecker(8, 17, 0, parentScreen.width, 800);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui()
|
||||
{
|
||||
this.entryList = createEditArrayEntries();
|
||||
|
||||
int undoGlyphWidth = mc.fontRenderer.getStringWidth(UNDO_CHAR) * 2;
|
||||
int resetGlyphWidth = mc.fontRenderer.getStringWidth(RESET_CHAR) * 2;
|
||||
int doneWidth = Math.max(mc.fontRenderer.getStringWidth(I18n.format("gui.done")) + 20, 100);
|
||||
int undoWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.undoChanges")) + undoGlyphWidth + 20;
|
||||
int resetWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.resetToDefault")) + resetGlyphWidth + 20;
|
||||
int buttonWidthHalf = (doneWidth + 5 + undoWidth + 5 + resetWidth) / 2;
|
||||
this.buttonList.add(btnDone = new GuiButtonExt(2000, this.width / 2 - buttonWidthHalf, this.height - 29, doneWidth, 20, I18n.format("gui.done")));
|
||||
this.buttonList.add(btnDefault = new GuiUnicodeGlyphButton(2001, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5,
|
||||
this.height - 29, resetWidth, 20, " " + I18n.format("fml.configgui.tooltip.resetToDefault"), RESET_CHAR, 2.0F));
|
||||
this.buttonList.add(btnUndoChanges = new GuiUnicodeGlyphButton(2002, this.width / 2 - buttonWidthHalf + doneWidth + 5,
|
||||
this.height - 29, undoWidth, 20, " " + I18n.format("fml.configgui.tooltip.undoChanges"), UNDO_CHAR, 2.0F));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button)
|
||||
{
|
||||
if (button.id == 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.entryList.saveListChanges();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOGGER.error("Error performing GuiEditArray action:", e);
|
||||
}
|
||||
this.mc.displayGuiScreen(this.parentScreen);
|
||||
}
|
||||
else if (button.id == 2001)
|
||||
{
|
||||
this.currentValues = configElement.getDefaults();
|
||||
this.entryList = createEditArrayEntries();
|
||||
}
|
||||
else if (button.id == 2002)
|
||||
{
|
||||
this.currentValues = Arrays.copyOf(beforeValues, beforeValues.length);
|
||||
this.entryList = createEditArrayEntries();
|
||||
}
|
||||
}
|
||||
|
||||
protected GuiEditArrayEntries createEditArrayEntries()
|
||||
{
|
||||
return new GuiEditArrayEntries(this, this.mc, this.configElement, this.beforeValues, this.currentValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException
|
||||
{
|
||||
super.handleMouseInput();
|
||||
this.entryList.handleMouseInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseClicked(int x, int y, int mouseEvent) throws IOException
|
||||
{
|
||||
if (mouseEvent != 0 || !this.entryList.mouseClicked(x, y, mouseEvent))
|
||||
{
|
||||
this.entryList.mouseClickedPassThru(x, y, mouseEvent);
|
||||
super.mouseClicked(x, y, mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseReleased(int x, int y, int mouseEvent)
|
||||
{
|
||||
if (mouseEvent != 0 || !this.entryList.mouseReleased(x, y, mouseEvent))
|
||||
{
|
||||
super.mouseReleased(x, y, mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void keyTyped(char eventChar, int eventKey)
|
||||
{
|
||||
if (eventKey == Keyboard.KEY_ESCAPE)
|
||||
this.mc.displayGuiScreen(parentScreen);
|
||||
else
|
||||
this.entryList.keyTyped(eventChar, eventKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateScreen()
|
||||
{
|
||||
super.updateScreen();
|
||||
this.entryList.updateScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int par1, int par2, float par3)
|
||||
{
|
||||
this.drawDefaultBackground();
|
||||
this.entryList.drawScreen(par1, par2, par3);
|
||||
this.drawCenteredString(this.fontRenderer, this.title, this.width / 2, 8, 16777215);
|
||||
|
||||
if (this.titleLine2 != null)
|
||||
this.drawCenteredString(this.fontRenderer, this.titleLine2, this.width / 2, 18, 16777215);
|
||||
|
||||
if (this.titleLine3 != null)
|
||||
this.drawCenteredString(this.fontRenderer, this.titleLine3, this.width / 2, 28, 16777215);
|
||||
|
||||
this.btnDone.enabled = this.entryList.isListSavable();
|
||||
this.btnDefault.enabled = enabled && !this.entryList.isDefault();
|
||||
this.btnUndoChanges.enabled = enabled && this.entryList.isChanged();
|
||||
super.drawScreen(par1, par2, par3);
|
||||
this.entryList.drawScreenPost(par1, par2, par3);
|
||||
|
||||
if (this.tooltipHoverChecker != null && this.tooltipHoverChecker.checkHover(par1, par2))
|
||||
drawToolTip(this.toolTip, par1, par2);
|
||||
}
|
||||
|
||||
public void drawToolTip(List<String> stringList, int x, int y)
|
||||
{
|
||||
GuiUtils.drawHoveringText(stringList, x, y, width, height, 300, fontRenderer);
|
||||
}
|
||||
}
|
|
@ -1,709 +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.fml.client.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiListExtended;
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.ArrayEntry;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.INVALID;
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.VALID;
|
||||
|
||||
/**
|
||||
* This class implements the scrolling list functionality of the GuiEditList screen. It also provides all the default controls
|
||||
* for editing array-type properties.
|
||||
*/
|
||||
public class GuiEditArrayEntries extends GuiListExtended
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
protected GuiEditArray owningGui;
|
||||
public IConfigElement configElement;
|
||||
public List<IArrayEntry> listEntries;
|
||||
public boolean isDefault;
|
||||
public boolean isChanged;
|
||||
public boolean canAddMoreEntries;
|
||||
public final int controlWidth;
|
||||
public final Object[] beforeValues;
|
||||
public Object[] currentValues;
|
||||
|
||||
public GuiEditArrayEntries(GuiEditArray parent, Minecraft mc, IConfigElement configElement, Object[] beforeValues, Object[] currentValues)
|
||||
{
|
||||
super(mc, parent.width, parent.height, parent.titleLine2 != null ? (parent.titleLine3 != null ? 43 : 33) : 23, parent.height - 32, 20);
|
||||
this.owningGui = parent;
|
||||
this.configElement = configElement;
|
||||
this.beforeValues = beforeValues;
|
||||
this.currentValues = currentValues;
|
||||
this.setShowSelectionBox(false);
|
||||
this.isChanged = !Arrays.deepEquals(beforeValues, currentValues);
|
||||
this.isDefault = Arrays.deepEquals(currentValues, configElement.getDefaults());
|
||||
this.canAddMoreEntries = !configElement.isListLengthFixed() && (configElement.getMaxListLength() == -1 || currentValues.length < configElement.getMaxListLength());
|
||||
|
||||
listEntries = new ArrayList<IArrayEntry>();
|
||||
|
||||
controlWidth = (parent.width / 2) - (configElement.isListLengthFixed() ? 0 : 48);
|
||||
|
||||
if (configElement.isList() && configElement.getArrayEntryClass() != null)
|
||||
{
|
||||
Class<? extends IArrayEntry> clazz = configElement.getArrayEntryClass();
|
||||
for (Object value : currentValues)
|
||||
{
|
||||
try
|
||||
{
|
||||
listEntries.add(clazz.getConstructor(GuiEditArray.class, GuiEditArrayEntries.class, IConfigElement.class, Object.class)
|
||||
.newInstance(this.owningGui, this, configElement, value));
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOGGER.error("There was a critical error instantiating the custom IGuiEditListEntry for property {}.", configElement.getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (configElement.isList() && configElement.getType().equals(ConfigGuiType.BOOLEAN))
|
||||
for (Object value : currentValues)
|
||||
listEntries.add(new BooleanEntry(this.owningGui, this, configElement, Boolean.valueOf(value.toString())));
|
||||
else if (configElement.isList() && configElement.getType().equals(ConfigGuiType.INTEGER))
|
||||
for (Object value : currentValues)
|
||||
listEntries.add(new IntegerEntry(this.owningGui, this, configElement, Integer.parseInt(value.toString())));
|
||||
else if (configElement.isList() && configElement.getType().equals(ConfigGuiType.DOUBLE))
|
||||
for (Object value : currentValues)
|
||||
listEntries.add(new DoubleEntry(this.owningGui, this, configElement, Double.parseDouble(value.toString())));
|
||||
else if (configElement.isList())
|
||||
for (Object value : currentValues)
|
||||
listEntries.add(new StringEntry(this.owningGui, this, configElement, value.toString()));
|
||||
|
||||
if (!configElement.isListLengthFixed())
|
||||
listEntries.add(new BaseEntry(this.owningGui, this, configElement));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollBarX()
|
||||
{
|
||||
return width - (width / 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the list
|
||||
*/
|
||||
@Override
|
||||
public int getListWidth()
|
||||
{
|
||||
return owningGui.width;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IArrayEntry getListEntry(int index)
|
||||
{
|
||||
return listEntries.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSize()
|
||||
{
|
||||
return listEntries.size();
|
||||
}
|
||||
|
||||
public void addNewEntry(int index)
|
||||
{
|
||||
if (configElement.isList() && configElement.getArrayEntryClass() != null)
|
||||
{
|
||||
Class<? extends IArrayEntry> clazz = configElement.getArrayEntryClass();
|
||||
try
|
||||
{
|
||||
Object value;
|
||||
switch (configElement.getType())
|
||||
{
|
||||
case BOOLEAN:
|
||||
value = true;
|
||||
break;
|
||||
case INTEGER:
|
||||
value = 0;
|
||||
break;
|
||||
case DOUBLE:
|
||||
value = 0.0D;
|
||||
break;
|
||||
default:
|
||||
value = "";
|
||||
}
|
||||
listEntries.add(index, clazz.getConstructor(GuiEditArray.class, GuiEditArrayEntries.class, IConfigElement.class, Object.class).newInstance(this.owningGui, this, configElement, value));
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOGGER.error("There was a critical error instantiating the custom IGuiEditListEntry for property {}.", configElement.getName(), e);
|
||||
}
|
||||
}
|
||||
else if (configElement.isList() && configElement.getType() == ConfigGuiType.BOOLEAN)
|
||||
listEntries.add(index, new BooleanEntry(this.owningGui, this, this.configElement, true));
|
||||
else if (configElement.isList() && configElement.getType() == ConfigGuiType.INTEGER)
|
||||
listEntries.add(index, new IntegerEntry(this.owningGui, this, this.configElement, 0));
|
||||
else if (configElement.isList() && configElement.getType() == ConfigGuiType.DOUBLE)
|
||||
listEntries.add(index, new DoubleEntry(this.owningGui, this, this.configElement, 0.0D));
|
||||
else if (configElement.isList())
|
||||
listEntries.add(index, new StringEntry(this.owningGui, this, this.configElement, ""));
|
||||
this.canAddMoreEntries = !configElement.isListLengthFixed()
|
||||
&& (configElement.getMaxListLength() == -1 || this.listEntries.size() - 1 < configElement.getMaxListLength());
|
||||
keyTyped((char) Keyboard.CHAR_NONE, Keyboard.KEY_END);
|
||||
}
|
||||
|
||||
public void removeEntry(int index)
|
||||
{
|
||||
this.listEntries.remove(index);
|
||||
this.canAddMoreEntries = !configElement.isListLengthFixed()
|
||||
&& (configElement.getMaxListLength() == -1 || this.listEntries.size() - 1 < configElement.getMaxListLength());
|
||||
keyTyped((char) Keyboard.CHAR_NONE, Keyboard.KEY_END);
|
||||
}
|
||||
|
||||
public boolean isChanged()
|
||||
{
|
||||
return isChanged;
|
||||
}
|
||||
|
||||
public boolean isDefault()
|
||||
{
|
||||
return isDefault;
|
||||
}
|
||||
|
||||
public void recalculateState()
|
||||
{
|
||||
isDefault = true;
|
||||
isChanged = false;
|
||||
|
||||
int listLength = configElement.isListLengthFixed() ? listEntries.size() : listEntries.size() - 1;
|
||||
|
||||
if (listLength != configElement.getDefaults().length)
|
||||
{
|
||||
isDefault = false;
|
||||
}
|
||||
|
||||
if (listLength != beforeValues.length)
|
||||
{
|
||||
isChanged = true;
|
||||
}
|
||||
|
||||
if (isDefault)
|
||||
for (int i = 0; i < listLength; i++)
|
||||
if (!configElement.getDefaults()[i].equals(listEntries.get(i).getValue()))
|
||||
isDefault = false;
|
||||
|
||||
if (!isChanged)
|
||||
for (int i = 0; i < listLength; i++)
|
||||
if (!beforeValues[i].equals(listEntries.get(i).getValue()))
|
||||
isChanged = true;
|
||||
}
|
||||
|
||||
protected void keyTyped(char eventChar, int eventKey)
|
||||
{
|
||||
for (IArrayEntry entry : this.listEntries)
|
||||
entry.keyTyped(eventChar, eventKey);
|
||||
|
||||
recalculateState();
|
||||
}
|
||||
|
||||
protected void updateScreen()
|
||||
{
|
||||
for (IArrayEntry entry : this.listEntries)
|
||||
entry.updateCursorCounter();
|
||||
}
|
||||
|
||||
protected void mouseClickedPassThru(int x, int y, int mouseEvent)
|
||||
{
|
||||
for (IArrayEntry entry : this.listEntries)
|
||||
entry.mouseClicked(x, y, mouseEvent);
|
||||
}
|
||||
|
||||
protected boolean isListSavable()
|
||||
{
|
||||
for (IArrayEntry entry : this.listEntries)
|
||||
if (!entry.isValueSavable())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void saveListChanges()
|
||||
{
|
||||
int listLength = configElement.isListLengthFixed() ? listEntries.size() : listEntries.size() - 1;
|
||||
|
||||
if (owningGui.slotIndex != -1 && owningGui.parentScreen != null
|
||||
&& owningGui.parentScreen instanceof GuiConfig
|
||||
&& ((GuiConfig) owningGui.parentScreen).entryList.getListEntry(owningGui.slotIndex) instanceof ArrayEntry)
|
||||
{
|
||||
ArrayEntry entry = (ArrayEntry) ((GuiConfig) owningGui.parentScreen).entryList.getListEntry(owningGui.slotIndex);
|
||||
|
||||
Object[] ao = new Object[listLength];
|
||||
for (int i = 0; i < listLength; i++)
|
||||
ao[i] = listEntries.get(i).getValue();
|
||||
|
||||
entry.setListFromChildScreen(ao);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (configElement.isList() && configElement.getType() == ConfigGuiType.BOOLEAN)
|
||||
{
|
||||
Boolean[] abol = new Boolean[listLength];
|
||||
for (int i = 0; i < listLength; i++)
|
||||
abol[i] = Boolean.valueOf(listEntries.get(i).getValue().toString());
|
||||
|
||||
configElement.set(abol);
|
||||
}
|
||||
else if (configElement.isList() && configElement.getType() == ConfigGuiType.INTEGER)
|
||||
{
|
||||
Integer[] ai = new Integer[listLength];
|
||||
for (int i = 0; i < listLength; i++)
|
||||
ai[i] = Integer.valueOf(listEntries.get(i).getValue().toString());
|
||||
|
||||
configElement.set(ai);
|
||||
}
|
||||
else if (configElement.isList() && configElement.getType() == ConfigGuiType.DOUBLE)
|
||||
{
|
||||
Double[] ad = new Double[listLength];
|
||||
for (int i = 0; i < listLength; i++)
|
||||
ad[i] = Double.valueOf(listEntries.get(i).getValue().toString());
|
||||
|
||||
configElement.set(ad);
|
||||
}
|
||||
else if (configElement.isList())
|
||||
{
|
||||
String[] as = new String[listLength];
|
||||
for (int i = 0; i < listLength; i++)
|
||||
as[i] = listEntries.get(i).getValue().toString();
|
||||
|
||||
configElement.set(as);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void drawScreenPost(int mouseX, int mouseY, float f)
|
||||
{
|
||||
for (IArrayEntry entry : this.listEntries)
|
||||
entry.drawToolTip(mouseX, mouseY);
|
||||
}
|
||||
|
||||
public Minecraft getMC()
|
||||
{
|
||||
return this.mc;
|
||||
}
|
||||
|
||||
/**
|
||||
* IGuiListEntry Inner Classes
|
||||
*/
|
||||
|
||||
public static class DoubleEntry extends StringEntry
|
||||
{
|
||||
public DoubleEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Double value)
|
||||
{
|
||||
super(owningScreen, owningEntryList, configElement, value);
|
||||
this.isValidated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char eventChar, int eventKey)
|
||||
{
|
||||
if (owningScreen.enabled || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|
||||
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
|
||||
{
|
||||
String validChars = "0123456789";
|
||||
String before = this.textFieldValue.getText();
|
||||
if (validChars.contains(String.valueOf(eventChar)) ||
|
||||
(!before.startsWith("-") && this.textFieldValue.getCursorPosition() == 0 && eventChar == '-')
|
||||
|| (!before.contains(".") && eventChar == '.')
|
||||
|| eventKey == Keyboard.KEY_BACK || eventKey == Keyboard.KEY_DELETE || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|
||||
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
|
||||
this.textFieldValue.textboxKeyTyped((owningScreen.enabled ? eventChar : Keyboard.CHAR_NONE), eventKey);
|
||||
|
||||
if (!textFieldValue.getText().trim().isEmpty() && !textFieldValue.getText().trim().equals("-"))
|
||||
{
|
||||
try
|
||||
{
|
||||
double value = Double.parseDouble(textFieldValue.getText().trim());
|
||||
if (value < Double.valueOf(configElement.getMinValue().toString()) || value > Double.valueOf(configElement.getMaxValue().toString()))
|
||||
this.isValidValue = false;
|
||||
else
|
||||
this.isValidValue = true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
this.isValidValue = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
this.isValidValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getValue()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Double.valueOf(this.textFieldValue.getText().trim());
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
return Double.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class IntegerEntry extends StringEntry
|
||||
{
|
||||
public IntegerEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Integer value)
|
||||
{
|
||||
super(owningScreen, owningEntryList, configElement, value);
|
||||
this.isValidated = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char eventChar, int eventKey)
|
||||
{
|
||||
if (owningScreen.enabled || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|
||||
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
|
||||
{
|
||||
String validChars = "0123456789";
|
||||
String before = this.textFieldValue.getText();
|
||||
if (validChars.contains(String.valueOf(eventChar))
|
||||
|| (!before.startsWith("-") && this.textFieldValue.getCursorPosition() == 0 && eventChar == '-')
|
||||
|| eventKey == Keyboard.KEY_BACK || eventKey == Keyboard.KEY_DELETE
|
||||
|| eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT || eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
|
||||
this.textFieldValue.textboxKeyTyped((owningScreen.enabled ? eventChar : Keyboard.CHAR_NONE), eventKey);
|
||||
|
||||
if (!textFieldValue.getText().trim().isEmpty() && !textFieldValue.getText().trim().equals("-"))
|
||||
{
|
||||
try
|
||||
{
|
||||
long value = Long.parseLong(textFieldValue.getText().trim());
|
||||
if (value < Integer.valueOf(configElement.getMinValue().toString()) || value > Integer.valueOf(configElement.getMaxValue().toString()))
|
||||
this.isValidValue = false;
|
||||
else
|
||||
this.isValidValue = true;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
this.isValidValue = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
this.isValidValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getValue()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Integer.valueOf(this.textFieldValue.getText().trim());
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringEntry extends BaseEntry
|
||||
{
|
||||
protected final GuiTextField textFieldValue;
|
||||
|
||||
public StringEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, Object value)
|
||||
{
|
||||
super(owningScreen, owningEntryList, configElement);
|
||||
this.textFieldValue = new GuiTextField(0, owningEntryList.getMC().fontRenderer, owningEntryList.width / 4 + 1, 0, owningEntryList.controlWidth - 3, 16);
|
||||
this.textFieldValue.setMaxStringLength(10000);
|
||||
this.textFieldValue.setText(value.toString());
|
||||
this.isValidated = configElement.getValidationPattern() != null;
|
||||
|
||||
if (configElement.getValidationPattern() != null)
|
||||
{
|
||||
if (configElement.getValidationPattern().matcher(this.textFieldValue.getText().trim()).matches())
|
||||
isValidValue = true;
|
||||
else
|
||||
isValidValue = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partial)
|
||||
{
|
||||
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partial);
|
||||
if (configElement.isListLengthFixed() || slotIndex != owningEntryList.listEntries.size() - 1)
|
||||
{
|
||||
this.textFieldValue.setVisible(true);
|
||||
this.textFieldValue.y = y + 1;
|
||||
this.textFieldValue.drawTextBox();
|
||||
}
|
||||
else
|
||||
this.textFieldValue.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char eventChar, int eventKey)
|
||||
{
|
||||
if (owningScreen.enabled || eventKey == Keyboard.KEY_LEFT || eventKey == Keyboard.KEY_RIGHT
|
||||
|| eventKey == Keyboard.KEY_HOME || eventKey == Keyboard.KEY_END)
|
||||
{
|
||||
this.textFieldValue.textboxKeyTyped((owningScreen.enabled ? eventChar : Keyboard.CHAR_NONE), eventKey);
|
||||
|
||||
if (configElement.getValidationPattern() != null)
|
||||
{
|
||||
if (configElement.getValidationPattern().matcher(this.textFieldValue.getText().trim()).matches())
|
||||
isValidValue = true;
|
||||
else
|
||||
isValidValue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCursorCounter()
|
||||
{
|
||||
this.textFieldValue.updateCursorCounter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int x, int y, int mouseEvent)
|
||||
{
|
||||
this.textFieldValue.mouseClicked(x, y, mouseEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return this.textFieldValue.getText().trim();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class BooleanEntry extends BaseEntry
|
||||
{
|
||||
protected final GuiButtonExt btnValue;
|
||||
private boolean value;
|
||||
|
||||
public BooleanEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement, boolean value)
|
||||
{
|
||||
super(owningScreen, owningEntryList, configElement);
|
||||
this.value = value;
|
||||
this.btnValue = new GuiButtonExt(0, 0, 0, owningEntryList.controlWidth, 18, I18n.format(String.valueOf(value)));
|
||||
this.btnValue.enabled = owningScreen.enabled;
|
||||
this.isValidated = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partial)
|
||||
{
|
||||
super.drawEntry(slotIndex, x, y, listWidth, slotHeight, mouseX, mouseY, isSelected, partial);
|
||||
this.btnValue.x = listWidth / 4;
|
||||
this.btnValue.y = y;
|
||||
|
||||
String trans = I18n.format(String.valueOf(value));
|
||||
if (!trans.equals(String.valueOf(value)))
|
||||
this.btnValue.displayString = trans;
|
||||
else
|
||||
this.btnValue.displayString = String.valueOf(value);
|
||||
btnValue.packedFGColour = value ? GuiUtils.getColorCode('2', true) : GuiUtils.getColorCode('4', true);
|
||||
|
||||
this.btnValue.drawButton(owningEntryList.getMC(), mouseX, mouseY, partial);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
|
||||
{
|
||||
if (this.btnValue.mousePressed(owningEntryList.getMC(), x, y))
|
||||
{
|
||||
btnValue.playPressSound(owningEntryList.getMC().getSoundHandler());
|
||||
value = !value;
|
||||
owningEntryList.recalculateState();
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.mousePressed(index, x, y, mouseEvent, relativeX, relativeY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
|
||||
{
|
||||
this.btnValue.mouseReleased(x, y);
|
||||
super.mouseReleased(index, x, y, mouseEvent, relativeX, relativeY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BaseEntry extends GuiListExtended.IGuiListEntry implements IArrayEntry
|
||||
{
|
||||
protected final GuiEditArray owningScreen;
|
||||
protected final GuiEditArrayEntries owningEntryList;
|
||||
protected final IConfigElement configElement;
|
||||
protected final GuiButtonExt btnAddNewEntryAbove;
|
||||
private final HoverChecker addNewEntryAboveHoverChecker;
|
||||
protected final GuiButtonExt btnRemoveEntry;
|
||||
private final HoverChecker removeEntryHoverChecker;
|
||||
private List<String> addNewToolTip, removeToolTip;
|
||||
protected boolean isValidValue = true;
|
||||
protected boolean isValidated = false;
|
||||
|
||||
public BaseEntry(GuiEditArray owningScreen, GuiEditArrayEntries owningEntryList, IConfigElement configElement)
|
||||
{
|
||||
this.owningScreen = owningScreen;
|
||||
this.owningEntryList = owningEntryList;
|
||||
this.configElement = configElement;
|
||||
this.btnAddNewEntryAbove = new GuiButtonExt(0, 0, 0, 18, 18, "+");
|
||||
this.btnAddNewEntryAbove.packedFGColour = GuiUtils.getColorCode('2', true);
|
||||
this.btnAddNewEntryAbove.enabled = owningScreen.enabled;
|
||||
this.btnRemoveEntry = new GuiButtonExt(0, 0, 0, 18, 18, "x");
|
||||
this.btnRemoveEntry.packedFGColour = GuiUtils.getColorCode('c', true);
|
||||
this.btnRemoveEntry.enabled = owningScreen.enabled;
|
||||
this.addNewEntryAboveHoverChecker = new HoverChecker(this.btnAddNewEntryAbove, 800);
|
||||
this.removeEntryHoverChecker = new HoverChecker(this.btnRemoveEntry, 800);
|
||||
this.addNewToolTip = new ArrayList<String>();
|
||||
this.removeToolTip = new ArrayList<String>();
|
||||
addNewToolTip.add(I18n.format("fml.configgui.tooltip.addNewEntryAbove"));
|
||||
removeToolTip.add(I18n.format("fml.configgui.tooltip.removeEntry"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void func_194999_a(int entryWidth, int entryHeight, int mouseX, int mouseY, boolean isHovered, float partial)
|
||||
{
|
||||
if (this.getValue() != null && this.isValidated)
|
||||
owningEntryList.getMC().fontRenderer.func_211126_b(
|
||||
isValidValue ? TextFormatting.GREEN + VALID : TextFormatting.RED + INVALID,
|
||||
entryWidth / 4 - owningEntryList.getMC().fontRenderer.getStringWidth(VALID) - 2,
|
||||
entryHeight / 2 - owningEntryList.getMC().fontRenderer.FONT_HEIGHT / 2,
|
||||
16777215);
|
||||
|
||||
int half = entryWidth / 2;
|
||||
if (owningEntryList.canAddMoreEntries)
|
||||
{
|
||||
this.btnAddNewEntryAbove.visible = true;
|
||||
this.btnAddNewEntryAbove.x = half + ((half / 2) - 44);
|
||||
this.btnAddNewEntryAbove.y = this.func_195001_c();
|
||||
this.btnAddNewEntryAbove.drawButton(owningEntryList.getMC(), mouseX, mouseY, partial);
|
||||
}
|
||||
else
|
||||
this.btnAddNewEntryAbove.visible = false;
|
||||
|
||||
if (!configElement.isListLengthFixed() && this.field_195005_b != owningEntryList.listEntries.size() - 1)
|
||||
{
|
||||
this.btnRemoveEntry.visible = true;
|
||||
this.btnRemoveEntry.x = half + ((half / 2) - 22);
|
||||
this.btnRemoveEntry.y = this.func_195001_c();
|
||||
this.btnRemoveEntry.drawButton(owningEntryList.getMC(), mouseX, mouseY, partial);
|
||||
}
|
||||
else
|
||||
this.btnRemoveEntry.visible = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawToolTip(int mouseX, int mouseY)
|
||||
{
|
||||
boolean canHover = mouseY < owningEntryList.bottom && mouseY > owningEntryList.top;
|
||||
if (this.btnAddNewEntryAbove.visible && this.addNewEntryAboveHoverChecker.checkHover(mouseX, mouseY, canHover))
|
||||
owningScreen.drawToolTip(this.addNewToolTip, mouseX, mouseY);
|
||||
if (this.btnRemoveEntry.visible && this.removeEntryHoverChecker.checkHover(mouseX, mouseY, canHover))
|
||||
owningScreen.drawToolTip(this.removeToolTip, mouseX, mouseY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
|
||||
{
|
||||
if (this.btnAddNewEntryAbove.mousePressed(owningEntryList.getMC(), x, y))
|
||||
{
|
||||
btnAddNewEntryAbove.playPressSound(owningEntryList.getMC().getSoundHandler());
|
||||
owningEntryList.addNewEntry(index);
|
||||
owningEntryList.recalculateState();
|
||||
return true;
|
||||
}
|
||||
else if (this.btnRemoveEntry.mousePressed(owningEntryList.getMC(), x, y))
|
||||
{
|
||||
btnRemoveEntry.playPressSound(owningEntryList.getMC().getSoundHandler());
|
||||
owningEntryList.removeEntry(index);
|
||||
owningEntryList.recalculateState();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
|
||||
{
|
||||
this.btnAddNewEntryAbove.mouseReleased(x, y);
|
||||
this.btnRemoveEntry.mouseReleased(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyTyped(char eventChar, int eventKey)
|
||||
{}
|
||||
|
||||
@Override
|
||||
public void updateCursorCounter()
|
||||
{}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(int x, int y, int mouseEvent)
|
||||
{}
|
||||
|
||||
@Override
|
||||
public boolean isValueSavable()
|
||||
{
|
||||
return isValidValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePosition(int p_178011_1_, int p_178011_2_, int p_178011_3_, float partial){}
|
||||
}
|
||||
|
||||
public static interface IArrayEntry
|
||||
{
|
||||
void keyTyped(char eventChar, int eventKey);
|
||||
|
||||
void updateCursorCounter();
|
||||
|
||||
void mouseClicked(int x, int y, int mouseEvent);
|
||||
|
||||
void drawToolTip(int mouseX, int mouseY);
|
||||
|
||||
boolean isValueSavable();
|
||||
|
||||
Object getValue();
|
||||
}
|
||||
}
|
|
@ -1,194 +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.fml.client.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.RESET_CHAR;
|
||||
import static net.minecraftforge.fml.client.config.GuiUtils.UNDO_CHAR;
|
||||
|
||||
/**
|
||||
* This class provides a screen that allows the user to select a value from a list.
|
||||
*
|
||||
* @author bspkrs
|
||||
*/
|
||||
public class GuiSelectString extends GuiScreen
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
protected GuiScreen parentScreen;
|
||||
protected IConfigElement configElement;
|
||||
protected GuiSelectStringEntries entryList;
|
||||
protected GuiButtonExt btnUndoChanges, btnDefault, btnDone;
|
||||
protected String title;
|
||||
protected String titleLine2;
|
||||
protected String titleLine3;
|
||||
protected int slotIndex;
|
||||
protected final Map<Object, String> selectableValues;
|
||||
public final Object beforeValue;
|
||||
public Object currentValue;
|
||||
protected HoverChecker tooltipHoverChecker;
|
||||
protected List<String> toolTip;
|
||||
protected boolean enabled;
|
||||
|
||||
public GuiSelectString(GuiScreen parentScreen, IConfigElement configElement, int slotIndex, Map<Object, String> selectableValues, Object currentValue, boolean enabled)
|
||||
{
|
||||
this.mc = Minecraft.getMinecraft();
|
||||
this.parentScreen = parentScreen;
|
||||
this.configElement = configElement;
|
||||
this.slotIndex = slotIndex;
|
||||
this.selectableValues = selectableValues;
|
||||
this.beforeValue = currentValue;
|
||||
this.currentValue = currentValue;
|
||||
this.toolTip = new ArrayList<String>();
|
||||
this.enabled = enabled;
|
||||
String propName = I18n.format(configElement.getLanguageKey());
|
||||
String comment;
|
||||
|
||||
comment = I18n.format(configElement.getLanguageKey() + ".tooltip",
|
||||
"\n" + TextFormatting.AQUA, configElement.getDefault(), configElement.getMinValue(), configElement.getMaxValue());
|
||||
|
||||
if (!comment.equals(configElement.getLanguageKey() + ".tooltip"))
|
||||
Collections.addAll(toolTip, (TextFormatting.GREEN + propName + "\n" + TextFormatting.YELLOW + comment).split("\n"));
|
||||
else if (configElement.getComment() != null && !configElement.getComment().trim().isEmpty())
|
||||
Collections.addAll(toolTip, (TextFormatting.GREEN + propName + "\n" + TextFormatting.YELLOW + configElement.getComment()).split("\n"));
|
||||
else
|
||||
Collections.addAll(toolTip, (TextFormatting.GREEN + propName + "\n" + TextFormatting.RED + "No tooltip defined.").split("\n"));
|
||||
|
||||
if (parentScreen instanceof GuiConfig)
|
||||
{
|
||||
this.title = ((GuiConfig) parentScreen).title;
|
||||
this.titleLine2 = ((GuiConfig) parentScreen).titleLine2;
|
||||
this.titleLine3 = I18n.format(configElement.getLanguageKey());
|
||||
this.tooltipHoverChecker = new HoverChecker(28, 37, 0, parentScreen.width, 800);
|
||||
if(titleLine3 != null && titleLine2 == null)
|
||||
{
|
||||
((GuiConfig) parentScreen).titleLine2 = "";
|
||||
this.titleLine2 = "";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.title = I18n.format(configElement.getLanguageKey());
|
||||
this.tooltipHoverChecker = new HoverChecker(8, 17, 0, parentScreen.width, 800);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initGui()
|
||||
{
|
||||
this.entryList = new GuiSelectStringEntries(this, this.mc, this.configElement, this.selectableValues);
|
||||
|
||||
int undoGlyphWidth = mc.fontRenderer.getStringWidth(UNDO_CHAR) * 2;
|
||||
int resetGlyphWidth = mc.fontRenderer.getStringWidth(RESET_CHAR) * 2;
|
||||
int doneWidth = Math.max(mc.fontRenderer.getStringWidth(I18n.format("gui.done")) + 20, 100);
|
||||
int undoWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.undoChanges")) + undoGlyphWidth + 20;
|
||||
int resetWidth = mc.fontRenderer.getStringWidth(" " + I18n.format("fml.configgui.tooltip.resetToDefault")) + resetGlyphWidth + 20;
|
||||
int buttonWidthHalf = (doneWidth + 5 + undoWidth + 5 + resetWidth) / 2;
|
||||
this.buttonList.add(btnDone = new GuiButtonExt(2000, this.width / 2 - buttonWidthHalf, this.height - 29, doneWidth, 20, I18n.format("gui.done")));
|
||||
this.buttonList.add(btnDefault = new GuiUnicodeGlyphButton(2001, this.width / 2 - buttonWidthHalf + doneWidth + 5 + undoWidth + 5,
|
||||
this.height - 29, resetWidth, 20, " " + I18n.format("fml.configgui.tooltip.resetToDefault"), RESET_CHAR, 2.0F));
|
||||
this.buttonList.add(btnUndoChanges = new GuiUnicodeGlyphButton(2002, this.width / 2 - buttonWidthHalf + doneWidth + 5,
|
||||
this.height - 29, undoWidth, 20, " " + I18n.format("fml.configgui.tooltip.undoChanges"), UNDO_CHAR, 2.0F));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void actionPerformed(GuiButton button)
|
||||
{
|
||||
if (button.id == 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.entryList.saveChanges();
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
LOGGER.error("Error performing GuiSelectString action:", e);
|
||||
}
|
||||
this.mc.displayGuiScreen(this.parentScreen);
|
||||
}
|
||||
else if (button.id == 2001)
|
||||
{
|
||||
this.currentValue = configElement.getDefault();
|
||||
this.entryList = new GuiSelectStringEntries(this, this.mc, this.configElement, this.selectableValues);
|
||||
}
|
||||
else if (button.id == 2002)
|
||||
{
|
||||
this.currentValue = beforeValue;
|
||||
this.entryList = new GuiSelectStringEntries(this, this.mc, this.configElement, this.selectableValues);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMouseInput() throws IOException
|
||||
{
|
||||
super.handleMouseInput();
|
||||
this.entryList.handleMouseInput();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mouseReleased(int x, int y, int mouseEvent)
|
||||
{
|
||||
if (mouseEvent != 0 || !this.entryList.mouseReleased(x, y, mouseEvent))
|
||||
{
|
||||
super.mouseReleased(x, y, mouseEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawScreen(int par1, int par2, float par3)
|
||||
{
|
||||
this.drawDefaultBackground();
|
||||
this.entryList.drawScreen(par1, par2, par3);
|
||||
this.drawCenteredString(this.fontRenderer, this.title, this.width / 2, 8, 16777215);
|
||||
|
||||
if (this.titleLine2 != null)
|
||||
this.drawCenteredString(this.fontRenderer, this.titleLine2, this.width / 2, 18, 16777215);
|
||||
|
||||
if (this.titleLine3 != null)
|
||||
this.drawCenteredString(this.fontRenderer, this.titleLine3, this.width / 2, 28, 16777215);
|
||||
|
||||
this.btnDone.enabled = currentValue != null;
|
||||
this.btnDefault.enabled = enabled && !this.entryList.isDefault();
|
||||
this.btnUndoChanges.enabled = enabled && this.entryList.isChanged();
|
||||
super.drawScreen(par1, par2, par3);
|
||||
|
||||
if (this.tooltipHoverChecker != null && this.tooltipHoverChecker.checkHover(par1, par2))
|
||||
drawToolTip(this.toolTip, par1, par2);
|
||||
}
|
||||
|
||||
public void drawToolTip(List<String> stringList, int x, int y)
|
||||
{
|
||||
GuiUtils.drawHoveringText(stringList, x, y, width, height, 300, fontRenderer);
|
||||
}
|
||||
}
|
|
@ -1,205 +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.fml.client.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiListExtended;
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.SelectValueEntry;
|
||||
|
||||
/**
|
||||
* This class implements the scrolling list functionality of the GuiSelectString screen.
|
||||
*
|
||||
* @author bspkrs
|
||||
*/
|
||||
public class GuiSelectStringEntries extends GuiListExtended
|
||||
{
|
||||
public GuiSelectString owningScreen;
|
||||
public Minecraft mc;
|
||||
public IConfigElement configElement;
|
||||
public List<IGuiSelectStringListEntry> listEntries;
|
||||
public final Map<Object, String> selectableValues;
|
||||
public int selectedIndex = -1;
|
||||
public int maxEntryWidth = 0;
|
||||
|
||||
public GuiSelectStringEntries(GuiSelectString owningScreen, Minecraft mc, IConfigElement configElement, Map<Object, String> selectableValues)
|
||||
{
|
||||
super(mc, owningScreen.width, owningScreen.height, owningScreen.titleLine2 != null ? (owningScreen.titleLine3 != null ? 43 : 33) : 23,
|
||||
owningScreen.height - 32, 11);
|
||||
this.owningScreen = owningScreen;
|
||||
this.mc = mc;
|
||||
this.configElement = configElement;
|
||||
this.selectableValues = selectableValues;
|
||||
this.setShowSelectionBox(true);
|
||||
|
||||
listEntries = new ArrayList<IGuiSelectStringListEntry>();
|
||||
|
||||
int index = 0;
|
||||
List<Entry<Object, String>> sortedList = new ArrayList<Entry<Object, String>>(selectableValues.entrySet());
|
||||
Collections.sort(sortedList, new EntryComparator());
|
||||
|
||||
for (Entry<Object, String> entry : sortedList)
|
||||
{
|
||||
listEntries.add(new ListEntry(this, entry));
|
||||
if (mc.fontRenderer.getStringWidth(entry.getValue()) > maxEntryWidth)
|
||||
maxEntryWidth = mc.fontRenderer.getStringWidth(entry.getValue());
|
||||
|
||||
if (owningScreen.currentValue.equals(entry.getKey()))
|
||||
{
|
||||
this.selectedIndex = index;
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
public static class EntryComparator implements Comparator<Entry<Object, String>>
|
||||
{
|
||||
@Override
|
||||
public int compare(Entry<Object, String> o1, Entry<Object, String> o2)
|
||||
{
|
||||
int compare = o1.getValue().toLowerCase(Locale.US).compareTo(o2.getValue().toLowerCase(Locale.US));
|
||||
|
||||
if (compare == 0)
|
||||
compare = o1.getKey().toString().toLowerCase(Locale.US).compareTo(o2.getKey().toString().toLowerCase(Locale.US));
|
||||
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The element in the slot that was clicked, boolean for whether it was double clicked or not
|
||||
*/
|
||||
@Override
|
||||
protected void elementClicked(int index, boolean doubleClick, int mouseX, int mouseY)
|
||||
{
|
||||
selectedIndex = index;
|
||||
owningScreen.currentValue = listEntries.get(index).getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the element passed in is currently selected
|
||||
*/
|
||||
@Override
|
||||
protected boolean isSelected(int index)
|
||||
{
|
||||
return index == selectedIndex;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrollBarX()
|
||||
{
|
||||
return width / 2 + this.maxEntryWidth / 2 + 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the list
|
||||
*/
|
||||
@Override
|
||||
public int getListWidth()
|
||||
{
|
||||
return maxEntryWidth + 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IGuiSelectStringListEntry getListEntry(int index)
|
||||
{
|
||||
return listEntries.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSize()
|
||||
{
|
||||
return listEntries.size();
|
||||
}
|
||||
|
||||
public boolean isChanged()
|
||||
{
|
||||
return owningScreen.beforeValue != null ? !owningScreen.beforeValue.equals(owningScreen.currentValue) : owningScreen.currentValue != null;
|
||||
}
|
||||
|
||||
public boolean isDefault()
|
||||
{
|
||||
return owningScreen.currentValue != null ? owningScreen.currentValue.equals(configElement.getDefault()) : configElement.getDefault() == null;
|
||||
}
|
||||
|
||||
public void saveChanges()
|
||||
{
|
||||
if (owningScreen.slotIndex != -1 && owningScreen.parentScreen != null
|
||||
&& owningScreen.parentScreen instanceof GuiConfig
|
||||
&& ((GuiConfig) owningScreen.parentScreen).entryList.getListEntry(owningScreen.slotIndex) instanceof SelectValueEntry)
|
||||
{
|
||||
SelectValueEntry entry = (SelectValueEntry) ((GuiConfig) owningScreen.parentScreen).entryList.getListEntry(owningScreen.slotIndex);
|
||||
|
||||
entry.setValueFromChildScreen(owningScreen.currentValue);
|
||||
}
|
||||
else
|
||||
configElement.set(owningScreen.currentValue);
|
||||
}
|
||||
|
||||
public static class ListEntry implements IGuiSelectStringListEntry
|
||||
{
|
||||
protected final GuiSelectStringEntries owningList;
|
||||
protected final Entry<Object, String> value;
|
||||
|
||||
public ListEntry(GuiSelectStringEntries owningList, Entry<Object, String> value)
|
||||
{
|
||||
this.owningList = owningList;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partial)
|
||||
{
|
||||
owningList.mc.fontRenderer.drawString(value.getValue(), x + 1, y, slotIndex == owningList.selectedIndex ? 16777215 : 14737632);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mousePressed(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(int index, int x, int y, int mouseEvent, int relativeX, int relativeY)
|
||||
{}
|
||||
|
||||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
return value.getKey();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePosition(int p_192633_1_, int p_192633_2_, int p_192633_3_, float p_192633_4_){}
|
||||
}
|
||||
|
||||
public static interface IGuiSelectStringListEntry extends GuiListExtended.IGuiListEntry
|
||||
{
|
||||
Object getValue();
|
||||
}
|
||||
}
|
|
@ -128,19 +128,11 @@ public class GuiSlider extends GuiButtonExt
|
|||
* e).
|
||||
*/
|
||||
@Override
|
||||
public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3)
|
||||
public void func_194829_a(double mouseX, double mouseY)
|
||||
{
|
||||
if (super.mousePressed(par1Minecraft, par2, par3))
|
||||
{
|
||||
this.sliderValue = (float)(par2 - (this.x + 4)) / (float)(this.width - 8);
|
||||
this.sliderValue = (mouseX - (this.x + 4)) / (this.width - 8);
|
||||
updateSlider();
|
||||
this.dragging = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSlider()
|
||||
|
@ -198,7 +190,7 @@ public class GuiSlider extends GuiButtonExt
|
|||
* Fired when the mouse button is released. Equivalent of MouseListener.mouseReleased(MouseEvent e).
|
||||
*/
|
||||
@Override
|
||||
public void mouseReleased(int par1, int par2)
|
||||
public void func_194831_b(double mouseX, double mouseY)
|
||||
{
|
||||
this.dragging = false;
|
||||
}
|
||||
|
|
|
@ -41,19 +41,20 @@ public class GuiUnicodeGlyphButton extends GuiButtonExt
|
|||
}
|
||||
|
||||
@Override
|
||||
public void drawButton(Minecraft mc, int mouseX, int mouseY, float partial)
|
||||
public void func_194828_a(int mouseX, int mouseY, float partial)
|
||||
{
|
||||
if (this.visible)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
this.hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||
int k = this.getHoverState(this.hovered);
|
||||
GuiUtils.drawContinuousTexturedBox(GuiButton.BUTTON_TEXTURES, this.x, this.y, 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.zLevel);
|
||||
this.mouseDragged(mc, mouseX, mouseY);
|
||||
int color = 14737632;
|
||||
|
||||
if (packedFGColour != 0)
|
||||
if (packedFGColor != 0)
|
||||
{
|
||||
color = packedFGColour;
|
||||
color = packedFGColor;
|
||||
}
|
||||
else if (!this.enabled)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package net.minecraftforge.fml.client.config;
|
||||
|
||||
public interface IArrayEntry
|
||||
{
|
||||
void keyTyped(char eventChar, int eventKey);
|
||||
|
||||
void updateCursorCounter();
|
||||
|
||||
void mouseClicked(int x, int y, int mouseEvent);
|
||||
|
||||
void drawToolTip(int mouseX, int mouseY);
|
||||
|
||||
boolean isValueSavable();
|
||||
|
||||
Object getValue();
|
||||
}
|
|
@ -22,9 +22,6 @@ package net.minecraftforge.fml.client.config;
|
|||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import net.minecraftforge.fml.client.config.GuiConfigEntries.IConfigEntry;
|
||||
import net.minecraftforge.fml.client.config.GuiEditArrayEntries.IArrayEntry;
|
||||
|
||||
/**
|
||||
* This interface provides the information needed by GuiConfig and GuiConfigEntries to display config elements for editing.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package net.minecraftforge.fml.client.config;
|
||||
|
||||
import net.minecraft.client.gui.GuiTextField;
|
||||
|
||||
/**
|
||||
* Provides an interface for defining GuiConfigEntry.listEntry objects.
|
||||
*/
|
||||
public interface IConfigEntry
|
||||
{
|
||||
/**
|
||||
* Gets the IConfigElement object owned by this entry.
|
||||
* @return
|
||||
*/
|
||||
IConfigElement getConfigElement();
|
||||
|
||||
/**
|
||||
* Gets the name of the ConfigElement owned by this entry.
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Gets the current value of this entry.
|
||||
*/
|
||||
Object getCurrentValue();
|
||||
|
||||
/**
|
||||
* Gets the current values of this list entry.
|
||||
*/
|
||||
Object[] getCurrentValues();
|
||||
|
||||
/**
|
||||
* Is this list entry enabled?
|
||||
*
|
||||
* @return true if this entry's controls should be enabled, false otherwise.
|
||||
*/
|
||||
boolean enabled();
|
||||
|
||||
/**
|
||||
* Handles user keystrokes for any GuiTextField objects in this entry. Call {@link GuiTextField#textboxKeyTyped(char, int)} for any GuiTextField
|
||||
* objects that should receive the input provided.
|
||||
*/
|
||||
void keyTyped(char eventChar, int eventKey);
|
||||
|
||||
/**
|
||||
* Call {@link GuiTextField#updateCursorCounter()} for any GuiTextField objects in this entry.
|
||||
*/
|
||||
void updateCursorCounter();
|
||||
|
||||
/**
|
||||
* Call {@link GuiTextField#mouseClicked(int, int, int)} for and GuiTextField objects in this entry.
|
||||
*/
|
||||
void mouseClicked(int x, int y, int mouseEvent);
|
||||
|
||||
/**
|
||||
* Is this entry's value equal to the default value? Generally true should be returned if this entry is not a property or category
|
||||
* entry.
|
||||
*
|
||||
* @return true if this entry's value is equal to this entry's default value.
|
||||
*/
|
||||
boolean isDefault();
|
||||
|
||||
/**
|
||||
* Sets this entry's value to the default value.
|
||||
*/
|
||||
void setToDefault();
|
||||
|
||||
/**
|
||||
* Handles reverting any changes that have occurred to this entry.
|
||||
*/
|
||||
void undoChanges();
|
||||
|
||||
/**
|
||||
* Has the value of this entry changed?
|
||||
*
|
||||
* @return true if changes have been made to this entry's value, false otherwise.
|
||||
*/
|
||||
boolean isChanged();
|
||||
|
||||
/**
|
||||
* Handles saving any changes that have been made to this entry back to the underlying object. It is a good practice to check
|
||||
* isChanged() before performing the save action. This method should return true if the element has changed AND REQUIRES A RESTART.
|
||||
*/
|
||||
boolean saveConfigElement();
|
||||
|
||||
/**
|
||||
* Handles drawing any tooltips that apply to this entry. This method is called after all other GUI elements have been drawn to the
|
||||
* screen, so it could also be used to draw any GUI element that needs to be drawn after all entries have had drawEntry() called.
|
||||
*/
|
||||
void drawToolTip(int mouseX, int mouseY);
|
||||
|
||||
/**
|
||||
* Gets this entry's label width.
|
||||
*/
|
||||
int getLabelWidth();
|
||||
|
||||
/**
|
||||
* Gets this entry's right-hand x boundary. This value is used to control where the scroll bar is placed.
|
||||
*/
|
||||
int getEntryRightBound();
|
||||
|
||||
/**
|
||||
* This method is called when the parent GUI is closed. Most handlers won't need this; it is provided for special cases.
|
||||
*/
|
||||
void onGuiClosed();
|
||||
}
|
|
@ -16,27 +16,23 @@
|
|||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/* TODO error GUIs
|
||||
package net.minecraftforge.fml.client.gui;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import net.minecraft.client.gui.GuiButton;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.gui.GuiYesNo;
|
||||
import net.minecraft.client.gui.GuiYesNoCallback;
|
||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||
import net.minecraftforge.fml.common.FMLLog;
|
||||
import net.minecraftforge.fml.StartupQuery;
|
||||
import net.minecraftforge.fml.common.ZipperUtil;
|
||||
|
||||
public class GuiOldSaveLoadConfirm extends GuiYesNo implements GuiYesNoCallback {
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private String dirName;
|
||||
private String saveName;
|
||||
private File zip;
|
||||
|
@ -111,3 +107,4 @@ public class GuiOldSaveLoadConfirm extends GuiYesNo implements GuiYesNoCallback
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -39,6 +39,7 @@ import javax.annotation.Nullable;
|
|||
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||
|
||||
|
@ -68,7 +69,7 @@ public class CommandSetDimension
|
|||
);
|
||||
}
|
||||
|
||||
private static int execute(CommandSource sender, Collection<? extends Entity> entities, int dim, BlockPos pos) throws CommandException
|
||||
private static int execute(CommandSource sender, Collection<? extends Entity> entities, int dim, BlockPos pos) throws CommandSyntaxException
|
||||
{
|
||||
entities.removeIf(CommandSetDimension::checkEntity);
|
||||
if (entities.isEmpty())
|
||||
|
|
Loading…
Reference in a new issue