Made MinestomBasicChunkLoader requires an InstanceContainer to be dynamic and simplify custom chunk implementation

This commit is contained in:
themode 2020-10-10 08:45:26 +02:00
parent b118fc717b
commit c78ee500e8
2 changed files with 32 additions and 24 deletions

View File

@ -75,12 +75,12 @@ public class InstanceContainer extends Instance {
this.storageLocation = storageLocation; this.storageLocation = storageLocation;
// Set the default chunk loader which use the instance's StorageLocation to save and load chunks
setChunkLoader(new MinestomBasicChunkLoader(storageLocation));
// Set the default chunk supplier using DynamicChunk // Set the default chunk supplier using DynamicChunk
setChunkSupplier((instance, biomes, chunkX, chunkZ) -> new DynamicChunk(instance, biomes, chunkX, chunkZ)); setChunkSupplier((instance, biomes, chunkX, chunkZ) -> new DynamicChunk(instance, biomes, chunkX, chunkZ));
// Set the default chunk loader which use the instance's StorageLocation and ChunkSupplier to save and load chunks
setChunkLoader(new MinestomBasicChunkLoader(this));
// Get instance data from the saved data if a StorageLocation is defined // Get instance data from the saved data if a StorageLocation is defined
if (storageLocation != null) { if (storageLocation != null) {
// Retrieve instance data // Retrieve instance data
@ -566,6 +566,10 @@ public class InstanceContainer extends Instance {
* Change which type of {@link Chunk} implementation to use once one needs to be loaded. * Change which type of {@link Chunk} implementation to use once one needs to be loaded.
* <p> * <p>
* Uses {@link DynamicChunk} by default. * Uses {@link DynamicChunk} by default.
* <p>
* WARNING: if you need to save this instance's chunks later,
* the code needs to be predictable for {@link IChunkLoader#loadChunk(Instance, int, int, ChunkCallback)}
* to create the correct type of {@link Chunk}. tl;dr: Need chunk save = no random
* *
* @param chunkSupplier the new {@link ChunkSupplier} of this instance, chunks need to be non-null * @param chunkSupplier the new {@link ChunkSupplier} of this instance, chunks need to be non-null
* @throws NullPointerException if {@code chunkSupplier} is null * @throws NullPointerException if {@code chunkSupplier} is null
@ -575,6 +579,17 @@ public class InstanceContainer extends Instance {
this.chunkSupplier = chunkSupplier; this.chunkSupplier = chunkSupplier;
} }
/**
* Get the current {@link ChunkSupplier}.
* <p>
* You shouldn't use it to generate a new chunk, but as a way to view which one is currently in use.
*
* @return the current {@link ChunkSupplier}
*/
public ChunkSupplier getChunkSupplier() {
return chunkSupplier;
}
/** /**
* Get all the {@link SharedInstance} linked to this container * Get all the {@link SharedInstance} linked to this container
* *

View File

@ -8,44 +8,35 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* A {@link IChunkLoader} used by default by {@link InstanceContainer} * A {@link IChunkLoader} used by {@link InstanceContainer}
* which is based on the {@link StorageLocation} associated to it * which is based on the {@link StorageLocation} and {@link ChunkSupplier} associated to it.
* <p> * <p>
* It simply save chunk serialized data from {@link Chunk#getSerializedData()} * It simply save chunk serialized data from {@link Chunk#getSerializedData()}
* and deserialize it later with {@link Chunk#readChunk(BinaryReader, ChunkCallback)} * and deserialize it later with {@link Chunk#readChunk(BinaryReader, ChunkCallback)}.
* <p> * <p>
* The key used in the {@link StorageLocation} is defined by {@link #getChunkKey(int, int)} and should NOT be changed * The key used in the {@link StorageLocation} is defined by {@link #getChunkKey(int, int)} and should NOT be changed.
*/ */
public class MinestomBasicChunkLoader implements IChunkLoader { public class MinestomBasicChunkLoader implements IChunkLoader {
private final static Logger LOGGER = LoggerFactory.getLogger(MinestomBasicChunkLoader.class); private final static Logger LOGGER = LoggerFactory.getLogger(MinestomBasicChunkLoader.class);
private final StorageLocation storageLocation; private final InstanceContainer instanceContainer;
private final ChunkSupplier chunkSupplier;
/** /**
* Create an {@link IChunkLoader} which use a {@link StorageLocation}. * Create an {@link IChunkLoader} which use a {@link StorageLocation}.
* <p> * <p>
* The {@link ChunkSupplier} is used to customize which type of {@link Chunk} this loader should use for loading. * The {@link ChunkSupplier} is used to customize which type of {@link Chunk} this loader should use for loading.
* <p> * <p>
* WARNING: {@link Chunk} implementations do not have to have the size serializing format, be careful. * WARNING: {@link Chunk} implementations do not need to have the same serializing format, be careful.
* *
* @param storageLocation the {@link StorageLocation} * @param instanceContainer the {@link InstanceContainer} linked to this loader
* @param chunkSupplier the {@link ChunkSupplier} executed when a chunk object needs to be created
*/ */
public MinestomBasicChunkLoader(StorageLocation storageLocation, ChunkSupplier chunkSupplier) { public MinestomBasicChunkLoader(InstanceContainer instanceContainer) {
this.storageLocation = storageLocation; this.instanceContainer = instanceContainer;
this.chunkSupplier = chunkSupplier;
}
public MinestomBasicChunkLoader(StorageLocation storageLocation) {
this(storageLocation, (instance, biomes, chunkX, chunkZ) ->
new DynamicChunk(instance, biomes, chunkX, chunkZ)
);
} }
@Override @Override
public void saveChunk(Chunk chunk, Runnable callback) { public void saveChunk(Chunk chunk, Runnable callback) {
final StorageLocation storageLocation = instanceContainer.getStorageLocation();
if (storageLocation == null) { if (storageLocation == null) {
callback.run(); callback.run();
LOGGER.warn("No storage location to save chunk!"); LOGGER.warn("No storage location to save chunk!");
@ -75,6 +66,7 @@ public class MinestomBasicChunkLoader implements IChunkLoader {
@Override @Override
public boolean loadChunk(Instance instance, int chunkX, int chunkZ, ChunkCallback callback) { public boolean loadChunk(Instance instance, int chunkX, int chunkZ, ChunkCallback callback) {
final StorageLocation storageLocation = instanceContainer.getStorageLocation();
final byte[] bytes = storageLocation == null ? null : storageLocation.get(getChunkKey(chunkX, chunkZ)); final byte[] bytes = storageLocation == null ? null : storageLocation.get(getChunkKey(chunkX, chunkZ));
if (bytes == null) { if (bytes == null) {
@ -83,8 +75,9 @@ public class MinestomBasicChunkLoader implements IChunkLoader {
} else { } else {
// Found, load from result bytes // Found, load from result bytes
BinaryReader reader = new BinaryReader(bytes); BinaryReader reader = new BinaryReader(bytes);
Chunk chunk = chunkSupplier.getChunk(instance, null, chunkX, chunkZ); // Create the chunk object using the instance's ChunkSupplier to support multiple implementations
// Execute the callback once all blocks are placed (allow for multithreaded implementation) Chunk chunk = instanceContainer.getChunkSupplier().getChunk(instance, null, chunkX, chunkZ);
// Execute the callback once all blocks are placed (allow for multithreaded implementations)
chunk.readChunk(reader, callback); chunk.readChunk(reader, callback);
return true; return true;
} }