From 0a45613e454debc137b7ac974de960a3ea946a9f Mon Sep 17 00:00:00 2001 From: OLEGSHA Date: Mon, 9 Aug 2021 20:32:15 +0300 Subject: [PATCH] Began work on integrating the new Contexts. Compiles but does not work - All TickContexts including TickContextMutable are deleted - Previous occurrences of TickContexts are replaced by appropriate ServerContexts - Added Context.popAndReturn methods for convenience Current known problems: - World does not generate properly on startup - No bulk methods in the new API (the likes of forEachTile, etc.) - AbsFace/RelFace ambiguity in the new API (see TestTileLogicGrass.java:68) - TestTileLogicGrass.java:53 is disabled for some reason --- .../common/world/context/Context.java | 20 + .../ru/windcorp/progressia/server/Server.java | 40 +- .../server/world/ChunkTickContext.java | 55 -- .../server/world/DefaultChunkLogic.java | 47 +- .../server/world/DefaultWorldLogic.java | 2 +- .../server/world/TickAndUpdateUtil.java | 132 +++-- .../progressia/server/world/TickContext.java | 49 -- .../server/world/TickContextMutable.java | 497 ------------------ .../server/world/UpdateTriggerer.java | 14 +- .../server/world/block/BlockLogic.java | 5 +- .../server/world/block/BlockTickContext.java | 114 ---- .../server/world/block/TickableBlock.java | 6 +- .../server/world/block/UpdateableBlock.java | 12 +- .../server/world/entity/EntityLogic.java | 4 +- .../world/tasks/BlockTriggeredUpdate.java | 9 +- .../server/world/tasks/ChangeEntity.java | 3 +- .../server/world/tasks/StateChange.java | 24 - .../server/world/tasks/TickChunk.java | 56 +- .../world/tasks/TileTriggeredUpdate.java | 19 +- .../server/world/tasks/WorldAccessor.java | 52 +- .../server/world/tile/HangingTileLogic.java | 21 +- .../server/world/tile/TSTickContext.java | 113 ---- .../server/world/tile/TickableTile.java | 6 +- .../server/world/tile/TileLogic.java | 5 +- .../server/world/tile/TileTickContext.java | 77 --- .../server/world/tile/UpdateableTile.java | 4 +- .../windcorp/progressia/test/TestContent.java | 6 +- .../test/TestEntityLogicStatie.java | 6 +- .../progressia/test/TestTileLogicGrass.java | 27 +- 29 files changed, 305 insertions(+), 1120 deletions(-) delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/TickContext.java delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java delete mode 100644 src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java diff --git a/src/main/java/ru/windcorp/progressia/common/world/context/Context.java b/src/main/java/ru/windcorp/progressia/common/world/context/Context.java index 73644ea..786e1eb 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/context/Context.java +++ b/src/main/java/ru/windcorp/progressia/common/world/context/Context.java @@ -135,5 +135,25 @@ public interface Context { * modifications to revert. */ void pop(); + + default T popAndReturn(T result) { + pop(); + return result; + } + + default boolean popAndReturn(boolean result) { + pop(); + return result; + } + + default int popAndReturn(int result) { + pop(); + return result; + } + + default float popAndReturn(float result) { + pop(); + return result; + } } diff --git a/src/main/java/ru/windcorp/progressia/server/Server.java b/src/main/java/ru/windcorp/progressia/server/Server.java index 0896caa..a57ce2f 100644 --- a/src/main/java/ru/windcorp/progressia/server/Server.java +++ b/src/main/java/ru/windcorp/progressia/server/Server.java @@ -35,6 +35,9 @@ 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.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.tasks.WorldAccessor; import ru.windcorp.progressia.server.world.ticking.Change; import ru.windcorp.progressia.server.world.ticking.Evaluation; @@ -97,6 +100,19 @@ public class Server { return world; } + /** + * 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. + * + * @return the context + */ + public ServerWorldContext createContext() { + + return new ReportingServerContext(DefaultServerContext.empty().inRealWorldOf(this).build()).withListener(worldAccessor); + + } + /** * Returns this server's {@link ClientManager}. Use this to deal with * communications, e.g. send packets. @@ -219,16 +235,20 @@ public class Server { return this.serverThread.getTicker().getUptimeTicks(); } - /** - * Returns the {@link WorldAccessor} object for this server. Use the - * provided accessor to request common {@link Evaluation}s and - * {@link Change}s. - * - * @return a {@link WorldAccessor} - * @see #requestChange(Change) - * @see #requestEvaluation(Evaluation) - */ - public WorldAccessor getWorldAccessor() { +// /** +// * Returns the {@link WorldAccessor} object for this server. Use the +// * provided accessor to request common {@link Evaluation}s and +// * {@link Change}s. +// * +// * @return a {@link WorldAccessor} +// * @see #requestChange(Change) +// * @see #requestEvaluation(Evaluation) +// */ +// public WorldAccessor getWorldAccessor() { +// return worldAccessor; +// } + + public WorldAccessor getWorldAccessor___really_bad_dont_use() { return worldAccessor; } diff --git a/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java deleted file mode 100644 index aec68fe..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/ChunkTickContext.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world; - -import java.util.function.Consumer; - -import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.world.DefaultChunkData; -import ru.windcorp.progressia.common.world.generic.GenericChunks; -import ru.windcorp.progressia.common.world.rels.AbsFace; -import ru.windcorp.progressia.server.world.block.BlockTickContext; - -public interface ChunkTickContext extends TickContext { - - Vec3i getChunk(); - - default DefaultChunkLogic getChunkLogic() { - return getWorld().getChunk(getChunk()); - } - - default DefaultChunkData getChunkData() { - DefaultChunkLogic chunkLogic = getChunkLogic(); - return chunkLogic == null ? null : chunkLogic.getData(); - } - - default AbsFace getUp() { - return getChunkData().getUp(); - } - - default void forEachBlock(Consumer action) { - TickContextMutable context = TickContextMutable.uninitialized(); - - GenericChunks.forEachBiC(blockInChunk -> { - context.rebuild().withServer(getServer()).withChunk(getChunk()).withBlockInChunk(blockInChunk).build(); - action.accept(context); - }); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java index 69fed5e..0e2dbbe 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultChunkLogic.java @@ -34,9 +34,13 @@ 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.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.ServerTileContextRO; +import ru.windcorp.progressia.server.world.context.ServerWorldContextRO; import ru.windcorp.progressia.server.world.tasks.TickChunk; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; import ru.windcorp.progressia.server.world.tile.TickableTile; @@ -221,28 +225,45 @@ public class DefaultChunkLogic implements ChunkLogic { } private void tmp_generateTickLists() { - ChunkTickContext context = TickContextMutable.start().withChunk(this).build(); - - context.forEachBlock(bctxt -> { - BlockLogic block = bctxt.getBlock(); + ServerWorldContextRO context = Server.getCurrentServer().createContext(); + Vec3i blockInChunk = new Vec3i(); + + forEachBiW(location -> { + + ServerBlockContextRO blockContext = context.push(location); + + BlockLogic block = blockContext.logic().getBlock(); + Coordinates.convertInWorldToInChunk(location, blockInChunk); if (!(block instanceof TickableBlock)) return; - if (((TickableBlock) block).getTickingPolicy(bctxt) == TickingPolicy.REGULAR) { - tickingBlocks.add(Coordinates.convertInWorldToInChunk(bctxt.getBlockInWorld(), null)); + if (((TickableBlock) block).getTickingPolicy(blockContext) == TickingPolicy.REGULAR) { + tickingBlocks.add(blockInChunk); } - bctxt.forEachFace(fctxt -> fctxt.forEachTile(tctxt -> { - TileLogic tile = tctxt.getTile(); + for (RelFace face : RelFace.getFaces()) { + TileLogicStack stack = getTilesOrNull(blockInChunk, face); + if (stack == null || stack.isEmpty()) continue; + + for (int i = 0; i < stack.size(); ++i) { + ServerTileContextRO tileContext = blockContext.push(face, i); + + TileLogic tile = stack.get(i); - if (!(tile instanceof TickableTile)) - return; + if (!(tile instanceof TickableTile)) + return; - if (((TickableTile) tile).getTickingPolicy(tctxt) == TickingPolicy.REGULAR) { - tickingTiles.add(tctxt.getReference()); + if (((TickableTile) tile).getTickingPolicy(tileContext) == TickingPolicy.REGULAR) { + tickingTiles.add(stack.getData().getReference(i)); + } + + tileContext.pop(); } - })); + } + + blockContext.pop(); + }); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java index d578fa7..f2b1883 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/DefaultWorldLogic.java @@ -65,7 +65,7 @@ public class DefaultWorldLogic implements WorldLogic { } }); - data.addListener(ChunkDataListeners.createAdder(new UpdateTriggerer(server))); + data.addListener(ChunkDataListeners.createAdder(new UpdateTriggerer(server.getWorldAccessor___really_bad_dont_use()))); } @Override diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java b/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java index 112d722..286a557 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java +++ b/src/main/java/ru/windcorp/progressia/server/world/TickAndUpdateUtil.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import glm.vec._3.i.Vec3i; @@ -24,19 +24,26 @@ import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.block.BlockLogic; -import ru.windcorp.progressia.server.world.block.BlockTickContext; 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.ServerTileContext; +import ru.windcorp.progressia.server.world.context.ServerTileStackContext; +import ru.windcorp.progressia.server.world.context.ServerWorldContext; import ru.windcorp.progressia.server.world.entity.EntityLogic; import ru.windcorp.progressia.server.world.entity.EntityLogicRegistry; import ru.windcorp.progressia.server.world.tile.TickableTile; import ru.windcorp.progressia.server.world.tile.TileLogic; -import ru.windcorp.progressia.server.world.tile.TileTickContext; import ru.windcorp.progressia.server.world.tile.UpdateableTile; public class TickAndUpdateUtil { - public static void tickBlock(TickableBlock block, BlockTickContext context) { + public static void tickBlock(ServerBlockContext context) { + BlockLogic uncheckedBlock = context.logic().getBlock(); + if (!(uncheckedBlock instanceof BlockLogic)) { + return; + } + TickableBlock block = (TickableBlock) uncheckedBlock; try { block.tick(context); } catch (Exception e) { @@ -44,16 +51,21 @@ public class TickAndUpdateUtil { } } - public static void tickBlock(DefaultWorldLogic world, Vec3i blockInWorld) { - BlockLogic block = world.getBlock(blockInWorld); - if (!(block instanceof TickableBlock)) - return; // also checks nulls - - BlockTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).build(); - tickBlock((TickableBlock) block, tickContext); + public static void tickBlock(Server server, Vec3i blockInWorld) { + BlockLogic block = server.getWorld().getBlock(blockInWorld); + if (!(block instanceof TickableBlock)) { + return; + } + ServerBlockContext context = server.createContext().push(blockInWorld); + tickBlock(context); } - public static void tickTile(TickableTile tile, TileTickContext context) { + public static void tickTile(ServerTileContext context) { + TileLogic uncheckedTile = context.logic().getTile(); + if (!(uncheckedTile instanceof TickableTile)) { + return; + } + TickableTile tile = (TickableTile) uncheckedTile; try { tile.tick(context); } catch (Exception e) { @@ -61,82 +73,88 @@ public class TickAndUpdateUtil { } } - public static void tickTile(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face, int layer) { - TileLogic tile = world.getTile(blockInWorld, face, layer); + public static void tickTile(Server server, Vec3i blockInWorld, BlockFace face, int layer) { + TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer); if (!(tile instanceof TickableTile)) { return; } - - TileTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face) - .withLayer(layer); - tickTile((TickableTile) tile, tickContext); + ServerTileContext context = server.createContext() + .push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer); + tickTile(context); } - public static void tickTiles(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face) { - if (!world.isLocationLoaded(blockInWorld)) { + public static void tickTiles(Server server, Vec3i blockInWorld, BlockFace face) { + if (!server.getWorld().hasTiles(blockInWorld, face)) { return; } - - TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face).build() - .forEachTile(context -> { - TileLogic tile = context.getTile(); - if (tile instanceof TickableTile) { - tickTile((TickableTile) tile, context); - } - }); + + ServerTileStackContext context = server.createContext() + .push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld))); + for (int i = 0; i < context.getTileCount(); ++i) { + tickTile(context.push(i)); + context.pop(); + } } - public static void updateBlock(UpdateableBlock block, BlockTickContext context) { + public static void updateBlock(ServerBlockContext context) { + BlockLogic uncheckedBlock = context.logic().getBlock(); + if (!(uncheckedBlock instanceof BlockLogic)) { + return; + } + UpdateableBlock block = (UpdateableBlock) uncheckedBlock; try { block.update(context); } catch (Exception e) { - throw CrashReports.report(e, "Could not update block {}", block); + throw CrashReports.report(e, "Could not update block %s", block); } } - public static void updateBlock(DefaultWorldLogic world, Vec3i blockInWorld) { - BlockLogic block = world.getBlock(blockInWorld); - if (!(block instanceof UpdateableBlock)) - return; // also checks nulls - - BlockTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).build(); - updateBlock((UpdateableBlock) block, tickContext); + public static void updateBlock(Server server, Vec3i blockInWorld) { + BlockLogic block = server.getWorld().getBlock(blockInWorld); + if (!(block instanceof UpdateableBlock)) { + return; + } + ServerBlockContext context = server.createContext().push(blockInWorld); + updateBlock(context); } - public static void updateTile(UpdateableTile tile, TileTickContext context) { + public static void updateTile(ServerTileContext context) { + TileLogic uncheckedTile = context.logic().getTile(); + if (!(uncheckedTile instanceof UpdateableTile)) { + return; + } + UpdateableTile tile = (UpdateableTile) uncheckedTile; try { tile.update(context); } catch (Exception e) { - throw CrashReports.report(e, "Could not update tile {}", tile); + throw CrashReports.report(e, "Could not tick tile %s", tile); } } - public static void updateTile(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face, int layer) { - TileLogic tile = world.getTile(blockInWorld, face, layer); + public static void updateTile(Server server, Vec3i blockInWorld, BlockFace face, int layer) { + TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer); if (!(tile instanceof UpdateableTile)) { return; } - - TileTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face) - .withLayer(layer); - updateTile((UpdateableTile) tile, tickContext); + ServerTileContext context = server.createContext() + .push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer); + updateTile(context); } - public static void updateTiles(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face) { - if (!world.isLocationLoaded(blockInWorld)) { + public static void updateTiles(Server server, Vec3i blockInWorld, BlockFace face) { + if (!server.getWorld().hasTiles(blockInWorld, face)) { return; } - - TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face).build() - .forEachTile(context -> { - TileLogic tile = context.getTile(); - if (tile instanceof UpdateableTile) { - updateTile((UpdateableTile) tile, context); - } - }); + + ServerTileStackContext context = server.createContext() + .push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld))); + for (int i = 0; i < context.getTileCount(); ++i) { + updateTile(context.push(i)); + context.pop(); + } } - public static void tickEntity(EntityLogic logic, EntityData data, TickContext context) { + public static void tickEntity(EntityLogic logic, EntityData data, ServerWorldContext context) { try { logic.tick(data, context); } catch (Exception e) { @@ -148,7 +166,7 @@ public class TickAndUpdateUtil { tickEntity( EntityLogicRegistry.getInstance().get(data.getId()), data, - TickContextMutable.start().withServer(server).build() + server.createContext() ); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickContext.java b/src/main/java/ru/windcorp/progressia/server/world/TickContext.java deleted file mode 100644 index 5d92f4a..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/TickContext.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world; - -import java.util.Random; - -import ru.windcorp.progressia.common.world.DefaultWorldData; -import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.server.world.tasks.WorldAccessor; - -public interface TickContext { - - float getTickLength(); - - Server getServer(); - - default DefaultWorldLogic getWorld() { - return getServer().getWorld(); - } - - default WorldAccessor getAccessor() { - return getServer().getWorldAccessor(); - } - - default Random getRandom() { - return getServer().getAdHocRandom(); - } - - default DefaultWorldData getWorldData() { - return getWorld().getData(); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java b/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java deleted file mode 100644 index a5eb592..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/TickContextMutable.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world; - -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; - -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.generic.TileGenericStackRO; -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.TileDataReference; -import ru.windcorp.progressia.server.Server; -import ru.windcorp.progressia.server.world.block.BlockTickContext; -import ru.windcorp.progressia.server.world.tile.TSTickContext; -import ru.windcorp.progressia.server.world.tile.TileTickContext; - -public abstract class TickContextMutable implements BlockTickContext, TSTickContext, TileTickContext { - - private static enum Role { - NONE, WORLD, CHUNK, BLOCK, TILE_STACK, TILE; - } - - /* - * TickContextMutable interface - */ - - // Only TickContextMutable.Impl can extend; extend Impl if need be - private TickContextMutable() { - } - - public abstract Builder.Empty rebuild(); - - /* - * Static methods - */ - - public static TickContextMutable uninitialized() { - return new Impl(); - } - - public static Builder.Empty start() { - return uninitialized().rebuild(); - } - - public static Builder.World copyWorld(TickContext context) { - return start().withServer(context.getServer()); - } - - public static Builder.Chunk copyChunk(ChunkTickContext context) { - return start().withChunk(context.getChunkLogic()); - } - - public static Builder.Block copyBlock(BlockTickContext context) { - return copyWorld(context).withBlock(context.getBlockInWorld()); - } - - public static Builder.TileStack copyTS(TSTickContext context) { - return copyBlock(context).withFace(context.getFace()); - } - - public static TileTickContext copyTile(TileTickContext context) { - return copyTS(context).withLayer(context.getLayer()); - } - - /* - * Builder interfaces - */ - - public static interface Builder { - TickContextMutable build(); - - public static interface Empty /* does not extend Builder */ { - World withServer(Server server); - - default Builder.World withWorld(DefaultWorldLogic world) { - Objects.requireNonNull(world, "world"); - return withServer(world.getServer()); - } - - default Builder.Chunk withChunk(DefaultChunkLogic chunk) { - Objects.requireNonNull(chunk, "chunk"); - return withWorld(chunk.getWorld()).withChunk(chunk.getPosition()); - } - } - - public static interface World extends Builder { - Chunk withChunk(Vec3i chunk); - - Block withBlock(Vec3i blockInWorld); - - TileStack withTS(TileGenericStackRO tileStack); - - default Builder.Chunk withChunk(DefaultChunkData chunk) { - Objects.requireNonNull(chunk, "chunk"); - return withChunk(chunk.getPosition()); - } - - default TileTickContext withTile(TileDataReference ref) { - Objects.requireNonNull(ref, "ref"); - return withTS(ref.getStack()).withLayer(ref.getIndex()); - } - } - - public static interface Chunk extends Builder { - Builder.Block withBlockInChunk(Vec3i blockInChunk); - } - - public static interface Block extends Builder { - Builder.TileStack withFace(BlockFace face); - } - - public static interface TileStack extends Builder { - TickContextMutable withLayer(int layer); - } - } - - /* - * Impl - */ - - public static class Impl - extends TickContextMutable - implements Builder.Empty, Builder.World, Builder.Chunk, Builder.Block, Builder.TileStack { - - protected Impl() { - } - - protected Server server; - protected final Vec3i chunk = new Vec3i(); - protected final Vec3i blockInWorld = new Vec3i(); - protected RelFace face; - protected int layer; - - protected Role role = Role.NONE; - protected boolean isBeingBuilt = false; - - /** - * Updated lazily - */ - protected final Vec3i blockInChunk = new Vec3i(); - - /* - * TickContextMutable - */ - - @Override - public Server getServer() { - checkContextState(Role.WORLD); - return this.server; - } - - @Override - public float getTickLength() { - checkContextState(Role.WORLD); - return (float) this.server.getTickLength(); - } - - @Override - public Vec3i getChunk() { - checkContextState(Role.CHUNK); - return this.chunk; - } - - @Override - public Vec3i getBlockInWorld() { - checkContextState(Role.BLOCK); - return this.blockInWorld; - } - - @Override - public RelFace getFace() { - checkContextState(Role.TILE_STACK); - return this.face; - } - - @Override - public int getLayer() { - checkContextState(Role.TILE); - return this.layer; - } - - @Override - public Builder.Empty rebuild() { - this.role = Role.NONE; - this.isBeingBuilt = true; - - this.server = null; - this.chunk.set(0); - this.blockInWorld.set(0); - this.face = null; - this.layer = -1; - - return this; - } - - /* - * Builder - * memo: do NOT use Context getters, they throw ISEs - */ - - @Override - public TickContextMutable build() { - checkBuilderState(null); - this.isBeingBuilt = false; - return this; - } - - @Override - public World withServer(Server server) { - Objects.requireNonNull(server, "server"); - checkBuilderState(Role.NONE); - this.server = server; - this.role = Role.WORLD; - return this; - } - - @Override - public Chunk withChunk(Vec3i chunk) { - Objects.requireNonNull(chunk, "chunk"); - checkBuilderState(Role.WORLD); - - this.chunk.set(chunk.x, chunk.y, chunk.z); - - this.role = Role.CHUNK; - return this; - } - - @Override - public Block withBlock(Vec3i blockInWorld) { - Objects.requireNonNull(blockInWorld, "blockInWorld"); - checkBuilderState(Role.WORLD); - - this.blockInWorld.set(blockInWorld.x, blockInWorld.y, blockInWorld.z); - Coordinates.convertInWorldToChunk(blockInWorld, this.chunk); - - this.role = Role.BLOCK; - return this; - } - - @Override - public TileStack withTS(TileGenericStackRO tileStack) { - Objects.requireNonNull(tileStack, "tileStack"); - - return withBlock( - tileStack.getBlockInWorld(this.blockInWorld) // This is safe - ).withFace(tileStack.getFace()); - } - - @Override - public Block withBlockInChunk(Vec3i blockInChunk) { - Objects.requireNonNull(blockInChunk, "blockInChunk"); - checkBuilderState(Role.CHUNK); - - Coordinates.getInWorld(this.chunk, blockInChunk, this.blockInWorld); - - this.role = Role.BLOCK; - return this; - } - - @Override - public TileStack withFace(BlockFace face) { - Objects.requireNonNull(face, "face"); - checkBuilderState(Role.BLOCK); - - this.face = face.relativize(server.getWorld().getChunk(chunk).getUp()); - - this.role = Role.TILE_STACK; - return this; - } - - @Override - public TickContextMutable withLayer(int layer) { - checkBuilderState(Role.TILE); - - this.layer = layer; - - this.role = Role.TILE; - return build(); - } - - /* - * Optimization - */ - - @Override - public Vec3i getBlockInChunk() { - return Coordinates.convertInWorldToInChunk(getBlockInWorld(), this.blockInChunk); - } - - @Override - public void forEachBlock(Consumer action) { - checkContextState(Role.CHUNK); - - Vec3i v = this.blockInWorld; - - int previousX = v.x; - int previousY = v.y; - int previousZ = v.z; - Role previousRole = this.role; - - this.role = Role.BLOCK; - - final int minX = Coordinates.getInWorld(chunk.x, 0); - final int minY = Coordinates.getInWorld(chunk.y, 0); - final int minZ = Coordinates.getInWorld(chunk.z, 0); - final int size = DefaultChunkData.BLOCKS_PER_CHUNK; - - for (v.x = minX; v.x < minX + size; ++v.x) { - for (v.y = minY; v.y < minY + size; ++v.y) { - for (v.z = minZ; v.z < minZ + size; ++v.z) { - action.accept(this); - } - } - } - - this.role = previousRole; - blockInWorld.set(previousX, previousY, previousZ); - } - - @Override - public void forEachFace(Consumer action) { - checkContextState(Role.BLOCK); - RelFace previousFace = this.face; - Role previousRole = this.role; - - this.role = Role.TILE_STACK; - for (int i = 0; i < BlockFace.BLOCK_FACE_COUNT; ++i) { - this.face = RelFace.getFaces().get(i); - action.accept(this); - } - - this.role = previousRole; - this.face = previousFace; - } - - @Override - public R evalNeighbor(Vec3i direction, Function action) { - this.blockInWorld.add(direction); - R result = action.apply(this); - this.blockInWorld.sub(direction); - - return result; - } - - @Override - public void forNeighbor(Vec3i direction, Consumer action) { - this.blockInWorld.add(direction); - action.accept(this); - this.blockInWorld.sub(direction); - } - - @Override - public boolean forEachTile(Consumer action) { - checkContextState(Role.TILE_STACK); - int previousLayer = this.layer; - Role previousRole = this.role; - - this.role = Role.TILE; - TileDataStack stack = getTDSOrNull(); - if (stack == null || stack.isEmpty()) - return false; - - for (this.layer = 0; this.layer < stack.size(); ++this.layer) { - action.accept(this); - } - - this.role = previousRole; - this.layer = previousLayer; - return true; - } - - @Override - public R evalComplementary(Function action) { - Objects.requireNonNull(action, "action"); - checkContextState(Role.TILE_STACK); - - Vec3i vector = this.face.getVector(getUp()); - - this.blockInWorld.add(vector); - this.face = this.face.getCounter(); - R result = action.apply(this); - this.face = this.face.getCounter(); - this.blockInWorld.sub(vector); - - return result; - } - - @Override - public void forComplementary(Consumer action) { - Objects.requireNonNull(action, "action"); - checkContextState(Role.TILE_STACK); - - Vec3i vector = this.face.getVector(getUp()); - - this.blockInWorld.add(vector); - this.face = this.face.getCounter(); - action.accept(this); - this.face = this.face.getCounter(); - this.blockInWorld.sub(vector); - } - - /* - * Misc - */ - - protected void checkContextState(Role requiredRole) { - if (isBeingBuilt) { - throw new IllegalStateException("This context is still being built"); - } - - if ((role == null) || (requiredRole.compareTo(role) > 0)) { - throw new IllegalStateException( - "This context is currently initialized as " + role + "; requested " + requiredRole - ); - } - } - - protected void checkBuilderState(Role requiredRole) { - if (!isBeingBuilt) { - throw new IllegalStateException("This context is already built"); - } - - if (requiredRole == null) { - if (role == Role.NONE) { - throw new IllegalStateException("This context is currently not initialized"); - } - } else { - if (role != requiredRole) { - throw new IllegalStateException( - "This context is currently initialized as " + role + "; requested " + requiredRole - ); - } - } - } - - @Override - public String toString() { - final String format; - - switch (this.role) { - case WORLD: - format = "TickContext"; - break; - case CHUNK: - format = "(%2$d; %3$d; %4$d)"; - break; - case BLOCK: - format = "(%5$d; %6$d; %7$d)"; - break; - case TILE_STACK: - format = "((%5$d; %6$d; %7$d); %8$6s)"; - break; - case TILE: - format = "((%5$d; %6$d; %7$d); %8$6s; %9$d)"; - break; - case NONE: - default: - format = "Uninitialized TickContextMutable"; - break; - } - - return String.format( - format, - this.chunk.x, - this.chunk.y, - this.chunk.z, - this.blockInWorld.x, - this.blockInWorld.y, - this.blockInWorld.z, - this.face, - this.layer - ); - } - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java b/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java index fc22047..8175937 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java +++ b/src/main/java/ru/windcorp/progressia/server/world/UpdateTriggerer.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world; import glm.vec._3.i.Vec3i; @@ -25,14 +25,14 @@ import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.block.BlockData; import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.world.tasks.WorldAccessor; public class UpdateTriggerer implements ChunkDataListener { - private final Server server; + private final WorldAccessor worldAccessor; - public UpdateTriggerer(Server server) { - this.server = server; + public UpdateTriggerer(WorldAccessor worldAccessor) { + this.worldAccessor = worldAccessor; } @Override @@ -42,7 +42,7 @@ public class UpdateTriggerer implements ChunkDataListener { BlockData previous, BlockData current ) { - server.getWorldAccessor().triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null)); + worldAccessor.triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null)); } @Override @@ -53,7 +53,7 @@ public class UpdateTriggerer implements ChunkDataListener { TileData tile, boolean wasAdded ) { - server.getWorldAccessor().triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null), face); + worldAccessor.triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null), face); } } diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java b/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java index 1d08194..7b2204f 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/BlockLogic.java @@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world.block; import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.world.generic.BlockGeneric; import ru.windcorp.progressia.common.world.rels.RelFace; +import ru.windcorp.progressia.server.world.context.ServerBlockContextRO; public class BlockLogic extends Namespaced implements BlockGeneric { @@ -28,7 +29,7 @@ public class BlockLogic extends Namespaced implements BlockGeneric { super(id); } - public boolean isSolid(BlockTickContext context, RelFace face) { + public boolean isSolid(ServerBlockContextRO context, RelFace face) { return isSolid(face); } @@ -36,7 +37,7 @@ public class BlockLogic extends Namespaced implements BlockGeneric { return true; } - public boolean isTransparent(BlockTickContext context) { + public boolean isTransparent(ServerBlockContextRO context) { return isTransparent(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java deleted file mode 100644 index 7069aa9..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/block/BlockTickContext.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world.block; - -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; - -import glm.vec._3.i.Vec3i; -import ru.windcorp.progressia.common.world.Coordinates; -import ru.windcorp.progressia.common.world.block.BlockData; -import ru.windcorp.progressia.common.world.rels.AbsFace; -import ru.windcorp.progressia.common.world.rels.BlockRelation; -import ru.windcorp.progressia.server.world.ChunkTickContext; -import ru.windcorp.progressia.server.world.TickContextMutable; -import ru.windcorp.progressia.server.world.tile.TSTickContext; - -public interface BlockTickContext extends ChunkTickContext { - - /** - * Returns the current world coordinates. - * - * @return the world coordinates of the block being ticked - */ - Vec3i getBlockInWorld(); - - default Vec3i getBlockInChunk() { - return Coordinates.convertInWorldToInChunk(getBlockInWorld(), null); - } - - default BlockLogic getBlock() { - return getWorld().getBlock(getBlockInWorld()); - } - - default BlockData getBlockData() { - return getWorldData().getBlock(getBlockInWorld()); - } - - default void forEachFace(Consumer action) { - Objects.requireNonNull(action, "action"); - TickContextMutable context = TickContextMutable.uninitialized(); - - for (AbsFace face : AbsFace.getFaces()) { - context.rebuild().withServer(getServer()).withBlock(getBlockInWorld()).withFace(face).build(); - action.accept(context); - } - } - - default BlockTickContext getNeighbor(Vec3i direction) { - Objects.requireNonNull(direction, "direction"); - return TickContextMutable.copyWorld(this).withBlock(getBlockInWorld().add_(direction)).build(); - } - - default BlockTickContext getNeighbor(BlockRelation relation) { - Objects.requireNonNull(relation, "relation"); - return getNeighbor(relation.getVector(getChunkData().getUp())); - } - - default R evalNeighbor(Vec3i direction, Function action) { - Objects.requireNonNull(action, "action"); - Objects.requireNonNull(direction, "direction"); - return action.apply(getNeighbor(direction)); - } - - default R evalNeighbor(BlockRelation relation, Function action) { - Objects.requireNonNull(action, "action"); - Objects.requireNonNull(relation, "relation"); - return evalNeighbor(relation.getVector(getChunkData().getUp()), action); - } - - default void forNeighbor(Vec3i direction, Consumer action) { - Objects.requireNonNull(action, "action"); - Objects.requireNonNull(direction, "direction"); - evalNeighbor(direction, (Function) ctxt -> { - action.accept(ctxt); - return null; - }); - } - - default void forNeighbor(BlockRelation relation, Consumer action) { - Objects.requireNonNull(action, "action"); - Objects.requireNonNull(relation, "relation"); - forNeighbor(relation.getVector(getChunkData().getUp()), action); - } - - /* - * Convenience methods - changes - */ - - default void setThisBlock(BlockData block) { - getAccessor().setBlock(getBlockInWorld(), block); - } - - default void setThisBlock(String id) { - getAccessor().setBlock(getBlockInWorld(), id); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java b/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java index 56ba938..bc4569b 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/TickableBlock.java @@ -18,12 +18,14 @@ package ru.windcorp.progressia.server.world.block; +import ru.windcorp.progressia.server.world.context.ServerBlockContext; +import ru.windcorp.progressia.server.world.context.ServerBlockContextRO; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; public interface TickableBlock { - void tick(BlockTickContext context); + void tick(ServerBlockContext context); - TickingPolicy getTickingPolicy(BlockTickContext context); + TickingPolicy getTickingPolicy(ServerBlockContextRO context); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java b/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java index 1497c92..757e972 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java +++ b/src/main/java/ru/windcorp/progressia/server/world/block/UpdateableBlock.java @@ -18,18 +18,10 @@ package ru.windcorp.progressia.server.world.block; -import org.apache.logging.log4j.LogManager; +import ru.windcorp.progressia.server.world.context.ServerBlockContext; public interface UpdateableBlock { - default void update(BlockTickContext context) { - LogManager.getLogger().info( - "Updating block {} @ ({}; {}; {})", - context.getBlock(), - context.getBlockInWorld().x, - context.getBlockInWorld().y, - context.getBlockInWorld().z - ); - } + void update(ServerBlockContext context); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java index 7725612..2ebd2d6 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/entity/EntityLogic.java @@ -20,7 +20,7 @@ package ru.windcorp.progressia.server.world.entity; import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.world.entity.EntityData; -import ru.windcorp.progressia.server.world.TickContext; +import ru.windcorp.progressia.server.world.context.ServerWorldContext; public class EntityLogic extends Namespaced { @@ -28,7 +28,7 @@ public class EntityLogic extends Namespaced { super(id); } - public void tick(EntityData entity, TickContext context) { + public void tick(EntityData entity, ServerWorldContext context) { entity.incrementAge(context.getTickLength()); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java index 120cd22..57d2c67 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/BlockTriggeredUpdate.java @@ -25,7 +25,6 @@ import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.TickAndUpdateUtil; -import ru.windcorp.progressia.server.world.DefaultWorldLogic; class BlockTriggeredUpdate extends CachedEvaluation { @@ -39,13 +38,11 @@ class BlockTriggeredUpdate extends CachedEvaluation { public void evaluate(Server server) { Vec3i cursor = new Vec3i(blockInWorld.x, blockInWorld.y, blockInWorld.z); - DefaultWorldLogic world = server.getWorld(); - for (AbsFace face : AbsFace.getFaces()) { - TickAndUpdateUtil.updateTiles(world, cursor, face); + TickAndUpdateUtil.updateTiles(server, cursor, face); cursor.add(face.getVector()); - TickAndUpdateUtil.updateBlock(world, cursor); - TickAndUpdateUtil.updateTiles(world, cursor, face.getCounter()); + TickAndUpdateUtil.updateBlock(server, cursor); + TickAndUpdateUtil.updateTiles(server, cursor, face.getCounter()); cursor.sub(face.getVector()); } } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java index 08f1212..8760460 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/ChangeEntity.java @@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.state.StateChange; import ru.windcorp.progressia.common.world.entity.EntityData; import ru.windcorp.progressia.common.world.entity.PacketChangeEntity; import ru.windcorp.progressia.server.Server; @@ -36,7 +37,7 @@ class ChangeEntity extends CachedChange { super(disposer); } - public void set(T entity, StateChange change) { + public void set(EntityData entity, StateChange change) { if (this.entity != null) throw new IllegalStateException("Entity is not null. Current: " + this.entity + "; requested: " + entity); diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java deleted file mode 100644 index 93d5f08..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/StateChange.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world.tasks; - -@FunctionalInterface -public interface StateChange { - void change(T object); -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java index 336f166..d7fabc1 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/TickChunk.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia.server.world.tasks; import java.util.ArrayList; @@ -27,17 +27,22 @@ 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.TickContextMutable; 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.ServerTileContext; +import ru.windcorp.progressia.server.world.context.ServerTileStackContext; +import ru.windcorp.progressia.server.world.context.ServerWorldContext; import ru.windcorp.progressia.server.world.ticking.Evaluation; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; -import ru.windcorp.progressia.server.world.tile.TSTickContext; import ru.windcorp.progressia.server.world.tile.TickableTile; import ru.windcorp.progressia.server.world.tile.TileLogic; import static ru.windcorp.progressia.common.world.DefaultChunkData.BLOCKS_PER_CHUNK; @@ -82,11 +87,11 @@ public class TickChunk extends Evaluation { if (!chunk.hasTickingBlocks()) return; - TickContextMutable context = TickContextMutable.uninitialized(); + ServerWorldContext context = server.createContext(); chunk.forEachTickingBlock((blockInChunk, block) -> { - context.rebuild().withChunk(chunk).withBlockInChunk(blockInChunk).build(); - ((TickableBlock) block).tick(context); + ((TickableBlock) block).tick(contextPushBiC(context, chunk, blockInChunk)); + context.pop(); }); } @@ -94,11 +99,14 @@ public class TickChunk extends Evaluation { if (!chunk.hasTickingTiles()) return; - TickContextMutable context = TickContextMutable.uninitialized(); + ServerWorldContext context = server.createContext(); + Vec3i blockInWorld = new Vec3i(); chunk.forEachTickingTile((ref, tile) -> { - context.rebuild().withServer(server).withTile(ref); - ((TickableTile) tile).tick(context); + ((TickableTile) tile).tick( + context.push(ref.getStack().getBlockInWorld(blockInWorld), ref.getStack().getFace(), ref.getIndex()) + ); + context.pop(); }); } @@ -144,7 +152,7 @@ public class TickChunk extends Evaluation { return; TickableBlock tickable = (TickableBlock) block; - TickContextMutable context = TickContextMutable.start().withChunk(chunk).withBlockInChunk(blockInChunk).build(); + ServerBlockContext context = contextPushBiC(server.createContext(), chunk, blockInChunk); if (tickable.getTickingPolicy(context) != TickingPolicy.RANDOM) return; @@ -164,18 +172,22 @@ public class TickChunk extends Evaluation { if (tiles == null || tiles.isEmpty()) return; - TSTickContext context = TickContextMutable.start().withServer(server).withTS(tiles).build(); + ServerTileStackContext context = contextPushBiC(server.createContext(), chunk, blockInChunk).push(face.relativize(chunk.getUp())); - context.forEachTile(tctxt -> { - TileLogic logic = tctxt.getTile(); + for (int i = 0; i < tiles.size(); ++i) { + ServerTileContext tileContext = context.push(i); + + TileLogic logic = tileContext.logic().getTile(); if (!(logic instanceof TickableTile)) return; TickableTile tickable = (TickableTile) logic; - if (tickable.getTickingPolicy(tctxt) != TickingPolicy.RANDOM) + if (tickable.getTickingPolicy(tileContext) != TickingPolicy.RANDOM) return; - tickable.tick(tctxt); - }); + tickable.tick(tileContext); + + tileContext.pop(); + } } private float computeRandomTicks(Server server) { @@ -184,6 +196,18 @@ 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(); diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java index 66e95a1..c052108 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/TileTriggeredUpdate.java @@ -25,7 +25,6 @@ import ru.windcorp.progressia.common.world.Coordinates; import ru.windcorp.progressia.common.world.rels.AbsFace; import ru.windcorp.progressia.server.Server; import ru.windcorp.progressia.server.world.TickAndUpdateUtil; -import ru.windcorp.progressia.server.world.DefaultWorldLogic; class TileTriggeredUpdate extends CachedEvaluation { @@ -40,17 +39,15 @@ class TileTriggeredUpdate extends CachedEvaluation { public void evaluate(Server server) { Vec3i cursor = new Vec3i(blockInWorld.x, blockInWorld.y, blockInWorld.z); - DefaultWorldLogic world = server.getWorld(); - - TickAndUpdateUtil.updateTiles(world, cursor, face); // Update facemates - // (also self) - TickAndUpdateUtil.updateBlock(world, cursor); // Update block on one - // side + // Update facemates (also self) + TickAndUpdateUtil.updateTiles(server, cursor, face); + // Update block on one side + TickAndUpdateUtil.updateBlock(server, cursor); cursor.add(face.getVector()); - TickAndUpdateUtil.updateBlock(world, cursor); // Update block on the - // other side - TickAndUpdateUtil.updateTiles(world, cursor, face.getCounter()); // Update - // complement + // Update block on the other side + TickAndUpdateUtil.updateBlock(server, cursor); + // Update complement + TickAndUpdateUtil.updateTiles(server, cursor, face.getCounter()); } public void init(Vec3i blockInWorld, AbsFace face) { diff --git a/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java b/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java index 15ab504..cb95063 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tasks/WorldAccessor.java @@ -21,17 +21,19 @@ package ru.windcorp.progressia.server.world.tasks; import java.util.function.Consumer; import glm.vec._3.i.Vec3i; +import ru.windcorp.progressia.common.state.StateChange; +import ru.windcorp.progressia.common.state.StatefulObject; import ru.windcorp.progressia.common.util.MultiLOC; import ru.windcorp.progressia.common.world.block.BlockData; -import ru.windcorp.progressia.common.world.block.BlockDataRegistry; import ru.windcorp.progressia.common.world.entity.EntityData; +import ru.windcorp.progressia.common.world.generic.EntityGeneric; import ru.windcorp.progressia.common.world.rels.BlockFace; import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.common.world.tile.TileDataRegistry; import ru.windcorp.progressia.server.Server; +import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext; import ru.windcorp.progressia.server.world.ticking.TickerTask; -public class WorldAccessor { +public class WorldAccessor implements ReportingServerContext.ChangeListener { private final MultiLOC cache; { @@ -54,38 +56,52 @@ public class WorldAccessor { this.server = server; } - public void setBlock(Vec3i blockInWorld, BlockData block) { + @Override + public void onBlockSet(Vec3i blockInWorld, BlockData block) { SetBlock change = cache.grab(SetBlock.class); change.getPacket().set(block, blockInWorld); server.requestChange(change); } - public void setBlock(Vec3i blockInWorld, String id) { - setBlock(blockInWorld, BlockDataRegistry.getInstance().get(id)); - } - - public void addTile(Vec3i blockInWorld, BlockFace face, TileData tile) { + @Override + public void onTileAdded(Vec3i blockInWorld, BlockFace face, TileData tile) { AddTile change = cache.grab(AddTile.class); change.getPacket().set(tile, blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld))); server.requestChange(change); } - public void addTile(Vec3i blockInWorld, BlockFace face, String id) { - addTile(blockInWorld, face, TileDataRegistry.getInstance().get(id)); - } - - public void removeTile(Vec3i blockInWorld, BlockFace face, int tag) { + @Override + public void onTileRemoved(Vec3i blockInWorld, BlockFace face, int tag) { RemoveTile change = cache.grab(RemoveTile.class); change.getPacket().set(blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)), tag); server.requestChange(change); } + + @Override + public void onEntityAdded(EntityData entity) { + // TODO Auto-generated method stub + + } + + @Override + public void onEntityRemoved(long entityId) { + // TODO Auto-generated method stub + + } + + @Override + public void onTimeChanged(float change) { + // TODO Auto-generated method stub + System.err.println("WorldAccessor.onTimeChanged() NYI!"); + } - public void changeEntity( - T entity, - StateChange stateChange + @Override + public void onEntityChanged( + SE entity, + StateChange stateChange ) { ChangeEntity change = cache.grab(ChangeEntity.class); - change.set(entity, stateChange); + change.set((EntityData) entity, stateChange); server.requestChange(change); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java b/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java index 745f289..f916a24 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/HangingTileLogic.java @@ -19,6 +19,8 @@ package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.server.world.block.BlockLogic; +import ru.windcorp.progressia.server.world.context.ServerTileContext; +import ru.windcorp.progressia.server.world.context.ServerTileContextRO; public class HangingTileLogic extends TileLogic implements UpdateableTile { @@ -27,15 +29,15 @@ public class HangingTileLogic extends TileLogic implements UpdateableTile { } @Override - public void update(TileTickContext context) { + public void update(ServerTileContext context) { if (!canOccupyFace(context)) { - context.removeThisTile(); + context.removeTile(); } } @Override - public boolean canOccupyFace(TileTickContext context) { - BlockLogic host = context.getBlock(); + public boolean canOccupyFace(ServerTileContextRO context) { + BlockLogic host = context.logic().getBlock(); if (host == null) return false; @@ -45,13 +47,14 @@ public class HangingTileLogic extends TileLogic implements UpdateableTile { if (canBeSquashed(context)) return true; - return context.evalComplementary(ctxt -> { - BlockLogic complHost = ctxt.getBlock(); - return complHost == null || !complHost.isSolid(ctxt, context.getFace()); - }); + context.pushOpposite(); + BlockLogic complHost = context.logic().getBlock(); + boolean result = complHost == null || !complHost.isSolid(context, context.getFace()); + context.pop(); + return result; } - public boolean canBeSquashed(TileTickContext context) { + public boolean canBeSquashed(ServerTileContextRO context) { return false; } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java deleted file mode 100644 index d805607..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TSTickContext.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world.tile; - -import java.util.Objects; -import java.util.function.Consumer; -import java.util.function.Function; - -import ru.windcorp.progressia.common.world.DefaultChunkData; -import ru.windcorp.progressia.common.world.rels.RelFace; -import ru.windcorp.progressia.common.world.TileDataStack; -import ru.windcorp.progressia.server.world.DefaultChunkLogic; -import ru.windcorp.progressia.server.world.TickContextMutable; -import ru.windcorp.progressia.server.world.TileLogicStackRO; -import ru.windcorp.progressia.server.world.block.BlockTickContext; - -public interface TSTickContext extends BlockTickContext { - - /* - * Specifications - */ - - RelFace getFace(); - - /* - * Getters - */ - - default TileLogicStackRO getTLSOrNull() { - DefaultChunkLogic chunkLogic = getChunkLogic(); - if (chunkLogic == null) - return null; - - return chunkLogic.getTilesOrNull(getBlockInChunk(), getFace()); - } - - default TileLogicStackRO getTLS() { - return getChunkLogic().getTiles(getBlockInChunk(), getFace()); - } - - default TileDataStack getTDSOrNull() { - DefaultChunkData chunkData = getChunkData(); - if (chunkData == null) - return null; - - return chunkData.getTilesOrNull(getBlockInChunk(), getFace()); - } - - default TileDataStack getTDS() { - return getChunkData().getTiles(getBlockInChunk(), getFace()); - } - - /* - * Contexts - */ - - default TileTickContext forLayer(int layer) { - return TickContextMutable.start().withServer(getServer()).withBlock(getBlockInWorld()).withFace(getFace()) - .withLayer(layer); - } - - default boolean forEachTile(Consumer action) { - TickContextMutable context = TickContextMutable.uninitialized(); - - TileDataStack stack = getTDSOrNull(); - if (stack == null || stack.isEmpty()) - return false; - - for (int layer = 0; layer < stack.size(); ++layer) { - context.rebuild().withServer(getServer()).withBlock(getBlockInWorld()).withFace(getFace()).withLayer(layer); - action.accept(context); - } - - return true; - } - - default TSTickContext getComplementary() { - return TickContextMutable.copyWorld(this) - .withBlock(getBlockInWorld().add_(getFace().getVector(getUp()))) - .withFace(getFace().getCounter()) - .build(); - } - - default R evalComplementary(Function action) { - Objects.requireNonNull(action, "action"); - return action.apply(getComplementary()); - } - - default void forComplementary(Consumer action) { - Objects.requireNonNull(action, "action"); - evalComplementary((Function) ctxt -> { - action.accept(ctxt); - return null; - }); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java index 4def3b0..ce2487d 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TickableTile.java @@ -18,12 +18,14 @@ package ru.windcorp.progressia.server.world.tile; +import ru.windcorp.progressia.server.world.context.ServerTileContext; +import ru.windcorp.progressia.server.world.context.ServerTileContextRO; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; public interface TickableTile { - void tick(TileTickContext context); + void tick(ServerTileContext context); - TickingPolicy getTickingPolicy(TileTickContext context); + TickingPolicy getTickingPolicy(ServerTileContextRO context); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java index 67466b5..229d7e3 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/TileLogic.java @@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world.tile; import ru.windcorp.progressia.common.util.namespaces.Namespaced; import ru.windcorp.progressia.common.world.generic.TileGeneric; import ru.windcorp.progressia.common.world.rels.RelFace; +import ru.windcorp.progressia.server.world.context.ServerTileContextRO; public class TileLogic extends Namespaced implements TileGeneric { @@ -28,7 +29,7 @@ public class TileLogic extends Namespaced implements TileGeneric { super(id); } - public boolean canOccupyFace(TileTickContext context) { + public boolean canOccupyFace(ServerTileContextRO context) { return canOccupyFace(context.getFace()); } @@ -36,7 +37,7 @@ public class TileLogic extends Namespaced implements TileGeneric { return true; } - public boolean isSolid(TileTickContext context) { + public boolean isSolid(ServerTileContextRO context) { return isSolid(); } diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java b/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java deleted file mode 100644 index 597291a..0000000 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/TileTickContext.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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 . - */ - -package ru.windcorp.progressia.server.world.tile; - -import ru.windcorp.progressia.common.world.tile.TileData; -import ru.windcorp.progressia.server.world.TileLogicStackRO; -import ru.windcorp.progressia.common.world.TileDataStack; -import ru.windcorp.progressia.common.world.TileDataReference; - -public interface TileTickContext extends TSTickContext { - - /* - * Specifications - */ - - /** - * Returns the current layer. - * - * @return the layer that the tile being ticked occupies in the tile stack - */ - int getLayer(); - - /* - * Getters - */ - - default TileLogic getTile() { - TileLogicStackRO stack = getTLSOrNull(); - if (stack == null) - return null; - return stack.get(getLayer()); - } - - default TileData getTileData() { - TileDataStack stack = getTDSOrNull(); - if (stack == null) - return null; - return stack.get(getLayer()); - } - - default TileDataReference getReference() { - return getTDS().getReference(getLayer()); - } - - default int getTag() { - return getTDS().getTagByIndex(getLayer()); - } - - /* - * Contexts - */ - - /* - * Convenience methods - changes - */ - - default void removeThisTile() { - getAccessor().removeTile(getBlockInWorld(), getFace(), getTag()); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java b/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java index bf114fa..3d63585 100644 --- a/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java +++ b/src/main/java/ru/windcorp/progressia/server/world/tile/UpdateableTile.java @@ -18,8 +18,10 @@ package ru.windcorp.progressia.server.world.tile; +import ru.windcorp.progressia.server.world.context.ServerTileContext; + public interface UpdateableTile { - void update(TileTickContext context); + void update(ServerTileContext context); } diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 46bf460..0ddc3e5 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -383,7 +383,7 @@ public class TestContent { ru.windcorp.progressia.server.comms.Client client ) { Vec3i blockInWorld = ((ControlBreakBlockData) packet.getControl()).getBlockInWorld(); - server.getWorldAccessor().setBlock(blockInWorld, BlockDataRegistry.getInstance().get("Test:Air")); + server.createContext().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.getWorldAccessor().setBlock(blockInWorld, block); + server.createContext().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.getWorldAccessor().addTile(blockInWorld, face, tile); + server.createContext().addTile(blockInWorld, face, tile); } private static void registerMisc() { diff --git a/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java b/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java index 5fa66fb..ac49fc9 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java +++ b/src/main/java/ru/windcorp/progressia/test/TestEntityLogicStatie.java @@ -19,7 +19,7 @@ package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.world.entity.EntityData; -import ru.windcorp.progressia.server.world.TickContext; +import ru.windcorp.progressia.server.world.context.ServerWorldContext; import ru.windcorp.progressia.server.world.entity.EntityLogic; public class TestEntityLogicStatie extends EntityLogic { @@ -29,13 +29,13 @@ public class TestEntityLogicStatie extends EntityLogic { } @Override - public void tick(EntityData entity, TickContext context) { + public void tick(EntityData entity, ServerWorldContext context) { super.tick(entity, context); TestEntityDataStatie statie = (TestEntityDataStatie) entity; int size = (int) (18 + 6 * Math.sin(entity.getAge())); - context.getServer().getWorldAccessor().changeEntity(statie, e -> e.setSizeNow(size)); + context.changeEntity(statie, e -> e.setSizeNow(size)); } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java b/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java index 246c882..b41f5a7 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java +++ b/src/main/java/ru/windcorp/progressia/test/TestTileLogicGrass.java @@ -20,11 +20,11 @@ package ru.windcorp.progressia.test; import ru.windcorp.progressia.common.world.rels.RelFace; import ru.windcorp.progressia.server.world.block.BlockLogic; -import ru.windcorp.progressia.server.world.block.BlockTickContext; +import ru.windcorp.progressia.server.world.context.ServerTileContext; +import ru.windcorp.progressia.server.world.context.ServerTileContextRO; import ru.windcorp.progressia.server.world.ticking.TickingPolicy; import ru.windcorp.progressia.server.world.tile.HangingTileLogic; import ru.windcorp.progressia.server.world.tile.TickableTile; -import ru.windcorp.progressia.server.world.tile.TileTickContext; public class TestTileLogicGrass extends HangingTileLogic implements TickableTile { @@ -33,7 +33,7 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile } @Override - public boolean canOccupyFace(TileTickContext context) { + public boolean canOccupyFace(ServerTileContextRO context) { return context.getFace() != RelFace.DOWN && super.canOccupyFace(context); } @@ -43,34 +43,31 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile } @Override - public TickingPolicy getTickingPolicy(TileTickContext context) { + public TickingPolicy getTickingPolicy(ServerTileContextRO context) { return TickingPolicy.RANDOM; } @Override - public void tick(TileTickContext context) { + public void tick(ServerTileContext context) { if (!isLocationSuitable(context)) { // context.removeThisTile(); } } @Override - public boolean canBeSquashed(TileTickContext context) { + public boolean canBeSquashed(ServerTileContextRO context) { return true; } - private boolean isLocationSuitable(TileTickContext context) { + private boolean isLocationSuitable(ServerTileContextRO context) { return canOccupyFace(context) && isBlockAboveTransparent(context); } - private boolean isBlockAboveTransparent(BlockTickContext context) { - return context.evalNeighbor(RelFace.UP, bctxt -> { - BlockLogic block = bctxt.getBlock(); - if (block == null) - return true; - - return block.isTransparent(bctxt); - }); + private boolean isBlockAboveTransparent(ServerTileContextRO context) { + // TODO rework + context.pushRelative(RelFace.UP.resolve(context.getServer().getWorld().getUp(context.getLocation()))); + BlockLogic block = context.logic().getBlock(); + return context.popAndReturn(block == null || block.isTransparent(context)); } }