First pass at exposing data fixers to modders.

Each mod gets its own version number, mods SHOULD NOT rely on other
mod's fixers, just care about yourself.
Walkers can use IDataFixerData to retrieve their version.
This commit is contained in:
LexManos 2016-11-28 16:05:41 -08:00
parent c17b40790b
commit 8d20258f3c
13 changed files with 390 additions and 28 deletions

View File

@ -152,7 +152,15 @@
this.field_71100_bB.func_75112_a(p_70037_1_);
this.field_71075_bZ.func_75095_b(p_70037_1_);
@@ -921,6 +965,23 @@
@@ -903,6 +947,7 @@
{
super.func_70014_b(p_70014_1_);
p_70014_1_.func_74768_a("DataVersion", 819);
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().getDataFixer().writeVersionData(p_70014_1_);
p_70014_1_.func_74782_a("Inventory", this.field_71071_by.func_70442_a(new NBTTagList()));
p_70014_1_.func_74768_a("SelectedItemSlot", this.field_71071_by.field_70461_c);
p_70014_1_.func_74757_a("Sleeping", this.field_71083_bS);
@@ -921,6 +966,23 @@
p_70014_1_.func_74757_a("SpawnForced", this.field_82248_d);
}
@ -176,7 +184,7 @@
this.field_71100_bB.func_75117_b(p_70014_1_);
this.field_71075_bZ.func_75091_a(p_70014_1_);
p_70014_1_.func_74782_a("EnderItems", this.field_71078_a.func_70487_g());
@@ -928,6 +989,7 @@
@@ -928,6 +990,7 @@
public boolean func_70097_a(DamageSource p_70097_1_, float p_70097_2_)
{
@ -184,7 +192,7 @@
if (this.func_180431_b(p_70097_1_))
{
return false;
@@ -1006,6 +1068,7 @@
@@ -1006,6 +1069,7 @@
if (this.field_184627_bm.func_190926_b())
{
EnumHand enumhand = this.func_184600_cs();
@ -192,7 +200,7 @@
if (enumhand == EnumHand.MAIN_HAND)
{
@@ -1041,7 +1104,10 @@
@@ -1041,7 +1105,10 @@
{
if (!this.func_180431_b(p_70665_1_))
{
@ -204,7 +212,7 @@
p_70665_2_ = this.func_70672_c(p_70665_1_, p_70665_2_);
float f = p_70665_2_;
p_70665_2_ = Math.max(p_70665_2_ - this.func_110139_bj(), 0.0F);
@@ -1111,6 +1177,7 @@
@@ -1111,6 +1178,7 @@
}
else
{
@ -212,7 +220,7 @@
ItemStack itemstack = this.func_184586_b(p_190775_2_);
ItemStack itemstack1 = itemstack.func_190926_b() ? ItemStack.field_190927_a : itemstack.func_77946_l();
@@ -1120,7 +1187,10 @@
@@ -1120,7 +1188,10 @@
{
itemstack.func_190920_e(itemstack1.func_190916_E());
}
@ -224,7 +232,7 @@
return EnumActionResult.SUCCESS;
}
else
@@ -1136,6 +1206,7 @@
@@ -1136,6 +1207,7 @@
{
if (itemstack.func_190926_b() && !this.field_71075_bZ.field_75098_d)
{
@ -232,7 +240,7 @@
this.func_184611_a(p_190775_2_, ItemStack.field_190927_a);
}
@@ -1161,6 +1232,7 @@
@@ -1161,6 +1233,7 @@
public void func_71059_n(Entity p_71059_1_)
{
@ -240,7 +248,7 @@
if (p_71059_1_.func_70075_an())
{
if (!p_71059_1_.func_85031_j(this))
@@ -1331,11 +1403,13 @@
@@ -1331,11 +1404,13 @@
if (!itemstack1.func_190926_b() && entity instanceof EntityLivingBase)
{
@ -254,7 +262,7 @@
}
}
@@ -1441,6 +1515,8 @@
@@ -1441,6 +1516,8 @@
public EntityPlayer.SleepResult func_180469_a(BlockPos p_180469_1_)
{
@ -263,7 +271,7 @@
EnumFacing enumfacing = (EnumFacing)this.field_70170_p.func_180495_p(p_180469_1_).func_177229_b(BlockHorizontal.field_185512_D);
if (!this.field_70170_p.field_72995_K)
@@ -1482,8 +1558,9 @@
@@ -1482,8 +1559,9 @@
this.func_70105_a(0.2F, 0.2F);
@ -275,7 +283,7 @@
float f1 = 0.5F + (float)enumfacing.func_82601_c() * 0.4F;
float f = 0.5F + (float)enumfacing.func_82599_e() * 0.4F;
this.func_175139_a(enumfacing);
@@ -1530,13 +1607,14 @@
@@ -1530,13 +1608,14 @@
public void func_70999_a(boolean p_70999_1_, boolean p_70999_2_, boolean p_70999_3_)
{
@ -293,7 +301,7 @@
if (blockpos == null)
{
@@ -1545,6 +1623,10 @@
@@ -1545,6 +1624,10 @@
this.func_70107_b((double)((float)blockpos.func_177958_n() + 0.5F), (double)((float)blockpos.func_177956_o() + 0.1F), (double)((float)blockpos.func_177952_p() + 0.5F));
}
@ -304,7 +312,7 @@
this.field_71083_bS = false;
@@ -1563,15 +1645,16 @@
@@ -1563,15 +1646,16 @@
private boolean func_175143_p()
{
@ -324,7 +332,7 @@
{
if (!p_180467_2_)
{
@@ -1586,16 +1669,17 @@
@@ -1586,16 +1670,17 @@
}
else
{
@ -345,7 +353,7 @@
switch (enumfacing)
{
@@ -1635,16 +1719,24 @@
@@ -1635,16 +1720,24 @@
public BlockPos func_180470_cg()
{
@ -372,7 +380,7 @@
if (p_180473_1_ != null)
{
this.field_71077_c = p_180473_1_;
@@ -1839,6 +1931,10 @@
@@ -1839,6 +1932,10 @@
super.func_180430_e(p_180430_1_, p_180430_2_);
}
@ -383,7 +391,7 @@
}
protected void func_71061_d_()
@@ -2039,6 +2135,18 @@
@@ -2039,6 +2136,18 @@
this.field_175152_f = p_71049_1_.field_175152_f;
this.field_71078_a = p_71049_1_.field_71078_a;
this.func_184212_Q().func_187227_b(field_184827_bp, p_71049_1_.func_184212_Q().func_187225_a(field_184827_bp));
@ -402,7 +410,7 @@
}
protected boolean func_70041_e_()
@@ -2137,7 +2245,10 @@
@@ -2137,7 +2246,10 @@
public ITextComponent func_145748_c_()
{
@ -414,7 +422,7 @@
itextcomponent.func_150256_b().func_150241_a(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/msg " + this.func_70005_c_() + " "));
itextcomponent.func_150256_b().func_150209_a(this.func_174823_aP());
itextcomponent.func_150256_b().func_179989_a(this.func_70005_c_());
@@ -2146,7 +2257,7 @@
@@ -2146,7 +2258,7 @@
public float func_70047_e()
{
@ -423,7 +431,7 @@
if (this.func_70608_bn())
{
@@ -2362,6 +2473,162 @@
@@ -2362,6 +2474,162 @@
return this.field_71075_bZ.field_75098_d && this.func_70003_b(2, "");
}

View File

@ -0,0 +1,10 @@
--- ../src-base/minecraft/net/minecraft/util/datafix/DataFixesManager.java
+++ ../src-work/minecraft/net/minecraft/util/datafix/DataFixesManager.java
@@ -158,6 +158,7 @@
public static DataFixer func_188279_a()
{
DataFixer datafixer = new DataFixer(819);
+ datafixer = new net.minecraftforge.common.util.CompoundDataFixer(datafixer);
WorldInfo.func_189967_a(datafixer);
EntityPlayer.func_189806_a(datafixer);
AnvilChunkLoader.func_189889_a(datafixer);

View File

@ -97,15 +97,17 @@
}
}
}
@@ -122,6 +181,7 @@
@@ -121,7 +180,9 @@
NBTTagCompound nbttagcompound1 = new NBTTagCompound();
nbttagcompound.func_74782_a("Level", nbttagcompound1);
nbttagcompound.func_74768_a("DataVersion", 819);
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().getDataFixer().writeVersionData(nbttagcompound);
this.func_75820_a(p_75816_2_, p_75816_1_, nbttagcompound1);
+ net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.world.ChunkDataEvent.Save(p_75816_2_, nbttagcompound));
this.func_75824_a(p_75816_2_.func_76632_l(), nbttagcompound);
}
catch (Exception exception)
@@ -307,8 +367,17 @@
@@ -307,8 +368,17 @@
if (entity.func_70039_c(nbttagcompound2))
{
@ -123,7 +125,7 @@
}
}
}
@@ -318,8 +387,17 @@
@@ -318,8 +388,17 @@
for (TileEntity tileentity : p_75820_1_.func_177434_r().values())
{
@ -141,7 +143,7 @@
}
p_75820_3_.func_74782_a("TileEntities", nbttaglist2);
@@ -388,6 +466,12 @@
@@ -388,6 +467,12 @@
chunk.func_76616_a(p_75823_2_.func_74770_j("Biomes"));
}
@ -154,7 +156,7 @@
NBTTagList nbttaglist1 = p_75823_2_.func_150295_c("Entities", 10);
for (int j1 = 0; j1 < nbttaglist1.func_74745_c(); ++j1)
@@ -431,8 +515,6 @@
@@ -431,8 +516,6 @@
p_75823_1_.func_180497_b(new BlockPos(nbttagcompound3.func_74762_e("x"), nbttagcompound3.func_74762_e("y"), nbttagcompound3.func_74762_e("z")), block, nbttagcompound3.func_74762_e("t"), nbttagcompound3.func_74762_e("p"));
}
}

View File

@ -0,0 +1,10 @@
--- ../src-base/minecraft/net/minecraft/world/gen/structure/template/Template.java
+++ ../src-work/minecraft/net/minecraft/world/gen/structure/template/Template.java
@@ -520,6 +520,7 @@
p_189552_1_.func_74782_a("size", this.func_186267_a(new int[] {this.field_186272_c.func_177958_n(), this.field_186272_c.func_177956_o(), this.field_186272_c.func_177952_p()}));
p_189552_1_.func_74778_a("author", this.field_186273_d);
p_189552_1_.func_74768_a("DataVersion", 819);
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().getDataFixer().writeVersionData(p_189552_1_);
return p_189552_1_;
}

View File

@ -8,7 +8,15 @@
protected WorldInfo()
{
@@ -807,6 +808,26 @@
@@ -335,6 +336,7 @@
nbttagcompound.func_74757_a("Snapshot", false);
p_76064_1_.func_74782_a("Version", nbttagcompound);
p_76064_1_.func_74768_a("DataVersion", 819);
+ net.minecraftforge.fml.common.FMLCommonHandler.instance().getDataFixer().writeVersionData(p_76064_1_);
p_76064_1_.func_74772_a("RandomSeed", this.field_76100_a);
p_76064_1_.func_74778_a("generatorName", this.field_76098_b.func_77127_a());
p_76064_1_.func_74768_a("generatorVersion", this.field_76098_b.func_77131_c());
@@ -807,6 +809,26 @@
});
}

View File

@ -0,0 +1,190 @@
/*
* Minecraft Forge
* Copyright (c) 2016.
*
* 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)
{
List<IDataWalker> ret = walkers.get(type);
if (ret == null)
{
ret = Lists.newArrayList();
walkers.put(type, ret);
}
return ret;
}
@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)
{
registerWalkerAdd(type, walker);
}
@Override
public void registerWalkerAdd(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);
}
}

View File

@ -0,0 +1,26 @@
/*
* Minecraft Forge
* Copyright (c) 2016.
*
* 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 net.minecraft.util.datafix.IDataFixer;
public interface IDataFixerData extends IDataFixer
{
public int getVersion(String mod);
}

View File

@ -0,0 +1,83 @@
/*
* Minecraft Forge
* Copyright (c) 2016.
*
* 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)
{
List<IFixableData> ret = this.fixes.get(type);
if (ret == null)
{
ret = Lists.newArrayList();
this.fixes.put(type, ret);
}
return ret;
}
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);
}
}

View File

@ -82,6 +82,7 @@ import net.minecraft.world.storage.SaveFormatOld;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.common.ForgeModContainer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.DummyModContainer;
import net.minecraftforge.fml.common.DuplicateModsFoundException;
@ -1060,4 +1061,10 @@ public class FMLClientHandler implements IFMLSidedHandler
{
MinecraftForge.EVENT_BUS.post(new ModelRegistryEvent());
}
@Override
public CompoundDataFixer getDataFixer()
{
return (CompoundDataFixer)this.client.getDataFixer();
}
}

View File

@ -57,6 +57,7 @@ import net.minecraft.world.storage.WorldInfo;
import net.minecraftforge.client.model.animation.Animation;
import net.minecraftforge.common.ForgeVersion;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.common.gameevent.InputEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
@ -751,4 +752,9 @@ public class FMLCommonHandler
{
sidedDelegate.fireSidedRegistryEvents();
}
public CompoundDataFixer getDataFixer()
{
return (CompoundDataFixer)sidedDelegate.getDataFixer();
}
}

View File

@ -27,6 +27,7 @@ import net.minecraft.network.INetHandler;
import net.minecraft.network.NetworkManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.IThreadListener;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.fml.common.eventhandler.EventBus;
import net.minecraftforge.fml.relauncher.Side;
@ -77,4 +78,6 @@ public interface IFMLSidedHandler
void reloadRenderers();
void fireSidedRegistryEvents();
CompoundDataFixer getDataFixer();
}

View File

@ -35,6 +35,7 @@ import net.minecraft.server.dedicated.PendingCommand;
import net.minecraft.util.IThreadListener;
import net.minecraft.util.text.translation.LanguageMap;
import net.minecraft.world.storage.SaveFormatOld;
import net.minecraftforge.common.util.CompoundDataFixer;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.IFMLSidedHandler;
@ -339,4 +340,9 @@ public class FMLServerHandler implements IFMLSidedHandler
{
// NOOP
}
@Override
public CompoundDataFixer getDataFixer()
{
return (CompoundDataFixer)this.server.getDataFixer();
}
}

View File

@ -287,4 +287,7 @@ public net.minecraft.potion.PotionHelper func_185204_a(Lnet/minecraft/potion/Pot
# TileEntityHopper
public net.minecraft.tileentity.TileEntityHopper func_174914_o()Z # mayTransfer
public net.minecraft.tileentity.TileEntityHopper func_145896_c(I)V # setTransferCooldown
public net.minecraft.tileentity.TileEntityHopper func_145896_c(I)V # setTransferCooldown
# DataFixer
public net.minecraft.util.datafix.DataFixer field_188262_d # version