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:
OLEGSHA 2021-08-13 16:11:46 +03:00
parent 78a1c25554
commit 54c66d28d6
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
14 changed files with 749 additions and 94 deletions

View File

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

View File

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

View File

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

View File

@ -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,17 +247,15 @@ 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) {
}
if (((TickableTile) tile).getTickingPolicy(tileContext) == TickingPolicy.REGULAR) {
tickingTiles.add(stack.getData().getReference(i)); tickingTiles.add(stack.getData().getReference(i));
} }
}
tileContext.pop(); tileContext.pop();
} }

View File

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

View File

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

View File

@ -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
*/ */

View File

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

View File

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

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

View File

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

View File

@ -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());
} }
private void tickRegulars(Server server) { tickRegulars(context);
tickRegularBlocks(server); tickRandom(context);
tickRegularTiles(server);
} }
private void tickRegularBlocks(Server server) { private void tickRegulars(ServerWorldContext context) {
tickRegularBlocks(context);
tickRegularTiles(context);
}
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();

View File

@ -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() {

View File

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