Added TransformingServerContext and RotatingServerContext. WIP
There is a problem with faces in contexts when up != POS_Z, world crashes soon after startup - Added TransformingServerContext - a common basis for context wrappers that alter the coordinate space - Added RotatingServerContext - a context wrapper that rotates the coordinate space - Used to ensure positive Z is up - PacketAffectTile now checks the provided tile tag for validity - This causes a crash when the invalid action is requested, not executed - TickChunk task reuses contexts
This commit is contained in:
parent
78a1c25554
commit
54c66d28d6
@ -20,7 +20,9 @@ package ru.windcorp.progressia.common.world.generic.context;
|
|||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.context.Context;
|
import ru.windcorp.progressia.common.world.context.Context;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsRelation;
|
import ru.windcorp.progressia.common.world.rels.AbsRelation;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -81,6 +83,80 @@ class WorldContexts {
|
|||||||
*/
|
*/
|
||||||
Tile push(Vec3i location, RelFace face, int layer);
|
Tile push(Vec3i location, RelFace face, int layer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the provided location given in the context's coordinate
|
||||||
|
* space to the underlying absolute coordinate space.
|
||||||
|
* <p>
|
||||||
|
* The definition of "absolute coordinate space" for contexts that are
|
||||||
|
* not {@linkplain #isReal() real} may be arbitrary, but methods
|
||||||
|
* {@link #toAbsolute(Vec3i, Vec3i)}, {@link #toAbsolute(BlockFace)},
|
||||||
|
* {@link #toContext(Vec3i, Vec3i)} and {@link #toContext(AbsFace)} are
|
||||||
|
* guaranteed to be consistent for all contexts.
|
||||||
|
*
|
||||||
|
* @param contextLocation the location expressed in context coordinate
|
||||||
|
* system
|
||||||
|
* @param output the {@link Vec3i} object to output the result
|
||||||
|
* into, or {@code null}
|
||||||
|
* @return The location expressed in absolute coordinate system. If
|
||||||
|
* {@code output} is not {@code null}, {@code output} is
|
||||||
|
* returned; otherwise, a new {@link Vec3i} is instantiated and
|
||||||
|
* returned
|
||||||
|
*/
|
||||||
|
Vec3i toAbsolute(Vec3i contextLocation, Vec3i output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the provided location given in the absolute coordinate
|
||||||
|
* space to the context coordinate space.
|
||||||
|
* <p>
|
||||||
|
* The definition of "absolute coordinate space" for contexts that are
|
||||||
|
* not {@linkplain #isReal() real} may be arbitrary, but methods
|
||||||
|
* {@link #toAbsolute(Vec3i, Vec3i)}, {@link #toAbsolute(BlockFace)},
|
||||||
|
* {@link #toContext(Vec3i, Vec3i)} and {@link #toContext(AbsFace)} are
|
||||||
|
* guaranteed to be consistent for all contexts.
|
||||||
|
*
|
||||||
|
* @param contextLocation the location expressed in absolute coordinate
|
||||||
|
* system
|
||||||
|
* @param output the {@link Vec3i} object to output the result
|
||||||
|
* into, or {@code null}
|
||||||
|
* @return The location expressed in context coordinate system. If
|
||||||
|
* {@code output} is not {@code null}, {@code output} is
|
||||||
|
* returned; otherwise, a new {@link Vec3i} is instantiated and
|
||||||
|
* returned
|
||||||
|
*/
|
||||||
|
Vec3i toContext(Vec3i absoluteLocation, Vec3i output);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the provided face given in the context's coordinate
|
||||||
|
* space to the underlying absolute coordinate space.
|
||||||
|
* <p>
|
||||||
|
* The definition of "absolute coordinate space" for contexts that are
|
||||||
|
* not {@linkplain #isReal() real} may be arbitrary, but methods
|
||||||
|
* {@link #toAbsolute(Vec3i, Vec3i)}, {@link #toAbsolute(BlockFace)},
|
||||||
|
* {@link #toContext(Vec3i, Vec3i)} and {@link #toContext(AbsFace)} are
|
||||||
|
* guaranteed to be consistent for all contexts.
|
||||||
|
*
|
||||||
|
* @param contextLocation the face expressed in context coordinate
|
||||||
|
* system
|
||||||
|
* @return the face expressed in absolute coordinate system
|
||||||
|
*/
|
||||||
|
AbsFace toAbsolute(BlockFace contextFace);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the provided face given in the absolute coordinate
|
||||||
|
* space to the context coordinate space.
|
||||||
|
* <p>
|
||||||
|
* The definition of "absolute coordinate space" for contexts that are
|
||||||
|
* not {@linkplain #isReal() real} may be arbitrary, but methods
|
||||||
|
* {@link #toAbsolute(Vec3i, Vec3i)}, {@link #toAbsolute(BlockFace)},
|
||||||
|
* {@link #toContext(Vec3i, Vec3i)} and {@link #toContext(AbsFace)} are
|
||||||
|
* guaranteed to be consistent for all contexts.
|
||||||
|
*
|
||||||
|
* @param contextLocation the face expressed in absolute coordinate
|
||||||
|
* system
|
||||||
|
* @return the face expressed in context coordinate system
|
||||||
|
*/
|
||||||
|
RelFace toContext(AbsFace absoluteFace);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,6 +51,10 @@ public abstract class PacketAffectTile extends PacketAffectChunk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void set(Vec3i blockInWorld, AbsFace face, int tag) {
|
public void set(Vec3i blockInWorld, AbsFace face, int tag) {
|
||||||
|
if (tag < 0) {
|
||||||
|
throw new IllegalArgumentException("Cannot affect tile with tag -1");
|
||||||
|
}
|
||||||
|
|
||||||
this.blockInWorld.set(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
this.blockInWorld.set(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
||||||
this.face = face;
|
this.face = face;
|
||||||
this.tag = tag;
|
this.tag = tag;
|
||||||
|
@ -24,20 +24,26 @@ import org.apache.logging.log4j.LogManager;
|
|||||||
|
|
||||||
import com.google.common.eventbus.EventBus;
|
import com.google.common.eventbus.EventBus;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.jputil.functions.ThrowingRunnable;
|
import ru.windcorp.jputil.functions.ThrowingRunnable;
|
||||||
import ru.windcorp.progressia.common.Units;
|
import ru.windcorp.progressia.common.Units;
|
||||||
import ru.windcorp.progressia.common.util.TaskQueue;
|
import ru.windcorp.progressia.common.util.TaskQueue;
|
||||||
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||||
import ru.windcorp.progressia.common.world.DefaultWorldData;
|
import ru.windcorp.progressia.common.world.DefaultWorldData;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AxisRotations;
|
||||||
import ru.windcorp.progressia.server.comms.ClientManager;
|
import ru.windcorp.progressia.server.comms.ClientManager;
|
||||||
import ru.windcorp.progressia.server.events.ServerEvent;
|
import ru.windcorp.progressia.server.events.ServerEvent;
|
||||||
import ru.windcorp.progressia.server.management.load.ChunkRequestDaemon;
|
import ru.windcorp.progressia.server.management.load.ChunkRequestDaemon;
|
||||||
import ru.windcorp.progressia.server.management.load.EntityRequestDaemon;
|
import ru.windcorp.progressia.server.management.load.EntityRequestDaemon;
|
||||||
import ru.windcorp.progressia.server.management.load.LoadManager;
|
import ru.windcorp.progressia.server.management.load.LoadManager;
|
||||||
import ru.windcorp.progressia.server.world.DefaultWorldLogic;
|
import ru.windcorp.progressia.server.world.DefaultWorldLogic;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
||||||
import ru.windcorp.progressia.server.world.context.impl.DefaultServerContext;
|
import ru.windcorp.progressia.server.world.context.impl.DefaultServerContext;
|
||||||
import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext;
|
import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext;
|
||||||
|
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;
|
||||||
@ -102,15 +108,54 @@ public class Server {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates and returns an new {@link ServerWorldContext} instance
|
* Instantiates and returns an new {@link ServerWorldContext} instance
|
||||||
* suitable for read and write access to the server's world. This is the
|
* suitable for read and write access to the server's world. This context
|
||||||
* preferred way to query or change the world.
|
* uses the absolute coordinate space (not rotated to match positive Z =
|
||||||
|
* up).
|
||||||
*
|
*
|
||||||
* @return the context
|
* @return the context
|
||||||
|
* @see #createContext(AbsFace)
|
||||||
*/
|
*/
|
||||||
public ServerWorldContext createContext() {
|
public ServerWorldContext createAbsoluteContext() {
|
||||||
|
return doCreateAbsoluteContext();
|
||||||
|
}
|
||||||
|
|
||||||
return new ReportingServerContext(DefaultServerContext.empty().inRealWorldOf(this).build()).withListener(worldAccessor).setPassToParent(false);
|
private ServerTileContext doCreateAbsoluteContext() {
|
||||||
|
return new ReportingServerContext(DefaultServerContext.empty().inRealWorldOf(this).build())
|
||||||
|
.withListener(worldAccessor).setPassToParent(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates and returns an new {@link ServerWorldContext} instance
|
||||||
|
* suitable for read and write access to the server's world. This is the
|
||||||
|
* preferred way to query or change the world. This context uses the
|
||||||
|
* coordinate space in which positive Z = {@code up}.
|
||||||
|
*
|
||||||
|
* @param up the desired up direction
|
||||||
|
* @return the context
|
||||||
|
* @see #createContext(Vec3i)
|
||||||
|
* @see #createAbsoluteContext()
|
||||||
|
*/
|
||||||
|
public ServerWorldContext createContext(AbsFace up) {
|
||||||
|
return new RotatingServerContext(doCreateAbsoluteContext(), up);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates and returns an new {@link ServerBlockContext} instance
|
||||||
|
* suitable for read and write access to the server's world. The context is
|
||||||
|
* initialized to point to the provided block. This is the preferred way to
|
||||||
|
* query or change the world. This context uses the coordinate space in
|
||||||
|
* which positive Z matches the discrete up direction of the provided
|
||||||
|
* location.
|
||||||
|
*
|
||||||
|
* @param up the desired up direction
|
||||||
|
* @return the context
|
||||||
|
* @see #createContext(AbsFace)
|
||||||
|
* @see #createAbsoluteContext()
|
||||||
|
*/
|
||||||
|
public ServerBlockContext createContext(Vec3i blockInWorld) {
|
||||||
|
AbsFace up = getWorld().getUp(blockInWorld);
|
||||||
|
Vec3i relativeBlockInWorld = AxisRotations.relativize(blockInWorld, up, null);
|
||||||
|
return new RotatingServerContext(doCreateAbsoluteContext(), up).push(relativeBlockInWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,17 +28,18 @@ import java.util.function.BiConsumer;
|
|||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.common.world.TileDataStack;
|
import ru.windcorp.progressia.common.world.TileDataStack;
|
||||||
|
import ru.windcorp.progressia.common.world.generic.GenericChunks;
|
||||||
import ru.windcorp.progressia.common.world.TileDataReference;
|
import ru.windcorp.progressia.common.world.TileDataReference;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
||||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerBlockContextRO;
|
import ru.windcorp.progressia.server.world.context.ServerBlockContextRO;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerContexts;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileContextRO;
|
import ru.windcorp.progressia.server.world.context.ServerTileContextRO;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerWorldContextRO;
|
import ru.windcorp.progressia.server.world.context.ServerWorldContextRO;
|
||||||
import ru.windcorp.progressia.server.world.tasks.TickChunk;
|
import ru.windcorp.progressia.server.world.tasks.TickChunk;
|
||||||
@ -225,15 +226,12 @@ public class DefaultChunkLogic implements ChunkLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void tmp_generateTickLists() {
|
private void tmp_generateTickLists() {
|
||||||
ServerWorldContextRO context = Server.getCurrentServer().createContext();
|
ServerWorldContextRO context = Server.getCurrentServer().createContext(getUp());
|
||||||
Vec3i blockInChunk = new Vec3i();
|
|
||||||
|
|
||||||
forEachBiW(location -> {
|
GenericChunks.forEachBiC(blockInChunk -> {
|
||||||
|
|
||||||
ServerBlockContextRO blockContext = context.push(location);
|
ServerBlockContextRO blockContext = ServerContexts.pushAbs(context, this, blockInChunk);
|
||||||
|
BlockLogic block = getBlock(blockInChunk);
|
||||||
BlockLogic block = blockContext.logic().getBlock();
|
|
||||||
Coordinates.convertInWorldToInChunk(location, blockInChunk);
|
|
||||||
|
|
||||||
if (!(block instanceof TickableBlock)) {
|
if (!(block instanceof TickableBlock)) {
|
||||||
blockContext.pop();
|
blockContext.pop();
|
||||||
@ -241,7 +239,7 @@ public class DefaultChunkLogic implements ChunkLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (((TickableBlock) block).getTickingPolicy(blockContext) == TickingPolicy.REGULAR) {
|
if (((TickableBlock) block).getTickingPolicy(blockContext) == TickingPolicy.REGULAR) {
|
||||||
tickingBlocks.add(blockInChunk);
|
tickingBlocks.add(blockInChunk.add_(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RelFace face : RelFace.getFaces()) {
|
for (RelFace face : RelFace.getFaces()) {
|
||||||
@ -249,16 +247,14 @@ public class DefaultChunkLogic implements ChunkLogic {
|
|||||||
if (stack == null || stack.isEmpty()) continue;
|
if (stack == null || stack.isEmpty()) continue;
|
||||||
|
|
||||||
for (int i = 0; i < stack.size(); ++i) {
|
for (int i = 0; i < stack.size(); ++i) {
|
||||||
ServerTileContextRO tileContext = blockContext.push(face, i);
|
ServerTileContextRO tileContext = blockContext.push(context.toContext(face.resolve(getUp())), i);
|
||||||
TileLogic tile = stack.get(i);
|
TileLogic tile = stack.get(i);
|
||||||
|
|
||||||
if (!(tile instanceof TickableTile)) {
|
if (tile instanceof TickableTile) {
|
||||||
tileContext.pop();
|
TickingPolicy policy = ((TickableTile) tile).getTickingPolicy(tileContext);
|
||||||
continue;
|
if (policy == TickingPolicy.REGULAR) {
|
||||||
}
|
tickingTiles.add(stack.getData().getReference(i));
|
||||||
|
}
|
||||||
if (((TickableTile) tile).getTickingPolicy(tileContext) == TickingPolicy.REGULAR) {
|
|
||||||
tickingTiles.add(stack.getData().getReference(i));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tileContext.pop();
|
tileContext.pop();
|
||||||
|
@ -21,12 +21,13 @@ package ru.windcorp.progressia.server.world;
|
|||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
import ru.windcorp.progressia.server.world.block.UpdateableBlock;
|
import ru.windcorp.progressia.server.world.block.UpdateableBlock;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerContexts;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileStackContext;
|
import ru.windcorp.progressia.server.world.context.ServerTileStackContext;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
||||||
@ -56,7 +57,7 @@ public class TickAndUpdateUtil {
|
|||||||
if (!(block instanceof TickableBlock)) {
|
if (!(block instanceof TickableBlock)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ServerBlockContext context = server.createContext().push(blockInWorld);
|
ServerBlockContext context = server.createContext(blockInWorld);
|
||||||
tickBlock(context);
|
tickBlock(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,23 +74,22 @@ public class TickAndUpdateUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickTile(Server server, Vec3i blockInWorld, BlockFace face, int layer) {
|
public static void tickTile(Server server, Vec3i blockInWorld, AbsFace face, int layer) {
|
||||||
TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer);
|
TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer);
|
||||||
if (!(tile instanceof TickableTile)) {
|
if (!(tile instanceof TickableTile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ServerTileContext context = server.createContext()
|
ServerTileContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face)
|
||||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer);
|
.push(layer);
|
||||||
tickTile(context);
|
tickTile(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickTiles(Server server, Vec3i blockInWorld, BlockFace face) {
|
public static void tickTiles(Server server, Vec3i blockInWorld, AbsFace face) {
|
||||||
if (!server.getWorld().hasTiles(blockInWorld, face)) {
|
if (!server.getWorld().hasTiles(blockInWorld, face)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerTileStackContext context = server.createContext()
|
ServerTileStackContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face);
|
||||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)));
|
|
||||||
for (int i = 0; i < context.getTileCount(); ++i) {
|
for (int i = 0; i < context.getTileCount(); ++i) {
|
||||||
tickTile(context.push(i));
|
tickTile(context.push(i));
|
||||||
context.pop();
|
context.pop();
|
||||||
@ -114,7 +114,7 @@ public class TickAndUpdateUtil {
|
|||||||
if (!(block instanceof UpdateableBlock)) {
|
if (!(block instanceof UpdateableBlock)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ServerBlockContext context = server.createContext().push(blockInWorld);
|
ServerBlockContext context = server.createContext(blockInWorld);
|
||||||
updateBlock(context);
|
updateBlock(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,23 +131,22 @@ public class TickAndUpdateUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateTile(Server server, Vec3i blockInWorld, BlockFace face, int layer) {
|
public static void updateTile(Server server, Vec3i blockInWorld, AbsFace face, int layer) {
|
||||||
TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer);
|
TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer);
|
||||||
if (!(tile instanceof UpdateableTile)) {
|
if (!(tile instanceof UpdateableTile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ServerTileContext context = server.createContext()
|
ServerTileContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face)
|
||||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer);
|
.push(layer);
|
||||||
updateTile(context);
|
updateTile(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateTiles(Server server, Vec3i blockInWorld, BlockFace face) {
|
public static void updateTiles(Server server, Vec3i blockInWorld, AbsFace face) {
|
||||||
if (!server.getWorld().hasTiles(blockInWorld, face)) {
|
if (!server.getWorld().hasTiles(blockInWorld, face)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerTileStackContext context = server.createContext()
|
ServerTileStackContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face);
|
||||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)));
|
|
||||||
for (int i = 0; i < context.getTileCount(); ++i) {
|
for (int i = 0; i < context.getTileCount(); ++i) {
|
||||||
updateTile(context.push(i));
|
updateTile(context.push(i));
|
||||||
context.pop();
|
context.pop();
|
||||||
@ -166,7 +165,7 @@ public class TickAndUpdateUtil {
|
|||||||
tickEntity(
|
tickEntity(
|
||||||
EntityLogicRegistry.getInstance().get(data.getId()),
|
EntityLogicRegistry.getInstance().get(data.getId()),
|
||||||
data,
|
data,
|
||||||
server.createContext()
|
server.createContext(data.getUpFace())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.world.context;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
|
import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
|
||||||
|
import ru.windcorp.progressia.common.world.generic.TileGenericReferenceRO;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
|
||||||
|
public class ServerContexts {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RW
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static ServerBlockContext pushAbs(ServerWorldContext context, Vec3i blockInWorld) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
context.toContext(blockInWorld, contextLocation);
|
||||||
|
ServerBlockContext blockContext = context.push(contextLocation);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return blockContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerBlockContext pushAbs(ServerWorldContext context, ChunkGenericRO<?, ?, ?, ?, ?> chunk, Vec3i blockInChunk) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
Coordinates.getInWorld(chunk.getPosition(), blockInChunk, contextLocation);
|
||||||
|
context.toContext(contextLocation, contextLocation);
|
||||||
|
ServerBlockContext blockContext = context.push(contextLocation);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return blockContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileStackContext pushAbs(ServerWorldContext context, Vec3i blockInWorld, AbsFace face) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
context.toContext(blockInWorld, contextLocation);
|
||||||
|
RelFace contextFace = context.toContext(face);
|
||||||
|
ServerTileStackContext tileStackContext = context.push(contextLocation, contextFace);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return tileStackContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileStackContext pushAbs(ServerWorldContext context, ChunkGenericRO<?, ?, ?, ?, ?> chunk, Vec3i blockInChunk, AbsFace face) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
Coordinates.getInWorld(chunk.getPosition(), blockInChunk, contextLocation);
|
||||||
|
context.toContext(contextLocation, contextLocation);
|
||||||
|
RelFace contextFace = context.toContext(face);
|
||||||
|
ServerTileStackContext tileStackContext = context.push(contextLocation, contextFace);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return tileStackContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileStackContext pushAbs(ServerBlockContext context, AbsFace face) {
|
||||||
|
return context.push(context.toContext(face));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileContext pushAbs(ServerWorldContext context, AbsFace up, TileGenericReferenceRO<?, ?, ?, ?, ?> ref) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
ref.getStack().getBlockInWorld(contextLocation);
|
||||||
|
context.toContext(contextLocation, contextLocation);
|
||||||
|
RelFace contextFace = context.toContext(ref.getStack().getFace().resolve(up));
|
||||||
|
ServerTileContext tileContext = context.push(contextLocation, contextFace, ref.getIndex());
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return tileContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RO
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static ServerBlockContextRO pushAbs(ServerWorldContextRO context, Vec3i blockInWorld) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
context.toContext(blockInWorld, contextLocation);
|
||||||
|
ServerBlockContextRO blockContextRO = context.push(contextLocation);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return blockContextRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerBlockContextRO pushAbs(ServerWorldContextRO context, ChunkGenericRO<?, ?, ?, ?, ?> chunk, Vec3i blockInChunk) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
Coordinates.getInWorld(chunk.getPosition(), blockInChunk, contextLocation);
|
||||||
|
context.toContext(contextLocation, contextLocation);
|
||||||
|
ServerBlockContextRO blockContextRO = context.push(contextLocation);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return blockContextRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileStackContextRO pushAbs(ServerWorldContextRO context, Vec3i blockInWorld, AbsFace face) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
context.toContext(blockInWorld, contextLocation);
|
||||||
|
RelFace contextFace = context.toContext(face);
|
||||||
|
ServerTileStackContextRO tileStackContextRO = context.push(contextLocation, contextFace);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return tileStackContextRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileStackContextRO pushAbs(ServerWorldContextRO context, ChunkGenericRO<?, ?, ?, ?, ?> chunk, Vec3i blockInChunk, AbsFace face) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
Coordinates.getInWorld(chunk.getPosition(), blockInChunk, contextLocation);
|
||||||
|
context.toContext(contextLocation, contextLocation);
|
||||||
|
RelFace contextFace = context.toContext(face);
|
||||||
|
ServerTileStackContextRO tileStackContextRO = context.push(contextLocation, contextFace);
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return tileStackContextRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileStackContextRO pushAbs(ServerBlockContextRO context, AbsFace face) {
|
||||||
|
return context.push(context.toContext(face));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ServerTileContextRO pushAbs(ServerWorldContextRO context, AbsFace up, TileGenericReferenceRO<?, ?, ?, ?, ?> ref) {
|
||||||
|
Vec3i contextLocation = Vectors.grab3i();
|
||||||
|
ref.getStack().getBlockInWorld(contextLocation);
|
||||||
|
context.toContext(contextLocation, contextLocation);
|
||||||
|
RelFace contextFace = context.toContext(ref.getStack().getFace().resolve(up));
|
||||||
|
ServerTileContextRO tileContextRO = context.push(contextLocation, contextFace, ref.getIndex());
|
||||||
|
Vectors.release(contextLocation);
|
||||||
|
return tileContextRO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ServerContexts() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -29,6 +29,7 @@ import ru.windcorp.progressia.common.world.WorldData;
|
|||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.generic.EntityGeneric;
|
import ru.windcorp.progressia.common.world.generic.EntityGeneric;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
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;
|
||||||
@ -291,6 +292,41 @@ class DefaultServerContextImpl extends DefaultServerContext
|
|||||||
return frame.layer;
|
return frame.layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ABSOLUTE COORDINATE CONVERSIONS
|
||||||
|
* (or lack thereof)
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toAbsolute(Vec3i contextLocation, Vec3i output) {
|
||||||
|
if (output == null) {
|
||||||
|
output = new Vec3i();
|
||||||
|
}
|
||||||
|
|
||||||
|
output.set(contextLocation.x, contextLocation.y, contextLocation.z);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toContext(Vec3i absoluteLocation, Vec3i output) {
|
||||||
|
if (output == null) {
|
||||||
|
output = new Vec3i();
|
||||||
|
}
|
||||||
|
|
||||||
|
output.set(absoluteLocation.x, absoluteLocation.y, absoluteLocation.z);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbsFace toAbsolute(BlockFace contextFace) {
|
||||||
|
return contextFace.resolve(AbsFace.POS_Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RelFace toContext(AbsFace absoluteFace) {
|
||||||
|
return absoluteFace.relativize(AbsFace.POS_Z);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RO CONTEXT INTERFACE
|
* RO CONTEXT INTERFACE
|
||||||
*/
|
*/
|
||||||
|
@ -23,6 +23,7 @@ import java.util.Random;
|
|||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
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;
|
||||||
@ -85,6 +86,26 @@ public class DefaultServerContextLogic implements ServerTileContext.Logic {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toAbsolute(Vec3i contextLocation, Vec3i output) {
|
||||||
|
return parent.toAbsolute(contextLocation, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toContext(Vec3i absoluteLocation, Vec3i output) {
|
||||||
|
return parent.toContext(absoluteLocation, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbsFace toAbsolute(BlockFace contextFace) {
|
||||||
|
return parent.toAbsolute(contextFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RelFace toContext(AbsFace absoluteFace) {
|
||||||
|
return parent.toContext(absoluteFace);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getTickLength() {
|
public double getTickLength() {
|
||||||
return parent.getTickLength();
|
return parent.getTickLength();
|
||||||
|
@ -27,6 +27,7 @@ import ru.windcorp.progressia.common.world.GravityModel;
|
|||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.generic.EntityGeneric;
|
import ru.windcorp.progressia.common.world.generic.EntityGeneric;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
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;
|
||||||
@ -200,6 +201,26 @@ public abstract class FilterServerContext implements ServerTileContext {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toAbsolute(Vec3i contextLocation, Vec3i output) {
|
||||||
|
return parent.toAbsolute(contextLocation, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toContext(Vec3i absoluteLocation, Vec3i output) {
|
||||||
|
return parent.toContext(absoluteLocation, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbsFace toAbsolute(BlockFace contextFace) {
|
||||||
|
return parent.toAbsolute(contextFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RelFace toContext(AbsFace absoluteFace) {
|
||||||
|
return parent.toContext(absoluteFace);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Server getServer() {
|
public Server getServer() {
|
||||||
return parent.getServer();
|
return parent.getServer();
|
||||||
|
@ -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.server.world.context.impl;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
|
||||||
|
public class RotatingServerContext extends TransformingServerContext {
|
||||||
|
|
||||||
|
private final AbsFace up;
|
||||||
|
|
||||||
|
public RotatingServerContext(ServerTileContext parent, AbsFace up) {
|
||||||
|
super(parent);
|
||||||
|
this.up = up;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void transform(Vec3i userLocation, Vec3i output) {
|
||||||
|
output.set(userLocation.x, userLocation.y, userLocation.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void untransform(Vec3i parentLocation, Vec3i output) {
|
||||||
|
output.set(parentLocation.x, parentLocation.y, parentLocation.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RelFace transform(RelFace userFace) {
|
||||||
|
return userFace.resolve(up).relativize(AbsFace.POS_Z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RelFace untransform(RelFace parentFace) {
|
||||||
|
return parentFace.resolve(AbsFace.POS_Z).relativize(up);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* 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.server.world.context.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileStackContext;
|
||||||
|
|
||||||
|
public abstract class TransformingServerContext extends FilterServerContext {
|
||||||
|
|
||||||
|
private final Vec3i location = new Vec3i();
|
||||||
|
private boolean isLocationValid = false;
|
||||||
|
|
||||||
|
private RelFace face;
|
||||||
|
|
||||||
|
private final List<Vec3i> vectorCache = new ArrayList<>(1);
|
||||||
|
|
||||||
|
public TransformingServerContext(ServerTileContext parent) {
|
||||||
|
super(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void transform(Vec3i userLocation, Vec3i output);
|
||||||
|
|
||||||
|
protected abstract void untransform(Vec3i parentLocation, Vec3i output);
|
||||||
|
|
||||||
|
protected abstract RelFace transform(RelFace userFace);
|
||||||
|
|
||||||
|
protected abstract RelFace untransform(RelFace parentFace);
|
||||||
|
|
||||||
|
protected void invalidateCache() {
|
||||||
|
isLocationValid = false;
|
||||||
|
face = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vec3i grabVector(Vec3i userVector) {
|
||||||
|
Vec3i parentVector;
|
||||||
|
|
||||||
|
if (vectorCache.isEmpty()) {
|
||||||
|
parentVector = new Vec3i();
|
||||||
|
} else {
|
||||||
|
parentVector = vectorCache.remove(vectorCache.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(userVector, parentVector);
|
||||||
|
|
||||||
|
return parentVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseVector(Vec3i parentVector) {
|
||||||
|
vectorCache.add(parentVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i getLocation() {
|
||||||
|
// Always invoke parent method to allow parent to determine validity
|
||||||
|
Vec3i parentLocation = super.getLocation();
|
||||||
|
|
||||||
|
if (!isLocationValid) {
|
||||||
|
untransform(parentLocation, location);
|
||||||
|
isLocationValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return location;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RelFace getFace() {
|
||||||
|
// Always invoke parent method to allow parent to determine validity
|
||||||
|
RelFace parentFace = super.getFace();
|
||||||
|
|
||||||
|
if (face == null) {
|
||||||
|
face = untransform(parentFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
return face;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pop() {
|
||||||
|
super.pop();
|
||||||
|
invalidateCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerBlockContext push(Vec3i userLocation) {
|
||||||
|
transform(userLocation, location);
|
||||||
|
isLocationValid = true;
|
||||||
|
super.push(location);
|
||||||
|
face = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerTileStackContext push(Vec3i userLocation, RelFace userFace) {
|
||||||
|
transform(userLocation, location);
|
||||||
|
isLocationValid = true;
|
||||||
|
face = transform(userFace);
|
||||||
|
super.push(location, face);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServerTileContext push(Vec3i userLocation, RelFace userFace, int layer) {
|
||||||
|
transform(userLocation, location);
|
||||||
|
isLocationValid = true;
|
||||||
|
face = transform(userFace);
|
||||||
|
super.push(location, face, layer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toAbsolute(Vec3i contextLocation, Vec3i output) {
|
||||||
|
if (output == null) {
|
||||||
|
output = new Vec3i();
|
||||||
|
}
|
||||||
|
|
||||||
|
transform(contextLocation, output);
|
||||||
|
|
||||||
|
return super.toAbsolute(output, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3i toContext(Vec3i absoluteLocation, Vec3i output) {
|
||||||
|
output = super.toContext(absoluteLocation, output);
|
||||||
|
untransform(output, output);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbsFace toAbsolute(BlockFace contextFace) {
|
||||||
|
return super.toAbsolute(transform(contextFace.relativize(AbsFace.POS_Z)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RelFace toContext(AbsFace absoluteFace) {
|
||||||
|
return untransform(super.toContext(absoluteFace));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLocationLoaded(Vec3i userLocation) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.isLocationLoaded(parentLocation);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockData getBlock(Vec3i userLocation) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.getBlock(parentLocation);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBlock(Vec3i userLocation, BlockData block) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
super.setBlock(parentLocation, block);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasTile(Vec3i userLocation, BlockFace userFace, int layer) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.hasTile(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)), layer);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileData getTile(Vec3i userLocation, BlockFace userFace, int layer) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.getTile(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)), layer);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTagValid(Vec3i userLocation, BlockFace userFace, int tag) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.isTagValid(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)), tag);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileData getTileByTag(Vec3i userLocation, BlockFace userFace, int tag) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.getTileByTag(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)), tag);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTileCount(Vec3i userLocation, BlockFace userFace) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
return super.getTileCount(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)));
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTile(Vec3i userLocation, BlockFace userFace, TileData tile) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
super.addTile(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)), tile);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeTile(Vec3i userLocation, BlockFace userFace, int tag) {
|
||||||
|
Vec3i parentLocation = grabVector(userLocation);
|
||||||
|
|
||||||
|
try {
|
||||||
|
super.removeTile(parentLocation, transform(userFace.relativize(AbsFace.POS_Z)), tag);
|
||||||
|
} finally {
|
||||||
|
releaseVector(parentLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -27,17 +27,15 @@ import com.google.common.collect.ImmutableList;
|
|||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.FloatMathUtil;
|
import ru.windcorp.progressia.common.util.FloatMathUtil;
|
||||||
import ru.windcorp.progressia.common.util.Vectors;
|
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
|
||||||
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.common.world.TileDataStack;
|
import ru.windcorp.progressia.common.world.TileDataStack;
|
||||||
import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
|
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.DefaultChunkLogic;
|
import ru.windcorp.progressia.server.world.DefaultChunkLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerContexts;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileStackContext;
|
import ru.windcorp.progressia.server.world.context.ServerTileStackContext;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
||||||
@ -53,20 +51,21 @@ public class TickChunk extends Evaluation {
|
|||||||
DefaultChunkData.BLOCKS_PER_CHUNK *
|
DefaultChunkData.BLOCKS_PER_CHUNK *
|
||||||
DefaultChunkData.BLOCKS_PER_CHUNK;
|
DefaultChunkData.BLOCKS_PER_CHUNK;
|
||||||
|
|
||||||
private final List<Consumer<Server>> randomTickMethods;
|
private final List<Consumer<ServerWorldContext>> randomTickMethods;
|
||||||
|
|
||||||
{
|
{
|
||||||
List<Consumer<Server>> randomTickMethods = new ArrayList<>();
|
List<Consumer<ServerWorldContext>> randomTickMethods = new ArrayList<>();
|
||||||
randomTickMethods.add(this::tickRandomBlock);
|
randomTickMethods.add(this::tickRandomBlock);
|
||||||
|
|
||||||
for (AbsFace face : AbsFace.getFaces()) {
|
for (AbsFace face : AbsFace.getFaces()) {
|
||||||
randomTickMethods.add(s -> this.tickRandomTile(s, face));
|
randomTickMethods.add(context -> this.tickRandomTile(face, context));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.randomTickMethods = ImmutableList.copyOf(randomTickMethods);
|
this.randomTickMethods = ImmutableList.copyOf(randomTickMethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final DefaultChunkLogic chunk;
|
private final DefaultChunkLogic chunk;
|
||||||
|
private ServerWorldContext context;
|
||||||
|
|
||||||
public TickChunk(DefaultChunkLogic chunk) {
|
public TickChunk(DefaultChunkLogic chunk) {
|
||||||
this.chunk = chunk;
|
this.chunk = chunk;
|
||||||
@ -74,44 +73,41 @@ public class TickChunk extends Evaluation {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evaluate(Server server) {
|
public void evaluate(Server server) {
|
||||||
tickRegulars(server);
|
if (context == null || context.getServer() != server) {
|
||||||
tickRandom(server);
|
context = server.createContext(chunk.getUp());
|
||||||
|
}
|
||||||
|
|
||||||
|
tickRegulars(context);
|
||||||
|
tickRandom(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRegulars(Server server) {
|
private void tickRegulars(ServerWorldContext context) {
|
||||||
tickRegularBlocks(server);
|
tickRegularBlocks(context);
|
||||||
tickRegularTiles(server);
|
tickRegularTiles(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRegularBlocks(Server server) {
|
private void tickRegularBlocks(ServerWorldContext context) {
|
||||||
if (!chunk.hasTickingBlocks())
|
if (!chunk.hasTickingBlocks())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ServerWorldContext context = server.createContext();
|
|
||||||
|
|
||||||
chunk.forEachTickingBlock((blockInChunk, block) -> {
|
chunk.forEachTickingBlock((blockInChunk, block) -> {
|
||||||
((TickableBlock) block).tick(contextPushBiC(context, chunk, blockInChunk));
|
((TickableBlock) block).tick(ServerContexts.pushAbs(context, chunk, blockInChunk));
|
||||||
context.pop();
|
context.pop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRegularTiles(Server server) {
|
private void tickRegularTiles(ServerWorldContext context) {
|
||||||
if (!chunk.hasTickingTiles())
|
if (!chunk.hasTickingTiles())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ServerWorldContext context = server.createContext();
|
|
||||||
Vec3i blockInWorld = new Vec3i();
|
|
||||||
|
|
||||||
chunk.forEachTickingTile((ref, tile) -> {
|
chunk.forEachTickingTile((ref, tile) -> {
|
||||||
((TickableTile) tile).tick(
|
((TickableTile) tile).tick(ServerContexts.pushAbs(context, chunk.getUp(), ref));
|
||||||
context.push(ref.getStack().getBlockInWorld(blockInWorld), ref.getStack().getFace(), ref.getIndex())
|
|
||||||
);
|
|
||||||
context.pop();
|
context.pop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRandom(Server server) {
|
private void tickRandom(ServerWorldContext context) {
|
||||||
float ticks = computeRandomTicks(server);
|
float ticks = computeRandomTicks(context.getServer());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are expected to run 3.25 random ticks per tick
|
* If we are expected to run 3.25 random ticks per tick
|
||||||
@ -122,23 +118,23 @@ public class TickChunk extends Evaluation {
|
|||||||
float extraTickChance = ticks - unconditionalTicks;
|
float extraTickChance = ticks - unconditionalTicks;
|
||||||
|
|
||||||
for (int i = 0; i < unconditionalTicks; ++i) {
|
for (int i = 0; i < unconditionalTicks; ++i) {
|
||||||
tickRandomOnce(server);
|
tickRandomOnce(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server.getAdHocRandom().nextFloat() < extraTickChance) {
|
if (context.getRandom().nextFloat() < extraTickChance) {
|
||||||
tickRandomOnce(server);
|
tickRandomOnce(context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRandomOnce(Server server) {
|
private void tickRandomOnce(ServerWorldContext context) {
|
||||||
// Pick a target at random: a block or one of 3 primary block faces
|
// Pick a target at random: a block or one of 3 primary block faces
|
||||||
randomTickMethods.get(
|
randomTickMethods.get(
|
||||||
server.getAdHocRandom().nextInt(randomTickMethods.size())
|
context.getRandom().nextInt(randomTickMethods.size())
|
||||||
).accept(server);
|
).accept(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRandomBlock(Server server) {
|
private void tickRandomBlock(ServerWorldContext context) {
|
||||||
Random random = server.getAdHocRandom();
|
Random random = context.getRandom();
|
||||||
|
|
||||||
Vec3i blockInChunk = new Vec3i(
|
Vec3i blockInChunk = new Vec3i(
|
||||||
random.nextInt(BLOCKS_PER_CHUNK),
|
random.nextInt(BLOCKS_PER_CHUNK),
|
||||||
@ -152,15 +148,17 @@ public class TickChunk extends Evaluation {
|
|||||||
return;
|
return;
|
||||||
TickableBlock tickable = (TickableBlock) block;
|
TickableBlock tickable = (TickableBlock) block;
|
||||||
|
|
||||||
ServerBlockContext context = contextPushBiC(server.createContext(), chunk, blockInChunk);
|
ServerBlockContext blockContext = ServerContexts.pushAbs(context, chunk, blockInChunk);
|
||||||
|
|
||||||
if (tickable.getTickingPolicy(context) != TickingPolicy.RANDOM)
|
if (tickable.getTickingPolicy(blockContext) != TickingPolicy.RANDOM)
|
||||||
return;
|
return;
|
||||||
tickable.tick(context);
|
tickable.tick(blockContext);
|
||||||
|
|
||||||
|
blockContext.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickRandomTile(Server server, AbsFace face) {
|
private void tickRandomTile(AbsFace face, ServerWorldContext context) {
|
||||||
Random random = server.getAdHocRandom();
|
Random random = context.getRandom();
|
||||||
|
|
||||||
Vec3i blockInChunk = new Vec3i(
|
Vec3i blockInChunk = new Vec3i(
|
||||||
random.nextInt(BLOCKS_PER_CHUNK),
|
random.nextInt(BLOCKS_PER_CHUNK),
|
||||||
@ -172,10 +170,10 @@ public class TickChunk extends Evaluation {
|
|||||||
if (tiles == null || tiles.isEmpty())
|
if (tiles == null || tiles.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ServerTileStackContext context = contextPushBiC(server.createContext(), chunk, blockInChunk).push(face.relativize(chunk.getUp()));
|
ServerTileStackContext tsContext = ServerContexts.pushAbs(context, chunk, blockInChunk, face);
|
||||||
|
|
||||||
for (int i = 0; i < tiles.size(); ++i) {
|
for (int i = 0; i < tiles.size(); ++i) {
|
||||||
ServerTileContext tileContext = context.push(i);
|
ServerTileContext tileContext = tsContext.push(i);
|
||||||
|
|
||||||
TileLogic logic = tileContext.logic().getTile();
|
TileLogic logic = tileContext.logic().getTile();
|
||||||
if (!(logic instanceof TickableTile)) {
|
if (!(logic instanceof TickableTile)) {
|
||||||
@ -192,6 +190,8 @@ public class TickChunk extends Evaluation {
|
|||||||
|
|
||||||
tileContext.pop();
|
tileContext.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tsContext.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private float computeRandomTicks(Server server) {
|
private float computeRandomTicks(Server server) {
|
||||||
@ -200,18 +200,6 @@ public class TickChunk extends Evaluation {
|
|||||||
server.getTickLength());
|
server.getTickLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerBlockContext contextPushBiC(
|
|
||||||
ServerWorldContext context,
|
|
||||||
ChunkGenericRO<?, ?, ?, ?, ?> chunk,
|
|
||||||
Vec3i blockInChunk
|
|
||||||
) {
|
|
||||||
Vec3i blockInWorld = Vectors.grab3i();
|
|
||||||
Coordinates.getInWorld(chunk.getPosition(), blockInChunk, blockInWorld);
|
|
||||||
ServerBlockContext blockContext = context.push(blockInWorld);
|
|
||||||
Vectors.release(blockInWorld);
|
|
||||||
return blockContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getRelevantChunk(Vec3i output) {
|
public void getRelevantChunk(Vec3i output) {
|
||||||
Vec3i p = chunk.getData().getPosition();
|
Vec3i p = chunk.getData().getPosition();
|
||||||
|
@ -383,7 +383,7 @@ public class TestContent {
|
|||||||
ru.windcorp.progressia.server.comms.Client client
|
ru.windcorp.progressia.server.comms.Client client
|
||||||
) {
|
) {
|
||||||
Vec3i blockInWorld = ((ControlBreakBlockData) packet.getControl()).getBlockInWorld();
|
Vec3i blockInWorld = ((ControlBreakBlockData) packet.getControl()).getBlockInWorld();
|
||||||
server.createContext().setBlock(blockInWorld, BlockDataRegistry.getInstance().get("Test:Air"));
|
server.createAbsoluteContext().setBlock(blockInWorld, BlockDataRegistry.getInstance().get("Test:Air"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void onBlockPlaceTrigger(ControlData control) {
|
private static void onBlockPlaceTrigger(ControlData control) {
|
||||||
@ -403,7 +403,7 @@ public class TestContent {
|
|||||||
Vec3i blockInWorld = controlData.getBlockInWorld();
|
Vec3i blockInWorld = controlData.getBlockInWorld();
|
||||||
if (server.getWorld().getData().getChunkByBlock(blockInWorld) == null)
|
if (server.getWorld().getData().getChunkByBlock(blockInWorld) == null)
|
||||||
return;
|
return;
|
||||||
server.createContext().setBlock(blockInWorld, block);
|
server.createAbsoluteContext().setBlock(blockInWorld, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void onTilePlaceTrigger(ControlData control) {
|
private static void onTilePlaceTrigger(ControlData control) {
|
||||||
@ -428,7 +428,7 @@ public class TestContent {
|
|||||||
return;
|
return;
|
||||||
if (server.getWorld().getData().getTiles(blockInWorld, face).isFull())
|
if (server.getWorld().getData().getTiles(blockInWorld, face).isFull())
|
||||||
return;
|
return;
|
||||||
server.createContext().addTile(blockInWorld, face, tile);
|
server.createAbsoluteContext().addTile(blockInWorld, face, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerMisc() {
|
private static void registerMisc() {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.test;
|
package ru.windcorp.progressia.test;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
@ -65,7 +66,7 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
|||||||
|
|
||||||
private boolean isBlockAboveTransparent(ServerTileContextRO context) {
|
private boolean isBlockAboveTransparent(ServerTileContextRO context) {
|
||||||
// TODO rework
|
// TODO rework
|
||||||
context.pushRelative(RelFace.UP.resolve(context.getServer().getWorld().getUp(context.getLocation())));
|
context.pushRelative(RelFace.UP.resolve(AbsFace.POS_Z));
|
||||||
BlockLogic block = context.logic().getBlock();
|
BlockLogic block = context.logic().getBlock();
|
||||||
return context.popAndReturn(block == null || block.isTransparent(context));
|
return context.popAndReturn(block == null || block.isTransparent(context));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user