JimiIT92 Posted September 1, 2015 Posted September 1, 2015 As by title, i don't know how to use reflection to change a vanilla value. In my particular case i need to change this values swingProgressInt from the EntityLivingBase class to make a faster animation when using a specific item (in my case a Katana). I tried this code Field field; try { field = Class.forName("net.minecraft.entity.EntityLivingBase").getDeclaredField("swingProgressInt"); field.setAccessible(true); field.setInt(arg0, 4); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } but i don't understand what to type in as arg0. The function takes an Object and an int. the in value is the new value of the variable i guess but the object i don't understand what it is Quote Don't blame me if i always ask for your help. I just want to learn to be better
JimiIT92 Posted September 1, 2015 Author Posted September 1, 2015 Someone in another post told me to do that Anyway i tried changing that value in the function by doing attacker.swingProgressInt = 2; but it doesn't affect the animation (is neither slower or faster) Quote Don't blame me if i always ask for your help. I just want to learn to be better
JimiIT92 Posted September 1, 2015 Author Posted September 1, 2015 Ok, so i've overrited this method @Override public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) { player.swingProgressInt = 1; return this.hitEntity(stack, (EntityLivingBase) entity, player); } and my katana is faster (wich is what i want), BUT if i hit an entity it doesn't deal damage Quote Don't blame me if i always ask for your help. I just want to learn to be better
LordMastodon Posted September 1, 2015 Posted September 1, 2015 Perhaps try adding super.onLeftClickEntity. Not sure if that'll work, but try it. Quote Who are you? Why have you brought me here? And why are there so many PewDiePie fanboys surrounding meeeeeeeee....... *falls into pit and dies*. Also this. Check it out. http://i.imgur.com/J4rrGt6.png[/img]
JimiIT92 Posted September 1, 2015 Author Posted September 1, 2015 Ok, so i've looked into the super method wich is only a return false statement. So i changed my function to this and it worked @Override public boolean onLeftClickEntity(ItemStack stack, EntityPlayer player, Entity entity) { player.swingProgressInt = 3; return false; } Also fun fact: it seems that i can make my item only faster but not slower. Quote Don't blame me if i always ask for your help. I just want to learn to be better
LordMastodon Posted September 1, 2015 Posted September 1, 2015 What about decimal values or negative numbers? Quote Who are you? Why have you brought me here? And why are there so many PewDiePie fanboys surrounding meeeeeeeee....... *falls into pit and dies*. Also this. Check it out. http://i.imgur.com/J4rrGt6.png[/img]
JimiIT92 Posted September 1, 2015 Author Posted September 1, 2015 Negative numbers makes my katana to not swing at all. I think that the exact value to set could be find in ths function private int getArmSwingAnimationEnd() { return this.isPotionActive(Potion.digSpeed) ? 6 - (1 + this.getActivePotionEffect(Potion.digSpeed).getAmplifier()) * 1 : (this.isPotionActive(Potion.digSlowdown) ? 6 + (1 + this.getActivePotionEffect(Potion.digSlowdown).getAmplifier()) * 2 : 6); } but since is a private function i can't access that to see what value it returns. I tried using the exact value that is supposed to return if the haste or slowdown effect is applied (level 1) (5 for digSpeed and 8 for digSlowdown) but nothing happens (instead with a value of 5 the katana do a weird animation). Quote Don't blame me if i always ask for your help. I just want to learn to be better
jeffryfisher Posted September 1, 2015 Posted September 1, 2015 Although you're no longer using reflection, I'd like to clarify something from your OP. You had this: try { field = Class.forName("net.minecraft.entity.EntityLivingBase").getDeclaredField("swingProgressInt"); field.setAccessible(true); field.setInt(arg0, 4); } catch... If I understand reflection correctly, then it is only necessary to getDeclaredField once and setAccessible once (perhaps in a constructor). Later, one may use the field to operate upon instances of its class to make value assignments many times. Do I have that right? Quote The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.
Failender Posted September 1, 2015 Posted September 1, 2015 Although you're no longer using reflection, I'd like to clarify something from your OP. You had this: try { field = Class.forName("net.minecraft.entity.EntityLivingBase").getDeclaredField("swingProgressInt"); field.setAccessible(true); field.setInt(arg0, 4); } catch... If I understand reflection correctly, then it is only necessary to getDeclaredField once and setAccessible once (perhaps in a constructor). Later, one may use the field to operate upon instances of its class to make value assignments many times. Do I have that right? yes. Quote
ItsAMysteriousYT Posted September 2, 2015 Posted September 2, 2015 There is an easier way made by forge. Its called ObfuscationReflectionHelper. In there use the methods getPrivateValue/setPrivatevalue etc Quote
JimiIT92 Posted September 2, 2015 Author Posted September 2, 2015 Understand, thank you Quote Don't blame me if i always ask for your help. I just want to learn to be better
ItsAMysteriousYT Posted September 2, 2015 Posted September 2, 2015 Why not? Whats so bad about it? Quote
coalbricks Posted January 11, 2021 Posted January 11, 2021 (edited) Replying for future modders. ObfuscationReflectionHelper is perfectly fine if you use it efficiently. You can use it to get a Field object, which you can store in a static member. Example: public class Example { private static Field someField = null; static { try { someField = ObfuscationReflectionHelper.findField(SomeMinecraftClass.class, "field_12345_a"); // You need to pass the SRG name someField.setAccessible(true); } catch (Exception e) { e.printStackTrace(); } } public void doStuff(SomeMinecraftClass minecraftThing) { try { Object o = someField.get(minecraftThing); } catch (Exception e) { e.printStackTrace(); } } } I would also advise against passing the fully qualified class name as a String if you can help it. It's better to use the Class object directly if you can, and in most cases you can. You can find SRG names at http://mcpbot.bspk.rs/ Edited January 11, 2021 by coalbricks Added link to MCPBot site Quote
coalbricks Posted January 11, 2021 Posted January 11, 2021 (edited) 12 hours ago, diesieben07 said: Your exception handling is inexcusable. This is not how you handle exceptions. The Field should be stored in a static final field, to allow further JVM optimizations. 1. It's a basic example. And that exception handling is fine for the purposes of being a basic example. It's also fine in production code in certain cases which I don't want to debate here, although I will admit the doStuff() function should have a null guard. 2. Yes while it would be better to store it in a static final field, the JVM optimizations obtained by making the member final are minimal at best, unless the field is being used to perform reflective gets/sets frequently. This pattern works perfectly fine in MOST cases but if you really care you can separate the static initializer logic into a separate function and make the field final; in most cases it's just not worth the trouble. Edited January 11, 2021 by coalbricks Added a note about final fields Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.