AstroEngiSci Posted January 29, 2016 Share Posted January 29, 2016 I'm building a mod that, among other things, contains teleporters. The location of target teleporters is stored in punch cards. On right-click on a teleporter with a blank punch card, the blank card is replaced with a written card. Then, the location of the target teleporter is written to the written card's NBT. All of that works just fine. The problem comes when reloading the world; for whatever reason, written punch cards don't persist in inventories through a world reload. I suspect the problem lies in my implementation of NBT. I don't totally understand NBT; it makes a convenient scapegoat. The code that replaces punch cards: public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { //Get the tile entity of this teleporter TeleporterTileEntity t = (TeleporterTileEntity) worldIn.getTileEntity(pos); //Check if they're holding a blank punch card ItemStack item = playerIn.getCurrentEquippedItem(); if(item != null && item.getItem() == EnderScience.blankPunch) { //Replace with written card ItemStack card = new ItemStack(EnderScience.writtenPunch, 1); int slot = playerIn.inventory.currentItem; playerIn.replaceItemInInventory(slot, card); //Store this teleporter's coordinates in the new punch card NBTTagCompound tag = new NBTTagCompound(); tag.setString("teleporter", pos.getX() + " " + pos.getY() + " " + pos.getZ()); card.setTagCompound(tag); if(playerIn.getCurrentEquippedItem().getTagCompound() == null) System.out.println("[Ender Science]: Failed to write card's NBT."); System.out.println("[Ender Science]: Teleporter coordinates: " + tag.getString("teleporter")); return true; } else if (item != null && item.getItem() == EnderScience.writtenPunch){ //TODO: Fix teleport call t.teleport(playerIn, worldIn, item.getTagCompound().getString("teleporter")); return true; } return true; } And the base class for the written punch card: public class WrittenPunchCard extends Item { public WrittenPunchCard() { setMaxStackSize(1); setUnlocalizedName("writtenpunch"); setCreativeTab(EnderScience.tab); } @Override public void addInformation(ItemStack stack, EntityPlayer playerIn, List tooltip, boolean advanced) { tooltip.add("Coordinates: " + stack.getTagCompound().getString("teleporter")); } } The problem persists when I comment out the code that writes the teleporter coordinates to the punch card. Quote Link to comment Share on other sites More sharing options...
Ernio Posted January 29, 2016 Share Posted January 29, 2016 public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumFacing side, float hitX, float hitY, float hitZ) { if (!worldIn.isRemote) // run on server { TeleporterTileEntity t = (TeleporterTileEntity) worldIn.getTileEntity(pos); if (t != null) { ItemStack stack = playerIn.getCurrentEquippedItem(); if (stack != null && stack.getItem() == EnderScience.card) // you don't need separate items, but if you do... well, you can replace ItemStack like you did before, just do it on server. { NBTTagCompound nbt = stack.getTagCompound(); if (nbt == null) { nbt = new NBTTagCompound(); stack.setTagCompound(nbt); } if (!nbt.getBoolean("punch")) // has NBT, but not punched, so punch { nbt.setBoolean("punched", true); nbt.setInteger("x", pos.getX()); nbt.setInteger("y", pos.getY()); nbt.setInteger("z", pos.getZ()); System.out.println("[Ender Science]: Teleporter coordinates: " + pos.getX() + " / " + pos.getY() + " / " + pos.getZ()); } else // punched, teleport { t.teleport(playerIn, worldIn, nbt.getInteger("x"), nbt.getInteger("y"), nbt.getInteger("z")); // change it to 3-arg coords. } } } } return true; } Ahh... this can be done nicer.... Quote 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
coolAlias Posted January 29, 2016 Share Posted January 29, 2016 Ahh... this can be done nicer.... Lol, yeah, I'd probably try to reduce the indentation a few levels, for one public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ) { TileEntity te = world.getTileEntity(pos); ItemStack stack = player.getHeldItem(); if (!worldIn.isRemote && te instanceof TeleporterTileEntity && stack != null && stack.getItem() == EnderScience.card) { // now we're cookin' with a whole lot less mess // do all your other stuff here } } But that's not really related to your problem... your problem sounds to me like you are managing the inventory from a client-side GUI and expecting it to persist, but the client is like a dream or a ghost - it is completely ephemeral. You need to make sure that any setting you do, be it adding items to inventories or changing NBT data, is done on the server. Quote http://i.imgur.com/NdrFdld.png[/img] Link to comment Share on other sites More sharing options...
Ernio Posted January 29, 2016 Share Posted January 29, 2016 Ahh... this can be done nicer.... Lol, yeah, I'd probably try to reduce the indentation a few levels, for one This is what happens when you get back to "micro-optimization-is-bullshit-java" after finishing algorithmics project in savage C (notice how hard I tried to declare fields in smallest scopes and other mad shit and I didn't even do that well thing well - #sleepy)... Worthless code. And yeah - main point was to use world.isRemote (which he OP didn't in main post). Quote 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
AstroEngiSci Posted January 29, 2016 Author Share Posted January 29, 2016 Thank you both! I modified the system so that written punch cards have different metadata than unwritten (I want them to have different names and have distinct icons). The call for server-only fixed the persistence issue; however, I have to call my teleport code client-side for it to work. The teleport code just calls player.setPosition(). Is there some other way I should be doing this so that it works from server-side? Quote Link to comment Share on other sites More sharing options...
Ernio Posted January 29, 2016 Share Posted January 29, 2016 There should be similar method "setPositionAndUpdate" . Look into vanilla, you should find it. Quote 1.7.10 is no longer supported by forge, you are on your own. Link to comment Share on other sites More sharing options...
AstroEngiSci Posted January 30, 2016 Author Share Posted January 30, 2016 Thank you both. Quote Link to comment Share on other sites More sharing options...
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.