mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-12 08:17:35 +00:00
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:
1 parent
c17b40790b
commit
8d20258f3c
13 files changed
+390
-28
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user