From 57d1a657a0db0495738ce0260918889883711733 Mon Sep 17 00:00:00 2001 From: Bernhard Bonigl Date: Sun, 29 Nov 2015 22:02:55 +0100 Subject: [PATCH] Add a PotionRegistry to handle dynamic distribution and remapping of Potion IDs --- .../net/minecraft/potion/Potion.java.patch | 43 ++++++++- .../fml/common/registry/GameData.java | 33 +++++++ .../fml/common/registry/GameRegistry.java | 6 ++ .../registry/PersistentRegistryManager.java | 5 ++ src/main/resources/forge_at.cfg | 2 + .../debug/PotionRegistryDebug.java | 88 +++++++++++++++++++ 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 src/test/java/net/minecraftforge/debug/PotionRegistryDebug.java diff --git a/patches/minecraft/net/minecraft/potion/Potion.java.patch b/patches/minecraft/net/minecraft/potion/Potion.java.patch index 8b374f8a0e..621a89f3c7 100644 --- a/patches/minecraft/net/minecraft/potion/Potion.java.patch +++ b/patches/minecraft/net/minecraft/potion/Potion.java.patch @@ -1,6 +1,47 @@ --- ../src-base/minecraft/net/minecraft/potion/Potion.java +++ ../src-work/minecraft/net/minecraft/potion/Potion.java -@@ -310,4 +310,27 @@ +@@ -21,7 +21,7 @@ + + public class Potion + { +- public static final Potion[] field_76425_a = new Potion[32]; ++ public static final Potion[] field_76425_a = new Potion[256]; + private static final Map field_180150_I = Maps.newHashMap(); + public static final Potion field_180151_b = null; + public static final Potion field_76424_c = (new Potion(1, new ResourceLocation("speed"), false, 8171462)).func_76390_b("potion.moveSpeed").func_76399_b(0, 0).func_111184_a(SharedMonsterAttributes.field_111263_d, "91AEAA56-376B-4498-935B-2F7F68070635", 0.20000000298023224D, 2); +@@ -64,8 +64,10 @@ + private double field_76412_L; + private boolean field_76413_M; + ++ @Deprecated // use the Constructor without potion ID or everything will explode. + protected Potion(int p_i45897_1_, ResourceLocation p_i45897_2_, boolean p_i45897_3_, int p_i45897_4_) + { ++ p_i45897_1_ = net.minecraftforge.fml.common.registry.GameRegistry.registerPotion(this, p_i45897_2_, p_i45897_1_); + this.field_76415_H = p_i45897_1_; + field_76425_a[p_i45897_1_] = this; + field_180150_I.put(p_i45897_2_, this); +@@ -83,14 +85,18 @@ + this.field_76414_N = p_i45897_4_; + } + ++ protected Potion(ResourceLocation location, boolean badEffect, int potionColor) { ++ this(-1, location, badEffect, potionColor); ++ } ++ + public static Potion func_180142_b(String p_180142_0_) + { +- return (Potion)field_180150_I.get(new ResourceLocation(p_180142_0_)); ++ return net.minecraftforge.fml.common.registry.GameData.getPotionRegistry().func_82594_a(new ResourceLocation(p_180142_0_)); + } + + public static Set func_181168_c() + { +- return field_180150_I.keySet(); ++ return net.minecraftforge.fml.common.registry.GameData.getPotionRegistry().func_148742_b(); + } + + protected Potion func_76399_b(int p_76399_1_, int p_76399_2_) +@@ -310,4 +316,27 @@ { return p_111183_2_.func_111164_d() * (double)(p_111183_1_ + 1); } diff --git a/src/main/java/net/minecraftforge/fml/common/registry/GameData.java b/src/main/java/net/minecraftforge/fml/common/registry/GameData.java index 71e8d7e090..f8e850b6d2 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/GameData.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/GameData.java @@ -19,6 +19,7 @@ import com.google.common.collect.Maps; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.item.Item; +import net.minecraft.potion.Potion; import net.minecraft.util.ObjectIntIdentityMap; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLLog; @@ -31,6 +32,8 @@ public class GameData static final int MAX_BLOCK_ID = 4095; static final int MIN_ITEM_ID = 4096; static final int MAX_ITEM_ID = 31999; + public static final int MIN_POTION_ID = 32; // 0-31 are vanilla, forge start at 32 + public static final int MAX_POTION_ID = 255; // S1DPacketEntityEffect sends bytes, we can only use 255 private static final GameData mainData = new GameData(); // public api @@ -55,6 +58,16 @@ public class GameData return getMain().iItemRegistry; } + /** + * Get the currently active potion registry. + * + * @return Potion Registry. + */ + public static FMLControlledNamespacedRegistry getPotionRegistry() { + return getMain().iPotionRegistry; + } + + /*************************************************** * INTERNAL CODE FROM HERE ON DO NOT USE! ***************************************************/ @@ -98,6 +111,7 @@ public class GameData // internal registry objects private final FMLControlledNamespacedRegistry iBlockRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.BLOCKS, Block.class, new ResourceLocation("minecraft:air"), MAX_BLOCK_ID, MIN_BLOCK_ID, true, BlockStateCapture.INSTANCE); private final FMLControlledNamespacedRegistry iItemRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.ITEMS, Item.class, null, MAX_ITEM_ID, MIN_ITEM_ID, true); + private final FMLControlledNamespacedRegistry iPotionRegistry = PersistentRegistryManager.createRegistry(PersistentRegistryManager.POTIONS, Potion.class, null, MAX_POTION_ID, MIN_POTION_ID, false, PotionArrayCapture.INSTANCE); int registerItem(Item item, String name) // from GameRegistry { @@ -133,6 +147,13 @@ public class GameData return iBlockRegistry.add(idHint, name, block); } + /** + * Called from GameRegistry, which is called from Potion-Constructor + */ + int registerPotion(Potion potion, ResourceLocation name, int id) { + return iPotionRegistry.add(id, name, potion); + } + /** * Prefix the supplied name with the current mod id. *

@@ -228,4 +249,16 @@ public class GameData } } } + + private static class PotionArrayCapture implements FMLControlledNamespacedRegistry.AddCallback + { + static final PotionArrayCapture INSTANCE = new PotionArrayCapture(); + + @Override + public void onAdd(Potion potion, int id) { + // fix the data in the potion and the potions-array + potion.id = id; + Potion.potionTypes[id] = potion; + } + } } \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java b/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java index 837f2ab7e6..954e2c6d3d 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/GameRegistry.java @@ -47,6 +47,7 @@ import net.minecraft.nbt.JsonToNBT; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTException; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.Potion; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; @@ -235,6 +236,11 @@ public class GameRegistry } } + /** Called from Potion Constructor */ + public static int registerPotion(Potion potion, ResourceLocation name, int potionID) { + return GameData.getMain().registerPotion(potion, name, potionID); + } + public static void addRecipe(ItemStack output, Object... params) { addShapedRecipe(output, params); diff --git a/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java b/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java index 138cfd882f..8cd1e07054 100644 --- a/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java +++ b/src/main/java/net/minecraftforge/fml/common/registry/PersistentRegistryManager.java @@ -1,6 +1,7 @@ package net.minecraftforge.fml.common.registry; import java.io.IOException; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -20,6 +21,7 @@ import com.google.common.collect.Sets.SetView; import net.minecraft.block.Block; import net.minecraft.item.Item; +import net.minecraft.potion.Potion; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLLog; @@ -122,6 +124,7 @@ public class PersistentRegistryManager public static final ResourceLocation BLOCKS = new ResourceLocation("minecraft:blocks"); public static final ResourceLocation ITEMS = new ResourceLocation("minecraft:items"); + public static final ResourceLocation POTIONS = new ResourceLocation("minecraft:potions"); public static FMLControlledNamespacedRegistry createRegistry(ResourceLocation registryName, Class registryType, ResourceLocation optionalDefaultKey, int maxId, int minId, boolean hasDelegates, FMLControlledNamespacedRegistry.AddCallback addCallback) { @@ -145,6 +148,8 @@ public class PersistentRegistryManager // Empty the blockstate map before loading GameData.getBlockStateIDMap().clear(); + // Clean up potion array before reloading it from the snapshot + Arrays.fill(Potion.potionTypes, null); // Load the snapshot into the "STAGING" registry for (Map.Entry snapshotEntry : snapshot.entries.entrySet()) diff --git a/src/main/resources/forge_at.cfg b/src/main/resources/forge_at.cfg index 754ae072b5..70b6348014 100644 --- a/src/main/resources/forge_at.cfg +++ b/src/main/resources/forge_at.cfg @@ -25,6 +25,8 @@ public net.minecraft.block.BlockFire func_176534_d(Lnet/minecraft/block/Block;)I public net.minecraft.item.Item func_77656_e(I)Lnet.minecraft.item.Item; #setMaxDamage public net.minecraft.item.Item func_77627_a(Z)Lnet.minecraft.item.Item; #setHasSubtypes public net.minecraft.item.Item func_77631_c(Ljava.lang.String;)Lnet.minecraft.item.Item; #setPotionEffect +# Potion +public-f net.minecraft.potion.Potion field_76415_H #id # EntityPlayer public net.minecraft.entity.player.EntityPlayer func_71012_a(Lnet/minecraft/entity/item/EntityItem;)V #joinEntityItemWithWorld public net.minecraft.client.entity.EntityPlayerSP func_71012_a(Lnet/minecraft/entity/item/EntityItem;)V #joinEntityItemWithWorld diff --git a/src/test/java/net/minecraftforge/debug/PotionRegistryDebug.java b/src/test/java/net/minecraftforge/debug/PotionRegistryDebug.java new file mode 100644 index 0000000000..072189262b --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/PotionRegistryDebug.java @@ -0,0 +1,88 @@ +package net.minecraftforge.debug; + +import gnu.trove.set.TIntSet; +import gnu.trove.set.hash.TIntHashSet; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.texture.TextureAtlasSprite; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; + +import java.util.Random; + +@Mod(modid=PotionRegistryDebug.MODID) +public class PotionRegistryDebug { + public static final String MODID = "ForgePotionRegistry"; + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) { + new PotionForge(new ResourceLocation("forge", "forge"), false, 0xff00ff); // test automatic id distribution + new PotionForge(200, new ResourceLocation("forge", "forgy"), true, 0x00ff00); // test that ids above 127 work + + Random rand = new Random(); + TIntSet taken = new TIntHashSet(100); + int ra = rand.nextInt(100) + 100; + taken.add(ra); + + // a new potion with a random id so that forge has to remap it + new PotionForge(ra, new ResourceLocation("forge", "realRandomPotion"), false, 0x0000ff); + + for(int i = 0; i < 20; i++) { + int r = rand.nextInt(200) + 35; + while(taken.contains(r)) + r = rand.nextInt(200) + 35; + //r = 32+i; + taken.add(r); + // this potions will most likely not have the same IDs between server and client. + // The forge handshake on connect should fix this. + new PotionForge(r, new ResourceLocation("forge", "randomPotion" + r), false, 0xff00ff); + } + } + + protected class PotionForge extends Potion { + + public PotionForge(int potionID, ResourceLocation location, boolean badEffect, int potionColor) { + super(potionID, location, badEffect, potionColor); + setPotionName("potion." + location.getResourcePath()); + } + + protected PotionForge(ResourceLocation location, boolean badEffect, int potionColor) { + super(location, badEffect, potionColor); + setPotionName("potion." + location.getResourcePath()); + } + + @Override + public void renderInventoryEffect(int x, int y, PotionEffect effect, Minecraft mc) { + Potion potion = Potion.potionTypes[effect.getPotionID()]; + + mc.getTextureManager().bindTexture(TextureMap.locationBlocksTexture); + TextureAtlasSprite sprite = mc.getTextureMapBlocks().getAtlasSprite("minecraft:blocks/fire_layer_0"); + + x += 6; + y += 7; + + int width = 18; + int height = width; +/* + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.startDrawingQuads(); + worldrenderer.setColorOpaque_I(potion.getLiquidColor()); + worldrenderer.addVertexWithUV((double) x, (double) (y + height), 0.0D, sprite.getMinU(), sprite.getMaxV()); + worldrenderer.addVertexWithUV((double)(x + width), (double)(y + height), 0.0D, sprite.getMaxU(), sprite.getMaxV()); + worldrenderer.addVertexWithUV((double)(x + width), (double)y, 0.0D, sprite.getMaxU(), sprite.getMinV()); + worldrenderer.addVertexWithUV((double)x, (double)y, 0.0D, sprite.getMinU(), sprite.getMinV()); + tessellator.draw();*/ + } + } +}