package me.km.utils; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; import java.util.Random; import java.util.UUID; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.PlayerCapabilities; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.server.management.PlayerList; import net.minecraft.util.DamageSource; import net.minecraft.util.FoodStats; import net.minecraft.world.Explosion; import net.minecraftforge.fml.relauncher.ReflectionHelper; public class ReflectionUtils { // ----------------------------------------------------------------------------------- // helper stuff // ----------------------------------------------------------------------------------- private static Method getMethod(Class c, String name, String obfusName, Class... pars) { try { return ReflectionHelper.findMethod(c, name, obfusName, pars); } catch(SecurityException | ReflectionHelper.UnableToFindMethodException ex) { System.out.println(name + ", " + obfusName + " - " + ex); } return null; } public static Field getField(Class c, String... field) { try { return ReflectionHelper.findField(c, field); } catch(SecurityException | ReflectionHelper.UnableToFindFieldException ex) { System.out.println(String.join(", ", field) + " - " + ex); } return null; } private static void setInt(T t, Field f, int i) { try { f.setInt(t, i); } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) { System.out.println(f + " - " + ex); } } private static int getInt(T t, Field f, int error) { try { return f.getInt(t); } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) { System.out.println(f + " - " + ex); return error; } } private static void setFloat(T t, Field f, float fl) { try { f.setFloat(t, fl); } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) { System.out.println(f + " - " + ex); } } private static float getFloat(T t, Field f, float error) { try { return f.getFloat(t); } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) { System.out.println(f + " - " + ex); return error; } } private static boolean getBoolean(T t, Field f, boolean error) { try { return f.getBoolean(t); } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) { System.out.println(f + " - " + ex); return error; } } private static T getFieldValue(Class cast, Object o, Field f) { try { return (T) f.get(o); } catch(SecurityException | IllegalAccessException | IllegalArgumentException ex) { System.out.println(f + " - " + ex); return null; } } public static void setFieldValue(Object o, Field f, Object value) { try { f.set(o, value); } catch(SecurityException | IllegalAccessException | IllegalArgumentException ex) { System.out.println(f + " - " + ex); } } // ----------------------------------------------------------------------------------- // villager stuff // ----------------------------------------------------------------------------------- private final static Field CARRER_LEVEL = getField(EntityVillager.class, "field_175562_bw", "careerLevel"); public static void setCareerLevel(EntityVillager v, int level) { setInt(v, CARRER_LEVEL, level); } // ----------------------------------------------------------------------------------- // food stats // ----------------------------------------------------------------------------------- private final static Field FOOD_EXHAUSTION_LEVEL = getField(FoodStats.class, "field_75126_c", "foodExhaustionLevel"); public static void setExhaustion(FoodStats stats, float f) { setFloat(stats, FOOD_EXHAUSTION_LEVEL, f); } public static float getExhaustion(FoodStats stats) { return getFloat(stats, FOOD_EXHAUSTION_LEVEL, 0); } private final static Field FOOD_SATURATION_LEVEL = getField(FoodStats.class, "field_75125_b", "foodSaturationLevel"); public static void setSaturation(FoodStats stats, float f) { setFloat(stats, FOOD_SATURATION_LEVEL, f); } // ----------------------------------------------------------------------------------- // player stats // ----------------------------------------------------------------------------------- private final static Field FLY_SPEED = getField(PlayerCapabilities.class, "field_75096_f", "flySpeed"); public static void setFlySpeed(PlayerCapabilities cap, float f) { setFloat(cap, FLY_SPEED, f); } private final static Field WALK_SPEED = getField(PlayerCapabilities.class, "field_75097_g", "walkSpeed"); public static void setWalkSpeed(PlayerCapabilities cap, float f) { setFloat(cap, WALK_SPEED, f); } // ----------------------------------------------------------------------------------- // explosion stuff // ----------------------------------------------------------------------------------- private final static Field IS_FLAMING = getField(Explosion.class, "field_77286_a", "causesFire"); private final static Field IS_SMOKING = getField(Explosion.class, "field_82755_b", "damagesTerrain"); private final static Field EXPLOSION_RNG = getField(Explosion.class, "field_77290_i", "random"); private final static Field EXPLOSION_SIZE = getField(Explosion.class, "field_77280_f", "size"); private final static Field EXPLODER = getField(Explosion.class, "field_77283_e", "exploder"); public static boolean isFlaming(Explosion ex) { return getBoolean(ex, IS_FLAMING, false); } public static boolean isSmoking(Explosion ex) { return getBoolean(ex, IS_SMOKING, false); } public static Random getRandom(Explosion ex) { return getFieldValue(Random.class, ex, EXPLOSION_RNG); } public static float getSize(Explosion ex) { return getFloat(ex, EXPLOSION_SIZE, 1); // 1 for preventing zero dividing } public static void setSize(Explosion ex, float f) { setFloat(ex, EXPLOSION_SIZE, f); } public static Entity getExploder(Explosion ex) { return getFieldValue(Entity.class, ex, EXPLODER); } // ----------------------------------------------------------------------------------- // random field gets // ----------------------------------------------------------------------------------- private final static Field TIME_IN_GROUND = getField(EntityArrow.class, "field_184552_b", "timeInGround"); public static int getArrowTimeInGround(EntityArrow arrow) { return getInt(arrow, TIME_IN_GROUND, 0); } private final static Field UUID_TO_PLAYER_MAP = getField(PlayerList.class, "field_177454_f", "uuidToPlayerMap"); public static Map getUuidToPlayerMap(PlayerList list) { return getFieldValue(Map.class, list, UUID_TO_PLAYER_MAP); } private final static Field ENTITY_ITEM_AGE = getField(EntityItem.class, "field_70292_b", "age"); public static int getAge(EntityItem item) { return getInt(item, ENTITY_ITEM_AGE, 0); } public static void setAge(EntityItem item, int age) { setInt(item, ENTITY_ITEM_AGE, age); } private final static Field BLOCK_MATERIAL = getField(Block.class, "field_149764_J", "blockMaterial"); public static Material getBlockMaterial(Block b) { return getFieldValue(Material.class, b, BLOCK_MATERIAL); } // ----------------------------------------------------------------------------------- // EntityLivingBase stuff // ----------------------------------------------------------------------------------- private final static Method APPLY_POTION_DAMAGE_CALCULATIONS = getMethod( EntityLivingBase.class, "applyPotionDamageCalculations", "func_70672_c", DamageSource.class, float.class); public static float applyPotionDamageCalculations(EntityLivingBase liv, DamageSource ds, float damage) { try { return (float) APPLY_POTION_DAMAGE_CALCULATIONS.invoke(liv, ds, damage); } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { return damage; } } private final static Method DAMAGE_ARMOR = getMethod( EntityLivingBase.class, "damageArmor", "func_70675_k", float.class); public static void damageArmor(EntityLivingBase liv, float damage) { try { DAMAGE_ARMOR.invoke(liv, damage); } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { } } }