Added SurfaceContexts to replace SurfaceWorld+Request. WIP
There is a problem with features when up != POS_Z
This commit is contained in:
parent
a6fd81ba1e
commit
d33b48578d
@ -47,6 +47,7 @@ import ru.windcorp.progressia.server.world.context.impl.RotatingServerContext;
|
|||||||
import ru.windcorp.progressia.server.world.tasks.WorldAccessor;
|
import ru.windcorp.progressia.server.world.tasks.WorldAccessor;
|
||||||
import ru.windcorp.progressia.server.world.ticking.Change;
|
import ru.windcorp.progressia.server.world.ticking.Change;
|
||||||
import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
||||||
|
import ru.windcorp.progressia.server.world.ticking.TickerCoordinator;
|
||||||
import ru.windcorp.progressia.test.gen.planet.Planet;
|
import ru.windcorp.progressia.test.gen.planet.Planet;
|
||||||
import ru.windcorp.progressia.test.gen.planet.TestPlanetGenerator;
|
import ru.windcorp.progressia.test.gen.planet.TestPlanetGenerator;
|
||||||
|
|
||||||
@ -232,13 +233,41 @@ public class Server {
|
|||||||
schedule(() -> task.accept(this));
|
schedule(() -> task.accept(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestChange(Change change) {
|
/**
|
||||||
|
* Delayed
|
||||||
|
*/
|
||||||
|
public void scheduleChange(Change change) {
|
||||||
serverThread.getTicker().requestChange(change);
|
serverThread.getTicker().requestChange(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void requestEvaluation(Evaluation evaluation) {
|
/**
|
||||||
|
* Delayed
|
||||||
|
*/
|
||||||
|
public void scheduleEvaluation(Evaluation evaluation) {
|
||||||
serverThread.getTicker().requestEvaluation(evaluation);
|
serverThread.getTicker().requestEvaluation(evaluation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediate if possible, otherwise delayed
|
||||||
|
*/
|
||||||
|
public void requestChange(Change change) {
|
||||||
|
if (serverThread.getTicker().getPhase() == TickerCoordinator.TickPhase.SYNCHRONOUS) {
|
||||||
|
change.affect(this);
|
||||||
|
} else {
|
||||||
|
serverThread.getTicker().requestChange(change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediate if possible, otherwise delayed
|
||||||
|
*/
|
||||||
|
public void requestEvaluation(Evaluation evaluation) {
|
||||||
|
if (serverThread.getTicker().getPhase() == TickerCoordinator.TickPhase.SYNCHRONOUS) {
|
||||||
|
evaluation.evaluate(this);
|
||||||
|
} else {
|
||||||
|
serverThread.getTicker().requestEvaluation(evaluation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void subscribe(Object object) {
|
public void subscribe(Object object) {
|
||||||
eventBus.register(object);
|
eventBus.register(object);
|
||||||
@ -279,20 +308,7 @@ public class Server {
|
|||||||
public long getUptimeTicks() {
|
public long getUptimeTicks() {
|
||||||
return this.serverThread.getTicker().getUptimeTicks();
|
return this.serverThread.getTicker().getUptimeTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
|
||||||
// * Returns the {@link WorldAccessor} object for this server. Use the
|
|
||||||
// * provided accessor to request common {@link Evaluation}s and
|
|
||||||
// * {@link Change}s.
|
|
||||||
// *
|
|
||||||
// * @return a {@link WorldAccessor}
|
|
||||||
// * @see #requestChange(Change)
|
|
||||||
// * @see #requestEvaluation(Evaluation)
|
|
||||||
// */
|
|
||||||
// public WorldAccessor getWorldAccessor() {
|
|
||||||
// return worldAccessor;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public WorldAccessor getWorldAccessor___really_bad_dont_use() {
|
public WorldAccessor getWorldAccessor___really_bad_dont_use() {
|
||||||
return worldAccessor;
|
return worldAccessor;
|
||||||
}
|
}
|
||||||
@ -338,8 +354,8 @@ public class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleWorldTicks(Server server) {
|
private void scheduleWorldTicks(Server server) {
|
||||||
server.getWorld().getChunks().forEach(chunk -> requestEvaluation(chunk.getTickTask()));
|
server.getWorld().getChunks().forEach(chunk -> scheduleEvaluation(chunk.getTickTask()));
|
||||||
requestEvaluation(server.getWorld().getTickEntitiesTask());
|
scheduleEvaluation(server.getWorld().getTickEntitiesTask());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,8 +23,8 @@ import java.util.Collection;
|
|||||||
import java.util.ConcurrentModificationException;
|
import java.util.ConcurrentModificationException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -47,6 +47,12 @@ import ru.windcorp.progressia.server.Server;
|
|||||||
* @author javapony
|
* @author javapony
|
||||||
*/
|
*/
|
||||||
public class TickerCoordinator {
|
public class TickerCoordinator {
|
||||||
|
|
||||||
|
public enum TickPhase {
|
||||||
|
SYNCHRONOUS,
|
||||||
|
EVALUATION,
|
||||||
|
CHANGE
|
||||||
|
}
|
||||||
|
|
||||||
static final int INITIAL_QUEUE_SIZE = 1024;
|
static final int INITIAL_QUEUE_SIZE = 1024;
|
||||||
|
|
||||||
@ -77,7 +83,7 @@ public class TickerCoordinator {
|
|||||||
|
|
||||||
private final AtomicInteger workingTickers = new AtomicInteger();
|
private final AtomicInteger workingTickers = new AtomicInteger();
|
||||||
|
|
||||||
private final AtomicBoolean canChange = new AtomicBoolean(true);
|
private final AtomicReference<TickPhase> phase = new AtomicReference<>(TickPhase.SYNCHRONOUS);
|
||||||
|
|
||||||
private boolean isTickStartSet = false;
|
private boolean isTickStartSet = false;
|
||||||
private long tickStart = -1;
|
private long tickStart = -1;
|
||||||
@ -96,17 +102,14 @@ public class TickerCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.tickers = ImmutableList.copyOf(tickerCollection);
|
this.tickers = ImmutableList.copyOf(tickerCollection);
|
||||||
this.threads = Collections2.transform(this.tickers, Ticker::getThread); // Immutable
|
|
||||||
// because
|
// Immutable because it is a view
|
||||||
// it
|
this.threads = Collections2.transform(this.tickers, Ticker::getThread);
|
||||||
// is
|
|
||||||
// a
|
|
||||||
// view
|
|
||||||
|
|
||||||
server.getWorld().getData().addListener(ChunkDataListeners.createAdder(new ChunkDataListener() {
|
server.getWorld().getData().addListener(ChunkDataListeners.createAdder(new ChunkDataListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onChunkChanged(DefaultChunkData chunk) {
|
public void onChunkChanged(DefaultChunkData chunk) {
|
||||||
if (!canChange.get()) {
|
if (phase.get() == TickPhase.EVALUATION) {
|
||||||
throw CrashReports.report(null, "A change has been detected during evaluation phase");
|
throw CrashReports.report(null, "A change has been detected during evaluation phase");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -156,8 +159,14 @@ public class TickerCoordinator {
|
|||||||
public long getUptimeTicks() {
|
public long getUptimeTicks() {
|
||||||
return ticks;
|
return ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TickPhase getPhase() {
|
||||||
|
return phase.get();
|
||||||
|
}
|
||||||
|
|
||||||
private void onTickStart() {
|
private void onTickStart() {
|
||||||
|
phase.set(TickPhase.EVALUATION);
|
||||||
|
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
if (isTickStartSet) {
|
if (isTickStartSet) {
|
||||||
@ -171,6 +180,7 @@ public class TickerCoordinator {
|
|||||||
|
|
||||||
private void onTickEnd() {
|
private void onTickEnd() {
|
||||||
ticks++;
|
ticks++;
|
||||||
|
phase.set(TickPhase.SYNCHRONOUS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -212,9 +222,9 @@ public class TickerCoordinator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void runOnePass() throws InterruptedException {
|
private synchronized void runOnePass() throws InterruptedException {
|
||||||
canChange.set(false);
|
phase.set(TickPhase.EVALUATION);
|
||||||
runPassStage(pendingEvaluations, "EVALUATION");
|
runPassStage(pendingEvaluations, "EVALUATION");
|
||||||
canChange.set(true);
|
phase.set(TickPhase.CHANGE);
|
||||||
runPassStage(pendingChanges, "CHANGE");
|
runPassStage(pendingChanges, "CHANGE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +22,9 @@ import ru.windcorp.progressia.common.util.VectorUtil;
|
|||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
|
||||||
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
|
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
|
||||||
import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
|
||||||
|
|
||||||
public class TestBushFeature extends SurfaceTopLayerFeature {
|
public class TestBushFeature extends SurfaceTopLayerFeature {
|
||||||
|
|
||||||
@ -32,35 +32,35 @@ public class TestBushFeature extends SurfaceTopLayerFeature {
|
|||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToSetLeaves(SurfaceWorld world, Vec3i posSfc, BlockData leaves) {
|
private void tryToSetLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) {
|
||||||
if (world.getBlockSfc(posSfc).getId().equals("Test:Air")) {
|
if (context.getBlock(location).getId().equals("Test:Air")) {
|
||||||
world.setBlockSfc(posSfc, leaves, false);
|
context.setBlock(location, leaves);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
|
protected void processTopBlock(SurfaceBlockContext context) {
|
||||||
if (request.getRandom().nextInt(10*10) > 0) return;
|
if (context.getRandom().nextInt(10*10) > 0) return;
|
||||||
|
|
||||||
Vec3i center = topBlock.add_(0, 0, 1);
|
Vec3i center = context.getLocation().add_(0, 0, 1);
|
||||||
|
|
||||||
BlockData log = BlockDataRegistry.getInstance().get("Test:Log");
|
BlockData log = BlockDataRegistry.getInstance().get("Test:Log");
|
||||||
BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
|
BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
|
||||||
|
|
||||||
world.setBlockSfc(center, log, false);
|
context.setBlock(center, log);
|
||||||
|
|
||||||
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 3, 3, 3, p -> {
|
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 3, 3, 3, p -> {
|
||||||
tryToSetLeaves(world, p, leaves);
|
tryToSetLeaves(context, p, leaves);
|
||||||
});
|
});
|
||||||
|
|
||||||
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 5, 5, 1, p -> {
|
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 5, 5, 1, p -> {
|
||||||
tryToSetLeaves(world, p, leaves);
|
tryToSetLeaves(context, p, leaves);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
|
protected boolean isSolid(SurfaceBlockContext context) {
|
||||||
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
|
return context.logic().getBlock().isSolid(RelFace.UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,13 +21,11 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||||
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
|
import ru.windcorp.progressia.common.world.tile.TileDataRegistry;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
|
||||||
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
|
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
|
||||||
import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
|
||||||
|
|
||||||
public class TestGrassFeature extends SurfaceTopLayerFeature {
|
public class TestGrassFeature extends SurfaceTopLayerFeature {
|
||||||
|
|
||||||
@ -44,8 +42,8 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
|
protected void processTopBlock(SurfaceBlockContext context) {
|
||||||
if (!WHITELIST.contains(world.getBlockSfc(topBlock).getId())) {
|
if (!WHITELIST.contains(context.getBlock().getId())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,15 +52,19 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
|
|||||||
for (RelFace face : RelFace.getFaces()) {
|
for (RelFace face : RelFace.getFaces()) {
|
||||||
if (face == RelFace.DOWN) continue;
|
if (face == RelFace.DOWN) continue;
|
||||||
|
|
||||||
if (BlockLogicRegistry.getInstance().get(world.getBlockSfc(topBlock.add_(face.getRelVector())).getId()).isTransparent()) {
|
if (context.pushRelative(face).logic().getBlock().isTransparent()) {
|
||||||
world.getTilesSfc(topBlock, face).addFarthest(grass);
|
context.pop();
|
||||||
|
context.addTile(face, grass);
|
||||||
|
} else {
|
||||||
|
context.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
|
protected boolean isSolid(SurfaceBlockContext context) {
|
||||||
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
|
return context.logic().getBlock().isSolid(RelFace.UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,25 +24,27 @@ import ru.windcorp.progressia.common.util.VectorUtil;
|
|||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
|
||||||
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
|
import ru.windcorp.progressia.test.gen.surface.SurfaceTopLayerFeature;
|
||||||
import ru.windcorp.progressia.test.gen.surface.SurfaceWorld;
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
|
||||||
|
|
||||||
public class TestTreeFeature extends SurfaceTopLayerFeature {
|
public class TestTreeFeature extends SurfaceTopLayerFeature {
|
||||||
|
|
||||||
public TestTreeFeature(String id) {
|
public TestTreeFeature(String id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToSetLeaves(SurfaceWorld world, Vec3i posSfc, BlockData leaves) {
|
private void tryToSetLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) {
|
||||||
if (world.getBlockSfc(posSfc).getId().equals("Test:Air")) {
|
if (context.getBlock(location).getId().equals("Test:Air")) {
|
||||||
world.setBlockSfc(posSfc, leaves, false);
|
context.setBlock(location, leaves);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void iterateSpheroid(Vec3i center, double horDiameter, double vertDiameter, Consumer<Vec3i> action) {
|
private void iterateSpheroid(Vec3i center, double horDiameter, double vertDiameter, Consumer<Vec3i> action) {
|
||||||
VectorUtil.iterateCuboidAround(
|
VectorUtil.iterateCuboidAround(
|
||||||
center.x, center.y, center.z,
|
center.x,
|
||||||
|
center.y,
|
||||||
|
center.z,
|
||||||
(int) Math.ceil(horDiameter) / 2 * 2 + 5,
|
(int) Math.ceil(horDiameter) / 2 * 2 + 5,
|
||||||
(int) Math.ceil(horDiameter) / 2 * 2 + 5,
|
(int) Math.ceil(horDiameter) / 2 * 2 + 5,
|
||||||
(int) Math.ceil(vertDiameter) / 2 * 2 + 5,
|
(int) Math.ceil(vertDiameter) / 2 * 2 + 5,
|
||||||
@ -50,54 +52,55 @@ public class TestTreeFeature extends SurfaceTopLayerFeature {
|
|||||||
double sx = (pos.x - center.x) / horDiameter;
|
double sx = (pos.x - center.x) / horDiameter;
|
||||||
double sy = (pos.y - center.y) / horDiameter;
|
double sy = (pos.y - center.y) / horDiameter;
|
||||||
double sz = (pos.z - center.z) / vertDiameter;
|
double sz = (pos.z - center.z) / vertDiameter;
|
||||||
|
|
||||||
if (sx*sx + sy*sy + sz*sz <= 1) {
|
if (sx * sx + sy * sy + sz * sz <= 1) {
|
||||||
action.accept(pos);
|
action.accept(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
|
protected void processTopBlock(SurfaceBlockContext context) {
|
||||||
if (request.getRandom().nextInt(20*20) > 0) return;
|
if (context.getRandom().nextInt(20 * 20) > 0)
|
||||||
|
return;
|
||||||
Vec3i start = topBlock.add_(0, 0, 1);
|
|
||||||
|
Vec3i start = context.getLocation().add_(0, 0, 1);
|
||||||
|
|
||||||
BlockData log = BlockDataRegistry.getInstance().get("Test:Log");
|
BlockData log = BlockDataRegistry.getInstance().get("Test:Log");
|
||||||
BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
|
BlockData leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
|
||||||
|
|
||||||
Vec3i center = start.add_(0);
|
Vec3i center = start.add_(0);
|
||||||
|
|
||||||
int height = request.getRandom().nextInt(3) + 5;
|
int height = context.getRandom().nextInt(3) + 5;
|
||||||
for (; center.z < start.z + height; ++center.z) {
|
for (; center.z < start.z + height; ++center.z) {
|
||||||
world.setBlockSfc(center, log, false);
|
context.setBlock(center, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
double branchHorDistance = 0;
|
double branchHorDistance = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
double branchSize = 0.5 + 1 * request.getRandom().nextDouble();
|
double branchSize = 0.5 + 1 * context.getRandom().nextDouble();
|
||||||
double branchHorAngle = 2 * Math.PI * request.getRandom().nextDouble();
|
double branchHorAngle = 2 * Math.PI * context.getRandom().nextDouble();
|
||||||
int branchVertOffset = -2 + request.getRandom().nextInt(3);
|
int branchVertOffset = -2 + context.getRandom().nextInt(3);
|
||||||
|
|
||||||
Vec3i branchCenter = center.add_(
|
Vec3i branchCenter = center.add_(
|
||||||
(int) (Math.sin(branchHorAngle) * branchHorDistance),
|
(int) (Math.sin(branchHorAngle) * branchHorDistance),
|
||||||
(int) (Math.cos(branchHorAngle) * branchHorDistance),
|
(int) (Math.cos(branchHorAngle) * branchHorDistance),
|
||||||
branchVertOffset
|
branchVertOffset
|
||||||
);
|
);
|
||||||
|
|
||||||
iterateSpheroid(branchCenter, 1.75 * branchSize, 2.5 * branchSize, p -> {
|
iterateSpheroid(branchCenter, 1.75 * branchSize, 2.5 * branchSize, p -> {
|
||||||
tryToSetLeaves(world, p, leaves);
|
tryToSetLeaves(context, p, leaves);
|
||||||
});
|
});
|
||||||
|
|
||||||
branchHorDistance = 1 + 2 * request.getRandom().nextDouble();
|
branchHorDistance = 1 + 2 * context.getRandom().nextDouble();
|
||||||
} while (request.getRandom().nextInt(8) > 1);
|
} while (context.getRandom().nextInt(8) > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
|
protected boolean isSolid(SurfaceBlockContext context) {
|
||||||
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
|
return context.logic().getBlock().isSolid(RelFace.UP);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import glm.vec._3.i.Vec3i;
|
|||||||
import ru.windcorp.progressia.common.util.VectorUtil;
|
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.test.TestBushFeature;
|
import ru.windcorp.progressia.test.TestBushFeature;
|
||||||
import ru.windcorp.progressia.test.TestGrassFeature;
|
import ru.windcorp.progressia.test.TestGrassFeature;
|
||||||
import ru.windcorp.progressia.test.TestTreeFeature;
|
import ru.windcorp.progressia.test.TestTreeFeature;
|
||||||
@ -57,11 +58,11 @@ public class PlanetFeatureGenerator {
|
|||||||
return parent;
|
return parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateFeatures(DefaultChunkData chunk) {
|
public void generateFeatures(Server server, DefaultChunkData chunk) {
|
||||||
if (isOrdinaryChunk(chunk.getPosition())) {
|
if (isOrdinaryChunk(chunk.getPosition())) {
|
||||||
generateOrdinaryFeatures(chunk);
|
generateOrdinaryFeatures(server, chunk);
|
||||||
} else {
|
} else {
|
||||||
generateBorderFeatures(chunk);
|
generateBorderFeatures(server, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk.setGenerationHint(true);
|
chunk.setGenerationHint(true);
|
||||||
@ -72,11 +73,11 @@ public class PlanetFeatureGenerator {
|
|||||||
return sorted.x != sorted.y;
|
return sorted.x != sorted.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateOrdinaryFeatures(DefaultChunkData chunk) {
|
private void generateOrdinaryFeatures(Server server, DefaultChunkData chunk) {
|
||||||
surfaceGenerators.get(chunk.getUp()).generateFeatures(chunk);
|
surfaceGenerators.get(chunk.getUp()).generateFeatures(server, chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateBorderFeatures(DefaultChunkData chunk) {
|
private void generateBorderFeatures(Server server, DefaultChunkData chunk) {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
|
|||||||
DefaultChunkData chunk = getWorldData().getChunk(chunkPos);
|
DefaultChunkData chunk = getWorldData().getChunk(chunkPos);
|
||||||
|
|
||||||
if (!isChunkReady(chunk.getGenerationHint())) {
|
if (!isChunkReady(chunk.getGenerationHint())) {
|
||||||
featureGenerator.generateFeatures(chunk);
|
featureGenerator.generateFeatures(getServer(), chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
return chunk;
|
return chunk;
|
||||||
|
@ -18,15 +18,13 @@
|
|||||||
package ru.windcorp.progressia.test.gen.surface;
|
package ru.windcorp.progressia.test.gen.surface;
|
||||||
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import glm.Glm;
|
import glm.Glm;
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.VectorUtil;
|
|
||||||
import ru.windcorp.progressia.common.util.Vectors;
|
|
||||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.generic.GenericChunks;
|
import ru.windcorp.progressia.common.world.generic.GenericChunks;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
|
||||||
|
|
||||||
public abstract class SurfaceFeature extends Namespaced {
|
public abstract class SurfaceFeature extends Namespaced {
|
||||||
|
|
||||||
@ -107,60 +105,6 @@ public abstract class SurfaceFeature extends Namespaced {
|
|||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void process(SurfaceWorld world, Request request);
|
public abstract void process(SurfaceWorldContext context);
|
||||||
|
|
||||||
/*
|
|
||||||
* Utility methods
|
|
||||||
*/
|
|
||||||
|
|
||||||
public boolean contains(Request request, Vec3i surfaceBlockInWorld) {
|
|
||||||
Vec3i bic = Vectors.grab3i();
|
|
||||||
bic.set(surfaceBlockInWorld.x, surfaceBlockInWorld.y, surfaceBlockInWorld.z);
|
|
||||||
bic.sub(request.minSfc);
|
|
||||||
boolean result = GenericChunks.containsBiC(bic);
|
|
||||||
Vectors.release(bic);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void forEach(Request request, Consumer<? super Vec3i> action) {
|
|
||||||
VectorUtil.iterateCuboid(
|
|
||||||
request.minSfc.x,
|
|
||||||
request.minSfc.y,
|
|
||||||
request.minSfc.z,
|
|
||||||
request.maxSfc.x + 1,
|
|
||||||
request.maxSfc.y + 1,
|
|
||||||
request.maxSfc.z + 1,
|
|
||||||
action
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provided vectors have z set to {@link #getMinZ()}.
|
|
||||||
*/
|
|
||||||
public void forEachOnFloor(Request request, Consumer<? super Vec3i> action) {
|
|
||||||
forEachOnLayer(request, action, request.getMinZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provided vectors have z set to {@link #getMaxZ()}.
|
|
||||||
*/
|
|
||||||
public void forEachOnCeiling(Request request, Consumer<? super Vec3i> action) {
|
|
||||||
forEachOnLayer(request, action, request.getMaxZ());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provided vectors have z set to layer.
|
|
||||||
*/
|
|
||||||
public void forEachOnLayer(Request request, Consumer<? super Vec3i> action, int layer) {
|
|
||||||
VectorUtil.iterateCuboid(
|
|
||||||
request.minSfc.x,
|
|
||||||
request.minSfc.y,
|
|
||||||
layer,
|
|
||||||
request.maxSfc.x + 1,
|
|
||||||
request.maxSfc.y + 1,
|
|
||||||
layer + 1,
|
|
||||||
action
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,13 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
import glm.Glm;
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.CoordinatePacker;
|
import ru.windcorp.progressia.common.util.CoordinatePacker;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceContextImpl;
|
||||||
|
|
||||||
public class SurfaceFeatureGenerator {
|
public class SurfaceFeatureGenerator {
|
||||||
|
|
||||||
@ -42,14 +47,27 @@ public class SurfaceFeatureGenerator {
|
|||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateFeatures(DefaultChunkData chunk) {
|
public void generateFeatures(Server server, DefaultChunkData chunk) {
|
||||||
SurfaceWorld world = new SurfaceWorld(surface, chunk.getWorld());
|
|
||||||
|
|
||||||
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/);
|
Random random = new Random(CoordinatePacker.pack3IntsIntoLong(chunk.getPosition()) /* ^ seed*/);
|
||||||
SurfaceFeature.Request request = new SurfaceFeature.Request(world, chunk, random);
|
|
||||||
|
SurfaceContextImpl context = new SurfaceContextImpl((ServerTileContext) server.createAbsoluteContext(), surface);
|
||||||
|
context.setRandom(random);
|
||||||
|
|
||||||
|
Vec3i tmpA = new Vec3i();
|
||||||
|
Vec3i tmpB = new Vec3i();
|
||||||
|
|
||||||
|
chunk.getMinBIW(tmpA);
|
||||||
|
chunk.getMaxBIW(tmpB);
|
||||||
|
|
||||||
|
context.toContext(tmpA, tmpA);
|
||||||
|
context.toContext(tmpB, tmpB);
|
||||||
|
|
||||||
|
Glm.min(tmpA, tmpB, context.getMin());
|
||||||
|
Glm.max(tmpA, tmpB, context.getMax());
|
||||||
|
|
||||||
for (SurfaceFeature feature : features) {
|
for (SurfaceFeature feature : features) {
|
||||||
feature.process(world, request);
|
feature.process(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
chunk.setGenerationHint(true);
|
chunk.setGenerationHint(true);
|
||||||
|
@ -18,41 +18,47 @@
|
|||||||
package ru.windcorp.progressia.test.gen.surface;
|
package ru.windcorp.progressia.test.gen.surface;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.Vectors;
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
|
||||||
|
|
||||||
public abstract class SurfaceTopLayerFeature extends SurfaceFeature {
|
public abstract class SurfaceTopLayerFeature extends SurfaceFeature {
|
||||||
|
|
||||||
public SurfaceTopLayerFeature(String id) {
|
public SurfaceTopLayerFeature(String id) {
|
||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock);
|
protected abstract void processTopBlock(SurfaceBlockContext context);
|
||||||
|
|
||||||
protected abstract boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld);
|
protected abstract boolean isSolid(SurfaceBlockContext context);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(SurfaceWorld world, Request request) {
|
public void process(SurfaceWorldContext context) {
|
||||||
Vec3i cursor = Vectors.grab3i();
|
Vec3i cursor = new Vec3i();
|
||||||
|
|
||||||
forEachOnLayer(request, pos -> {
|
context.forEachOnFloor(pos -> {
|
||||||
|
|
||||||
cursor.set(pos.x, pos.y, pos.z);
|
cursor.set(pos.x, pos.y, pos.z);
|
||||||
|
|
||||||
if (!isSolid(world, cursor)) {
|
if (!isSolid(context.push(cursor))) {
|
||||||
|
context.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
context.pop();
|
||||||
for (cursor.z += 1; cursor.z <= request.getMaxZ() + 1; ++cursor.z) {
|
|
||||||
if (!isSolid(world, cursor)) {
|
for (cursor.z += 1; cursor.z <= context.getMaxZ() + 1; ++cursor.z) {
|
||||||
cursor.z -= 1;
|
SurfaceBlockContext blockContext = context.push(cursor);
|
||||||
processTopBlock(world, request, cursor);
|
|
||||||
|
if (!isSolid(blockContext)) {
|
||||||
|
processTopBlock(blockContext.pushRelative(0, 0, -1));
|
||||||
|
context.pop();
|
||||||
|
context.pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, request.getMinZ());
|
});
|
||||||
|
|
||||||
Vectors.release(cursor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelRelation;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
|
||||||
|
public interface SurfaceBlockContext extends ServerBlockContext, SurfaceWorldContext {
|
||||||
|
|
||||||
|
public interface Logic extends ServerBlockContext.Logic, SurfaceWorldContext.Logic {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceBlockContext data();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceBlockContext.Logic pushRelative(int dx, int dy, int dz) {
|
||||||
|
return push(getLocation().add_(dx, dy, dz));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceBlockContext.Logic pushRelative(Vec3i direction) {
|
||||||
|
return push(getLocation().add_(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceBlockContext.Logic pushRelative(RelRelation direction) {
|
||||||
|
return push(getLocation().add_(direction.getRelVector()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileStackContext.Logic push(RelFace face) {
|
||||||
|
return push(getLocation(), face);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext.Logic push(RelFace face, int layer) {
|
||||||
|
return push(getLocation(), face, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceBlockContext.Logic logic();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceBlockContext pushRelative(int dx, int dy, int dz) {
|
||||||
|
return push(getLocation().add_(dx, dy, dz));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceBlockContext pushRelative(Vec3i direction) {
|
||||||
|
return push(getLocation().add_(direction));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceBlockContext pushRelative(RelRelation direction) {
|
||||||
|
return push(getLocation().add_(direction.getRelVector()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileStackContext push(RelFace face) {
|
||||||
|
return push(getLocation(), face);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext push(RelFace face, int layer) {
|
||||||
|
return push(getLocation(), face, layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.util.VectorUtil;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.Surface;
|
||||||
|
|
||||||
|
public interface SurfaceContext {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Surface} object relevant to this context.
|
||||||
|
*
|
||||||
|
* @return the surface details
|
||||||
|
*/
|
||||||
|
Surface getSurface();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns lower bounds (inclusive) on the coordinates of the requested
|
||||||
|
* region.
|
||||||
|
*
|
||||||
|
* @return the coordinates of the minimum corner of the region that
|
||||||
|
* should be processed
|
||||||
|
*/
|
||||||
|
Vec3i getMin();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns upper bounds (inclusive) on the coordinates of the requested
|
||||||
|
* region.
|
||||||
|
*
|
||||||
|
* @return the coordinates of the maximum corner of the region that
|
||||||
|
* should be processed
|
||||||
|
*/
|
||||||
|
Vec3i getMax();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convenience methods
|
||||||
|
*/
|
||||||
|
|
||||||
|
default int getMinX() {
|
||||||
|
return getMin().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getMinY() {
|
||||||
|
return getMin().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getMinZ() {
|
||||||
|
return getMin().z;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getMaxX() {
|
||||||
|
return getMax().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getMaxY() {
|
||||||
|
return getMax().y;
|
||||||
|
}
|
||||||
|
|
||||||
|
default int getMaxZ() {
|
||||||
|
return getMax().z;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isRequested(int x, int y, int z) {
|
||||||
|
Vec3i min = getMin();
|
||||||
|
Vec3i max = getMax();
|
||||||
|
return (min.x <= x && x <= max.x) && (min.y <= y && y <= max.y) && (min.z <= z && z <= max.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isRequested(Vec3i location) {
|
||||||
|
return isRequested(location.x, location.y, location.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void forEachRequested(Consumer<? super Vec3i> action) {
|
||||||
|
Vec3i min = getMin();
|
||||||
|
Vec3i max = getMax();
|
||||||
|
VectorUtil.iterateCuboid(
|
||||||
|
min.x,
|
||||||
|
min.y,
|
||||||
|
min.z,
|
||||||
|
max.x + 1,
|
||||||
|
max.y + 1,
|
||||||
|
max.z + 1,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provided vectors have z set to {@link #getMinZ()}.
|
||||||
|
*/
|
||||||
|
default void forEachOnFloor(Consumer<? super Vec3i> action) {
|
||||||
|
forEachOnLayer(action, getMinZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provided vectors have z set to {@link #getMaxZ()}.
|
||||||
|
*/
|
||||||
|
default void forEachOnCeiling(Consumer<? super Vec3i> action) {
|
||||||
|
forEachOnLayer(action, getMaxZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provided vectors have z set to layer.
|
||||||
|
*/
|
||||||
|
default void forEachOnLayer(Consumer<? super Vec3i> action, int layer) {
|
||||||
|
Vec3i min = getMin();
|
||||||
|
Vec3i max = getMax();
|
||||||
|
VectorUtil.iterateCuboid(
|
||||||
|
min.x,
|
||||||
|
min.y,
|
||||||
|
layer,
|
||||||
|
max.x + 1,
|
||||||
|
max.y + 1,
|
||||||
|
layer + 1,
|
||||||
|
action
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.impl.RotatingServerContext;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.Surface;
|
||||||
|
|
||||||
|
public class SurfaceContextImpl extends RotatingServerContext implements SurfaceTileContext {
|
||||||
|
|
||||||
|
final Surface surface;
|
||||||
|
final Vec3i min = new Vec3i();
|
||||||
|
final Vec3i max = new Vec3i();
|
||||||
|
private Random random;
|
||||||
|
|
||||||
|
private final SurfaceContextImplLogic logic;
|
||||||
|
|
||||||
|
public SurfaceContextImpl(ServerTileContext parent, Surface surface) {
|
||||||
|
super(parent, surface.getUp());
|
||||||
|
this.logic = new SurfaceContextImplLogic(this);
|
||||||
|
|
||||||
|
this.surface = surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void transform(Vec3i userLocation, Vec3i output) {
|
||||||
|
output.set(userLocation.x, userLocation.y, userLocation.z);
|
||||||
|
output.z += surface.getSeaLevel();
|
||||||
|
super.transform(output, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void untransform(Vec3i parentLocation, Vec3i output) {
|
||||||
|
super.untransform(parentLocation, output);
|
||||||
|
output.z -= surface.getSeaLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Surface getSurface() {
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @implNote can rw
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Vec3i getMin() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*
|
||||||
|
* @implNote can rw
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Vec3i getMax() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Random getRandom() {
|
||||||
|
return random;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRandom(Random random) {
|
||||||
|
this.random = random;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceContextImplLogic logic() {
|
||||||
|
return logic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceTileContext push(Vec3i location) {
|
||||||
|
super.push(location);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceTileContext push(Vec3i location, RelFace face) {
|
||||||
|
super.push(location, face);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceTileContext push(Vec3i location, RelFace face, int layer) {
|
||||||
|
super.push(location, face, layer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.server.world.context.impl.DefaultServerContextLogic;
|
||||||
|
import ru.windcorp.progressia.test.gen.surface.Surface;
|
||||||
|
|
||||||
|
public class SurfaceContextImplLogic extends DefaultServerContextLogic implements SurfaceTileContext.Logic {
|
||||||
|
|
||||||
|
private final SurfaceContextImpl surfaceParent;
|
||||||
|
|
||||||
|
public SurfaceContextImplLogic(SurfaceContextImpl surfaceParent) {
|
||||||
|
super(surfaceParent);
|
||||||
|
this.surfaceParent = surfaceParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Surface getSurface() {
|
||||||
|
return this.surfaceParent.surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i getMin() {
|
||||||
|
return this.surfaceParent.min;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i getMax() {
|
||||||
|
return this.surfaceParent.max;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceContextImpl data() {
|
||||||
|
return this.surfaceParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceTileContext.Logic push(Vec3i location) {
|
||||||
|
super.push(location);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceTileContext.Logic push(Vec3i location, RelFace face) {
|
||||||
|
super.push(location, face);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SurfaceTileContext.Logic push(Vec3i location, RelFace face, int layer) {
|
||||||
|
super.push(location, face, layer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
|
||||||
|
public interface SurfaceTileContext extends ServerTileContext, SurfaceTileStackContext {
|
||||||
|
|
||||||
|
public interface Logic extends ServerTileContext.Logic, SurfaceTileStackContext.Logic {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileContext data();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext.Logic pushCloser() {
|
||||||
|
return push(getLocation(), getFace(), getLayer() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext.Logic pushFarther() {
|
||||||
|
return push(getLocation(), getFace(), getLayer() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileContext.Logic logic();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext pushCloser() {
|
||||||
|
return push(getLocation(), getFace(), getLayer() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext pushFarther() {
|
||||||
|
return push(getLocation(), getFace(), getLayer() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileStackContext;
|
||||||
|
|
||||||
|
public interface SurfaceTileStackContext extends ServerTileStackContext, SurfaceBlockContext {
|
||||||
|
|
||||||
|
public interface Logic extends ServerTileStackContext.Logic, SurfaceBlockContext.Logic {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileStackContext data();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext.Logic push(int layer) {
|
||||||
|
return push(getLocation(), getFace(), layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileStackContext.Logic pushCounter() {
|
||||||
|
return push(getFace().getCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileStackContext.Logic pushOpposite() {
|
||||||
|
return push(getLocation().add_(getFace().getRelVector()), getFace().getCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileStackContext.Logic logic();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileContext push(int layer) {
|
||||||
|
return push(getLocation(), getFace(), layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileStackContext pushCounter() {
|
||||||
|
return push(getFace().getCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
default SurfaceTileStackContext pushOpposite() {
|
||||||
|
return push(getLocation().add_(getFace().getRelVector()), getFace().getCounter());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Progressia
|
||||||
|
* Copyright (C) 2020-2021 Wind Corporation and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package ru.windcorp.progressia.test.gen.surface.context;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
||||||
|
|
||||||
|
public interface SurfaceWorldContext extends ServerWorldContext, SurfaceContext {
|
||||||
|
|
||||||
|
public interface Logic extends ServerWorldContext.Logic, SurfaceContext {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceWorldContext data();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceBlockContext.Logic push(Vec3i location);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileStackContext.Logic push(Vec3i location, RelFace face);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileContext.Logic push(Vec3i location, RelFace face, int layer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceWorldContext.Logic logic();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceBlockContext push(Vec3i location);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileStackContext push(Vec3i location, RelFace face);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
SurfaceTileContext push(Vec3i location, RelFace face, int layer);
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user