diff --git a/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java b/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java index 6161d984f..360284cfc 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/registry/FMLControlledNamespacedRegistry.java @@ -93,6 +93,11 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul } } + + @SuppressWarnings("unchecked") + void setFrom(FMLControlledNamespacedRegistry registry) { + set((FMLControlledNamespacedRegistry) registry); + } void set(FMLControlledNamespacedRegistry registry) { if (this.superType != registry.superType) throw new IllegalArgumentException("incompatible registry"); @@ -520,4 +525,9 @@ public class FMLControlledNamespacedRegistry extends RegistryNamespacedDefaul if (this.optionalDefaultKey != null) Validate.notNull(this.optionalDefaultObject); } + + + FMLControlledNamespacedRegistry makeShallowCopy() { + return new FMLControlledNamespacedRegistry(optionalDefaultKey, maxId, minId, superType); + } } diff --git a/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java b/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java index c8a5e341b..9c2e573b4 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/registry/GameData.java @@ -142,6 +142,9 @@ public class GameData { GameDataSnapshot snap = new GameDataSnapshot(); snap.entries.put("fml:blocks", new GameDataSnapshot.Entry(getMain().getBlockRegistry())); snap.entries.put("fml:items", new GameDataSnapshot.Entry(getMain().getItemRegistry())); + for (Map.Entry> e : getMain().genericRegistries.entrySet()) { + snap.entries.put("fmlgr:"+e.getKey(), new GameDataSnapshot.Entry(e.getValue())); + } return snap; } @@ -445,6 +448,11 @@ public class GameData { List missedMappings = Loader.instance().fireMissingMappingEvent(missingBlocks, missingItems, isLocalWorld, newData, remapBlocks, remapItems); if (!missedMappings.isEmpty()) return missedMappings; + // If we got here - the load was accepted. We'll load generic repositories here. + // Generic registries can fail by returning a missing mapping. + missedMappings = newData.loadGenericRegistries(snapshot, getMain()); + if (!missedMappings.isEmpty()) return missedMappings; + if (injectFrozenData) // add blocks + items missing from the map { Map newBlocks = frozen.iBlockRegistry.getEntriesNotIn(newData.iBlockRegistry); @@ -665,6 +673,7 @@ public class GameData { iItemRegistry = new FMLControlledNamespacedRegistry(null, MAX_ITEM_ID, MIN_ITEM_ID, Item.class); availabilityMap = new BitSet(MAX_ITEM_ID + 1); blockedIds = new HashSet(); + genericRegistries = new HashMap>(); } private GameData(GameData data) @@ -681,6 +690,17 @@ public class GameData { availabilityMap.or(data.availabilityMap); blockedIds.clear(); blockedIds.addAll(data.blockedIds); + copyGenericRegistries(data); + } + + private void copyGenericRegistries(GameData data) { + for (Map.Entry> e : data.genericRegistries.entrySet()) { + FMLControlledNamespacedRegistry orig = e.getValue(); + FMLControlledNamespacedRegistry copy = orig.makeShallowCopy(); + // UGLY AS FUCK + copy.setFrom(orig); + genericRegistries.put(e.getKey(), copy); + } } int register(Object obj, String name, int idHint) // from FMLControlledNamespacedRegistry.addObject @@ -966,4 +986,65 @@ public class GameData { this.objectList.clear(); } } + + private Map> genericRegistries; + + @SuppressWarnings("unchecked") + private FMLControlledNamespacedRegistry getGenericRegistry(String registryName, Class type) { + FMLControlledNamespacedRegistry fmlControlledNamespacedRegistry = genericRegistries.get(registryName); + return (FMLControlledNamespacedRegistry) fmlControlledNamespacedRegistry; + } + + @SuppressWarnings("unchecked") + private FMLControlledNamespacedRegistry createGenericRegistry(String registryName, Class type, int minId, int maxId) { + FMLControlledNamespacedRegistry fmlControlledNamespacedRegistry = new FMLControlledNamespacedRegistry(null, maxId, minId, type); + return (FMLControlledNamespacedRegistry) fmlControlledNamespacedRegistry; + } + + public static FMLControlledNamespacedRegistry createRegistry(String registryName, Class type, int minId, int maxId) { + return getMain().createGenericRegistry(registryName, type, minId, maxId); + } + private List loadGenericRegistries(GameDataSnapshot snapshot, GameData existing) { + List result = Lists.newArrayList(); + for (Map.Entry> e : existing.genericRegistries.entrySet()) + { + String regName = e.getKey(); + FMLControlledNamespacedRegistry registry = e.getValue(); + FMLControlledNamespacedRegistry newRegistry = genericRegistries.get(regName); + GameDataSnapshot.Entry regSnap = snapshot.entries.get("fmlgr:"+regName); + if (regSnap == null) { + FMLLog.info("Weird, there was no registry data for registry %s found in the snapshot", regName); + continue; + } + + for (Entry entry : regSnap.ids.entrySet()) + { + String entryName = entry.getKey(); + int entryId = entry.getValue(); + int currId = registry.getId(entryName); + + if (currId == -1) + { + FMLLog.info("Found a missing id in registry %s from the world %s", regName, entryName); + result.add(regName+"{"+entryName+"}="+entryId); + continue; // no block/item -> nothing to add + } + else if (currId != entryId) + { + FMLLog.fine("Fixed registry %s id mismatch %s: %d (init) -> %d (map).", regName, entryName, currId, entryId); + } + + newRegistry.register(entryId, entryName, registry.getRaw(entryName)); + + } + } + return result; + } + + public static FMLControlledNamespacedRegistry getRegistry(String registryName, Class type) { + return getMain().getGenericRegistry(registryName, type); + } + + + } \ No newline at end of file diff --git a/fml/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java b/fml/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java index cf3999a66..b4af63763 100644 --- a/fml/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java +++ b/fml/src/main/java/net/minecraftforge/fml/common/registry/VillagerRegistry.java @@ -20,9 +20,11 @@ import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Random; +import java.util.Set; import org.apache.commons.lang3.Validate; +import net.minecraft.block.Block; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.passive.EntityVillager.*; import net.minecraft.init.Blocks; @@ -31,6 +33,8 @@ import net.minecraft.item.EnumDyeColor; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; +import net.minecraft.util.ObjectIntIdentityMap; +import net.minecraft.util.RegistryNamespacedDefaultedByKey; import net.minecraft.util.ResourceLocation; import net.minecraft.util.Tuple; import net.minecraft.village.MerchantRecipeList; @@ -112,6 +116,7 @@ public class VillagerRegistry * Register your villager id * @param id */ + @Deprecated // Doesn't work at all. public void registerVillagerId(int id) { if (newVillagerIds.contains(id)) @@ -128,6 +133,7 @@ public class VillagerRegistry * @param villagerSkin */ @SideOnly(Side.CLIENT) + @Deprecated // Doesn't work at all. public void registerVillagerSkin(int villagerId, ResourceLocation villagerSkin) { if (newVillagers == null) @@ -154,6 +160,7 @@ public class VillagerRegistry * @param defaultSkin */ @SideOnly(Side.CLIENT) + @Deprecated // Doesn't work at all. public static ResourceLocation getVillagerSkin(int villagerType, ResourceLocation defaultSkin) { if (instance().newVillagers != null && instance().newVillagers.containsKey(villagerType)) @@ -168,6 +175,7 @@ public class VillagerRegistry * * @return newVillagerIds */ + @Deprecated // Doesn't work at all. public static Collection getRegisteredVillagers() { return Collections.unmodifiableCollection(instance().newVillagerIds); @@ -191,12 +199,15 @@ public class VillagerRegistry public void register(VillagerProfession prof) { - //blah + register(prof, -1); + } + private void register(VillagerProfession prof, int id) + { + professions.register(id, prof.name, prof); } private boolean hasInit = false; - private List professions = Lists.newArrayList(); - + private FMLControlledNamespacedRegistry professions = GameData.createRegistry("villagerprofessions", VillagerProfession.class, 0, 1024); private void init() @@ -206,7 +217,7 @@ public class VillagerRegistry VillagerProfession prof = new VillagerProfession("minecraft:farmer", "minecraft:textures/entity/villager/farmer.png"); { - register(prof); + register(prof, 0); (new VillagerCareer(prof, "farmer" )).init(VanillaTrades.trades[0][0]); (new VillagerCareer(prof, "fisherman" )).init(VanillaTrades.trades[0][1]); (new VillagerCareer(prof, "shepherd" )).init(VanillaTrades.trades[0][2]); @@ -214,24 +225,24 @@ public class VillagerRegistry } prof = new VillagerProfession("minecraft:librarian", "minecraft:textures/entity/villager/librarian.png"); { - register(prof); + register(prof, 1); (new VillagerCareer(prof, "librarian")).init(VanillaTrades.trades[1][0]); } prof = new VillagerProfession("minecraft:priest", "minecraft:textures/entity/villager/priest.png"); { - register(prof); + register(prof, 2); (new VillagerCareer(prof, "cleric")).init(VanillaTrades.trades[2][0]); } prof = new VillagerProfession("minecraft:smith", "minecraft:textures/entity/villager/smith.png"); { - register(prof); + register(prof, 3); (new VillagerCareer(prof, "armor" )).init(VanillaTrades.trades[3][0]); (new VillagerCareer(prof, "weapon")).init(VanillaTrades.trades[3][1]); (new VillagerCareer(prof, "tool" )).init(VanillaTrades.trades[3][2]); } prof = new VillagerProfession("minecraft:butcher", "minecraft:textures/entity/villager/butcher.png"); { - register(prof); + register(prof, 4); (new VillagerCareer(prof, "butcher")).init(VanillaTrades.trades[4][0]); (new VillagerCareer(prof, "leather")).init(VanillaTrades.trades[4][1]); } @@ -242,11 +253,13 @@ public class VillagerRegistry private ResourceLocation name; private ResourceLocation texture; private List careers = Lists.newArrayList(); + private RegistryDelegate delegate = GameData.getRegistry("villagerprofessions", VillagerProfession.class).getDelegate(this, VillagerProfession.class); public VillagerProfession(String name, String texture) { this.name = new ResourceLocation(name); this.texture = new ResourceLocation(texture); + ((RegistryDelegate.Delegate)delegate).setName(name); } private void register(VillagerCareer career) @@ -293,6 +306,8 @@ public class VillagerRegistry */ public static void setRandomProfession(EntityVillager entity, Random rand) { + Set entries = INSTANCE.professions.getKeys(); + int prof = rand.nextInt(entries.size()); //TODO: Grab id range from internal registry entity.setProfession(rand.nextInt(5)); }