ReflectionUtils.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. package me.km.utils;
  2. import cpw.mods.modlauncher.api.INameMappingService;
  3. import java.lang.reflect.Constructor;
  4. import java.lang.reflect.Field;
  5. import java.lang.reflect.InvocationTargetException;
  6. import java.lang.reflect.Method;
  7. import java.util.Map;
  8. import java.util.Set;
  9. import java.util.function.Function;
  10. import net.minecraft.command.Commands;
  11. import net.minecraft.entity.Entity;
  12. import net.minecraft.entity.ai.goal.GoalSelector;
  13. import net.minecraft.entity.ai.goal.PrioritizedGoal;
  14. import net.minecraft.entity.player.PlayerAbilities;
  15. import net.minecraft.entity.player.ServerPlayerEntity;
  16. import net.minecraft.server.MinecraftServer;
  17. import net.minecraft.server.management.PlayerInteractionManager;
  18. import net.minecraft.server.management.PlayerList;
  19. import net.minecraft.util.FoodStats;
  20. import net.minecraft.util.ResourceLocation;
  21. import net.minecraft.world.Explosion;
  22. import net.minecraft.world.GameRules;
  23. import net.minecraft.world.GameType;
  24. import net.minecraft.world.IWorld;
  25. import net.minecraft.world.World;
  26. import net.minecraft.world.biome.Biome;
  27. import net.minecraft.world.biome.provider.BiomeProvider;
  28. import net.minecraft.world.biome.provider.BiomeProviderType;
  29. import net.minecraft.world.biome.provider.IBiomeProviderSettings;
  30. import net.minecraft.world.gen.feature.IFeatureConfig;
  31. import net.minecraft.world.gen.feature.structure.Structure;
  32. import net.minecraft.world.storage.WorldInfo;
  33. import net.minecraftforge.common.DimensionManager;
  34. import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
  35. import static net.minecraftforge.fml.common.ObfuscationReflectionHelper.remapName;
  36. import org.apache.logging.log4j.LogManager;
  37. public class ReflectionUtils {
  38. // -----------------------------------------------------------------------------------
  39. // helper stuff
  40. // -----------------------------------------------------------------------------------
  41. public static Method getMethod(Class c, String name, Class... pars) {
  42. try {
  43. return ObfuscationReflectionHelper.findMethod(c, name, pars);
  44. } catch(Exception ex) {
  45. LogManager.getLogger().warn(name + " - " + ex);
  46. }
  47. return null;
  48. }
  49. public static Field getField(Class c, String field) {
  50. try {
  51. Field f = c.getDeclaredField(remapName(INameMappingService.Domain.FIELD, field));
  52. f.setAccessible(true);
  53. return f;
  54. } catch(Exception ex) {
  55. LogManager.getLogger().warn(field + " - " + ex);
  56. }
  57. return null;
  58. }
  59. private static <T> void setInt(T t, Field f, int i) {
  60. try {
  61. f.setInt(t, i);
  62. } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) {
  63. LogManager.getLogger().warn(f + " - " + ex);
  64. }
  65. }
  66. private static <T> int getInt(T t, Field f, int error) {
  67. try {
  68. return f.getInt(t);
  69. } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) {
  70. LogManager.getLogger().warn(f + " - " + ex);
  71. return error;
  72. }
  73. }
  74. private static <T> void setFloat(T t, Field f, float fl) {
  75. try {
  76. f.setFloat(t, fl);
  77. } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) {
  78. LogManager.getLogger().warn(f + " - " + ex);
  79. }
  80. }
  81. private static <T> float getFloat(T t, Field f, float error) {
  82. try {
  83. return f.getFloat(t);
  84. } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) {
  85. LogManager.getLogger().warn(f + " - " + ex);
  86. return error;
  87. }
  88. }
  89. private static <T> boolean getBoolean(T t, Field f, boolean error) {
  90. try {
  91. return f.getBoolean(t);
  92. } catch(SecurityException | IllegalArgumentException | IllegalAccessException | NullPointerException ex) {
  93. LogManager.getLogger().warn(f + " - " + ex);
  94. return error;
  95. }
  96. }
  97. public static <T> T getFieldValue(Class<T> cast, Object o, Field f) {
  98. try {
  99. return (T) f.get(o);
  100. } catch(SecurityException | IllegalAccessException | IllegalArgumentException ex) {
  101. LogManager.getLogger().warn(f + " - " + ex);
  102. return null;
  103. }
  104. }
  105. public static void setFieldValue(Object instance, Field f, Object value) {
  106. try {
  107. f.set(instance, value);
  108. } catch(SecurityException | IllegalAccessException | IllegalArgumentException ex) {
  109. LogManager.getLogger().warn(f + " - " + ex);
  110. }
  111. }
  112. public static <T> T getFieldValue(Class<T> cast, Class c, Object instance, String field) {
  113. Field f = getField(c, field);
  114. if(f == null) {
  115. return null;
  116. }
  117. return getFieldValue(cast, instance, f);
  118. }
  119. // -----------------------------------------------------------------------------------
  120. // food stats
  121. // -----------------------------------------------------------------------------------
  122. private final static Field FOOD_EXHAUSTION_LEVEL = getField(FoodStats.class, "field_75126_c"); // foodExhaustionLevel
  123. public static void setExhaustion(FoodStats stats, float f) {
  124. setFloat(stats, FOOD_EXHAUSTION_LEVEL, f);
  125. }
  126. public static float getExhaustion(FoodStats stats) {
  127. return getFloat(stats, FOOD_EXHAUSTION_LEVEL, 0);
  128. }
  129. private final static Field FOOD_SATURATION_LEVEL = getField(FoodStats.class, "field_75125_b"); // foodSaturationLevel
  130. public static void setSaturation(FoodStats stats, float f) {
  131. setFloat(stats, FOOD_SATURATION_LEVEL, f);
  132. }
  133. // -----------------------------------------------------------------------------------
  134. // player stats
  135. // -----------------------------------------------------------------------------------
  136. private final static Field FLY_SPEED = getField(PlayerAbilities.class, "field_75096_f"); // flySpeed
  137. public static void setFlySpeed(PlayerAbilities cap, float f) {
  138. setFloat(cap, FLY_SPEED, f);
  139. }
  140. private final static Field WALK_SPEED = getField(PlayerAbilities.class, "field_75097_g"); // walkSpeed
  141. public static void setWalkSpeed(PlayerAbilities cap, float f) {
  142. setFloat(cap, WALK_SPEED, f);
  143. }
  144. // -----------------------------------------------------------------------------------
  145. // PlayerList
  146. // -----------------------------------------------------------------------------------
  147. private final static Method SET_GAMETYPE = getMethod(PlayerList.class, "func_72381_a",
  148. ServerPlayerEntity.class, ServerPlayerEntity.class, IWorld.class); // setPlayerGameTypeBasedOnOther
  149. public static void setPlayerGameTypeBasedOnOther(PlayerList pl, ServerPlayerEntity target, ServerPlayerEntity source, IWorld worldIn) {
  150. try {
  151. SET_GAMETYPE.invoke(pl, target, source, worldIn);
  152. } catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
  153. LogManager.getLogger().warn("setPlayerGameTypeBasedOnOther - " + ex);
  154. }
  155. }
  156. // -----------------------------------------------------------------------------------
  157. // minecraft server
  158. // -----------------------------------------------------------------------------------
  159. private final static Field COMMAND_MANAGER = getField(MinecraftServer.class, "field_195579_af"); // commandManager
  160. public static void setCommandManager(MinecraftServer server, Commands manager) {
  161. setFieldValue(server, COMMAND_MANAGER, manager);
  162. }
  163. // -----------------------------------------------------------------------------------
  164. // DimensionManager
  165. // -----------------------------------------------------------------------------------
  166. private final static Field SAVED_ENTRIES = getField(DimensionManager.class, "savedEntries"); // forge name
  167. public static void removeDimensionSaveEntry(ResourceLocation rl) {
  168. // the map seems to be always empty ...
  169. getFieldValue(Map.class, null, SAVED_ENTRIES).remove(rl);
  170. }
  171. // -----------------------------------------------------------------------------------
  172. // explosion stuff
  173. // -----------------------------------------------------------------------------------
  174. private final static Field MODE = getField(Explosion.class, "field_222260_b"); // mode
  175. private final static Field EXPLODER = getField(Explosion.class, "field_77283_e"); // exploder
  176. private final static Field SIZE = getField(Explosion.class, "field_77280_f"); // size
  177. public static void setNoBreakMode(Explosion ex) {
  178. Explosion.Mode mode = getFieldValue(Explosion.Mode.class, ex, MODE);
  179. if(mode == Explosion.Mode.DESTROY) {
  180. setFieldValue(ex, MODE, Explosion.Mode.BREAK);
  181. }
  182. }
  183. public static Entity getExploder(Explosion ex) {
  184. return getFieldValue(Entity.class, ex, EXPLODER);
  185. }
  186. public static float getSize(Explosion ex) {
  187. return getFloat(ex, SIZE, 1);
  188. }
  189. // -----------------------------------------------------------------------------------
  190. // world info
  191. // -----------------------------------------------------------------------------------
  192. private final static Field WORLD_INFO = getField(World.class, "field_72986_A"); // worldInfo
  193. public static void setWorldInfo(World w, WorldInfo info) {
  194. setFieldValue(w, WORLD_INFO, info);
  195. }
  196. // -----------------------------------------------------------------------------------
  197. // gamerule integer value
  198. // -----------------------------------------------------------------------------------
  199. private final static Field INTEGER_VALUE = getField(GameRules.IntegerValue.class, "field_223566_a"); // value
  200. public static void setIntegerValue(GameRules.IntegerValue rule, int value) {
  201. setInt(rule, INTEGER_VALUE, value);
  202. }
  203. public static <C extends IBiomeProviderSettings, T extends BiomeProvider> BiomeProviderType
  204. newBiomeProviderType(Function<C, T> factory, Function<WorldInfo, C> settingsFactory) {
  205. try {
  206. Constructor<BiomeProviderType> con = (Constructor<BiomeProviderType>) BiomeProviderType.class.getDeclaredConstructors()[0];
  207. con.setAccessible(true);
  208. return con.newInstance(factory, settingsFactory);
  209. } catch(Exception ex) {
  210. return null;
  211. }
  212. }
  213. // -----------------------------------------------------------------------------------
  214. // game type setter without update for dirty hack
  215. // -----------------------------------------------------------------------------------
  216. private final static Field GAME_TYPE = getField(PlayerInteractionManager.class, "field_73091_c");
  217. public static void setGameType(PlayerInteractionManager m, GameType type) {
  218. setFieldValue(m, GAME_TYPE, type);
  219. }
  220. // -----------------------------------------------------------------------------------
  221. // biome map
  222. // -----------------------------------------------------------------------------------
  223. private final static Field BIOME_STRUCTURE = getField(Biome.class, "field_201874_aj");
  224. public static Map<Structure<?>, IFeatureConfig> getBiomeStructures(Biome b) {
  225. return getFieldValue(Map.class, b, BIOME_STRUCTURE);
  226. }
  227. // -----------------------------------------------------------------------------------
  228. // for clearing ai
  229. // -----------------------------------------------------------------------------------
  230. private final static Field GOALS = getField(GoalSelector.class, "field_220892_d");
  231. public static Set<PrioritizedGoal> getGoals(GoalSelector gs) {
  232. return getFieldValue(Set.class, gs, GOALS);
  233. }
  234. }