<commit_before>package de.domisum.exziff.world;

import de.domisum.exziff.world.block.Block;
import de.domisum.exziff.world.chunkclusterstorage.ChunkClusterStorage;
import lombok.Getter;
import lombok.Setter;

public class World
{

	// CONSTANTS
	private static final int CHUNK_CLUSTER_RADIUS = 64+4;

	// DATA
	private final ChunkClusterField clusterField = new ChunkClusterField(CHUNK_CLUSTER_RADIUS);

	// REFERENCES
	@Setter
	private ChunkClusterStorage chunkClusterStorage;

	// SETTINGS
	/**
	 * A ChunkCluster takes up at least 32MiB of memory.
	 * <p>
	 * Assuming no BlockAttributes:
	 * 128 ChunkClusters ^= 4 GiB
	 * 256 ChunkClusters ^= 8 GiB
	 * 512 ChunkClusters ^= 16 GiB
	 */
	@Getter
	@Setter
	private int maximumLoadedChunkClusters = 128;


	// INIT
	public World(ChunkClusterStorage chunkClusterStorage)
	{
		this.chunkClusterStorage = chunkClusterStorage;
	}


	// GETTERS
	public Block getBlock(int x, int y, int z)
	{
		if((y < 0) || (y >= Chunk.HEIGHT))
			throw new IllegalArgumentException("supplied y value is out of bounds: "+y);

		Chunk chunk = getChunkAt(x, z);
		int icX = getInChunkXOrZ(x);
		int icZ = getInChunkXOrZ(z);

		return chunk.getBlock(icX, y, icZ);
	}


	// SETTERS
	public void setBlock(int x, int y, int z, Block block)
	{
		if((y < 0) || (y >= Chunk.HEIGHT))
			throw new IllegalArgumentException("supplied y value is out of bounds: "+y);

		Chunk chunk = getChunkAt(x, z);
		int icX = getInChunkXOrZ(x);
		int icZ = getInChunkXOrZ(z);

		chunk.setBlock(icX, y, icZ, block);
	}


	// CHUNK AND CLUSTER
	private Chunk getChunkAt(int x, int z)
	{
		int cX = getChunkXorZ(x);
		int cZ = getChunkXorZ(z);

		int clX = getChunkClusterXorZ(cX);
		int clZ = getChunkClusterXorZ(cZ);
		ChunkCluster chunkCluster = getChunkCluster(clX, clZ);

		int iclX = getInChunkClusterXorZ(cX);
		int iclZ = getInChunkClusterXorZ(cZ);

		Chunk chunk = chunkCluster.getChunk(iclX, iclZ);
		return chunk;
	}

	private ChunkCluster getChunkCluster(int clX, int clZ)
	{
		ChunkCluster chunkCluster = clusterField.getCluster(clX, clZ);

		// chunk cluster not loaded, loading it
		if(chunkCluster == null)
			chunkCluster = loadChunkCluster(clX, clZ);

		return chunkCluster;
	}


	// LOADING/SAVING
	private ChunkCluster loadChunkCluster(int clX, int clZ)
	{
		// if number of currently loaded chunk clusters is too high, unload
		while(clusterField.getClusterList().size() >= maximumLoadedChunkClusters)
			unloadLongestUnusedChunkCluster();

		ChunkCluster chunkCluster = chunkClusterStorage.loadChunkCluster(clX, clZ);

		// chunk cluster not saved to disk, create new chunk cluster
		if(chunkCluster == null)
			chunkCluster = new ChunkCluster(clX, clZ);

		clusterField.addCluster(chunkCluster);
		return chunkCluster;
	}

	private void unloadLongestUnusedChunkCluster()
	{
		ChunkCluster longestUnusedChunkCluster = clusterField.getLongestUnusedChunkCluster();

		chunkClusterStorage.saveChunkCluster(longestUnusedChunkCluster);
		clusterField.removeCluster(longestUnusedChunkCluster);
	}

	public void save()
	{
		for(ChunkCluster cluster : clusterField.getClusterList())
			chunkClusterStorage.saveChunkCluster(cluster);
	}


	// INTERNAL CALCULATIONS
	private static int getChunkClusterXorZ(int cXorZ)
	{
		return getContainerXorZ(cXorZ, ChunkCluster.WIDTH);
	}

	private static int getInChunkClusterXorZ(int cXorZ)
	{
		return getInContainerXorZ(cXorZ, ChunkCluster.WIDTH);<commit_msg>Increased ChunkCluster field size<commit_after>package de.domisum.exziff.world;

import de.domisum.exziff.world.block.Block;
import de.domisum.exziff.world.chunkclusterstorage.ChunkClusterStorage;
import lombok.Getter;
import lombok.Setter;

public class World
{

	// CONSTANTS
	private static final int CHUNK_CLUSTER_RADIUS = 256+16;

	// DATA
	private final ChunkClusterField clusterField = new ChunkClusterField(CHUNK_CLUSTER_RADIUS);

	// REFERENCES
	@Setter
	private ChunkClusterStorage chunkClusterStorage;

	// SETTINGS
	/**
	 * A ChunkCluster takes up at least 32MiB of memory.
	 * <p>
	 * Assuming no BlockAttributes:
	 * 128 ChunkClusters ^= 4 GiB
	 * 256 ChunkClusters ^= 8 GiB
	 * 512 ChunkClusters ^= 16 GiB
	 * 1024 ChunkClusters ^= 32 GiB
	 */
	@Getter
	@Setter
	private int maximumLoadedChunkClusters = 128;


	// INIT
	public World(ChunkClusterStorage chunkClusterStorage)
	{
		this.chunkClusterStorage = chunkClusterStorage;
	}


	// GETTERS
	public Block getBlock(int x, int y, int z)
	{
		if((y < 0) || (y >= Chunk.HEIGHT))
			throw new IllegalArgumentException("supplied y value is out of bounds: "+y);

		Chunk chunk = getChunkAt(x, z);
		int icX = getInChunkXOrZ(x);
		int icZ = getInChunkXOrZ(z);

		return chunk.getBlock(icX, y, icZ);
	}


	// SETTERS
	public void setBlock(int x, int y, int z, Block block)
	{
		if((y < 0) || (y >= Chunk.HEIGHT))
			throw new IllegalArgumentException("supplied y value is out of bounds: "+y);

		Chunk chunk = getChunkAt(x, z);
		int icX = getInChunkXOrZ(x);
		int icZ = getInChunkXOrZ(z);

		chunk.setBlock(icX, y, icZ, block);
	}


	// CHUNK AND CLUSTER
	private Chunk getChunkAt(int x, int z)
	{
		int cX = getChunkXorZ(x);
		int cZ = getChunkXorZ(z);

		int clX = getChunkClusterXorZ(cX);
		int clZ = getChunkClusterXorZ(cZ);
		ChunkCluster chunkCluster = getChunkCluster(clX, clZ);

		int iclX = getInChunkClusterXorZ(cX);
		int iclZ = getInChunkClusterXorZ(cZ);

		Chunk chunk = chunkCluster.getChunk(iclX, iclZ);
		return chunk;
	}

	private ChunkCluster getChunkCluster(int clX, int clZ)
	{
		ChunkCluster chunkCluster = clusterField.getCluster(clX, clZ);

		// chunk cluster not loaded, loading it
		if(chunkCluster == null)
			chunkCluster = loadChunkCluster(clX, clZ);

		return chunkCluster;
	}


	// LOADING/SAVING
	private ChunkCluster loadChunkCluster(int clX, int clZ)
	{
		// if number of currently loaded chunk clusters is too high, unload
		while(clusterField.getClusterList().size() >= maximumLoadedChunkClusters)
			unloadLongestUnusedChunkCluster();

		ChunkCluster chunkCluster = chunkClusterStorage.loadChunkCluster(clX, clZ);

		// chunk cluster was not saved on disk, create new chunk cluster
		if(chunkCluster == null)
			chunkCluster = new ChunkCluster(clX, clZ);

		clusterField.addCluster(chunkCluster);
		return chunkCluster;
	}

	private void unloadLongestUnusedChunkCluster()
	{
		ChunkCluster longestUnusedChunkCluster = clusterField.getLongestUnusedChunkCluster();

		chunkClusterStorage.saveChunkCluster(longestUnusedChunkCluster);
		clusterField.removeCluster(longestUnusedChunkCluster);
	}

	public void save()
	{
		for(ChunkCluster cluster : clusterField.getClusterList())
			chunkClusterStorage.saveChunkCluster(cluster);
	}


	// INTERNAL CALCULATIONS
	private static int getChunkClusterXorZ(int cXorZ)
	{
		return getContainerXorZ(cXorZ, ChunkCluster.WIDTH);
	}

	private static int getInChunkClusterXorZ(int cXorZ)
	{
		return getInContainerXorZ(cXorZ, ChunkCluster.WIDTH);
{'fraction_non_alphanumeric': 0.09705498331640795, 'fraction_numerical': 0.007834034527781808, 'mean_word_length': 4.591240875912408, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3307060', 'n_tokens_mistral': 2598, 'n_tokens_neox': 2357, 'n_words': 573}