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 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.BlockFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
|
||||
/**
|
||||
@ -81,6 +83,80 @@ class WorldContexts {
|
||||
*/
|
||||
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) {
|
||||
if (tag < 0) {
|
||||
throw new IllegalArgumentException("Cannot affect tile with tag -1");
|
||||
}
|
||||
|
||||
this.blockInWorld.set(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
||||
this.face = face;
|
||||
this.tag = tag;
|
||||
|
@ -24,20 +24,26 @@ import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.google.common.eventbus.EventBus;
|
||||
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.jputil.functions.ThrowingRunnable;
|
||||
import ru.windcorp.progressia.common.Units;
|
||||
import ru.windcorp.progressia.common.util.TaskQueue;
|
||||
import ru.windcorp.progressia.common.util.crash.ReportingEventBus;
|
||||
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.events.ServerEvent;
|
||||
import ru.windcorp.progressia.server.management.load.ChunkRequestDaemon;
|
||||
import ru.windcorp.progressia.server.management.load.EntityRequestDaemon;
|
||||
import ru.windcorp.progressia.server.management.load.LoadManager;
|
||||
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.impl.DefaultServerContext;
|
||||
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.ticking.Change;
|
||||
import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
||||
@ -102,15 +108,54 @@ public class Server {
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* suitable for read and write access to the server's world. This context
|
||||
* uses the absolute coordinate space (not rotated to match positive Z =
|
||||
* up).
|
||||
*
|
||||
* @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 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.BlockFace;
|
||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||
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.server.Server;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||
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.ServerWorldContextRO;
|
||||
import ru.windcorp.progressia.server.world.tasks.TickChunk;
|
||||
@ -225,15 +226,12 @@ public class DefaultChunkLogic implements ChunkLogic {
|
||||
}
|
||||
|
||||
private void tmp_generateTickLists() {
|
||||
ServerWorldContextRO context = Server.getCurrentServer().createContext();
|
||||
Vec3i blockInChunk = new Vec3i();
|
||||
ServerWorldContextRO context = Server.getCurrentServer().createContext(getUp());
|
||||
|
||||
forEachBiW(location -> {
|
||||
GenericChunks.forEachBiC(blockInChunk -> {
|
||||
|
||||
ServerBlockContextRO blockContext = context.push(location);
|
||||
|
||||
BlockLogic block = blockContext.logic().getBlock();
|
||||
Coordinates.convertInWorldToInChunk(location, blockInChunk);
|
||||
ServerBlockContextRO blockContext = ServerContexts.pushAbs(context, this, blockInChunk);
|
||||
BlockLogic block = getBlock(blockInChunk);
|
||||
|
||||
if (!(block instanceof TickableBlock)) {
|
||||
blockContext.pop();
|
||||
@ -241,7 +239,7 @@ public class DefaultChunkLogic implements ChunkLogic {
|
||||
}
|
||||
|
||||
if (((TickableBlock) block).getTickingPolicy(blockContext) == TickingPolicy.REGULAR) {
|
||||
tickingBlocks.add(blockInChunk);
|
||||
tickingBlocks.add(blockInChunk.add_(0));
|
||||
}
|
||||
|
||||
for (RelFace face : RelFace.getFaces()) {
|
||||
@ -249,17 +247,15 @@ public class DefaultChunkLogic implements ChunkLogic {
|
||||
if (stack == null || stack.isEmpty()) continue;
|
||||
|
||||
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);
|
||||
|
||||
if (!(tile instanceof TickableTile)) {
|
||||
tileContext.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((TickableTile) tile).getTickingPolicy(tileContext) == TickingPolicy.REGULAR) {
|
||||
if (tile instanceof TickableTile) {
|
||||
TickingPolicy policy = ((TickableTile) tile).getTickingPolicy(tileContext);
|
||||
if (policy == TickingPolicy.REGULAR) {
|
||||
tickingTiles.add(stack.getData().getReference(i));
|
||||
}
|
||||
}
|
||||
|
||||
tileContext.pop();
|
||||
}
|
||||
|
@ -21,12 +21,13 @@ package ru.windcorp.progressia.server.world;
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.util.crash.CrashReports;
|
||||
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.world.block.BlockLogic;
|
||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||
import ru.windcorp.progressia.server.world.block.UpdateableBlock;
|
||||
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.ServerTileStackContext;
|
||||
import ru.windcorp.progressia.server.world.context.ServerWorldContext;
|
||||
@ -56,7 +57,7 @@ public class TickAndUpdateUtil {
|
||||
if (!(block instanceof TickableBlock)) {
|
||||
return;
|
||||
}
|
||||
ServerBlockContext context = server.createContext().push(blockInWorld);
|
||||
ServerBlockContext context = server.createContext(blockInWorld);
|
||||
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);
|
||||
if (!(tile instanceof TickableTile)) {
|
||||
return;
|
||||
}
|
||||
ServerTileContext context = server.createContext()
|
||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer);
|
||||
ServerTileContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face)
|
||||
.push(layer);
|
||||
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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerTileStackContext context = server.createContext()
|
||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)));
|
||||
ServerTileStackContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face);
|
||||
for (int i = 0; i < context.getTileCount(); ++i) {
|
||||
tickTile(context.push(i));
|
||||
context.pop();
|
||||
@ -114,7 +114,7 @@ public class TickAndUpdateUtil {
|
||||
if (!(block instanceof UpdateableBlock)) {
|
||||
return;
|
||||
}
|
||||
ServerBlockContext context = server.createContext().push(blockInWorld);
|
||||
ServerBlockContext context = server.createContext(blockInWorld);
|
||||
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);
|
||||
if (!(tile instanceof UpdateableTile)) {
|
||||
return;
|
||||
}
|
||||
ServerTileContext context = server.createContext()
|
||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer);
|
||||
ServerTileContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face)
|
||||
.push(layer);
|
||||
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)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ServerTileStackContext context = server.createContext()
|
||||
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)));
|
||||
ServerTileStackContext context = ServerContexts.pushAbs(server.createContext(blockInWorld), blockInWorld, face);
|
||||
for (int i = 0; i < context.getTileCount(); ++i) {
|
||||
updateTile(context.push(i));
|
||||
context.pop();
|
||||
@ -166,7 +165,7 @@ public class TickAndUpdateUtil {
|
||||
tickEntity(
|
||||
EntityLogicRegistry.getInstance().get(data.getId()),
|
||||
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.entity.EntityData;
|
||||
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.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
@ -291,6 +292,41 @@ class DefaultServerContextImpl extends DefaultServerContext
|
||||
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
|
||||
*/
|
||||
|
@ -23,6 +23,7 @@ import java.util.Random;
|
||||
import glm.vec._3.i.Vec3i;
|
||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
||||
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.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
@ -85,6 +86,26 @@ public class DefaultServerContextLogic implements ServerTileContext.Logic {
|
||||
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
|
||||
public double 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.entity.EntityData;
|
||||
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.RelFace;
|
||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||
@ -200,6 +201,26 @@ public abstract class FilterServerContext implements ServerTileContext {
|
||||
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
|
||||
public Server 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 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.rels.AbsFace;
|
||||
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.world.DefaultChunkLogic;
|
||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||
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.ServerTileStackContext;
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
for (AbsFace face : AbsFace.getFaces()) {
|
||||
randomTickMethods.add(s -> this.tickRandomTile(s, face));
|
||||
randomTickMethods.add(context -> this.tickRandomTile(face, context));
|
||||
}
|
||||
|
||||
this.randomTickMethods = ImmutableList.copyOf(randomTickMethods);
|
||||
}
|
||||
|
||||
private final DefaultChunkLogic chunk;
|
||||
private ServerWorldContext context;
|
||||
|
||||
public TickChunk(DefaultChunkLogic chunk) {
|
||||
this.chunk = chunk;
|
||||
@ -74,44 +73,41 @@ public class TickChunk extends Evaluation {
|
||||
|
||||
@Override
|
||||
public void evaluate(Server server) {
|
||||
tickRegulars(server);
|
||||
tickRandom(server);
|
||||
if (context == null || context.getServer() != server) {
|
||||
context = server.createContext(chunk.getUp());
|
||||
}
|
||||
|
||||
private void tickRegulars(Server server) {
|
||||
tickRegularBlocks(server);
|
||||
tickRegularTiles(server);
|
||||
tickRegulars(context);
|
||||
tickRandom(context);
|
||||
}
|
||||
|
||||
private void tickRegularBlocks(Server server) {
|
||||
private void tickRegulars(ServerWorldContext context) {
|
||||
tickRegularBlocks(context);
|
||||
tickRegularTiles(context);
|
||||
}
|
||||
|
||||
private void tickRegularBlocks(ServerWorldContext context) {
|
||||
if (!chunk.hasTickingBlocks())
|
||||
return;
|
||||
|
||||
ServerWorldContext context = server.createContext();
|
||||
|
||||
chunk.forEachTickingBlock((blockInChunk, block) -> {
|
||||
((TickableBlock) block).tick(contextPushBiC(context, chunk, blockInChunk));
|
||||
((TickableBlock) block).tick(ServerContexts.pushAbs(context, chunk, blockInChunk));
|
||||
context.pop();
|
||||
});
|
||||
}
|
||||
|
||||
private void tickRegularTiles(Server server) {
|
||||
private void tickRegularTiles(ServerWorldContext context) {
|
||||
if (!chunk.hasTickingTiles())
|
||||
return;
|
||||
|
||||
ServerWorldContext context = server.createContext();
|
||||
Vec3i blockInWorld = new Vec3i();
|
||||
|
||||
chunk.forEachTickingTile((ref, tile) -> {
|
||||
((TickableTile) tile).tick(
|
||||
context.push(ref.getStack().getBlockInWorld(blockInWorld), ref.getStack().getFace(), ref.getIndex())
|
||||
);
|
||||
((TickableTile) tile).tick(ServerContexts.pushAbs(context, chunk.getUp(), ref));
|
||||
context.pop();
|
||||
});
|
||||
}
|
||||
|
||||
private void tickRandom(Server server) {
|
||||
float ticks = computeRandomTicks(server);
|
||||
private void tickRandom(ServerWorldContext context) {
|
||||
float ticks = computeRandomTicks(context.getServer());
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
for (int i = 0; i < unconditionalTicks; ++i) {
|
||||
tickRandomOnce(server);
|
||||
tickRandomOnce(context);
|
||||
}
|
||||
|
||||
if (server.getAdHocRandom().nextFloat() < extraTickChance) {
|
||||
tickRandomOnce(server);
|
||||
if (context.getRandom().nextFloat() < extraTickChance) {
|
||||
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
|
||||
randomTickMethods.get(
|
||||
server.getAdHocRandom().nextInt(randomTickMethods.size())
|
||||
).accept(server);
|
||||
context.getRandom().nextInt(randomTickMethods.size())
|
||||
).accept(context);
|
||||
}
|
||||
|
||||
private void tickRandomBlock(Server server) {
|
||||
Random random = server.getAdHocRandom();
|
||||
private void tickRandomBlock(ServerWorldContext context) {
|
||||
Random random = context.getRandom();
|
||||
|
||||
Vec3i blockInChunk = new Vec3i(
|
||||
random.nextInt(BLOCKS_PER_CHUNK),
|
||||
@ -152,15 +148,17 @@ public class TickChunk extends Evaluation {
|
||||
return;
|
||||
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;
|
||||
tickable.tick(context);
|
||||
tickable.tick(blockContext);
|
||||
|
||||
blockContext.pop();
|
||||
}
|
||||
|
||||
private void tickRandomTile(Server server, AbsFace face) {
|
||||
Random random = server.getAdHocRandom();
|
||||
private void tickRandomTile(AbsFace face, ServerWorldContext context) {
|
||||
Random random = context.getRandom();
|
||||
|
||||
Vec3i blockInChunk = new Vec3i(
|
||||
random.nextInt(BLOCKS_PER_CHUNK),
|
||||
@ -172,10 +170,10 @@ public class TickChunk extends Evaluation {
|
||||
if (tiles == null || tiles.isEmpty())
|
||||
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) {
|
||||
ServerTileContext tileContext = context.push(i);
|
||||
ServerTileContext tileContext = tsContext.push(i);
|
||||
|
||||
TileLogic logic = tileContext.logic().getTile();
|
||||
if (!(logic instanceof TickableTile)) {
|
||||
@ -192,6 +190,8 @@ public class TickChunk extends Evaluation {
|
||||
|
||||
tileContext.pop();
|
||||
}
|
||||
|
||||
tsContext.pop();
|
||||
}
|
||||
|
||||
private float computeRandomTicks(Server server) {
|
||||
@ -200,18 +200,6 @@ public class TickChunk extends Evaluation {
|
||||
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
|
||||
public void getRelevantChunk(Vec3i output) {
|
||||
Vec3i p = chunk.getData().getPosition();
|
||||
|
@ -383,7 +383,7 @@ public class TestContent {
|
||||
ru.windcorp.progressia.server.comms.Client client
|
||||
) {
|
||||
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) {
|
||||
@ -403,7 +403,7 @@ public class TestContent {
|
||||
Vec3i blockInWorld = controlData.getBlockInWorld();
|
||||
if (server.getWorld().getData().getChunkByBlock(blockInWorld) == null)
|
||||
return;
|
||||
server.createContext().setBlock(blockInWorld, block);
|
||||
server.createAbsoluteContext().setBlock(blockInWorld, block);
|
||||
}
|
||||
|
||||
private static void onTilePlaceTrigger(ControlData control) {
|
||||
@ -428,7 +428,7 @@ public class TestContent {
|
||||
return;
|
||||
if (server.getWorld().getData().getTiles(blockInWorld, face).isFull())
|
||||
return;
|
||||
server.createContext().addTile(blockInWorld, face, tile);
|
||||
server.createAbsoluteContext().addTile(blockInWorld, face, tile);
|
||||
}
|
||||
|
||||
private static void registerMisc() {
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
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.server.world.block.BlockLogic;
|
||||
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||
@ -65,7 +66,7 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
||||
|
||||
private boolean isBlockAboveTransparent(ServerTileContextRO context) {
|
||||
// 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();
|
||||
return context.popAndReturn(block == null || block.isTransparent(context));
|
||||
}
|
||||
|
Reference in New Issue
Block a user