Merged in forwolk/fix/region-fix (pull request #3)
Region managed moved to CubicWorld
This commit is contained in:
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user