tommyte Posted April 7, 2017 Posted April 7, 2017 Hello there, I am trying to create a multiblock structure, which will have to disassemble when the world(or the chunk it is in) unloads. I am trying to use events for this, because I'd like my multiblock to be independant of tileentities, which is more of a challnge for me than something functional. Anyways, loading it seems to work fine, but unloading is an issue. Event class: package com.tommyte.skymod.main; import java.util.ArrayList; import java.util.List; import java.util.Set; import com.google.common.collect.ImmutableMultiset; import com.tommyte.skymod.multiblocks.Multiblock; import net.minecraft.client.Minecraft; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; public class SkyblockWorldEvent { @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { onLoad(event.getWorld(), event.getChunk().xPosition, event.getChunk().zPosition); } @SubscribeEvent public void onWorldload(WorldEvent.Load event) { ChunkPos[] key = event.getWorld().getPersistentChunks().keys().toArray(new ChunkPos[]{}); for(int i = 0; i < key.length; i++) { onLoad(event.getWorld(), key[i].chunkXPos, key[i].chunkZPos); } } private void onLoad(World worldIn, int x, int z) { NBTTagCompound[] nbtArray = WorldSavedData.get(worldIn).getMultiblocksInChunk(x, z); System.out.println("load"); for(int i = 0; i < nbtArray.length; i++) { Multiblock.multiblockCreate(worldIn, nbtArray[i]); } } @SubscribeEvent public void onChunkUnload(ChunkEvent.Unload event) { onUnload(event.getWorld(), event.getChunk().xPosition, event.getChunk().zPosition); } @SubscribeEvent public void onWorldUnload(WorldEvent.Unload event) { System.out.println("duut"); ChunkPos[] key = event.getWorld().getPersistentChunks().keys().toArray(new ChunkPos[]{}); for(int i = 0; i < key.length; i++) { onUnload(event.getWorld(), key[i].chunkXPos, key[i].chunkZPos); } } private void onUnload(World worldIn, int x, int z) { System.out.println("unload"); NBTTagCompound nbt = WorldSavedData.get(worldIn).getNBT(); if(nbt.hasKey(WorldSavedData.getStringFromChunk(x, z))) { NBTTagCompound chunkTag = nbt.getCompoundTag(WorldSavedData.getStringFromChunk(x, z)); for(int i = 0; i < chunkTag.getKeySet().size(); i++) { Multiblock block = Multiblock.multiblocks.get(chunkTag.getKeySet().toArray(new BlockPos[]{})[i]); block.markMultiblockDestroy(); } } } } So, how should I detect which chunks are still loaded (and should be unloaded) when the world is unloading. Then I can save my multiblock to the chunk. Also, I have no idea what 'getPersistentChunks()' really is, so it might help if someone would explain that too (: Thanks! ps. the console prints 'duut', but not 'unload', so it probably has to do with getPersistentChunks().keys().toArray(new ChunkPos[]{}); returning an empty array. Quote
Draco18s Posted April 7, 2017 Posted April 7, 2017 1 hour ago, tommyte said: so it probably has to do with getPersistentChunks().keys().toArray(new ChunkPos[]{}); returning an empty array. Persistent chunks are chunks that persist, i.e. are chunkloaded so that they NEVER unload unless the game is shutting down. So yes, that array would be empty. If you want to check for chunk unloading, subscribe to the ChunkEvent / ChunkDataEvent events (there's at least three between those that will be of interest). 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.
tommyte Posted April 7, 2017 Author Posted April 7, 2017 18 minutes ago, Draco18s said: If you want to check for chunk unloading, subscribe to the ChunkEvent / ChunkDataEvent events (there's at least three between those that will be of interest). But 'ChunkEvent.Unload' doesn't seem to fire when I close the world. This is a problem for me. I'll try to use 'WorldEvent.Unload' at the same time. Maybe that will work. Quote
tommyte Posted April 7, 2017 Author Posted April 7, 2017 Alright, I think I got a problem with NBT now. It doesn't seem to save very well. Gets called after initialization of the Multiblock public void writeToNBT() { NBTTagCompound compound = WorldSavedData.get(worldObj).getNBTForBlock(worldObj.getChunkFromBlockCoords(pos).xPosition, worldObj.getChunkFromBlockCoords(pos).zPosition, pos); compound.setIntArray("pos", new int[]{pos.getX(), pos.getY(), pos.getZ()}); compound.setInteger("facing", facing.getIndex()); compound.setString("id", classToNameMap.get(this.getClass())); WorldSavedData.get(worldObj).say(worldObj.getChunkFromBlockCoords(pos).xPosition, worldObj.getChunkFromBlockCoords(pos).zPosition); WorldSavedData.get(worldObj).markDirty(); } WorldSavedData: package com.tommyte.skymod.main; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import javax.annotation.Nullable; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.storage.MapStorage; public class WorldSavedData extends net.minecraft.world.WorldSavedData{ private NBTTagCompound worldData = new NBTTagCompound(); private String tagKey = new String("savedData"); private Hashtable<int[], String> chunks = new Hashtable<int[], String>(); public WorldSavedData() { super(Main.MODID + "_saved_data"); } @Override public void readFromNBT(NBTTagCompound nbt) { worldData = nbt.getCompoundTag(tagKey); } @Override public NBTTagCompound writeToNBT(NBTTagCompound compound) { compound.setTag(tagKey, worldData); return compound; } public NBTTagCompound getNBT() { return worldData; } public NBTTagCompound getNBTForBlock(int x, int z, BlockPos pos) { if(!worldData.hasKey(getStringFromChunk(x, z))) { worldData.setTag(getStringFromChunk(x, z), new NBTTagCompound()); } NBTTagCompound chunkTag = (NBTTagCompound) worldData.getTag(getStringFromChunk(x, z)); if(!chunkTag.hasKey(getStringFromPos(pos))) { chunkTag.setTag(getStringFromPos(pos), new NBTTagCompound()); } NBTTagCompound posTag = (NBTTagCompound) chunkTag.getTag(getStringFromPos(pos)); System.out.println(posTag); return posTag; } public NBTTagCompound[] getMultiblocksInChunk(int CX, int CZ) { List<NBTTagCompound> compound = new ArrayList<NBTTagCompound>(); if(worldData.hasKey(getStringFromChunk(CX, CZ))) { System.out.println("yes 1"); NBTTagCompound chunkTag = worldData.getCompoundTag(getStringFromChunk(CX, CZ)); for(int i = 0; i < chunkTag.getKeySet().size(); i++) { compound.add(chunkTag.getKeySet().toArray(new NBTTagCompound[]{})[i]); } } return compound.toArray(new NBTTagCompound[]{}); } public static String getStringFromPos(BlockPos pos) { return "blockpos: "+pos.getX()+"_"+pos.getY()+"_"+pos.getZ(); } public static BlockPos getPosFromString(String string) { int x = Integer.parseInt(string.substring(13, 14)); int y = Integer.parseInt(string.substring(15, 16)); int z = Integer.parseInt(string.substring(16, 17)); return new BlockPos(x,y,z); } public static String getStringFromChunk(int x, int z) { return "chunkpos: "+x+"_"+z; } public static int[] getChunkFromString(String string) { int x = Integer.parseInt(string.substring(12, 13)); int z = Integer.parseInt(string.substring(14, 15)); return new int[]{x,z}; } public static WorldSavedData get(World worldIn) { MapStorage storage = worldIn.getMapStorage(); WorldSavedData instance = (WorldSavedData) storage.getOrLoadData(WorldSavedData.class, "TSkyBlock"); if (instance == null) { instance = new WorldSavedData(); storage.setData("TSkyBlock", instance); } return instance; } public void say(int x, int z) { for(int i = 0; i < worldData.getKeySet().size(); i ++) { System.out.println(worldData.getKeySet().toArray(new String[]{})[i]); for(int j = 0; j < ((NBTTagCompound) worldData.getTag(worldData.getKeySet().toArray(new String[]{})[i])).getKeySet().size(); j++) { System.out.println(((NBTTagCompound) worldData.getTag(worldData.getKeySet().toArray(new String[]{})[i])).getKeySet().toArray(new String[]{})[j]); } } if(worldData.hasKey(getStringFromChunk(x,z))) { System.out.println("yes 2"); } } } EventClass: package com.tommyte.skymod.main; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import com.google.common.collect.ImmutableMultiset; import com.tommyte.skymod.multiblocks.Multiblock; import net.minecraft.client.Minecraft; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class SkyblockWorldEvent { @SubscribeEvent public void onChunkLoad(ChunkEvent.Load event) { if(!event.getWorld().isRemote) { NBTTagCompound[] compounds = WorldSavedData.get(event.getWorld()).getMultiblocksInChunk(event.getChunk().xPosition, event.getChunk().zPosition); for(int i = 0; i < compounds.length; i ++) { System.out.println(compounds[i]); Multiblock.multiblockCreate(event.getWorld(), compounds[i]); } } } @SubscribeEvent public void onChunkUnload(ChunkEvent.Unload event) { if(!event.getWorld().isRemote) { NBTTagCompound[] compounds = WorldSavedData.get(event.getWorld()).getMultiblocksInChunk(event.getChunk().xPosition, event.getChunk().zPosition); for(int i = 0; i < compounds.length; i ++) { System.out.println(compounds); BlockPos pos = new BlockPos(compounds[i].getIntArray("pos")[0], compounds[i].getIntArray("pos")[1], compounds[i].getIntArray("pos")[2]); Multiblock.multiblocks.get(pos).markMultiblockDestroy(); } } } @SubscribeEvent public void onWorldUnload(WorldEvent.Unload event) { Collection<Multiblock> collection = Multiblock.multiblocks.values(); for(int i = 0; i < collection.size(); i++) { System.out.println(WorldSavedData.get(event.getWorld()).getNBT().getKeySet()); ((Multiblock)collection.toArray()[i]).markMultiblockDestroy(); } } } After the Multiblock is initialized, the say(x,z) method does print everything in there. So a tag has been created and filled. But.. When I reload my world, I basically get no feedback, so my data seems to be empty again. Quote
tommyte Posted April 8, 2017 Author Posted April 8, 2017 I got it! Turns out I was saving to and loading from a different tag. Thx! 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.