package me.km.utils; import cpw.mods.modlauncher.api.INameMappingService; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Set; import net.minecraft.block.Block; import net.minecraft.block.Blocks; import net.minecraft.block.FireBlock; import net.minecraft.command.Commands; import net.minecraft.entity.ai.goal.GoalSelector; import net.minecraft.entity.ai.goal.PrioritizedGoal; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.resources.DataPackRegistries; import net.minecraft.server.MinecraftServer; import net.minecraft.server.management.PlayerInteractionManager; import net.minecraft.server.management.PlayerList; import net.minecraft.tileentity.SignTileEntity; import net.minecraft.util.FoodStats; import net.minecraft.util.IIntArray; import net.minecraft.util.IntReferenceHolder; import net.minecraft.util.text.ITextComponent; import net.minecraft.world.Explosion; import net.minecraft.world.GameRules; import net.minecraft.world.GameType; import net.minecraft.world.World; import net.minecraft.world.server.ServerWorld; import net.minecraft.world.storage.DerivedWorldInfo; import net.minecraft.world.storage.IServerConfiguration; import net.minecraft.world.storage.IServerWorldInfo; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import static net.minecraftforge.fml.common.ObfuscationReflectionHelper.remapName; import org.apache.logging.log4j.LogManager; public class ReflectionUtils { public static Method getMethod(Class c, String name, Class... pars) { try { return ObfuscationReflectionHelper.findMethod(c, name, pars); } catch(Exception ex) { LogManager.getLogger().warn(name + " - " + ex); } return null; } public static Field getField(Class c, String field) { try { Field f = c.getDeclaredField(remapName(INameMappingService.Domain.FIELD, field)); f.setAccessible(true); return f; } catch(Exception ex) { LogManager.getLogger().warn(field + " - " + ex); } return null; } private static void setInt(T t, Field f, int i) { try { f.setInt(t, i); } catch(Exception ex) { LogManager.getLogger().warn(f + " - " + ex); } } private static void setFloat(T t, Field f, float fl) { try { f.setFloat(t, fl); } catch(Exception ex) { LogManager.getLogger().warn(f + " - " + ex); } } private static float getFloat(T t, Field f, float error) { try { return f.getFloat(t); } catch(Exception ex) { LogManager.getLogger().warn(f + " - " + ex); return error; } } public static T getFieldValue(Class cast, Object o, Field f) { try { return cast.cast(f.get(o)); } catch(Exception ex) { LogManager.getLogger().warn(f + " - " + ex); return null; } } public static void setFieldValue(Object instance, Field f, Object value) { try { f.set(instance, value); } catch(Exception ex) { LogManager.getLogger().warn(f + " - " + ex); } } public static T getFieldValue(Class cast, Class c, Object instance, String field) { Field f = getField(c, field); if(f == null) { return null; } return getFieldValue(cast, instance, f); } 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); } private final static Method SET_GAMETYPE = getMethod(PlayerList.class, "func_72381_a", ServerPlayerEntity.class, ServerPlayerEntity.class, ServerWorld.class); // setPlayerGameTypeBasedOnOther public static void setPlayerGameTypeBasedOnOther(PlayerList pl, ServerPlayerEntity target, ServerPlayerEntity source, ServerWorld sw) { try { SET_GAMETYPE.invoke(pl, target, source, sw); } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { LogManager.getLogger().warn("setPlayerGameTypeBasedOnOther - " + ex); } } private final static Field COMMAND_MANAGER = getField(DataPackRegistries.class, "field_240953_c_"); // commands public static void setCommandManager(MinecraftServer server, Commands manager) { setFieldValue(server.getDataPackRegistries(), COMMAND_MANAGER, manager); } private final static Field MODE = getField(Explosion.class, "field_222260_b"); // mode public static void setNoBreakMode(Explosion ex) { Explosion.Mode mode = getFieldValue(Explosion.Mode.class, ex, MODE); if(mode == Explosion.Mode.DESTROY) { setFieldValue(ex, MODE, Explosion.Mode.BREAK); } } private final static Field INTEGER_VALUE = getField(GameRules.IntegerValue.class, "field_223566_a"); // value public static void setIntegerValue(GameRules.IntegerValue rule, int value) { setInt(rule, INTEGER_VALUE, value); } // ----------------------------------------------------------------------------------- // game type setter without update for dirty hack // ----------------------------------------------------------------------------------- private final static Field GAME_TYPE = getField(PlayerInteractionManager.class, "field_73091_c"); public static void setGameType(PlayerInteractionManager m, GameType type) { setFieldValue(m, GAME_TYPE, type); } // ----------------------------------------------------------------------------------- // for clearing ai // ----------------------------------------------------------------------------------- private final static Field GOALS = getField(GoalSelector.class, "field_220892_d"); @SuppressWarnings("unchecked") public static Set getGoals(GoalSelector gs) { return getFieldValue(Set.class, gs, GOALS); } private final static Method SET_FIRE_INFO = getMethod(FireBlock.class, "func_180686_a", Block.class, int.class, int.class); public static void setFireInfo(Block b, int encouragement, int flammability) { FireBlock fireblock = (FireBlock) Blocks.FIRE; try { SET_FIRE_INFO.invoke(fireblock, b, encouragement, flammability); } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { LogManager.getLogger().warn("setFireInfo - " + ex); } } private final static Field SIGN_TEXT = getField(SignTileEntity.class, "field_145915_a"); public static ITextComponent getSignText(SignTileEntity ent, int index) { return getFieldValue(ITextComponent[].class, ent, SIGN_TEXT)[index]; } private final static Field WORLD_INFO = getField(World.class, "field_72986_A"); // worldInfo private final static Field SERVER_WORLD_INFO = getField(ServerWorld.class, "field_241103_E_"); // worldInfo public static void setWorldInfo(ServerWorld w, IServerWorldInfo info) { setFieldValue(w, WORLD_INFO, info); setFieldValue(w, SERVER_WORLD_INFO, info); } private final static Field DERIVED_WORLD_INFO_DELEGATE = getField(DerivedWorldInfo.class, "field_76115_a"); public static IServerWorldInfo getDerivedWorldInfoDelegate(DerivedWorldInfo info) { return getFieldValue(IServerWorldInfo.class, info, DERIVED_WORLD_INFO_DELEGATE); } private final static Field DERIVED_WORLD_INFO_CONFIGURATION = getField(DerivedWorldInfo.class, "field_237244_a_"); public static IServerConfiguration getDerivedWorldInfoConfiguration(DerivedWorldInfo info) { return getFieldValue(IServerConfiguration.class, info, DERIVED_WORLD_INFO_CONFIGURATION); } private final static Method ADD_SLOT = getMethod(Container.class, "func_75146_a", Slot.class); // addSlot private final static Method TRACK_INT = getMethod(Container.class, "func_216958_a", IntReferenceHolder.class); // trackInt private final static Method TRACK_INT_ARRAY = getMethod(Container.class, "func_216961_a", IIntArray.class); // trackIntArray private final static Method CLEAR_CONTAINER = getMethod(Container.class, "func_193327_a", PlayerEntity.class, World.class, IInventory.class); // clearContainer private final static Method MERGE_ITEM_STACK = getMethod(Container.class, "func_75135_a", ItemStack.class, int.class, int.class, boolean.class); // mergeItemStack private final static Method RESET_DRAG = getMethod(Container.class, "func_94533_d"); // resetDrag public static Slot addSlot(Container c, Slot slot) { try { return (Slot) ADD_SLOT.invoke(c, slot); } catch(Exception ex) { LogManager.getLogger().warn("addSlot - " + ex); } return null; } public static IntReferenceHolder trackInt(Container c, IntReferenceHolder i) { try { return (IntReferenceHolder) TRACK_INT.invoke(c, i); } catch(Exception ex) { LogManager.getLogger().warn("trackInt - " + ex); } return null; } public static void trackIntArray(Container c, IIntArray array) { try { TRACK_INT_ARRAY.invoke(c, array); } catch(Exception ex) { LogManager.getLogger().warn("trackIntArray - " + ex); } } public static void clearContainer(Container c, PlayerEntity p, World w, IInventory i) { try { CLEAR_CONTAINER.invoke(c, p, w, i); } catch(Exception ex) { LogManager.getLogger().warn("clearContainer - " + ex); } } public static boolean mergeItemStack(Container c, ItemStack stack, int startIndex, int endIndex, boolean reverseDirection) { try { return (boolean) MERGE_ITEM_STACK.invoke(c, stack, startIndex, endIndex, reverseDirection); } catch(Exception ex) { LogManager.getLogger().warn("mergeItemStack - " + ex); } return false; } public static void resetDrag(Container c) { try { RESET_DRAG.invoke(c); } catch(Exception ex) { LogManager.getLogger().warn("resetDrag - " + ex); } } }