Jump to content

Recommended Posts

Posted

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.

Posted
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).

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.

Posted
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.

Posted

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.

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.