Archived
0

Merge branch 'forwolk/dev/location-world' into anarok/loop-3-merge

# Conflicts:
#	core/src/main/java/mc/core/Location.java
This commit is contained in:
Daniil
2018-08-05 23:10:44 +07:00
22 changed files with 470 additions and 355 deletions

View File

@@ -4,21 +4,21 @@
*/ */
package mc.core; package mc.core;
import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import mc.core.exception.ResourceUnloadedException;
import mc.core.world.Chunk; import mc.core.world.Chunk;
import mc.core.world.Region;
import mc.core.world.World;
import sun.reflect.generics.reflectiveObjects.NotImplementedException; import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.io.Serializable; import java.io.Serializable;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
@AllArgsConstructor
@Data @Data
public class Location implements Serializable{ public class Location implements Serializable{
private double x, y, z; private double x, y, z;
private Reference<World> world;
public Location(long compactValue) {
set(compactValue);
}
private static int floor_double(double value) { private static int floor_double(double value) {
int i = (int)value; int i = (int)value;
@@ -29,12 +29,36 @@ public class Location implements Serializable {
return new Location( return new Location(
location.x, location.x,
location.y, location.y,
location.z location.z,
location.getWorld()
); );
} }
public Location (double x, double y, double z, World world) {
this.x = x;
this.y = y;
this.z = z;
this.world = new WeakReference<>(world);
}
public Location (double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public static Location startPointLocation () { public static Location startPointLocation () {
return new Location(0, 10, 0); return new Location(0,10,0, null);
}
public Location(long compactValue) {
set(compactValue);
this.world = new WeakReference<>(null);
}
public Location(long compactValue, World world) {
set(compactValue);
this.world = new WeakReference<>(world);
} }
public void set(Location location) { public void set(Location location) {
@@ -53,15 +77,11 @@ public class Location implements Serializable {
return new Location( return new Location(
this.x - location.x, this.x - location.x,
this.y - location.y, this.y - location.y,
this.z - location.z this.z - location.z,
this.getWorld().equals(location.getWorld()) ? this.getWorld() : null
); );
} }
public Chunk getChunk() {
// TODO: Implement
throw new NotImplementedException();
}
public int getBlockX() { public int getBlockX() {
return (int) x; return (int) x;
} }
@@ -79,4 +99,24 @@ public class Location implements Serializable {
| ((floor_double(y) & 0xFFF) << 26) | ((floor_double(y) & 0xFFF) << 26)
| (floor_double(z) & 0x3FFFFFF); | (floor_double(z) & 0x3FFFFFF);
} }
public World getWorld () {
if (world == null) {
return null;
}
if (world.get() == null) {
throw new ResourceUnloadedException("You're trying to get unloaded world");
}
return this.world.get();
}
public void setWorld (World world) {
this.world = new WeakReference<>(world);
}
public Chunk getChunk() {
Region region = getWorld().getRegion((int) (x / 256), (int) (z / 256));
return region.getChunk((int) ((x % 256) / 16), (int) ((z % 256) / 16));
}
} }

View File

@@ -0,0 +1,12 @@
package mc.core.exception;
public abstract class McCoreUncheckedException extends RuntimeException {
public McCoreUncheckedException() {
super();
}
public McCoreUncheckedException(String msg) {
super(msg);
}
}

View File

@@ -0,0 +1,8 @@
package mc.core.exception;
public class ResourceUnloadedException extends McCoreUncheckedException {
public ResourceUnloadedException(String msg) {
super(msg);
}
}

View File

@@ -1,10 +1,10 @@
package mc.core.serialization; package mc.core.serialization;
import mc.core.world.Chunk; import mc.core.world.ChunkSection;
import mc.core.world.Region; import mc.core.world.Region;
import java.io.IOException; import java.io.IOException;
public interface IChunkReader { public interface IChunkReader {
Chunk read (Region region, int x, int y, int z) throws IOException; ChunkSection read (Region region, int x, int y, int z) throws IOException;
} }

View File

@@ -1,50 +1,12 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-04-15
*/
package mc.core.world; package mc.core.world;
import mc.core.block.Block; public interface Chunk {
import java.io.Serializable; World getWorld();
ChunkSection getChunkSection(int height);
/** ChunkSection setChunkSection(int height, ChunkSection chunkSection);
* Serialization chunk info Region getRegion();
*
* +-------------+----------------+------------+
* | param | range | bits |
* +-------------+----------------+------------+
* | blocks | array | 24*count |
* +-------------+----------------+------------+
*
* Total: 24 * block_count bits (3 * block_count bytes)
* Max size: 12288 bytes (~12 Kb per chunk)
*
*/
/* 16x16x16 */
public interface Chunk extends Serializable{
int getBlockType(int x, int y, int z);
void setBlockType(int x, int y, int z, int type);
int getBlockMetadata(int x, int y, int z);
void setBlockMetadata(int x, int y, int z, int metadata);
int getBlockLight(int x, int y, int z);
void setBlockLight(int x, int y, int z, int lightLevel);
int getSkyLight(int x, int y, int z);
void setSkyLight(int x, int y, int z, int lightLevel);
int getAddition(int x, int y, int z);
void setAddition(int x, int y, int z, int value);
Biome getBiome(int x, int z);
void setBiome(int x, int z, Biome biome);
int getX(); int getX();
int getY();
int getZ(); int getZ();
void setBlock (int x, int y, int z, Block block);
Block getBlock (int x, int y, int z);
} }

View File

@@ -12,7 +12,7 @@ public interface ChunkLoader {
* @param z chunk position * @param z chunk position
* @return optional of chunk (nullable) * @return optional of chunk (nullable)
*/ */
Optional<Chunk> loadChunk (int x, int y, int z); Optional<ChunkSection> loadChunk (int x, int y, int z);
/** /**
* Tries to load chunk like {@link #loadChunk(int, int, int)} * Tries to load chunk like {@link #loadChunk(int, int, int)}
@@ -23,5 +23,5 @@ public interface ChunkLoader {
* @param z chunk position * @param z chunk position
* @return chunk * @return chunk
*/ */
Chunk loadOrGenerateChunk (int x, int y, int z); ChunkSection loadOrGenerateChunk (int x, int y, int z);
} }

View File

@@ -0,0 +1,53 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-04-15
*/
package mc.core.world;
import mc.core.block.Block;
import java.io.Serializable;
/**
* Serialization chunk info
*
* +-------------+----------------+------------+
* | param | range | bits |
* +-------------+----------------+------------+
* | blocks | array | 24*count |
* +-------------+----------------+------------+
*
* Total: 24 * block_count bits (3 * block_count bytes)
* Max size: 12288 bytes (~12 Kb per chunk)
*
*/
/* 16x16x16 */
public interface ChunkSection extends Serializable{
int getBlockType(int x, int y, int z);
void setBlockType(int x, int y, int z, int type);
int getBlockMetadata(int x, int y, int z);
void setBlockMetadata(int x, int y, int z, int metadata);
int getBlockLight(int x, int y, int z);
void setBlockLight(int x, int y, int z, int lightLevel);
int getSkyLight(int x, int y, int z);
void setSkyLight(int x, int y, int z, int lightLevel);
int getAddition(int x, int y, int z);
void setAddition(int x, int y, int z, int value);
Biome getBiome(int x, int z);
void setBiome(int x, int z, Biome biome);
int getX();
int getY();
int getZ();
void setBlock(int x, int y, int z, Block block);
Block getBlock(int x, int y, int z);
Region getRegion();
World getWorld();
}

View File

@@ -21,8 +21,13 @@ import java.io.Serializable;
* *
*/ */
public interface Region extends Serializable{ public interface Region extends Serializable{
Chunk getChunkAt(int x, int y, int z); Chunk getChunk (int x, int z);
void setChunk(int x, int y, int z, Chunk chunk); void setChunk(int x, int z, Chunk chunk);
@Deprecated
ChunkSection getChunkAt(int x, int y, int z);
@Deprecated
void setChunk(int x, int y, int z, ChunkSection chunkSection);
int getX(); int getX();
int getZ(); int getZ();
@@ -30,5 +35,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);
void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWritter) throws IOException; World getWorld();
void save(Serializer<ChunkSection> chunkSerializer, IRegionReaderWriter regionReaderWritter) throws IOException;
} }

View File

@@ -4,7 +4,6 @@
*/ */
package mc.core.world; package mc.core.world;
import mc.core.Location;
import mc.core.WarpPosition; import mc.core.WarpPosition;
import mc.core.nbt.Taggable; import mc.core.nbt.Taggable;
@@ -49,8 +48,8 @@ public interface World extends Taggable, Serializable{
WarpPosition getSpawn(); WarpPosition getSpawn();
void setSpawn(WarpPosition location); void setSpawn(WarpPosition location);
Chunk getChunk(int x, int y, int z); ChunkSection getChunk(int x, int y, int z);
void setChunk(int x, int y, int z, Chunk chunk); void setChunk(int x, int y, int z, ChunkSection chunkSection);
Region getRegion(int x, int z); Region getRegion(int x, int z);
void setRegion(int x, int z, Region region); void setRegion(int x, int z, Region region);

View File

@@ -25,7 +25,7 @@ public class FlatWorld implements World {
@Getter @Getter
@Setter @Setter
private WarpPosition spawn = new WarpPosition(new Location(0, 6, 0), new Look(0, 0)); private WarpPosition spawn = new WarpPosition(new Location(0, 6, 0), new Look(0, 0));
private Chunk chunk = new SimpleChunk(); private ChunkSection chunkSection = new SimpleChunkSection();
@Override @Override
public IWorldType getWorldType() { public IWorldType getWorldType() {
@@ -33,12 +33,12 @@ public class FlatWorld implements World {
} }
@Override @Override
public Chunk getChunk(int x, int y, int z) { public ChunkSection getChunk(int x, int y, int z) {
return chunk; return chunkSection;
} }
@Override @Override
public void setChunk(int x, int y, int z, Chunk chunk) { public void setChunk(int x, int y, int z, ChunkSection chunkSection) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@@ -1,107 +0,0 @@
/*
* DmitriyMX <dimon550@gmail.com>
* 2018-04-28
*/
package mc.world.flat;
import mc.core.block.Block;
import mc.core.block.BlockFactory;
import mc.core.block.BlockType;
import mc.core.world.Biome;
import mc.core.world.Chunk;
public class SimpleChunk implements Chunk {
@Override
public int getBlockType(int x, int y, int z) {
if (y == 0) return 7;
else if (y >= 1 && y <= 2) return 3;
else if (y == 3) return 2;
else return 0;
}
@Override
public void setBlockType(int x, int y, int z, int type) {
}
@Override
public int getBlockMetadata(int x, int y, int z) {
return 0;
}
@Override
public void setBlockMetadata(int x, int y, int z, int metadata) {
}
@Override
public int getBlockLight(int x, int y, int z) {
return 0;
}
@Override
public void setBlockLight(int x, int y, int z, int lightLevel) {
}
@Override
public int getSkyLight(int x, int y, int z) {
if (y <= 3) return 0;
else return 15;
}
@Override
public void setSkyLight(int x, int y, int z, int lightLevel) {
}
@Override
public int getAddition(int x, int y, int z) {
return 0;
}
@Override
public void setAddition(int x, int y, int z, int value) {
}
@Override
public Biome getBiome(int x, int z) {
return Biome.PLAINS;
}
@Override
public void setBiome(int x, int z, Biome biome) {
}
@Override
public int getX() {
return 0;
}
@Override
public int getY() {
return 0;
}
@Override
public int getZ() {
return 0;
}
@Override
public void setBlock(int x, int y, int z, Block block) {
}
@Override
public Block getBlock(int x, int y, int z) {
BlockFactory blockFactory = new BlockFactory();
if (y == 0) return blockFactory.create(BlockType.BEDROCK, 0);
else if (y >= 1 && y <= 2) return blockFactory.create(BlockType.DIRT, 0);
else if (y == 3) return blockFactory.create(BlockType.GRASS, 0);
else return Block.airBlock(x, y, z);
}
}

View File

@@ -1,100 +1,61 @@
package mc.world.generated_world.chunk; package mc.world.generated_world.chunk;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import mc.core.exception.ResourceUnloadedException;
import mc.core.block.Block;
import mc.core.block.BlockType;
import mc.core.world.Biome;
import mc.core.world.Chunk; import mc.core.world.Chunk;
import mc.core.world.ChunkSection;
import mc.core.world.Region; import mc.core.world.Region;
import mc.core.world.World;
import java.lang.ref.Reference;
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;
@Getter @Getter
private final int y;
@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 Reference<Region> regionReference;
private final transient Region region; private ChunkSection[] sections = new ChunkSection[WORLD_CHUNK_SIZE];
@Override public ChunkImpl (int x, int z, Region region) {
public int getBlockType(int x, int y, int z) { this.x = x;
return blocks[x][y][z].getId(); this.z = z;
this.regionReference = new WeakReference<>(region);
} }
@Override @Override
public void setBlockType(int x, int y, int z, int type) { public World getWorld() {
Region region = getRegion();
if (region == null) {
throw new ResourceUnloadedException("Region is unloaded");
}
return region.getWorld();
} }
@Override @Override
public int getBlockMetadata(int x, int y, int z) { public ChunkSection getChunkSection(int height) {
return 0; return sections[height];
} }
@Override @Override
public void setBlockMetadata(int x, int y, int z, int metadata) { public ChunkSection setChunkSection(int height, ChunkSection chunkSection) {
sections[height] = chunkSection;
return chunkSection;
} }
@Override @Override
public int getBlockLight(int x, int y, int z) { public Region getRegion() {
return 15; if (regionReference == null) {
return null;
} }
@Override if (regionReference.get() == null) {
public void setBlockLight(int x, int y, int z, int lightLevel) { throw new ResourceUnloadedException("Region is unloaded");
} }
@Override return regionReference.get();
public int getSkyLight(int x, int y, int z) {
return 15;
}
@Override
public void setSkyLight(int x, int y, int z, int lightLevel) {
}
@Override
public int getAddition(int x, int y, int z) {
return 0;
}
@Override
public void setAddition(int x, int y, int z, int value) {
}
@Override
public Biome getBiome(int x, int z) {
return region.getBiomeAt(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE);
}
@Override
public void setBiome(int x, int z, Biome biome) {
region.setBiome(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE, biome);
}
@Override
public void setBlock(int x, int y, int z, Block block) {
if (block.getBlockType() == BlockType.AIR) {
blocks[x][y][z] = null;
}
blocks[x][y][z] = block;
}
@Override
public Block getBlock(int x, int y, int z) {
Block block = blocks[x][y][z];
if (block == null) {
return Block.airBlock(x, y, z);
}
return blocks[x][y][z];
} }
} }

View File

@@ -0,0 +1,127 @@
package mc.world.generated_world.chunk;
import lombok.Getter;
import mc.core.block.Block;
import mc.core.block.BlockType;
import mc.core.exception.ResourceUnloadedException;
import mc.core.world.Biome;
import mc.core.world.ChunkSection;
import mc.core.world.Region;
import mc.core.world.World;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE;
public class ChunkSectionImpl implements ChunkSection {
@Getter
private final int x;
@Getter
private final int y;
@Getter
private final int z;
private final Block[][][] blocks = new Block[WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE][WORLD_CHUNK_SIZE];
private final transient Reference<Region> region;
public ChunkSectionImpl(int x, int y, int z, Region region) {
this.x = x;
this.y = y;
this.z = z;
this.region = new WeakReference<>(region);
}
@Override
public int getBlockType(int x, int y, int z) {
return blocks[x][y][z].getId();
}
@Override
public void setBlockType(int x, int y, int z, int type) {
}
@Override
public int getBlockMetadata(int x, int y, int z) {
return 0;
}
@Override
public void setBlockMetadata(int x, int y, int z, int metadata) {
}
@Override
public int getBlockLight(int x, int y, int z) {
return 15;
}
@Override
public void setBlockLight(int x, int y, int z, int lightLevel) {
}
@Override
public int getSkyLight(int x, int y, int z) {
return 15;
}
@Override
public void setSkyLight(int x, int y, int z, int lightLevel) {
}
@Override
public int getAddition(int x, int y, int z) {
return 0;
}
@Override
public void setAddition(int x, int y, int z, int value) {
}
@Override
public Biome getBiome(int x, int z) {
return getRegion().getBiomeAt(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE);
}
@Override
public void setBiome(int x, int z, Biome biome) {
getRegion().setBiome(x + this.x * WORLD_CHUNK_SIZE,z + this.z * WORLD_CHUNK_SIZE, biome);
}
@Override
public void setBlock(int x, int y, int z, Block block) {
if (block.getBlockType() == BlockType.AIR) {
blocks[x][y][z] = null;
return;
}
blocks[x][y][z] = block;
}
@Override
public Block getBlock(int x, int y, int z) {
Block block = blocks[x][y][z];
if (block == null) {
return Block.airBlock(x, y, z);
}
return blocks[x][y][z];
}
@Override
public Region getRegion() {
if (region == null) {
return null;
}
if (region.get() == null) {
throw new ResourceUnloadedException("Region is unloaded");
}
return region.get();
}
@Override
public World getWorld() {
return getRegion().getWorld();
}
}

View File

@@ -2,28 +2,30 @@ 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.ChunkSection;
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;
public class ChunkProxy implements Chunk { public class ChunkSectionProxy implements ChunkSection {
private final Chunk chunk; private final ChunkSection chunkSection;
private volatile transient long lastUsage = System.currentTimeMillis(); private volatile transient long lastUsage = System.currentTimeMillis();
private final transient ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private final transient ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public ChunkProxy(Chunk chunk) { public ChunkSectionProxy(ChunkSection chunkSection) {
this.chunk = chunk; this.chunkSection = chunkSection;
} }
public long getLastUsage() { public long getLastUsage() {
synchronized (chunk) { synchronized (chunkSection) {
return lastUsage; return lastUsage;
} }
} }
private final void use () { private final void use () {
synchronized (chunk) { synchronized (chunkSection) {
lastUsage = System.currentTimeMillis(); lastUsage = System.currentTimeMillis();
} }
} }
@@ -31,102 +33,114 @@ public class ChunkProxy implements Chunk {
@Override @Override
public int getBlockType(int x, int y, int z) { public int getBlockType(int x, int y, int z) {
use(); use();
return chunk.getBlockType(x, y, z); return chunkSection.getBlockType(x, y, z);
} }
@Override @Override
public void setBlockType(int x, int y, int z, int type) { public void setBlockType(int x, int y, int z, int type) {
use(); use();
chunk.setBlockType(x, y, z, type); chunkSection.setBlockType(x, y, z, type);
} }
@Override @Override
public int getBlockMetadata(int x, int y, int z) { public int getBlockMetadata(int x, int y, int z) {
use(); use();
return chunk.getBlockMetadata(x, y, z); return chunkSection.getBlockMetadata(x, y, z);
} }
@Override @Override
public void setBlockMetadata(int x, int y, int z, int metadata) { public void setBlockMetadata(int x, int y, int z, int metadata) {
use(); use();
chunk.setBlockMetadata(x, y, z, metadata); chunkSection.setBlockMetadata(x, y, z, metadata);
} }
@Override @Override
public int getBlockLight(int x, int y, int z) { public int getBlockLight(int x, int y, int z) {
use(); use();
return chunk.getBlockLight(x, y, z); return chunkSection.getBlockLight(x, y, z);
} }
@Override @Override
public void setBlockLight(int x, int y, int z, int lightLevel) { public void setBlockLight(int x, int y, int z, int lightLevel) {
use(); use();
chunk.setBlockLight(x, y, z, lightLevel); chunkSection.setBlockLight(x, y, z, lightLevel);
} }
@Override @Override
public int getSkyLight(int x, int y, int z) { public int getSkyLight(int x, int y, int z) {
use(); use();
return chunk.getSkyLight(x, y, z); return chunkSection.getSkyLight(x, y, z);
} }
@Override @Override
public void setSkyLight(int x, int y, int z, int lightLevel) { public void setSkyLight(int x, int y, int z, int lightLevel) {
use(); use();
chunk.setSkyLight(x, y, z, lightLevel); chunkSection.setSkyLight(x, y, z, lightLevel);
} }
@Override @Override
public int getAddition(int x, int y, int z) { public int getAddition(int x, int y, int z) {
use(); use();
return chunk.getAddition(x, y, z); return chunkSection.getAddition(x, y, z);
} }
@Override @Override
public void setAddition(int x, int y, int z, int value) { public void setAddition(int x, int y, int z, int value) {
use(); use();
chunk.setAddition(x, y, z, value); chunkSection.setAddition(x, y, z, value);
} }
@Override @Override
public Biome getBiome(int x, int z) { public Biome getBiome(int x, int z) {
use(); use();
return chunk.getBiome(x, z); return chunkSection.getBiome(x, z);
} }
@Override @Override
public void setBiome(int x, int z, Biome biome) { public void setBiome(int x, int z, Biome biome) {
use(); use();
chunk.setBiome(x, z, biome); chunkSection.setBiome(x, z, biome);
} }
@Override @Override
public int getX() { public int getX() {
use(); use();
return chunk.getX(); return chunkSection.getX();
} }
@Override @Override
public int getY() { public int getY() {
use(); use();
return chunk.getY(); return chunkSection.getY();
} }
@Override @Override
public int getZ() { public int getZ() {
use(); use();
return chunk.getZ(); return chunkSection.getZ();
} }
@Override @Override
public void setBlock(int x, int y, int z, Block block) { public void setBlock(int x, int y, int z, Block block) {
use(); use();
chunk.setBlock(x, y, z, block); chunkSection.setBlock(x, y, z, block);
} }
@Override @Override
public Block getBlock(int x, int y, int z) { public Block getBlock(int x, int y, int z) {
use(); use();
return chunk.getBlock(x, y, z); return chunkSection.getBlock(x, y, z);
}
@Override
public Region getRegion() {
use();
return chunkSection.getRegion();
}
@Override
public World getWorld() {
use();
return chunkSection.getWorld();
} }
} }

View File

@@ -25,7 +25,7 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
@Autowired @Autowired
private ChunkReader chunkReader; private ChunkReader chunkReader;
@Autowired @Autowired
private Serializer<Chunk> chunkSerializer; private Serializer<ChunkSection> chunkSerializer;
@Autowired @Autowired
private RegionReaderWriter regionReaderWritter; private RegionReaderWriter regionReaderWritter;
@@ -44,14 +44,14 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
} }
@Override @Override
public Optional<Chunk> loadChunk(int x, int y, int z) { public Optional<ChunkSection> loadChunk(int x, int y, int z) {
File file = getChuckFile(x, y, z); File file = getChuckFile(x, y, z);
if (!file.exists()) { if (!file.exists()) {
return Optional.empty(); return Optional.empty();
} else { } else {
try { try {
Chunk chunk = chunkReader.read(world.getRegion(x / WORLD_CHUNK_SIZE, z / WORLD_CHUNK_SIZE), x, y, z); ChunkSection chunkSection = chunkReader.read(world.getRegion(x / WORLD_CHUNK_SIZE, z / WORLD_CHUNK_SIZE), x, y, z);
return Optional.of(chunk); return Optional.of(chunkSection);
} catch (IOException e) { } catch (IOException e) {
log.error("Error occurred while reading chunk file: " + file.getAbsolutePath(), e); log.error("Error occurred while reading chunk file: " + file.getAbsolutePath(), e);
return Optional.empty(); return Optional.empty();
@@ -60,12 +60,12 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
} }
@Override @Override
public Chunk loadOrGenerateChunk(int x, int y, int z) { public ChunkSection loadOrGenerateChunk(int x, int y, int z) {
int regX = x / WORLD_CHUNK_SIZE; int regX = x / WORLD_CHUNK_SIZE;
int regZ = z / WORLD_CHUNK_SIZE; int regZ = z / WORLD_CHUNK_SIZE;
File regionFile = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, regX, regZ)); File regionFile = new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, regX, regZ));
Region region; Region region;
Chunk chunk; ChunkSection chunkSection;
if (!regionFile.exists()) { if (!regionFile.exists()) {
log.debug("Region [{}, {}] not found. Generating!", regX, regZ); log.debug("Region [{}, {}] not found. Generating!", regX, regZ);
regionFile.mkdirs(); regionFile.mkdirs();
@@ -76,17 +76,17 @@ public class InMemoryCacheChunkLoader implements ChunkLoader {
log.error("Error occurred while writting biome file", e); log.error("Error occurred while writting biome file", e);
} }
saveRegion(region); saveRegion(region);
chunk = region.getChunkAt(x % WORLD_CHUNK_SIZE, y % WORLD_CHUNK_SIZE, z % WORLD_CHUNK_SIZE); chunkSection = region.getChunkAt(x % WORLD_CHUNK_SIZE, y % WORLD_CHUNK_SIZE, z % WORLD_CHUNK_SIZE);
} else { } else {
try { try {
region = regionReaderWritter.read(regX, regZ, world); region = regionReaderWritter.read(regX, regZ, world);
chunk = chunkReader.read(region, x, y, z); chunkSection = chunkReader.read(region, x, y, z);
} catch (IOException e) { } catch (IOException e) {
log.error("Error occurred while reading chunk file", e); log.error("Error occurred while reading chunkSection file", e);
return null; return null;
} }
} }
return chunk; return chunkSection;
} }
private void saveRegion (Region region) { private void saveRegion (Region region) {

View File

@@ -8,7 +8,6 @@ import mc.core.world.*;
import mc.world.generated_world.region.RegionImpl; import mc.world.generated_world.region.RegionImpl;
import mc.world.generated_world.serialization.ChunkSerializer; import mc.world.generated_world.serialization.ChunkSerializer;
import mc.world.generated_world.serialization.RegionReaderWriter; import mc.world.generated_world.serialization.RegionReaderWriter;
import mc.world.generated_world.serialization.WorldReaderWriter;
import mc.world.generated_world.world.CubicWorld; import mc.world.generated_world.world.CubicWorld;
import mc.world.generated_world.world.Temperature; import mc.world.generated_world.world.Temperature;
import mc.world.generated_world.world.Wetness; import mc.world.generated_world.world.Wetness;
@@ -28,7 +27,7 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 2626949); World world = new CubicWorld(UUID.fromString("00000000-0000-0000-C000-000000000046"), 2626949);
Region region = worldGenerator.generateRegion(0, 0, world); Region region = worldGenerator.generateRegion(0, 0, world);
region.save(new ChunkSerializer(), new RegionReaderWriter(new File("worlds", world.getWorldId().toString()))); region.save(new ChunkSerializer(), new RegionReaderWriter(new File("worlds", world.getWorldId().toString())));
new WorldReaderWriter(new File("worlds")).writeWorldInfo(world); // new WorldReaderWriter(new File("worlds")).writeWorldInfo(world);
/*worldGenerator.generateRegion(1, 0, world); /*worldGenerator.generateRegion(1, 0, world);
worldGenerator.generateRegion(-1, 0, world); worldGenerator.generateRegion(-1, 0, world);
worldGenerator.generateRegion(0, 1, world); worldGenerator.generateRegion(0, 1, world);
@@ -306,37 +305,37 @@ public class SeedBasedWorldGenerator implements WorldGenerator {
region.setBiome(x, z, biomes[x][z]); region.setBiome(x, z, biomes[x][z]);
if (heightMap[x][z] < WORLD_SEA_LEVEL) { if (heightMap[x][z] < WORLD_SEA_LEVEL) {
for (int y = 0; y < WORLD_SEA_LEVEL; y ++) { for (int y = 0; y < WORLD_SEA_LEVEL; y ++) {
Chunk chunk = region.getChunkAt(x / 16, y / 16, z / 16); ChunkSection chunkSection = region.getChunkAt(x / 16, y / 16, z / 16);
if (y == 0) { if (y == 0) {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.BEDROCK, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.BEDROCK, 0));
continue; continue;
} }
if (y < heightMap[x][z]) { if (y < heightMap[x][z]) {
if (y < heightMap[x][z] - grassMap[x][z]) { if (y < heightMap[x][z] - grassMap[x][z]) {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.STONE, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.STONE, 0));
} else { } else {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.SAND, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.SAND, 0));
} }
} else { } else {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.WATER, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.WATER, 0));
} }
} }
} else { } else {
for (int y = 0; y < heightMap[x][z]; y++) { for (int y = 0; y < heightMap[x][z]; y++) {
Chunk chunk = region.getChunkAt(x / 16, y / 16, z / 16); ChunkSection chunkSection = region.getChunkAt(x / 16, y / 16, z / 16);
if (y == 0) { if (y == 0) {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.BEDROCK, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.BEDROCK, 0));
continue; continue;
} }
if (y < heightMap[x][z] - grassMap[x][z]) { if (y < heightMap[x][z] - grassMap[x][z]) {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.STONE, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.STONE, 0));
} else { } else {
if (biomes[x][z] == Biome.DESERT || biomes[x][z] == Biome.DESERT_HILLS) { if (biomes[x][z] == Biome.DESERT || biomes[x][z] == Biome.DESERT_HILLS) {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.SAND, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.SAND, 0));
} else if (biomes[x][z] == Biome.TAIGA || biomes[x][z] == Biome.TAIGA_HILLS) { } else if (biomes[x][z] == Biome.TAIGA || biomes[x][z] == Biome.TAIGA_HILLS) {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.DIRT, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.DIRT, 0));
} else { } else {
chunk.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.GRASS, 0)); chunkSection.setBlock(x % 16, y % 16, z % 16, blockFactory.create(BlockType.GRASS, 0));
} }
} }
} }

View File

@@ -1,59 +1,88 @@
package mc.world.generated_world.region; package mc.world.generated_world.region;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import mc.core.exception.ResourceUnloadedException;
import mc.core.serialization.IRegionReaderWriter; import mc.core.serialization.IRegionReaderWriter;
import mc.core.serialization.Serializer; import mc.core.serialization.Serializer;
import mc.core.world.*; import mc.core.world.*;
import mc.world.generated_world.chunk.InMemoryCacheChunkLoader;
import mc.world.generated_world.chunk.ChunkImpl; import mc.world.generated_world.chunk.ChunkImpl;
import mc.world.generated_world.chunk.ChunkProxy; import mc.world.generated_world.chunk.ChunkSectionImpl;
import mc.world.generated_world.chunk.ChunkSectionProxy;
import mc.world.generated_world.chunk.InMemoryCacheChunkLoader;
import org.springframework.beans.factory.annotation.Autowired; 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.Reference;
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;
@Getter @Getter
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 ChunkSection[][][] chunkSectionProxies = new ChunkSectionProxy[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 Reference<World> world;
private final transient World world; private final Chunk[][] chunks = new Chunk[WORLD_REGION_SIZE/WORLD_CHUNK_SIZE][WORLD_REGION_SIZE/WORLD_CHUNK_SIZE];
@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 getChunk(int x, int z) {
if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) { if (x < 0 || z < 0 || x >= 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}]", x, z));
} }
if (chunkLoader == null) {
chunkLoader = new InMemoryCacheChunkLoader(world); Chunk chunk = chunks[x][z];
}
Chunk chunk = chunks[x][y][z];
if (chunk == null) { if (chunk == null) {
chunk = chunkLoader.loadChunk(x + this.x * WORLD_REGION_SIZE, y, this.z * WORLD_REGION_SIZE).orElse(new ChunkImpl(x, y, z, this)); chunk = new ChunkImpl(x, z, this);
chunks[x][y][z] = new ChunkProxy(chunk); for (int y = 0; y < WORLD_CHUNK_SIZE; y ++) {
chunk.setChunkSection(y, getChunkAt(x, y, z));
}
} }
return chunk; return chunk;
} }
@Override @Override
public void setChunk(int x, int y, int z, Chunk chunk) { public void setChunk(int x, int z, Chunk chunk) {
if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) { chunks[x][z] = chunk;
throw new RuntimeException(MessageFormat.format("Invalid chunk coordinates [{0} {1} {2}]", x, y, z));
} }
chunks[x][y][z] = new ChunkProxy(chunk);
@Override
public ChunkSection getChunkAt(int x, int y, int z) {
if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) {
throw new RuntimeException(MessageFormat.format("Invalid chunkSection coordinates [{0} {1} {2}]", x, y, z));
}
if (chunkLoader == null) {
chunkLoader = new InMemoryCacheChunkLoader(getWorld());
}
ChunkSection chunkSection = chunkSectionProxies[x][y][z];
if (chunkSection == null) {
chunkSection = chunkLoader.loadChunk(x + this.x * WORLD_REGION_SIZE, y, this.z * WORLD_REGION_SIZE).orElse(new ChunkSectionImpl(x, y, z, this));
chunkSectionProxies[x][y][z] = new ChunkSectionProxy(chunkSection);
}
return chunkSection;
}
@Override
public void setChunk(int x, int y, int z, ChunkSection chunkSection) {
if (x < 0 || y < 0 || z < 0 || x >= 16 || y >= 16 || z >= 16) {
throw new RuntimeException(MessageFormat.format("Invalid chunkSection coordinates [{0} {1} {2}]", x, y, z));
}
chunkSectionProxies[x][y][z] = new ChunkSectionProxy(chunkSection);
} }
@Override @Override
@@ -73,9 +102,20 @@ public class RegionImpl implements Region{
} }
@Override @Override
public void save(Serializer<Chunk> chunkSerializer, IRegionReaderWriter regionReaderWriter) throws IOException { public World getWorld() {
if (world == null) {
return null;
}
if (world.get() == null) {
throw new ResourceUnloadedException("World is unloaded");
}
return world.get();
}
@Override
public void save(Serializer<ChunkSection> 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();
@@ -84,8 +124,8 @@ public class RegionImpl implements Region{
for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) { for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) {
for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) { for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) {
for (int y = 0; y < WORLD_CHUNK_SIZE; y++) { for (int y = 0; y < WORLD_CHUNK_SIZE; y++) {
Chunk chunk = this.getChunkAt(x, y, z); ChunkSection chunkSection = this.getChunkAt(x, y, z);
byte[] chunkBytes = chunkSerializer.serialize(chunk); byte[] chunkBytes = chunkSerializer.serialize(chunkSection);
if (chunkBytes.length > 0) { if (chunkBytes.length > 0) {
File chunkFile = new File(regionFile, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z)); File chunkFile = new File(regionFile, MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z));
try (FileOutputStream fileOutputStream = new FileOutputStream(chunkFile)) { try (FileOutputStream fileOutputStream = new FileOutputStream(chunkFile)) {

View File

@@ -5,7 +5,7 @@ import mc.core.block.BlockFactory;
import mc.core.block.BlockType; import mc.core.block.BlockType;
import mc.core.serialization.Deserializer; import mc.core.serialization.Deserializer;
import mc.core.serialization.Serializer; import mc.core.serialization.Serializer;
import mc.core.world.Chunk; import mc.core.world.ChunkSection;
/** /**
* Prototype * Prototype
@@ -13,20 +13,20 @@ import mc.core.world.Chunk;
public class BlockSerializerDeserializer implements Serializer<Block>, Deserializer<Block> { public class BlockSerializerDeserializer implements Serializer<Block>, Deserializer<Block> {
private BlockFactory blockFactory; private BlockFactory blockFactory;
private Chunk chunk; private ChunkSection chunkSection;
public BlockSerializerDeserializer(BlockFactory blockFactory, Chunk chunk) { public BlockSerializerDeserializer(BlockFactory blockFactory, ChunkSection chunkSection) {
this.blockFactory = blockFactory; this.blockFactory = blockFactory;
this.chunk = chunk; this.chunkSection = chunkSection;
} }
@Override @Override
public Block deserialize(byte[] bytes) { public Block deserialize(byte[] bytes) {
int id = bytes[0] + 128; int id = bytes[0] + 128;
int meta = bytes[1] >> 4; int meta = bytes[1] >> 4;
int x = (bytes[1] & 0xf) + chunk.getX() * 16; int x = (bytes[1] & 0xf) + chunkSection.getX() * 16;
int y = bytes[2] >> 4 + chunk.getY() * 16; int y = bytes[2] >> 4 + chunkSection.getY() * 16;
int z = (bytes[2] & 0xf) + chunk.getZ() * 16; int z = (bytes[2] & 0xf) + chunkSection.getZ() * 16;
BlockType type = BlockType.values()[id]; BlockType type = BlockType.values()[id];
Block block = blockFactory.create(type, meta); Block block = blockFactory.create(type, meta);
block.getLocation().setX(x); block.getLocation().setX(x);

View File

@@ -4,9 +4,9 @@ import mc.core.Location;
import mc.core.block.Block; import mc.core.block.Block;
import mc.core.serialization.Deserializer; import mc.core.serialization.Deserializer;
import mc.core.serialization.IChunkReader; import mc.core.serialization.IChunkReader;
import mc.core.world.Chunk; import mc.core.world.ChunkSection;
import mc.core.world.Region; import mc.core.world.Region;
import mc.world.generated_world.chunk.ChunkImpl; import mc.world.generated_world.chunk.ChunkSectionImpl;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.io.File; import java.io.File;
@@ -27,14 +27,14 @@ public class ChunkReader implements IChunkReader{
} }
@Override @Override
public Chunk read (Region region, int x, int y, int z) throws IOException { public ChunkSection read (Region region, int x, int y, int z) throws IOException {
x %= WORLD_REGION_SIZE; x %= WORLD_REGION_SIZE;
y %= WORLD_REGION_SIZE; y %= WORLD_REGION_SIZE;
z %= WORLD_REGION_SIZE; z %= WORLD_REGION_SIZE;
File chunkFile = new File(new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ())), MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z)); File chunkFile = new File(new File(worldFolder, MessageFormat.format(REGION_FILE_NAME_TEMPLATE, region.getX(), region.getZ())), MessageFormat.format(CHUNK_FILE_NAME_TEMPLATE, x, y, z));
byte[] chunkBytes = Files.readAllBytes(Paths.get(chunkFile.toURI())); byte[] chunkBytes = Files.readAllBytes(Paths.get(chunkFile.toURI()));
int blocks = (chunkBytes.length) / 3; int blocks = (chunkBytes.length) / 3;
Chunk chunk = new ChunkImpl(x, y, z, region); ChunkSection chunkSection = new ChunkSectionImpl(x, y, z, region);
for (int i = 0; i < blocks; i ++) { for (int i = 0; i < blocks; i ++) {
byte[] blockBytes = new byte[3]; byte[] blockBytes = new byte[3];
blockBytes[0] = chunkBytes[3 * i]; blockBytes[0] = chunkBytes[3 * i];
@@ -42,8 +42,8 @@ public class ChunkReader implements IChunkReader{
blockBytes[2] = chunkBytes[2 + 3 * i]; blockBytes[2] = chunkBytes[2 + 3 * i];
Block block = blockDeserializer.deserialize(blockBytes); Block block = blockDeserializer.deserialize(blockBytes);
Location blockLocation = block.getLocation(); Location blockLocation = block.getLocation();
chunk.setBlock(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ(), block); chunkSection.setBlock(blockLocation.getBlockX(), blockLocation.getBlockY(), blockLocation.getBlockZ(), block);
} }
return chunk; return chunkSection;
} }
} }

View File

@@ -5,7 +5,7 @@ import mc.core.block.Block;
import mc.core.block.BlockFactory; import mc.core.block.BlockFactory;
import mc.core.block.BlockType; import mc.core.block.BlockType;
import mc.core.serialization.Serializer; import mc.core.serialization.Serializer;
import mc.core.world.Chunk; import mc.core.world.ChunkSection;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
@@ -14,20 +14,20 @@ import java.io.IOException;
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE; import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE;
@Slf4j @Slf4j
public class ChunkSerializer implements Serializer<Chunk> { public class ChunkSerializer implements Serializer<ChunkSection> {
@Autowired @Autowired
private Serializer<Block> blockSerializer; private Serializer<Block> blockSerializer;
@Override @Override
public byte[] serialize(Chunk chunk) { public byte[] serialize(ChunkSection chunkSection) {
Serializer<Block> blockSerializer = new BlockSerializerDeserializer(new BlockFactory(), chunk); Serializer<Block> blockSerializer = new BlockSerializerDeserializer(new BlockFactory(), chunkSection);
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
Block current; Block current;
for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) { for (int x = 0; x < WORLD_CHUNK_SIZE; x ++) {
for (int y = 0; y < WORLD_CHUNK_SIZE; y ++) { for (int y = 0; y < WORLD_CHUNK_SIZE; y ++) {
for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) { for (int z = 0; z < WORLD_CHUNK_SIZE; z ++) {
current = chunk.getBlock(x, y, z); current = chunkSection.getBlock(x, y, z);
if (current != null && current.getBlockType() != BlockType.AIR) { if (current != null && current.getBlockType() != BlockType.AIR) {
try { try {
baos.write(blockSerializer.serialize(current)); baos.write(blockSerializer.serialize(current));

View File

@@ -8,7 +8,7 @@ import mc.core.Location;
import mc.core.WarpPosition; import mc.core.WarpPosition;
import mc.core.block.BlockType; import mc.core.block.BlockType;
import mc.core.player.Look; import mc.core.player.Look;
import mc.core.world.Chunk; import mc.core.world.ChunkSection;
import mc.core.world.IWorldType; import mc.core.world.IWorldType;
import mc.core.world.Region; import mc.core.world.Region;
import mc.core.world.World; import mc.core.world.World;
@@ -68,8 +68,8 @@ public class CubicWorld implements World {
log.warn("Spawn location is not defined. Trying to select best location"); log.warn("Spawn location is not defined. Trying to select best location");
warpPosition = new WarpPosition(Location.startPointLocation(), new Look(0, 0)); warpPosition = new WarpPosition(Location.startPointLocation(), new Look(0, 0));
for (int y = WORLD_MAX_HEIGHT; y > 0; y --) { for (int y = WORLD_MAX_HEIGHT; y > 0; y --) {
Chunk chunk = getChunk(0,y / WORLD_CHUNK_SIZE, 0); ChunkSection chunkSection = getChunk(0,y / WORLD_CHUNK_SIZE, 0);
if (chunk.getBlock(0, y, 0).getBlockType() != BlockType.AIR) { if (chunkSection.getBlock(0, y, 0).getBlockType() != BlockType.AIR) {
warpPosition = new WarpPosition(new Location(0, y + 1, 0), new Look(0, 0)); warpPosition = new WarpPosition(new Location(0, y + 1, 0), new Look(0, 0));
break; break;
} }
@@ -89,12 +89,12 @@ public class CubicWorld implements World {
} }
@Override @Override
public Chunk getChunk(int x, int y, int z) { public ChunkSection getChunk(int x, int y, int z) {
return null; return null;
} }
@Override @Override
public void setChunk(int x, int y, int z, Chunk chunk) { public void setChunk(int x, int y, int z, ChunkSection chunkSection) {
} }

View File

@@ -48,8 +48,8 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
Player player = playerManager.getPlayer(packet.getPlayerName()) Player player = playerManager.getPlayer(packet.getPlayerName())
.orElseGet(() -> playerManager.createPlayer( .orElseGet(() -> playerManager.createPlayer(
packet.getPlayerName(), packet.getPlayerName(),
world.getSpawn(), world.getSpawn().getLocation(),
new Look(0f, 0f))); world.getSpawn().getLook()));
channel.writeAndFlush(new LoginSuccessPacket( channel.writeAndFlush(new LoginSuccessPacket(
player.getUUID(), player.getUUID(),
@@ -68,7 +68,7 @@ public class LoginHandler extends AbstractStateHandler implements LoginStateHand
// Spawn Position // Spawn Position
SpawnPositionPacket pkt2 = new SpawnPositionPacket(); SpawnPositionPacket pkt2 = new SpawnPositionPacket();
pkt2.setLocation(world.getSpawn()); pkt2.setLocation(world.getSpawn().getLocation());
channel.write(pkt2); channel.write(pkt2);
// Player Abilities // Player Abilities