Skip to content

Commit

Permalink
Potions: Extended, Enchantments: Extended
Browse files Browse the repository at this point in the history
Yes, you read right. Potions and Enchantments are extended and both will be in the same update. Thank you zabi94 for helping me getting both of these extended, potions absolutely sucked extending and enchants had a single pain to deal with.

So yeah, go for it damn it.
  • Loading branch information
ZombieHDGaming committed Oct 3, 2018
1 parent 3811159 commit d095e79
Show file tree
Hide file tree
Showing 15 changed files with 373 additions and 233 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ jar {
"FMLCorePluginContainsFMLMod": "true",
"TweakClass": "org.spongepowered.asm.launch.MixinTweaker",
"FMLCorePlugin": "org.dimdev.jeid.JEIDLoadingPlugin",
"ForceLoadAsMod": "true"
"ForceLoadAsMod": "true",
"FMLAT": "jeid_at.cfg"
)
}

Expand Down
42 changes: 38 additions & 4 deletions src/main/java/org/dimdev/jeid/JEID.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.potion.Potion;
Expand All @@ -12,6 +15,7 @@
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeVoid;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.registries.IForgeRegistry;
Expand All @@ -27,6 +31,7 @@ public class JEID {
private static final boolean DEBUG_ITEM_IDS = false;
private static final boolean DEBUG_BIOME_IDS = false;
private static final boolean DEBUG_POTION_IDS = false;
private static final boolean DEBUG_ENCHANT_IDS = false;
public static final Biome errorBiome = new BiomeVoid(new Biome.BiomeProperties("A mod doesn't support extended biome IDs -- report to JEID"))
.setRegistryName("jeid:error_biome");

Expand All @@ -35,6 +40,9 @@ public void onPreInit(FMLPreInitializationEvent event) {
// Register messages
MessageManager.init();

// Error Biome Registration
GameRegistry.findRegistry(Biome.class).register(errorBiome);

// Debug code
if (DEBUG_BLOCK_IDS) {
IForgeRegistry<Block> blockRegistry = GameRegistry.findRegistry(Block.class);
Expand Down Expand Up @@ -72,8 +80,6 @@ public void onPreInit(FMLPreInitializationEvent event) {
}
}

GameRegistry.findRegistry(Biome.class).register(errorBiome);

if (DEBUG_POTION_IDS) {
IForgeRegistry<Potion> potionRegistry = GameRegistry.findRegistry(Potion.class);
IForgeRegistry<PotionType> potionTypeRegistry = GameRegistry.findRegistry(PotionType.class);
Expand All @@ -83,11 +89,29 @@ public void onPreInit(FMLPreInitializationEvent event) {
}

for (int i = 0; i < 300; i++) {
PotionType pt = new PotionType(new PotionEffect(Potion.REGISTRY.getObject(new ResourceLocation("jeid:potion_" + i)), 2000, 0, false, true));
PotionType pt = new PotionType(new PotionEffect(Potion.REGISTRY.getObject(new ResourceLocation("jeid:potion_" + i)),
2000,
0,
false,
true));
pt.setRegistryName(new ResourceLocation("jeid:potiontype_"+i));
potionTypeRegistry.register(pt);
}
}

if (DEBUG_ENCHANT_IDS) {
IForgeRegistry<Enchantment> enchantRegistry = GameRegistry.findRegistry(Enchantment.class);
for (int i = 0; i < Short.MAX_VALUE; i++) {
Enchantment ench = new EnchantTest(i).setRegistryName(new ResourceLocation("jeid:enchant_"+i));

enchantRegistry.register(ench);
}
}
}

@Mod.EventHandler
public void postInit(FMLPostInitializationEvent e) {
JEIDTransformer.REGISTRY = net.minecraftforge.registries.GameData.getWrapper(Potion.class);
}

public static class PotionTest extends Potion {
Expand All @@ -105,4 +129,14 @@ public String getName() {
return nm;
}
}
}

public static class EnchantTest extends Enchantment {

public EnchantTest(int i)
{
super(Rarity.COMMON, EnumEnchantmentType.BOW, new EntityEquipmentSlot[EntityEquipmentSlot.CHEST.getIndex()]);
this.setName("Test Enchantment #"+i);
}

}
}
2 changes: 1 addition & 1 deletion src/main/java/org/dimdev/jeid/JEIDLoadingPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public JEIDLoadingPlugin() {
Mixins.addConfiguration("mixins.jeid.init.json");
}

@Override public String[] getASMTransformerClass() { Obf.loadData(); return new String[]{ "org.dimdev.jeid.PotionTransformer" }; }
@Override public String[] getASMTransformerClass() { Obf.loadData(); return new String[]{ "org.dimdev.jeid.JEIDTransformer" }; }
@Override public String getModContainerClass() { return null; }
@Nullable @Override public String getSetupClass() { return null; }
@Override public void injectData(Map<String, Object> data) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import net.minecraft.launchwrapper.Launch;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.RegistryNamespaced;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
Expand All @@ -15,22 +17,32 @@

/**
* This class was borrowed from Zabi94's MaxPotionIDExtender
* until we can figure out the issue with two of our Mixin
* classes with mappings. All credit in this class goes to Zabi
* and his incredible work on figuring out how to make this work.
* under MIT License and with full help of Zabi. All credit in this class goes to Zabi
* and his incredible work on figuring out how to make this work and helping out.
*
* https://github.com/zabi94/MaxPotionIDExtender
*/
public class PotionTransformer implements IClassTransformer {
public class JEIDTransformer implements IClassTransformer {

public static RegistryNamespaced<ResourceLocation, Potion> REGISTRY;

@Override
public byte[] transform(String name, String transformedName, byte[] basicClass) {
if (transformedName.equals("net.minecraft.client.network.NetHandlerPlayClient")) {
return transformNetHandlerPlayClient(basicClass);
}
if (transformedName.equals("net.minecraft.potion.PotionEffect")) {
return transformPotionEffect(basicClass);
}
if (transformedName.equals("net.minecraft.network.play.server.SPacketEntityEffect")) {
return transformSPacketEntityEffect(basicClass);
}
if (transformedName.equals("net.minecraft.network.play.server.SPacketRemoveEntityEffect")) {
return transformSPacketRemoveEntityEffect(basicClass);
}
if (transformedName.equals("net.minecraft.item.ItemStack")) {
return transformItemStack(basicClass);
}
if (transformedName.equals("net.minecraft.nbt.NBTTagCompound")) {
ClassReader cr = new ClassReader(basicClass);
ClassNode cn = new ClassNode();
Expand Down Expand Up @@ -66,13 +78,29 @@ private static AbstractInsnNode locateTargetInsn(MethodNode mn, Predicate<Abstra
}
}
if (target==null) {
//throw new ASMException("Can't locate target instruction in "+mn.name, mn);
throw new RuntimeException("Can't locate target instruction in "+mn.name);
}
return target;
}
private byte[] transformItemStack(byte[] basicClass) {
ClassReader cr = new ClassReader(basicClass);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);

String descr = "(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/client/util/ITooltipFlag;)Ljava/util/List;";
String getIntegerName = Obf.isDeobf()?"getInteger":"func_74762_e";

MethodNode mn = locateMethod(cn, descr, "func_82840_a", "getTooltip");
AbstractInsnNode target = locateTargetInsn(mn, n -> n.getOpcode()==Opcodes.INVOKEVIRTUAL && n.getPrevious().getOpcode()==Opcodes.LDC && ((LdcInsnNode)n.getPrevious()).cst.toString().equals("id"));
mn.instructions.insertBefore(target, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, getIntegerName, "(Ljava/lang/String;)I", false));
mn.instructions.remove(target);

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}

private byte[] transformSPacketRemoveEntityEffect(byte[] basicClass) {
//Log.i("Patching SPacketRemoveEntityEffect");
ClassReader cr = new ClassReader(basicClass);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
Expand All @@ -89,12 +117,10 @@ private byte[] transformSPacketRemoveEntityEffect(byte[] basicClass) {

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
//Log.i("Patch Successful");
return cw.toByteArray();
}

private byte[] transformSPacketEntityEffect(byte[] basicClass) {
//Log.i("Patching SPacketEntityEffect");
ClassReader cr = new ClassReader(basicClass);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);
Expand Down Expand Up @@ -122,7 +148,7 @@ private byte[] transformSPacketEntityEffect(byte[] basicClass) {
}

if (targetNode == null) {
//throw new ASMException("Can't find target node for SPacketEntityEffect constructor");
throw new RuntimeException("Can't find target node for SPacketEntityEffect constructor");
}

//These are reversed, they get pushed down the stack
Expand Down Expand Up @@ -161,14 +187,59 @@ private byte[] transformSPacketEntityEffect(byte[] basicClass) {

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
//Log.i("Patch Successful");
return cw.toByteArray();
}

public int getIdFromPotEffect(PotionEffect pe) {
return Potion.getIdFromPotion(pe.getPotion());
private byte[] transformPotionEffect(byte[] basicClass) {
ClassReader cr = new ClassReader(basicClass);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);

if (!cn.name.equals(Obf.PotionEffect)) {
throw new RuntimeException("Mapping mismatch! PotionEffect is "+cn.name+", not "+Obf.PotionEffect);
}

MethodNode mn = locateMethod(cn, "(L"+Obf.NBTTagCompound+";)L"+Obf.NBTTagCompound+";", "writeCustomPotionEffectToNBT", "a");
AbstractInsnNode ant = locateTargetInsn(mn, n -> n.getOpcode() == Opcodes.I2B);
String mname = (Obf.isDeobf()?"setInteger":"a");
MethodInsnNode call = new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, mname, "(Ljava/lang/String;I)V", false);
mn.instructions.remove(ant.getNext());
mn.instructions.insert(ant, call);
mn.instructions.remove(ant);


MethodNode mn2 = locateMethod(cn, "(L"+Obf.NBTTagCompound+";)L"+Obf.PotionEffect+";", "readCustomPotionEffectFromNBT", "b");
AbstractInsnNode ant2 = locateTargetInsn(mn2, n -> n.getOpcode() == Opcodes.INVOKEVIRTUAL);

String name2 = (Obf.isDeobf()?"getInteger":"h");

mn2.instructions.remove(ant2.getNext());
mn2.instructions.remove(ant2.getNext());
mn2.instructions.insert(ant2, new MethodInsnNode(Opcodes.INVOKEVIRTUAL, Obf.NBTTagCompound, name2, "(Ljava/lang/String;)I", false));
mn2.instructions.remove(ant2);

ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}

private byte[] transformNetHandlerPlayClient(byte[] basicClass) {
ClassReader cr = new ClassReader(basicClass);
ClassNode cn = new ClassNode();
cr.accept(cn, 0);

MethodNode mn = locateMethod(cn, "(L"+Obf.SPacketEntityEffect+";)V", "handleEntityEffect", "a");
AbstractInsnNode target = locateTargetInsn(mn, n -> n.getOpcode()==Opcodes.SIPUSH);
mn.instructions.remove(target.getPrevious());
mn.instructions.remove(target.getNext());
mn.instructions.insertBefore(target, new FieldInsnNode(Opcodes.GETFIELD, Obf.SPacketEntityEffect, "effectInt", "I"));
mn.instructions.remove(target);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
cn.accept(cw);
return cw.toByteArray();
}

public static int getIdFromPotEffect(PotionEffect pe) { return REGISTRY.getIDForObject(pe.getPotion()); }
}

class Obf {
Expand Down
114 changes: 114 additions & 0 deletions src/main/java/org/dimdev/jeid/mixin/core/MixinEnchantmentHelper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package org.dimdev.jeid.mixin.core;

import com.google.common.collect.Maps;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentData;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.init.Items;
import net.minecraft.item.ItemEnchantedBook;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;

import java.util.Map;

@Mixin(EnchantmentHelper.class)
public class MixinEnchantmentHelper {

/** @reason Mojang really likes modifying their original type into something else **/
@Overwrite
public static int getEnchantmentLevel(Enchantment enchID, ItemStack stack)
{
if (stack.isEmpty())
{
return 0;
}
else
{
NBTTagList nbttaglist = stack.getEnchantmentTagList();

for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
Enchantment enchantment = Enchantment.getEnchantmentByID(nbttagcompound.getInteger("id"));

if (enchantment == enchID)
{
return nbttagcompound.getShort("lvl");
}
}

return 0;
}
}

/** @reason Mojang really likes modifying their original type into something else **/
@Overwrite
public static Map<Enchantment, Integer> getEnchantments(ItemStack stack)
{
Map<Enchantment, Integer> map = Maps.<Enchantment, Integer>newLinkedHashMap();
NBTTagList nbttaglist = stack.getItem() == Items.ENCHANTED_BOOK ? ItemEnchantedBook.getEnchantments(stack) : stack.getEnchantmentTagList();

for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
Enchantment enchantment = Enchantment.getEnchantmentByID(nbttagcompound.getInteger("id"));
map.put(enchantment, Integer.valueOf(nbttagcompound.getShort("lvl")));
}

return map;
}

@Overwrite
public static void setEnchantments(Map<Enchantment, Integer> enchMap, ItemStack stack)
{
NBTTagList nbttaglist = new NBTTagList();

for (Map.Entry<Enchantment, Integer> entry : enchMap.entrySet())
{
Enchantment enchantment = entry.getKey();

if (enchantment != null)
{
NBTTagCompound nbttagcompound = new NBTTagCompound();
nbttagcompound.setInteger("id", Enchantment.getEnchantmentID(enchantment));
nbttagcompound.setShort("lvl", entry.getValue().shortValue());
nbttaglist.appendTag(nbttagcompound);

if (stack.getItem() == Items.ENCHANTED_BOOK) { ItemEnchantedBook.addEnchantment(stack, new EnchantmentData(enchantment, entry.getValue().shortValue())); }
}
}

if (nbttaglist.isEmpty())
{
if (stack.hasTagCompound())
{
stack.getTagCompound().removeTag("ench");
}
}
else if (stack.getItem() != Items.ENCHANTED_BOOK)
{
stack.setTagInfo("ench", nbttaglist);
}
}

@Overwrite
private static void applyEnchantmentModifier(EnchantmentHelper.IModifier modifier, ItemStack stack)
{
if (!stack.isEmpty())
{
NBTTagList nbttaglist = stack.getEnchantmentTagList();

for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
if (Enchantment.getEnchantmentByID(nbttaglist.getCompoundTagAt(i).getInteger("id")) != null)
{
modifier.calculateModifier(Enchantment.getEnchantmentByID(nbttaglist.getCompoundTagAt(i).getInteger("id")), nbttaglist.getCompoundTagAt(i).getShort("lvl"));
}
}
}
}

}
4 changes: 4 additions & 0 deletions src/main/java/org/dimdev/jeid/mixin/core/MixinGameData.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ private static int getPotionIDLimit(int value) {
/** @reason Removes the biome ID limit. */
@ModifyConstant(method = "init", constant = @Constant(intValue = 255, ordinal = 1), remap = false)
private static int getBiomeIDLimit(int value) { return Integer.MAX_VALUE - 1; }

/** @reason Removes the enchantment ID limit. */
@ModifyConstant(method = "init", constant = @Constant(intValue = Short.MAX_VALUE - 1, ordinal = 0), remap = false)
private static int getEnchantmentIDLimit(int value) { return Integer.MAX_VALUE - 1; }
}
Loading

0 comments on commit d095e79

Please sign in to comment.