Added SurfaceContexts to replace SurfaceWorld+Request. WIP

There is a problem with features when up != POS_Z
This commit is contained in:
OLEGSHA 2021-08-17 16:05:44 +03:00
parent a6fd81ba1e
commit d33b48578d
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
17 changed files with 757 additions and 176 deletions

View File

@ -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.ticking.Change;
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.TestPlanetGenerator;
@ -232,14 +233,42 @@ public class Server {
schedule(() -> task.accept(this));
}
public void requestChange(Change change) {
/**
* Delayed
*/
public void scheduleChange(Change change) {
serverThread.getTicker().requestChange(change);
}
public void requestEvaluation(Evaluation evaluation) {
/**
* Delayed
*/
public void scheduleEvaluation(Evaluation 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) {
eventBus.register(object);
}
@ -280,19 +309,6 @@ public class Server {
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() {
return worldAccessor;
}
@ -338,8 +354,8 @@ public class Server {
}
private void scheduleWorldTicks(Server server) {
server.getWorld().getChunks().forEach(chunk -> requestEvaluation(chunk.getTickTask()));
requestEvaluation(server.getWorld().getTickEntitiesTask());
server.getWorld().getChunks().forEach(chunk -> scheduleEvaluation(chunk.getTickTask()));
scheduleEvaluation(server.getWorld().getTickEntitiesTask());
}
/**

View File

@ -23,8 +23,8 @@ import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -48,6 +48,12 @@ import ru.windcorp.progressia.server.Server;
*/
public class TickerCoordinator {
public enum TickPhase {
SYNCHRONOUS,
EVALUATION,
CHANGE
}
static final int INITIAL_QUEUE_SIZE = 1024;
private final Server server;
@ -77,7 +83,7 @@ public class TickerCoordinator {
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 long tickStart = -1;
@ -96,17 +102,14 @@ public class TickerCoordinator {
}
this.tickers = ImmutableList.copyOf(tickerCollection);
this.threads = Collections2.transform(this.tickers, Ticker::getThread); // Immutable
// because
// it
// is
// a
// view
// Immutable because it is a view
this.threads = Collections2.transform(this.tickers, Ticker::getThread);
server.getWorld().getData().addListener(ChunkDataListeners.createAdder(new ChunkDataListener() {
@Override
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");
}
}
@ -157,7 +160,13 @@ public class TickerCoordinator {
return ticks;
}
public TickPhase getPhase() {
return phase.get();
}
private void onTickStart() {
phase.set(TickPhase.EVALUATION);
long now = System.currentTimeMillis();
if (isTickStartSet) {
@ -171,6 +180,7 @@ public class TickerCoordinator {
private void onTickEnd() {
ticks++;
phase.set(TickPhase.SYNCHRONOUS);
}
/*
@ -212,9 +222,9 @@ public class TickerCoordinator {
}
private synchronized void runOnePass() throws InterruptedException {
canChange.set(false);
phase.set(TickPhase.EVALUATION);
runPassStage(pendingEvaluations, "EVALUATION");
canChange.set(true);
phase.set(TickPhase.CHANGE);
runPassStage(pendingChanges, "CHANGE");
}

View File

@ -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.BlockDataRegistry;
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.SurfaceWorld;
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
public class TestBushFeature extends SurfaceTopLayerFeature {
@ -32,35 +32,35 @@ public class TestBushFeature extends SurfaceTopLayerFeature {
super(id);
}
private void tryToSetLeaves(SurfaceWorld world, Vec3i posSfc, BlockData leaves) {
if (world.getBlockSfc(posSfc).getId().equals("Test:Air")) {
world.setBlockSfc(posSfc, leaves, false);
private void tryToSetLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) {
if (context.getBlock(location).getId().equals("Test:Air")) {
context.setBlock(location, leaves);
}
}
@Override
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
if (request.getRandom().nextInt(10*10) > 0) return;
protected void processTopBlock(SurfaceBlockContext context) {
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 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 -> {
tryToSetLeaves(world, p, leaves);
tryToSetLeaves(context, p, leaves);
});
VectorUtil.iterateCuboidAround(center.x, center.y, center.z, 5, 5, 1, p -> {
tryToSetLeaves(world, p, leaves);
tryToSetLeaves(context, p, leaves);
});
}
@Override
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
protected boolean isSolid(SurfaceBlockContext context) {
return context.logic().getBlock().isSolid(RelFace.UP);
}
}

View File

@ -21,13 +21,11 @@ import java.util.Set;
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.tile.TileData;
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.SurfaceWorld;
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
public class TestGrassFeature extends SurfaceTopLayerFeature {
@ -44,8 +42,8 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
}
@Override
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
if (!WHITELIST.contains(world.getBlockSfc(topBlock).getId())) {
protected void processTopBlock(SurfaceBlockContext context) {
if (!WHITELIST.contains(context.getBlock().getId())) {
return;
}
@ -54,15 +52,19 @@ public class TestGrassFeature extends SurfaceTopLayerFeature {
for (RelFace face : RelFace.getFaces()) {
if (face == RelFace.DOWN) continue;
if (BlockLogicRegistry.getInstance().get(world.getBlockSfc(topBlock.add_(face.getRelVector())).getId()).isTransparent()) {
world.getTilesSfc(topBlock, face).addFarthest(grass);
if (context.pushRelative(face).logic().getBlock().isTransparent()) {
context.pop();
context.addTile(face, grass);
} else {
context.pop();
}
}
}
@Override
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
protected boolean isSolid(SurfaceBlockContext context) {
return context.logic().getBlock().isSolid(RelFace.UP);
}
}

View File

@ -24,9 +24,9 @@ import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.block.BlockData;
import ru.windcorp.progressia.common.world.block.BlockDataRegistry;
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.SurfaceWorld;
import ru.windcorp.progressia.test.gen.surface.context.SurfaceBlockContext;
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
public class TestTreeFeature extends SurfaceTopLayerFeature {
@ -34,15 +34,17 @@ public class TestTreeFeature extends SurfaceTopLayerFeature {
super(id);
}
private void tryToSetLeaves(SurfaceWorld world, Vec3i posSfc, BlockData leaves) {
if (world.getBlockSfc(posSfc).getId().equals("Test:Air")) {
world.setBlockSfc(posSfc, leaves, false);
private void tryToSetLeaves(SurfaceWorldContext context, Vec3i location, BlockData leaves) {
if (context.getBlock(location).getId().equals("Test:Air")) {
context.setBlock(location, leaves);
}
}
private void iterateSpheroid(Vec3i center, double horDiameter, double vertDiameter, Consumer<Vec3i> action) {
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(vertDiameter) / 2 * 2 + 5,
@ -51,7 +53,7 @@ public class TestTreeFeature extends SurfaceTopLayerFeature {
double sy = (pos.y - center.y) / horDiameter;
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);
}
}
@ -59,27 +61,28 @@ public class TestTreeFeature extends SurfaceTopLayerFeature {
}
@Override
protected void processTopBlock(SurfaceWorld world, Request request, Vec3i topBlock) {
if (request.getRandom().nextInt(20*20) > 0) return;
protected void processTopBlock(SurfaceBlockContext context) {
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 leaves = BlockDataRegistry.getInstance().get("Test:TemporaryLeaves");
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) {
world.setBlockSfc(center, log, false);
context.setBlock(center, log);
}
double branchHorDistance = 0;
do {
double branchSize = 0.5 + 1 * request.getRandom().nextDouble();
double branchHorAngle = 2 * Math.PI * request.getRandom().nextDouble();
int branchVertOffset = -2 + request.getRandom().nextInt(3);
double branchSize = 0.5 + 1 * context.getRandom().nextDouble();
double branchHorAngle = 2 * Math.PI * context.getRandom().nextDouble();
int branchVertOffset = -2 + context.getRandom().nextInt(3);
Vec3i branchCenter = center.add_(
(int) (Math.sin(branchHorAngle) * branchHorDistance),
@ -88,16 +91,16 @@ public class TestTreeFeature extends SurfaceTopLayerFeature {
);
iterateSpheroid(branchCenter, 1.75 * branchSize, 2.5 * branchSize, p -> {
tryToSetLeaves(world, p, leaves);
tryToSetLeaves(context, p, leaves);
});
branchHorDistance = 1 + 2 * request.getRandom().nextDouble();
} while (request.getRandom().nextInt(8) > 1);
branchHorDistance = 1 + 2 * context.getRandom().nextDouble();
} while (context.getRandom().nextInt(8) > 1);
}
@Override
protected boolean isSolid(SurfaceWorld world, Vec3i surfaceBlockInWorld) {
return BlockLogicRegistry.getInstance().get(world.getBlockSfc(surfaceBlockInWorld).getId()).isSolid(RelFace.UP);
protected boolean isSolid(SurfaceBlockContext context) {
return context.logic().getBlock().isSolid(RelFace.UP);
}
}

View File

@ -25,6 +25,7 @@ import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.util.VectorUtil;
import ru.windcorp.progressia.common.world.DefaultChunkData;
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.TestGrassFeature;
import ru.windcorp.progressia.test.TestTreeFeature;
@ -57,11 +58,11 @@ public class PlanetFeatureGenerator {
return parent;
}
public void generateFeatures(DefaultChunkData chunk) {
public void generateFeatures(Server server, DefaultChunkData chunk) {
if (isOrdinaryChunk(chunk.getPosition())) {
generateOrdinaryFeatures(chunk);
generateOrdinaryFeatures(server, chunk);
} else {
generateBorderFeatures(chunk);
generateBorderFeatures(server, chunk);
}
chunk.setGenerationHint(true);
@ -72,11 +73,11 @@ public class PlanetFeatureGenerator {
return sorted.x != sorted.y;
}
private void generateOrdinaryFeatures(DefaultChunkData chunk) {
surfaceGenerators.get(chunk.getUp()).generateFeatures(chunk);
private void generateOrdinaryFeatures(Server server, DefaultChunkData chunk) {
surfaceGenerators.get(chunk.getUp()).generateFeatures(server, chunk);
}
private void generateBorderFeatures(DefaultChunkData chunk) {
private void generateBorderFeatures(Server server, DefaultChunkData chunk) {
// Do nothing
}

View File

@ -81,7 +81,7 @@ public class TestPlanetGenerator extends AbstractWorldGenerator<Boolean> {
DefaultChunkData chunk = getWorldData().getChunk(chunkPos);
if (!isChunkReady(chunk.getGenerationHint())) {
featureGenerator.generateFeatures(chunk);
featureGenerator.generateFeatures(getServer(), chunk);
}
return chunk;

View File

@ -18,15 +18,13 @@
package ru.windcorp.progressia.test.gen.surface;
import java.util.Random;
import java.util.function.Consumer;
import glm.Glm;
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.world.DefaultChunkData;
import ru.windcorp.progressia.common.world.generic.GenericChunks;
import ru.windcorp.progressia.test.gen.surface.context.SurfaceWorldContext;
public abstract class SurfaceFeature extends Namespaced {
@ -107,60 +105,6 @@ public abstract class SurfaceFeature extends Namespaced {
super(id);
}
public abstract void process(SurfaceWorld world, Request request);
/*
* 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
);
}
public abstract void process(SurfaceWorldContext context);
}

View File

@ -21,8 +21,13 @@ import java.util.ArrayList;
import java.util.Collection;
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.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 {
@ -42,14 +47,27 @@ public class SurfaceFeatureGenerator {
return surface;
}
public void generateFeatures(DefaultChunkData chunk) {
SurfaceWorld world = new SurfaceWorld(surface, chunk.getWorld());
public void generateFeatures(Server server, DefaultChunkData chunk) {
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) {
feature.process(world, request);
feature.process(context);
}
chunk.setGenerationHint(true);

View File

@ -18,7 +18,8 @@
package ru.windcorp.progressia.test.gen.surface;
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 {
@ -26,33 +27,38 @@ public abstract class SurfaceTopLayerFeature extends SurfaceFeature {
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
public void process(SurfaceWorld world, Request request) {
Vec3i cursor = Vectors.grab3i();
public void process(SurfaceWorldContext context) {
Vec3i cursor = new Vec3i();
forEachOnLayer(request, pos -> {
context.forEachOnFloor(pos -> {
cursor.set(pos.x, pos.y, pos.z);
if (!isSolid(world, cursor)) {
if (!isSolid(context.push(cursor))) {
context.pop();
return;
}
context.pop();
for (cursor.z += 1; cursor.z <= context.getMaxZ() + 1; ++cursor.z) {
SurfaceBlockContext blockContext = context.push(cursor);
if (!isSolid(blockContext)) {
processTopBlock(blockContext.pushRelative(0, 0, -1));
context.pop();
context.pop();
return;
}
for (cursor.z += 1; cursor.z <= request.getMaxZ() + 1; ++cursor.z) {
if (!isSolid(world, cursor)) {
cursor.z -= 1;
processTopBlock(world, request, cursor);
return;
}
context.pop();
}
}, request.getMinZ());
Vectors.release(cursor);
});
}
}

View File

@ -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);
}
}

View File

@ -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
);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}