Archived
0

Region managed moved to CubicWorld

This commit is contained in:
Forwolk
2018-08-08 00:17:07 +03:00
parent e8b02b8e28
commit f51dba79a6
3 changed files with 124 additions and 169 deletions

View File

@@ -4,34 +4,65 @@ import com.flowpowered.nbt.Tag;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import mc.core.Direction;
import mc.core.Location; import mc.core.Location;
import mc.core.WarpPosition; import mc.core.WarpPosition;
import mc.core.world.block.BlockType;
import mc.core.player.Look; import mc.core.player.Look;
import mc.core.world.chunk.Chunk;
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;
import mc.core.world.WorldGenerator;
import mc.core.world.block.BlockType;
import mc.core.world.chunk.Chunk;
import mc.world.generated_world.serialization.RegionReaderWriter;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Stream; import java.util.stream.Stream;
import static mc.world.generated_world.WorldConstants.WORLD_CHUNK_SIZE; import static mc.world.generated_world.WorldConstants.*;
import static mc.world.generated_world.WorldConstants.WORLD_MAX_HEIGHT;
/*
* NORTH
*
* EAST WEST
*
* SOUTH
*
* + ----> X
* |
* |
* |
* V Z
*/
@Slf4j @Slf4j
public class CubicWorld implements World { public class CubicWorld implements World {
private int pointX = -1;
private int pointZ = -1;
private int sizeX = 2;
private int sizeZ = 2;
private Region[][] regions = new Region[sizeX][sizeZ];
private final Lock regionSaveLock = new ReentrantLock();
@Autowired
private RegionReaderWriter regionReaderWriter;
@Autowired
private WorldGenerator worldGenerator;
@Setter
private boolean autoSaveRegionAfterGenerating = true;
@Getter @Getter
private final UUID worldId; private final UUID worldId;
private final int seed; private final int seed;
private volatile WarpPosition warpPosition; private volatile WarpPosition warpPosition;
private final transient Object spawnLocationLock = new Object(); private final transient Object spawnLocationLock = new Object();
private final Map<String, Tag<?>> nbtTagMap = new HashMap<>(); private final Map<String, Tag<?>> nbtTagMap = new HashMap<>();
@Autowired
private RegionManager regionManager;
@Getter@Setter @Getter@Setter
private String name; private String name;
@@ -62,23 +93,8 @@ public class CubicWorld implements World {
@Override @Override
public WarpPosition getSpawn() { public WarpPosition getSpawn() {
if (warpPosition == null) { /* FIXME */
synchronized (spawnLocationLock) { return new WarpPosition(new Location(0, 100, 0), new Look(0, 0));
if (warpPosition == null) {
log.warn("Spawn location is not defined. Trying to select best location");
warpPosition = new WarpPosition(Location.startPointLocation(), new Look(0, 0));
for (int y = WORLD_MAX_HEIGHT; y > 0; y --) {
Chunk chunk = getChunk(0,y / WORLD_CHUNK_SIZE, 0);
if (chunk.getBlock(0, y, 0).getBlockType() != BlockType.AIR) {
warpPosition = new WarpPosition(new Location(0, y + 1, 0), new Look(0, 0));
break;
}
}
warpPosition = new WarpPosition(Location.startPointLocation(), new Look(0,0));
}
}
}
return warpPosition;
} }
@Override @Override
@@ -90,7 +106,8 @@ public class CubicWorld implements World {
@Override @Override
public Chunk getChunk(int x, int y, int z) { public Chunk getChunk(int x, int y, int z) {
return null; Region region = getRegion(x / 16, z / 16);
return region.getChunkAt(x % 16, y % 16, z % 16);
} }
@Override @Override
@@ -100,12 +117,42 @@ public class CubicWorld implements World {
@Override @Override
public Region getRegion(int x, int z) { public Region getRegion(int x, int z) {
return null; checkCoordsInCache(x, z);
Region region;
if (regions[x - pointX][z - pointZ] == null) {
File file = new File(new File("worlds", this.getWorldId().toString()), MessageFormat.format(REGION_FILE_NAME_TEMPLATE, x, z));
if (!file.exists()) {
region = worldGenerator.generateRegion(x, z, this);
if (autoSaveRegionAfterGenerating) {
try {
regionReaderWriter.write(region);
} catch (IOException e) {
log.error("Error occurred while saving region data");
}
}
} else {
try {
region = regionReaderWriter.read(x, z, this);
} catch (IOException e) {
log.error("Error occurred while loading region");
region = null;
}
}
setRegion(region.getX(), region.getZ(), region);
} else {
region = regions[x - pointX][z - pointZ];
}
return region;
} }
@Override @Override
public void setRegion(int x, int z, Region region) { public void setRegion(int x, int z, Region region) {
try {
regionSaveLock.lock();
regions[x - pointX][z - pointZ] = region;
} finally {
regionSaveLock.unlock();
}
} }
@Override @Override
@@ -127,4 +174,53 @@ public class CubicWorld implements World {
public Stream<Tag<?>> tagStream() { public Stream<Tag<?>> tagStream() {
return nbtTagMap.values().stream(); return nbtTagMap.values().stream();
} }
private void checkCoordsInCache (int x, int z) {
if (x < pointX) {
addLines(Direction.EAST, pointX - x);
} else if (x > pointX + sizeX) {
addLines(Direction.WEST, x - (pointX + sizeX));
} else if (z < pointZ) {
addLines(Direction.NORTH, pointZ - z);
} else if (z > pointZ + sizeZ) {
addLines(Direction.SOUTH, z - (pointZ + sizeZ));
}
}
private void addLines (Direction direction, int amount) {
int addBeforeX = 0;
int addAfterX = 0;
int addBeforeZ = 0;
int addAfterZ = 0;
switch (direction) {
case NORTH:
addBeforeZ = amount;
break;
case EAST:
addBeforeX = amount;
break;
case WEST:
addAfterX = amount;
break;
case SOUTH:
addAfterZ = amount;
break;
}
try {
regionSaveLock.lock();
int tempSizeX = sizeX + addAfterX + addBeforeX;
int tempSizeZ = sizeZ + addAfterZ + addBeforeZ;
Region[][] temp = new Region[tempSizeX][tempSizeZ];
for (int x = 0; x < sizeX; x ++) {
System.arraycopy(regions[x], 0, temp[x + addBeforeX], addBeforeZ, sizeZ);
}
this.sizeX = tempSizeX;
this.sizeZ = tempSizeZ;
this.pointX = pointX - addBeforeX;
this.pointZ = pointZ - addBeforeZ;
} finally {
regionSaveLock.unlock();
}
}
} }

View File

@@ -1,143 +0,0 @@
package mc.world.generated_world.world;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import mc.core.Direction;
import mc.core.world.Region;
import mc.core.world.World;
import mc.core.world.WorldGenerator;
import mc.world.generated_world.serialization.RegionReaderWriter;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static mc.world.generated_world.WorldConstants.REGION_FILE_NAME_TEMPLATE;
/*
* NORTH
*
* EAST WEST
*
* SOUTH
*
* + ----> X
* |
* |
* |
* V Z
*/
@Slf4j
public class RegionManager {
private final World world;
private int pointX = -1;
private int pointZ = -1;
private int sizeX = 2;
private int sizeZ = 2;
private Region[][] regions = new Region[sizeX][sizeZ];
private final Lock regionSaveLock = new ReentrantLock();
@Autowired
private RegionReaderWriter regionReaderWriter;
@Autowired
private WorldGenerator worldGenerator;
@Setter
private boolean autoSaveRegionAfterGenerating = true;
public RegionManager(World world) {
this.world = world;
}
public void setRegion (Region region) {
int x = region.getX();
int z = region.getZ();
try {
regionSaveLock.lock();
regions[x - pointX][z - pointZ] = region;
} finally {
regionSaveLock.unlock();
}
}
private void checkCoordsInCache (int x, int z) {
if (x < pointX) {
addLines(Direction.EAST, pointX - x);
} else if (x > pointX + sizeX) {
addLines(Direction.WEST, x - (pointX + sizeX));
} else if (z < pointZ) {
addLines(Direction.NORTH, pointZ - z);
} else if (z > pointZ + sizeZ) {
addLines(Direction.SOUTH, z - (pointZ + sizeZ));
}
}
public Region getRegion (int x, int z) {
checkCoordsInCache(x, z);
Region region;
if (regions[x - pointX][z - pointZ] == null) {
File file = new File(new File("worlds", world.getWorldId().toString()), MessageFormat.format(REGION_FILE_NAME_TEMPLATE, x, z));
if (!file.exists()) {
region = worldGenerator.generateRegion(x, z, world);
if (autoSaveRegionAfterGenerating) {
try {
regionReaderWriter.write(region);
} catch (IOException e) {
log.error("Error occurred while saving region data");
}
}
} else {
try {
region = regionReaderWriter.read(x, z, world);
} catch (IOException e) {
log.error("Error occurred while loading region");
region = null;
}
}
setRegion(region);
} else {
region = regions[x - pointX][z - pointZ];
}
return region;
}
private void addLines (Direction direction, int amount) {
int addBeforeX = 0;
int addAfterX = 0;
int addBeforeZ = 0;
int addAfterZ = 0;
switch (direction) {
case NORTH:
addBeforeZ = amount;
break;
case EAST:
addBeforeX = amount;
break;
case WEST:
addAfterX = amount;
break;
case SOUTH:
addAfterZ = amount;
break;
}
try {
int tempSizeX = sizeX + addAfterX + addBeforeX;
int tempSizeZ = sizeZ + addAfterZ + addBeforeZ;
Region[][] temp = new Region[tempSizeX][tempSizeZ];
for (int x = 0; x < sizeX; x ++) {
System.arraycopy(regions[x], 0, temp[x + addBeforeX], addBeforeZ, sizeZ);
}
this.sizeX = tempSizeX;
this.sizeZ = tempSizeZ;
this.pointX = pointX - addBeforeX;
this.pointZ = pointZ - addBeforeZ;
} finally {
regionSaveLock.unlock();
}
}
}

View File

@@ -1,6 +1,7 @@
package mc.world.generated_world; package mc.world.generated_world;
import mc.world.generated_world.generator.SeedRandomGenerator; import mc.world.generated_world.generator.SeedRandomGenerator;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@@ -9,6 +10,7 @@ import java.io.File;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@Ignore
public class SeedRandomGeneratorTest { public class SeedRandomGeneratorTest {
@Test @Test