Archived
0

World <-- Region <-- Chunk Weak references

This commit is contained in:
Forwolk
2018-08-04 13:19:08 +03:00
parent d84e6ca749
commit 610981b7b8
6 changed files with 71 additions and 12 deletions

View File

@@ -47,4 +47,7 @@ public interface Chunk extends Serializable{
void setBlock(int x, int y, int z, Block block); void setBlock(int x, int y, int z, Block block);
Block getBlock(int x, int y, int z); Block getBlock(int x, int y, int z);
Region getRegion();
World getWorld();
} }

View File

@@ -30,5 +30,7 @@ public interface Region extends Serializable{
Biome getBiomeAt (int x, int z); Biome getBiomeAt (int x, int z);
void setBiome (int x, int z, Biome biome); void setBiome (int x, int z, Biome biome);
World getWorld();
void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWritter) throws IOException; void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWritter) throws IOException;
} }

View File

@@ -9,6 +9,8 @@ import mc.core.block.BlockFactory;
import mc.core.block.BlockType; import mc.core.block.BlockType;
import mc.core.world.Biome; import mc.core.world.Biome;
import mc.core.world.Chunk; import mc.core.world.Chunk;
import mc.core.world.Region;
import mc.core.world.World;
public class SimpleChunk implements Chunk { public class SimpleChunk implements Chunk {
@Override @Override
@@ -104,4 +106,14 @@ public class SimpleChunk implements Chunk {
else if (y == 3) return blockFactory.create(BlockType.GRASS, 0); else if (y == 3) return blockFactory.create(BlockType.GRASS, 0);
else return Block.airBlock(x, y, z); else return Block.airBlock(x, y, z);
} }
@Override
public Region getRegion() {
throw new UnsupportedOperationException();
}
@Override
public World getWorld() {
throw new UnsupportedOperationException();
}
} }

View File

@@ -1,16 +1,17 @@
package mc.world.generated_world.chunk; package mc.world.generated_world.chunk;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import mc.core.block.Block; import mc.core.block.Block;
import mc.core.block.BlockType; import mc.core.block.BlockType;
import mc.core.world.Biome; import mc.core.world.Biome;
import mc.core.world.Chunk; import mc.core.world.Chunk;
import mc.core.world.Region; import mc.core.world.Region;
import mc.core.world.World;
import java.lang.ref.WeakReference;
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE; import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE;
@RequiredArgsConstructor
public class ChunkImpl implements Chunk{ public class ChunkImpl implements Chunk{
@Getter @Getter
private final int x; private final int x;
@@ -19,7 +20,14 @@ public class ChunkImpl implements Chunk{
@Getter @Getter
private final int z; private final int z;
private final Block[][][] blocks = new Block[WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE]; private final Block[][][] blocks = new Block[WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE];
private final transient Region region; private final transient WeakReference<Region> region;
public ChunkImpl(int x, int y, int z, Region region) {
this.x = x;
this.y = y;
this.z = z;
this.region = new WeakReference<>(region);
}
@Override @Override
public int getBlockType(int x, int y, int z) { public int getBlockType(int x, int y, int z) {
@@ -73,12 +81,12 @@ public class ChunkImpl implements Chunk{
@Override @Override
public Biome getBiome(int x, int z) { public Biome getBiome(int x, int z) {
return region.getBiomeAt(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE); return getRegion().getBiomeAt(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE);
} }
@Override @Override
public void setBiome(int x, int z, Biome biome) { public void setBiome(int x, int z, Biome biome) {
region.setBiome(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE, biome); getRegion().setBiome(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE, biome);
} }
@Override @Override
@@ -98,4 +106,14 @@ public class ChunkImpl implements Chunk{
} }
return blocks[x][y][z]; return blocks[x][y][z];
} }
@Override
public Region getRegion() {
return region.get();
}
@Override
public World getWorld() {
return getRegion().getWorld();
}
} }

View File

@@ -3,6 +3,8 @@ package mc.world.generated_world.chunk;
import mc.core.block.Block; import mc.core.block.Block;
import mc.core.world.Biome; import mc.core.world.Biome;
import mc.core.world.Chunk; import mc.core.world.Chunk;
import mc.core.world.Region;
import mc.core.world.World;
import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -129,4 +131,16 @@ public class ChunkProxy implements Chunk {
use(); use();
return chunk.getBlock(x, y, z); return chunk.getBlock(x, y, z);
} }
@Override
public Region getRegion() {
use();
return chunk.getRegion();
}
@Override
public World getWorld() {
use();
return chunk.getWorld();
}
} }

View File

@@ -14,12 +14,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.ref.WeakReference;
import java.text.MessageFormat; import java.text.MessageFormat;
import static mc.world.generated_world.WorldConstants.*; import static mc.world.generated_world.WorldConstants.*;
@Slf4j @Slf4j
@RequiredArgsConstructor
public class RegionImpl implements Region{ public class RegionImpl implements Region{
@Getter @Getter
private final int x; private final int x;
@@ -27,18 +27,23 @@ public class RegionImpl implements Region{
private final int z; private final int z;
private final ChunkProxy[][][] chunks = new ChunkProxy[WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE]; private final ChunkProxy[][][] chunks = new ChunkProxy[WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE];
private final Biome[][] biomes = new Biome[WORLD_REGION_SIZE][WORLD_REGION_SIZE]; private final Biome[][] biomes = new Biome[WORLD_REGION_SIZE][WORLD_REGION_SIZE];
@Getter private final transient WeakReference<World> world;
private final transient World world;
@Autowired @Autowired
private ChunkLoader chunkLoader; private ChunkLoader chunkLoader;
public RegionImpl (int x, int z, World world) {
this.x = x;
this.z = z;
this.world = new WeakReference<>(world);
}
@Override @Override
public Chunk getChunkAt(int x, int y, int z) { public Chunk getChunkAt(int x, int y, int z) {
if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) { if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) {
throw new RuntimeException(MessageFormat.format("Invalid chunk coordinates [{0} {1} {2}]", x, y, z)); throw new RuntimeException(MessageFormat.format("Invalid chunk coordinates [{0} {1} {2}]", x, y, z));
} }
if (chunkLoader == null) { if (chunkLoader == null) {
chunkLoader = new InMemoryCacheChunkLoader(world); chunkLoader = new InMemoryCacheChunkLoader(getWorld());
} }
Chunk chunk = chunks[x][y][z]; Chunk chunk = chunks[x][y][z];
if (chunk == null) { if (chunk == null) {
@@ -72,10 +77,15 @@ public class RegionImpl implements Region{
biomes[x][z] = biome; biomes[x][z] = biome;
} }
@Override
public World getWorld() {
return world.get();
}
@Override @Override
public void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWriter) throws IOException { public void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWriter) throws IOException {
String worldPath = System.getProperty("worlds.folder", "worlds"); String worldPath = System.getProperty("worlds.folder", "worlds");
File worldFile = new File(worldPath, world.getWorldId().toString()); File worldFile = new File(worldPath, getWorld().getWorldId().toString());
File regionFile = new File(worldFile, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, this.getX(), this.getZ())); File regionFile = new File(worldFile, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, this.getX(), this.getZ()));
if (!regionFile.exists()) { if (!regionFile.exists()) {
regionFile.mkdirs(); regionFile.mkdirs();