The chests are probably empty because the client doesn't know what's in them. You'll likely have to re-implement the packet system that sends and receives the tile entity's inventory.
That's what I was afraid of. At this point it would probably be easier and more effective to just use ASM byte code to change the declaration of whatever field I want in the base files from private to public, which in my case is the private IInventory field for the chest in GuiChest.
That's what I was afraid of. At this point it would probably be easier and more effective to just use ASM byte code to change the declaration of whatever field I want in the base files from private to public, which in my case is the private IInventory field for the chest in GuiChest.
Would you not be able to use reflection? I know it is somewhat worse performance-wise, but you wouldn't have to deal with ASM.
Would you not be able to use reflection? I know it is somewhat worse performance-wise, but you wouldn't have to deal with ASM.
Wow! I didn't even know you could do this in compiled languages like Java (I do it all the time in JavaScript however). This was such an easy and simple solution I can't believe we had a full page of comments before someone mentioned it.
After a quick Google search I found this easy to use stack overflow post showing how to use Reflection in Java to access private variables.
If you want to know the specific code I used for my solution to get the IInventory of a chest by looking at it's GUI (GuiChest), this is the method I used:
private static IInventory GetByReflection_lowerChestInventory(GuiChest guiChest)
{
Field field = null;
try
{
//this is the deobfuscated field name - works in single player (and maybe forge servers?)
field = guiChest.getClass().getDeclaredField("lowerChestInventory");
}
catch(NoSuchFieldException e)
{
System.out.println("NoSuchFieldException");
mc.fontRenderer.drawStringWithShadow("NoSuchFieldException (lowerChestInventory)", 1, 20, 0xffffff);
e.printStackTrace();
}
if(field == null)
{
try
{
//this field obfuscated field name - it was obtained from the /mcp/conf/fields.csv file
field = guiChest.getClass().getDeclaredField("field_74219_p");
}
catch(NoSuchFieldException e)
{
System.out.println("NoSuchFieldException");
mc.fontRenderer.drawStringWithShadow("NoSuchFieldException (field_74219_p)", 1, 30, 0xffffff);
e.printStackTrace();
}
}
if(field != null)
{
field.setAccessible(true);
IInventory lowerChestInventory = null;
try
{
lowerChestInventory = (IInventory) field.get(guiChest);
}
catch (IllegalArgumentException e)
{
System.out.println("IllegalArgumentException");
mc.fontRenderer.drawStringWithShadow("IllegalArgumentException", 1, 40, 0xffffff);
e.printStackTrace();
}
catch (IllegalAccessException e)
{
System.out.println("IllegalAccessException");
mc.fontRenderer.drawStringWithShadow("IllegalAccessException", 1, 50, 0xffffff);
e.printStackTrace();
}
mc.fontRenderer.drawStringWithShadow("returning lowerChestInventory", 1, 60, 0xffffff);
return lowerChestInventory;
}
mc.fontRenderer.drawStringWithShadow("returning null", 1, 70, 0xffffff);
return null;
}
This successfully gets the inventory object and all of the ItemStacks within it, but whenever I attempt to manipulate the contents of the chest, or the players inventory while looking at my overridden GuiChest the changes are not persistent. As soon as I close the GuiChest screen the inventories revert back to what they were before.
Wow! I didn't even know you could do this in compiled languages like Java (I do it all the time in JavaScript however). This was such an easy and simple solution I can't believe we had a full page of comments before someone mentioned it.
After a quick Google search I found this easy to use stack overflow post showing how to use Reflection in Java to access private variables.
If you want to know the specific code I used for my solution to get the IInventory of a chest by looking at it's GUI (GuiChest), this is the method I used:
...
field = guiChest.getClass().getDeclaredField("lowerChestInventory");
...
It still does not work on servers, however.
That is strange that it won't work on servers, but then again, I'm not totally sure how TileEntityChest does its syncing.
Be careful with that line, too. In all likelihood, that getDeclaredField() will throw an exception and break your stuff when you try to use it outside of your devspace. The string won't get changed by the reobfuscation script, so it'll still be looking for "lowerChestInventory" when the field you want is now named something like "field_123456_a". You'll need to use getDeclaredFields() and know the index of the field you want.
I always set my code (while in my devspace) to check the name and throw an exception if the name is not what I'm looking for, so that I don't forget to update the index when fields are added/removed in front of the field I want in newer MC versions.
That's what I was afraid of. At this point it would probably be easier and more effective to just use ASM byte code to change the declaration of whatever field I want in the base files from private to public, which in my case is the private IInventory field for the chest in GuiChest.
Would you not be able to use reflection? I know it is somewhat worse performance-wise, but you wouldn't have to deal with ASM.
Wow! I didn't even know you could do this in compiled languages like Java (I do it all the time in JavaScript however). This was such an easy and simple solution I can't believe we had a full page of comments before someone mentioned it.
After a quick Google search I found this easy to use stack overflow post showing how to use Reflection in Java to access private variables.
If you want to know the specific code I used for my solution to get the IInventory of a chest by looking at it's GUI (GuiChest), this is the method I used:
This successfully gets the inventory object and all of the ItemStacks within it, but whenever I attempt to manipulate the contents of the chest, or the players inventory while looking at my overridden GuiChest the changes are not persistent. As soon as I close the GuiChest screen the inventories revert back to what they were before.
That is strange that it won't work on servers, but then again, I'm not totally sure how TileEntityChest does its syncing.
Be careful with that line, too. In all likelihood, that getDeclaredField() will throw an exception and break your stuff when you try to use it outside of your devspace. The string won't get changed by the reobfuscation script, so it'll still be looking for "lowerChestInventory" when the field you want is now named something like "field_123456_a". You'll need to use getDeclaredFields() and know the index of the field you want.
I always set my code (while in my devspace) to check the name and throw an exception if the name is not what I'm looking for, so that I don't forget to update the index when fields are added/removed in front of the field I want in newer MC versions.