kauan99 Posted March 6, 2016 Posted March 6, 2016 How do I save that hash map? or does the game has already a map of all TileEntity instances in game (i mean instances, not classes)? If this is the case all I need is to instantiate and populate the hash map when the server starts. Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
Failender Posted March 6, 2016 Posted March 6, 2016 Why do you need that? You can use WorldSaveddata, but I'm not sure if it exists in 1.7 But you can still use plain java and save it as file Quote
Choonster Posted March 6, 2016 Posted March 6, 2016 You can probably take a similar approach to the one I recommended in this thread. Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 You can probably take a similar approach to the one I recommended in this thread. Looks like exactly what I need. I'll try to implement and then I'll let you know if it worked. Thanks. Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 A few doubts: Block#onBlockAdded is invoked whenever a block is placed in the world, no matter by what means (during game loading, during world generation, or if a player or machine or whatever adds the block). Is this correct? I need to add a TileEntity to my HashMap<String, TileEntity>. Is it correct to assume the TileEntity is already in place when Block#onBlockAdded is invoked? Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
Choonster Posted March 6, 2016 Posted March 6, 2016 Block#onBlockAdded is invoked whenever a block is placed in the world, no matter by what means (during game loading, during world generation, or if a player or machine or whatever adds the block). Is this correct? Yes, it's called by Chunk#setBlockIDWithMetadata , which is called by World#setBlock . This is used to place blocks in the world by everything except the initial terrain generation ( BiomeGenBase#genTerrainBlocks ), which deals with raw Block and metadata arrays that later become an actual Chunk . I need to add a TileEntity to my HashMap<String, TileEntity>. Is it correct to assume the TileEntity is already in place when Block#onBlockAdded is invoked? No, the TileEntity is only created after Block#onBlockAdded is called. If you use per-dimension WorldSavedData , you can store the positions of each block instead of the TileEntity objects. Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 I have 2 types of TileEntities: one inserts items into a nearby inventory, the other extracts from a nearby inventory and sends to the inserter so it can put the items into it's inventory. The player can configure which inserter the extractor is paired with by name: they give a name to the inserter and also tell the extractor the name of its inserter counterpart. I need to keep a dictionary of inserters by name for this to work. Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 WorldSavedData would be a good approach for that, like Failender already pointed out. Keep a record of which names point to which coordinates (not TileEntity instances!) for both sender and receiver. Then when you need to send you can go grab the coords and check if the chunk holding the remote part is loaded and if so grab the TE there. Yes, that's what I thought would be the solution. Thanks everyone. Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 Is WorldSavedData available when TileEntity#readFromNBT is invoked? Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
Choonster Posted March 6, 2016 Posted March 6, 2016 Is WorldSavedData available when TileEntity#readFromNBT is invoked? WorldSavedData is loaded on demand and should be available as soon as the World has been constructed, but TileEntity#readFromNBT is called before the TileEntity exists in any World . Quote Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 ok. So I need to add the x,y,z position of my Block to my HashMap<String, Position> field in my custom WorldSavedData , and for that I should use Block#onBlockAdded . But I have no access to the user given name of each particular TileEntity instance. That name should serve as the key of the HashMap . I can't see how to make this work. I probably need to invoke MyWorldData#add from somewhere else, but because I don't know the inner workings of Minecraft I can't figure out where. class MyWorldData extends WorldSavedData { private HashMap<String, Position> map = new HashMap<>(); public static MyWorldData get(World world) { MapStorage storage = world.perWorldStorage; MyWorldDatainstance = (MyWorldData) storage.loadData(MyWorldData.class, "myworlddata"); if (instance == null) { instance = new MyWorldData(); storage.setData("myworlddata", instance); } return instance; } public boolean add(String key, int x, int y, int z) { if(key == null || key.length() < 1) { return false; } if(!map.containsKey(key)) { map.put(key, new Position(x, y, z)); this.markDirty(); return true; } else { return false; } } public boolean rename(String key, String newKey) { if(key == null || key.length() < 1 || newKey == null || newKey.length() < 1) { return false; } Position pos = map.remove(key); if(pos == null) { return false; } else { map.put(newKey, pos); this.markDirty(); return true; } } public Position get(String key) { return map.get(key); } public Position remove(String key) { Postition pos = map.remove(key); if(pos != null) this.markDirty(); return pos; } } class MyBlock implements ITileEntityProvider { @Override public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) { return new MyTileEntity(); } @Override public void onBlockAdded(World world, int x, int y, int z) { super.onBlockAdded(world, x, y, z); MyWorldData wd = MyWorldData.get(world); wd.add(, x, y, z);//there's no name to add } } Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 How is the name of a block determined? The player chooses it via GUI Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 Because the player only needs to set the name once. Then it's supposed to be saved forever, unless the player wants to change it. I want to persist the HashMap<String, Position> through game sessions. Is there a better method I can use so I can have direct access to the TileEntity? Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
kauan99 Posted March 6, 2016 Author Posted March 6, 2016 Yes but I'm not sure how it works. Currently, after what you said, I'm gonna try this approach: class MyWorldData extends WorldSavedData { private static final HashMap<String, Position> map = new HashMap<String, Position>(); public MyWorldData () { super("myworlddata"); } public MyWorldData (String s) { super(s); } public static MyWorldData get(World world) { MapStorage storage = world.perWorldStorage; MyWorldData instance = (MyWorldData) storage.loadData(MyWorldData .class, "myworlddata"); if (instance == null) { instance = new MyWorldData(); storage.setData("myworlddata", instance); } return instance; } @Override public void readFromNBT(NBTTagCompound nbt) { map.clear(); NBTTagList list = nbt.getTagList("map", NBT.TAG_COMPOUND); int listSize = list.tagCount(); for(int i = 0; i < listSize; ++i) { NBTTagCompound listItem = list.getCompoundTagAt(i); String key= listItem.getString("key"); int x = listItem.getInteger("x"); int y = listItem.getInteger("y"); int z = listItem.getInteger("z"); Position pos = new Position(x, y, z); map.put(name, pos); } } @Override public void writeToNBT(NBTTagCompound nbt) { NBTTagList list = new NBTTagList(); map.forEach((name, pos) -> { NBTTagCompound listItem = new NBTTagCompound(); listItem.setString("name", name); listItem.setInteger("x", pos.getX()); listItem.setInteger("y", pos.getY()); listItem.setInteger("z", pos.getZ()); list.appendTag(listItem); }); nbt.setTag("map", list); } public boolean contains(String key) { return map.containsKey(key); } public boolean add(String key, int x, int y, int z) { if(key == null || key.length() < 1) { return false; } if(!map.containsKey(key)) { map.put(key, new Position(x, y, z)); this.markDirty(); return true; } else { return false; } } public boolean rename(String key, String newKey) { if(key == null || key.length() < 1 || newKey == null || newKey.length() < 1) { return false; } Position pos = map.remove(key); if(pos == null) { return false; } else { map.put(newKey, pos); return true; } } public Position get(String key) { return map.get(key); } public Position remove(String key) { Position pos = map.remove(key); if(pos != null) this.markDirty(); return pos; } } public class MyTileEntity extends TileEntity { private String key = null; public boolean containsKey(String key) { MyWorldData wd = MyWorldData.get(this.worldObj); return wd.contains(key); } public boolean setKey(String key) { MyWorldData wd = MyWorldData.get(this.worldObj); if(wd.contains(key)) return false; if(this.key == null) { this.key = key; return wd.add(key, xCoord, yCoord, zCoord); } else { wd.rename(this.key, key); this.key = key; return true; } } public String getKey() { return this.name; } @Override public boolean canUpdate() { return false; } @Override public Packet getDescriptionPacket() { NBTTagCompound nbtTagCompound = new NBTTagCompound(); writeToNBT(nbtTagCompound); int metadata = getBlockMetadata(); return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, metadata, nbtTagCompound); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { readFromNBT(pkt.func_148857_g()); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); this.key = nbt.getString("key"); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setString("name", this.key); } public static MyTileEntity getByKey(String key, World world) { MyWorldData wd = MyWorldData .get(world); Position pos = wd.get(key); TileEntity te = world.getTileEntity(pos.getX(), pos.getY(), pos.getZ()); if(te instanceof MyTileEntity) return (MyTileEntity)te; else return null; } } I was trying to add unnamed TileEntities to my map and this was getting really complicated. Will this version of the code work now?? I only add a TileEntity to the map once the player gives it a name. One last thing: from where should I invoke WorldSavedData#remove ? Block.breakBlock ? Quote WIP mods: easyautomation, easyenergy, easyelectronics, easymoney, easytrasportation, easysecurity, easymultiverse, easyfactions, easymagick, easyalchemy, easyseasons
ZeroNoRyouki Posted March 7, 2016 Posted March 7, 2016 uhm sorry to intrude, but I really don't understand why you fell the need to save that data on disk and load it all back after a restart If the TE chunk isn't loaded you can't do anything with the TE even if you known it should be there.. or are you also implementing some sort of chunk loading on demand? Also, what do you do about "abandoned" blocks: say that a player on a server build it's sorting system with dozens of your blocks and then for some reason never use it again (he build a new base somewhere else, never log back in, etc). Are you going to keep track of his TEs forever? Just keep track of the TEs that are actually loaded in the game: they are the only ones that players can actually use Quote
Draco18s Posted March 7, 2016 Posted March 7, 2016 uhm sorry to intrude, but I really don't understand why you fell the need to save that data on disk and load it all back after a restart Probably because the block's functionality should persist after the player quits the game. Quote Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable. If you think this is the case, JUST REPORT ME. Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice. Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked. DO NOT PM ME WITH PROBLEMS. No help will be given.
ZeroNoRyouki Posted March 7, 2016 Posted March 7, 2016 uhm sorry to intrude, but I really don't understand why you fell the need to save that data on disk and load it all back after a restart Probably because the block's functionality should persist after the player quits the game. and what's preventing it? 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.