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
This commit is contained in:
parent
5fb4c601ff
commit
0a45613e45
@ -135,5 +135,25 @@ public interface Context {
|
|||||||
* modifications to revert.
|
* modifications to revert.
|
||||||
*/
|
*/
|
||||||
void pop();
|
void pop();
|
||||||
|
|
||||||
|
default <T> 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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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.EntityRequestDaemon;
|
||||||
import ru.windcorp.progressia.server.management.load.LoadManager;
|
import ru.windcorp.progressia.server.management.load.LoadManager;
|
||||||
import ru.windcorp.progressia.server.world.DefaultWorldLogic;
|
import ru.windcorp.progressia.server.world.DefaultWorldLogic;
|
||||||
|
import ru.windcorp.progressia.server.world.context.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.tasks.WorldAccessor;
|
||||||
import ru.windcorp.progressia.server.world.ticking.Change;
|
import ru.windcorp.progressia.server.world.ticking.Change;
|
||||||
import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
||||||
@ -97,6 +100,19 @@ public class Server {
|
|||||||
return world;
|
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
|
* Returns this server's {@link ClientManager}. Use this to deal with
|
||||||
* communications, e.g. send packets.
|
* communications, e.g. send packets.
|
||||||
@ -219,16 +235,20 @@ public class Server {
|
|||||||
return this.serverThread.getTicker().getUptimeTicks();
|
return this.serverThread.getTicker().getUptimeTicks();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Returns the {@link WorldAccessor} object for this server. Use the
|
// * Returns the {@link WorldAccessor} object for this server. Use the
|
||||||
* provided accessor to request common {@link Evaluation}s and
|
// * provided accessor to request common {@link Evaluation}s and
|
||||||
* {@link Change}s.
|
// * {@link Change}s.
|
||||||
*
|
// *
|
||||||
* @return a {@link WorldAccessor}
|
// * @return a {@link WorldAccessor}
|
||||||
* @see #requestChange(Change)
|
// * @see #requestChange(Change)
|
||||||
* @see #requestEvaluation(Evaluation)
|
// * @see #requestEvaluation(Evaluation)
|
||||||
*/
|
// */
|
||||||
public WorldAccessor getWorldAccessor() {
|
// public WorldAccessor getWorldAccessor() {
|
||||||
|
// return worldAccessor;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public WorldAccessor getWorldAccessor___really_bad_dont_use() {
|
||||||
return worldAccessor;
|
return worldAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<BlockTickContext> action) {
|
|
||||||
TickContextMutable context = TickContextMutable.uninitialized();
|
|
||||||
|
|
||||||
GenericChunks.forEachBiC(blockInChunk -> {
|
|
||||||
context.rebuild().withServer(getServer()).withChunk(getChunk()).withBlockInChunk(blockInChunk).build();
|
|
||||||
action.accept(context);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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.rels.RelFace;
|
||||||
import ru.windcorp.progressia.common.world.TileDataStack;
|
import ru.windcorp.progressia.common.world.TileDataStack;
|
||||||
import ru.windcorp.progressia.common.world.TileDataReference;
|
import ru.windcorp.progressia.common.world.TileDataReference;
|
||||||
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
import ru.windcorp.progressia.server.world.block.BlockLogicRegistry;
|
||||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContextRO;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContextRO;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerWorldContextRO;
|
||||||
import ru.windcorp.progressia.server.world.tasks.TickChunk;
|
import ru.windcorp.progressia.server.world.tasks.TickChunk;
|
||||||
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
||||||
@ -221,28 +225,45 @@ public class DefaultChunkLogic implements ChunkLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void tmp_generateTickLists() {
|
private void tmp_generateTickLists() {
|
||||||
ChunkTickContext context = TickContextMutable.start().withChunk(this).build();
|
ServerWorldContextRO context = Server.getCurrentServer().createContext();
|
||||||
|
Vec3i blockInChunk = new Vec3i();
|
||||||
context.forEachBlock(bctxt -> {
|
|
||||||
BlockLogic block = bctxt.getBlock();
|
forEachBiW(location -> {
|
||||||
|
|
||||||
|
ServerBlockContextRO blockContext = context.push(location);
|
||||||
|
|
||||||
|
BlockLogic block = blockContext.logic().getBlock();
|
||||||
|
Coordinates.convertInWorldToInChunk(location, blockInChunk);
|
||||||
|
|
||||||
if (!(block instanceof TickableBlock))
|
if (!(block instanceof TickableBlock))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (((TickableBlock) block).getTickingPolicy(bctxt) == TickingPolicy.REGULAR) {
|
if (((TickableBlock) block).getTickingPolicy(blockContext) == TickingPolicy.REGULAR) {
|
||||||
tickingBlocks.add(Coordinates.convertInWorldToInChunk(bctxt.getBlockInWorld(), null));
|
tickingBlocks.add(blockInChunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
bctxt.forEachFace(fctxt -> fctxt.forEachTile(tctxt -> {
|
for (RelFace face : RelFace.getFaces()) {
|
||||||
TileLogic tile = tctxt.getTile();
|
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))
|
if (!(tile instanceof TickableTile))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (((TickableTile) tile).getTickingPolicy(tctxt) == TickingPolicy.REGULAR) {
|
if (((TickableTile) tile).getTickingPolicy(tileContext) == TickingPolicy.REGULAR) {
|
||||||
tickingTiles.add(tctxt.getReference());
|
tickingTiles.add(stack.getData().getReference(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
tileContext.pop();
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
|
|
||||||
|
blockContext.pop();
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
@Override
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.windcorp.progressia.server.world;
|
package ru.windcorp.progressia.server.world;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
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.common.world.rels.BlockFace;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockTickContext;
|
|
||||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
import ru.windcorp.progressia.server.world.block.UpdateableBlock;
|
import ru.windcorp.progressia.server.world.block.UpdateableBlock;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.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.EntityLogic;
|
||||||
import ru.windcorp.progressia.server.world.entity.EntityLogicRegistry;
|
import ru.windcorp.progressia.server.world.entity.EntityLogicRegistry;
|
||||||
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
||||||
import ru.windcorp.progressia.server.world.tile.TileLogic;
|
import ru.windcorp.progressia.server.world.tile.TileLogic;
|
||||||
import ru.windcorp.progressia.server.world.tile.TileTickContext;
|
|
||||||
import ru.windcorp.progressia.server.world.tile.UpdateableTile;
|
import ru.windcorp.progressia.server.world.tile.UpdateableTile;
|
||||||
|
|
||||||
public class TickAndUpdateUtil {
|
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 {
|
try {
|
||||||
block.tick(context);
|
block.tick(context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -44,16 +51,21 @@ public class TickAndUpdateUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickBlock(DefaultWorldLogic world, Vec3i blockInWorld) {
|
public static void tickBlock(Server server, Vec3i blockInWorld) {
|
||||||
BlockLogic block = world.getBlock(blockInWorld);
|
BlockLogic block = server.getWorld().getBlock(blockInWorld);
|
||||||
if (!(block instanceof TickableBlock))
|
if (!(block instanceof TickableBlock)) {
|
||||||
return; // also checks nulls
|
return;
|
||||||
|
}
|
||||||
BlockTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).build();
|
ServerBlockContext context = server.createContext().push(blockInWorld);
|
||||||
tickBlock((TickableBlock) block, tickContext);
|
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 {
|
try {
|
||||||
tile.tick(context);
|
tile.tick(context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -61,82 +73,88 @@ public class TickAndUpdateUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickTile(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face, int layer) {
|
public static void tickTile(Server server, Vec3i blockInWorld, BlockFace face, int layer) {
|
||||||
TileLogic tile = world.getTile(blockInWorld, face, layer);
|
TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer);
|
||||||
if (!(tile instanceof TickableTile)) {
|
if (!(tile instanceof TickableTile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ServerTileContext context = server.createContext()
|
||||||
TileTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face)
|
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer);
|
||||||
.withLayer(layer);
|
tickTile(context);
|
||||||
tickTile((TickableTile) tile, tickContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickTiles(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face) {
|
public static void tickTiles(Server server, Vec3i blockInWorld, BlockFace face) {
|
||||||
if (!world.isLocationLoaded(blockInWorld)) {
|
if (!server.getWorld().hasTiles(blockInWorld, face)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face).build()
|
ServerTileStackContext context = server.createContext()
|
||||||
.forEachTile(context -> {
|
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)));
|
||||||
TileLogic tile = context.getTile();
|
for (int i = 0; i < context.getTileCount(); ++i) {
|
||||||
if (tile instanceof TickableTile) {
|
tickTile(context.push(i));
|
||||||
tickTile((TickableTile) tile, context);
|
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 {
|
try {
|
||||||
block.update(context);
|
block.update(context);
|
||||||
} catch (Exception e) {
|
} 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) {
|
public static void updateBlock(Server server, Vec3i blockInWorld) {
|
||||||
BlockLogic block = world.getBlock(blockInWorld);
|
BlockLogic block = server.getWorld().getBlock(blockInWorld);
|
||||||
if (!(block instanceof UpdateableBlock))
|
if (!(block instanceof UpdateableBlock)) {
|
||||||
return; // also checks nulls
|
return;
|
||||||
|
}
|
||||||
BlockTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).build();
|
ServerBlockContext context = server.createContext().push(blockInWorld);
|
||||||
updateBlock((UpdateableBlock) block, tickContext);
|
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 {
|
try {
|
||||||
tile.update(context);
|
tile.update(context);
|
||||||
} catch (Exception e) {
|
} 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) {
|
public static void updateTile(Server server, Vec3i blockInWorld, BlockFace face, int layer) {
|
||||||
TileLogic tile = world.getTile(blockInWorld, face, layer);
|
TileLogic tile = server.getWorld().getTile(blockInWorld, face, layer);
|
||||||
if (!(tile instanceof UpdateableTile)) {
|
if (!(tile instanceof UpdateableTile)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ServerTileContext context = server.createContext()
|
||||||
TileTickContext tickContext = TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face)
|
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)), layer);
|
||||||
.withLayer(layer);
|
updateTile(context);
|
||||||
updateTile((UpdateableTile) tile, tickContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void updateTiles(DefaultWorldLogic world, Vec3i blockInWorld, BlockFace face) {
|
public static void updateTiles(Server server, Vec3i blockInWorld, BlockFace face) {
|
||||||
if (!world.isLocationLoaded(blockInWorld)) {
|
if (!server.getWorld().hasTiles(blockInWorld, face)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TickContextMutable.start().withWorld(world).withBlock(blockInWorld).withFace(face).build()
|
ServerTileStackContext context = server.createContext()
|
||||||
.forEachTile(context -> {
|
.push(blockInWorld, face.relativize(server.getWorld().getUp(blockInWorld)));
|
||||||
TileLogic tile = context.getTile();
|
for (int i = 0; i < context.getTileCount(); ++i) {
|
||||||
if (tile instanceof UpdateableTile) {
|
updateTile(context.push(i));
|
||||||
updateTile((UpdateableTile) tile, context);
|
context.pop();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void tickEntity(EntityLogic logic, EntityData data, TickContext context) {
|
public static void tickEntity(EntityLogic logic, EntityData data, ServerWorldContext context) {
|
||||||
try {
|
try {
|
||||||
logic.tick(data, context);
|
logic.tick(data, context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -148,7 +166,7 @@ public class TickAndUpdateUtil {
|
|||||||
tickEntity(
|
tickEntity(
|
||||||
EntityLogicRegistry.getInstance().get(data.getId()),
|
EntityLogicRegistry.getInstance().get(data.getId()),
|
||||||
data,
|
data,
|
||||||
TickContextMutable.start().withServer(server).build()
|
server.createContext()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<BlockTickContext> 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<TSTickContext> 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> R evalNeighbor(Vec3i direction, Function<BlockTickContext, R> action) {
|
|
||||||
this.blockInWorld.add(direction);
|
|
||||||
R result = action.apply(this);
|
|
||||||
this.blockInWorld.sub(direction);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void forNeighbor(Vec3i direction, Consumer<BlockTickContext> action) {
|
|
||||||
this.blockInWorld.add(direction);
|
|
||||||
action.accept(this);
|
|
||||||
this.blockInWorld.sub(direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean forEachTile(Consumer<TileTickContext> 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> R evalComplementary(Function<TSTickContext, R> 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<TSTickContext> 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.windcorp.progressia.server.world;
|
package ru.windcorp.progressia.server.world;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
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.block.BlockData;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.world.tasks.WorldAccessor;
|
||||||
|
|
||||||
public class UpdateTriggerer implements ChunkDataListener {
|
public class UpdateTriggerer implements ChunkDataListener {
|
||||||
|
|
||||||
private final Server server;
|
private final WorldAccessor worldAccessor;
|
||||||
|
|
||||||
public UpdateTriggerer(Server server) {
|
public UpdateTriggerer(WorldAccessor worldAccessor) {
|
||||||
this.server = server;
|
this.worldAccessor = worldAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -42,7 +42,7 @@ public class UpdateTriggerer implements ChunkDataListener {
|
|||||||
BlockData previous,
|
BlockData previous,
|
||||||
BlockData current
|
BlockData current
|
||||||
) {
|
) {
|
||||||
server.getWorldAccessor().triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null));
|
worldAccessor.triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -53,7 +53,7 @@ public class UpdateTriggerer implements ChunkDataListener {
|
|||||||
TileData tile,
|
TileData tile,
|
||||||
boolean wasAdded
|
boolean wasAdded
|
||||||
) {
|
) {
|
||||||
server.getWorldAccessor().triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null), face);
|
worldAccessor.triggerUpdates(Coordinates.getInWorld(chunk.getPosition(), blockInChunk, null), face);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world.block;
|
|||||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||||
import ru.windcorp.progressia.common.world.generic.BlockGeneric;
|
import ru.windcorp.progressia.common.world.generic.BlockGeneric;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContextRO;
|
||||||
|
|
||||||
public class BlockLogic extends Namespaced implements BlockGeneric {
|
public class BlockLogic extends Namespaced implements BlockGeneric {
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ public class BlockLogic extends Namespaced implements BlockGeneric {
|
|||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSolid(BlockTickContext context, RelFace face) {
|
public boolean isSolid(ServerBlockContextRO context, RelFace face) {
|
||||||
return isSolid(face);
|
return isSolid(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ public class BlockLogic extends Namespaced implements BlockGeneric {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isTransparent(BlockTickContext context) {
|
public boolean isTransparent(ServerBlockContextRO context) {
|
||||||
return isTransparent();
|
return isTransparent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<TSTickContext> 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> R evalNeighbor(Vec3i direction, Function<BlockTickContext, R> action) {
|
|
||||||
Objects.requireNonNull(action, "action");
|
|
||||||
Objects.requireNonNull(direction, "direction");
|
|
||||||
return action.apply(getNeighbor(direction));
|
|
||||||
}
|
|
||||||
|
|
||||||
default <R> R evalNeighbor(BlockRelation relation, Function<BlockTickContext, R> action) {
|
|
||||||
Objects.requireNonNull(action, "action");
|
|
||||||
Objects.requireNonNull(relation, "relation");
|
|
||||||
return evalNeighbor(relation.getVector(getChunkData().getUp()), action);
|
|
||||||
}
|
|
||||||
|
|
||||||
default void forNeighbor(Vec3i direction, Consumer<BlockTickContext> action) {
|
|
||||||
Objects.requireNonNull(action, "action");
|
|
||||||
Objects.requireNonNull(direction, "direction");
|
|
||||||
evalNeighbor(direction, (Function<BlockTickContext, Void>) ctxt -> {
|
|
||||||
action.accept(ctxt);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
default void forNeighbor(BlockRelation relation, Consumer<BlockTickContext> 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -18,12 +18,14 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.server.world.block;
|
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;
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
|
|
||||||
public interface TickableBlock {
|
public interface TickableBlock {
|
||||||
|
|
||||||
void tick(BlockTickContext context);
|
void tick(ServerBlockContext context);
|
||||||
|
|
||||||
TickingPolicy getTickingPolicy(BlockTickContext context);
|
TickingPolicy getTickingPolicy(ServerBlockContextRO context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,18 +18,10 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.server.world.block;
|
package ru.windcorp.progressia.server.world.block;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
|
||||||
public interface UpdateableBlock {
|
public interface UpdateableBlock {
|
||||||
|
|
||||||
default void update(BlockTickContext context) {
|
void update(ServerBlockContext context);
|
||||||
LogManager.getLogger().info(
|
|
||||||
"Updating block {} @ ({}; {}; {})",
|
|
||||||
context.getBlock(),
|
|
||||||
context.getBlockInWorld().x,
|
|
||||||
context.getBlockInWorld().y,
|
|
||||||
context.getBlockInWorld().z
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ package ru.windcorp.progressia.server.world.entity;
|
|||||||
|
|
||||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
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 {
|
public class EntityLogic extends Namespaced {
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ public class EntityLogic extends Namespaced {
|
|||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tick(EntityData entity, TickContext context) {
|
public void tick(EntityData entity, ServerWorldContext context) {
|
||||||
entity.incrementAge(context.getTickLength());
|
entity.incrementAge(context.getTickLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import ru.windcorp.progressia.common.world.Coordinates;
|
|||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.TickAndUpdateUtil;
|
import ru.windcorp.progressia.server.world.TickAndUpdateUtil;
|
||||||
import ru.windcorp.progressia.server.world.DefaultWorldLogic;
|
|
||||||
|
|
||||||
class BlockTriggeredUpdate extends CachedEvaluation {
|
class BlockTriggeredUpdate extends CachedEvaluation {
|
||||||
|
|
||||||
@ -39,13 +38,11 @@ class BlockTriggeredUpdate extends CachedEvaluation {
|
|||||||
public void evaluate(Server server) {
|
public void evaluate(Server server) {
|
||||||
Vec3i cursor = new Vec3i(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
Vec3i cursor = new Vec3i(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
||||||
|
|
||||||
DefaultWorldLogic world = server.getWorld();
|
|
||||||
|
|
||||||
for (AbsFace face : AbsFace.getFaces()) {
|
for (AbsFace face : AbsFace.getFaces()) {
|
||||||
TickAndUpdateUtil.updateTiles(world, cursor, face);
|
TickAndUpdateUtil.updateTiles(server, cursor, face);
|
||||||
cursor.add(face.getVector());
|
cursor.add(face.getVector());
|
||||||
TickAndUpdateUtil.updateBlock(world, cursor);
|
TickAndUpdateUtil.updateBlock(server, cursor);
|
||||||
TickAndUpdateUtil.updateTiles(world, cursor, face.getCounter());
|
TickAndUpdateUtil.updateTiles(server, cursor, face.getCounter());
|
||||||
cursor.sub(face.getVector());
|
cursor.sub(face.getVector());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world.tasks;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
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.EntityData;
|
||||||
import ru.windcorp.progressia.common.world.entity.PacketChangeEntity;
|
import ru.windcorp.progressia.common.world.entity.PacketChangeEntity;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
@ -36,7 +37,7 @@ class ChangeEntity extends CachedChange {
|
|||||||
super(disposer);
|
super(disposer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T extends EntityData> void set(T entity, StateChange<T> change) {
|
public void set(EntityData entity, StateChange<?> change) {
|
||||||
if (this.entity != null)
|
if (this.entity != null)
|
||||||
throw new IllegalStateException("Entity is not null. Current: " + this.entity + "; requested: " + entity);
|
throw new IllegalStateException("Entity is not null. Current: " + this.entity + "; requested: " + entity);
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package ru.windcorp.progressia.server.world.tasks;
|
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface StateChange<T> {
|
|
||||||
void change(T object);
|
|
||||||
}
|
|
@ -15,7 +15,7 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package ru.windcorp.progressia.server.world.tasks;
|
package ru.windcorp.progressia.server.world.tasks;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -27,17 +27,22 @@ import com.google.common.collect.ImmutableList;
|
|||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
import ru.windcorp.progressia.common.util.FloatMathUtil;
|
import ru.windcorp.progressia.common.util.FloatMathUtil;
|
||||||
|
import ru.windcorp.progressia.common.util.Vectors;
|
||||||
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
import ru.windcorp.progressia.common.world.DefaultChunkData;
|
||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.common.world.TileDataStack;
|
import ru.windcorp.progressia.common.world.TileDataStack;
|
||||||
|
import ru.windcorp.progressia.common.world.generic.ChunkGenericRO;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.DefaultChunkLogic;
|
import ru.windcorp.progressia.server.world.DefaultChunkLogic;
|
||||||
import ru.windcorp.progressia.server.world.TickContextMutable;
|
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerBlockContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.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.Evaluation;
|
||||||
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
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.TickableTile;
|
||||||
import ru.windcorp.progressia.server.world.tile.TileLogic;
|
import ru.windcorp.progressia.server.world.tile.TileLogic;
|
||||||
import static ru.windcorp.progressia.common.world.DefaultChunkData.BLOCKS_PER_CHUNK;
|
import static ru.windcorp.progressia.common.world.DefaultChunkData.BLOCKS_PER_CHUNK;
|
||||||
@ -82,11 +87,11 @@ public class TickChunk extends Evaluation {
|
|||||||
if (!chunk.hasTickingBlocks())
|
if (!chunk.hasTickingBlocks())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TickContextMutable context = TickContextMutable.uninitialized();
|
ServerWorldContext context = server.createContext();
|
||||||
|
|
||||||
chunk.forEachTickingBlock((blockInChunk, block) -> {
|
chunk.forEachTickingBlock((blockInChunk, block) -> {
|
||||||
context.rebuild().withChunk(chunk).withBlockInChunk(blockInChunk).build();
|
((TickableBlock) block).tick(contextPushBiC(context, chunk, blockInChunk));
|
||||||
((TickableBlock) block).tick(context);
|
context.pop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,11 +99,14 @@ public class TickChunk extends Evaluation {
|
|||||||
if (!chunk.hasTickingTiles())
|
if (!chunk.hasTickingTiles())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TickContextMutable context = TickContextMutable.uninitialized();
|
ServerWorldContext context = server.createContext();
|
||||||
|
Vec3i blockInWorld = new Vec3i();
|
||||||
|
|
||||||
chunk.forEachTickingTile((ref, tile) -> {
|
chunk.forEachTickingTile((ref, tile) -> {
|
||||||
context.rebuild().withServer(server).withTile(ref);
|
((TickableTile) tile).tick(
|
||||||
((TickableTile) tile).tick(context);
|
context.push(ref.getStack().getBlockInWorld(blockInWorld), ref.getStack().getFace(), ref.getIndex())
|
||||||
|
);
|
||||||
|
context.pop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +152,7 @@ public class TickChunk extends Evaluation {
|
|||||||
return;
|
return;
|
||||||
TickableBlock tickable = (TickableBlock) block;
|
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)
|
if (tickable.getTickingPolicy(context) != TickingPolicy.RANDOM)
|
||||||
return;
|
return;
|
||||||
@ -164,18 +172,22 @@ public class TickChunk extends Evaluation {
|
|||||||
if (tiles == null || tiles.isEmpty())
|
if (tiles == null || tiles.isEmpty())
|
||||||
return;
|
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 -> {
|
for (int i = 0; i < tiles.size(); ++i) {
|
||||||
TileLogic logic = tctxt.getTile();
|
ServerTileContext tileContext = context.push(i);
|
||||||
|
|
||||||
|
TileLogic logic = tileContext.logic().getTile();
|
||||||
if (!(logic instanceof TickableTile))
|
if (!(logic instanceof TickableTile))
|
||||||
return;
|
return;
|
||||||
TickableTile tickable = (TickableTile) logic;
|
TickableTile tickable = (TickableTile) logic;
|
||||||
|
|
||||||
if (tickable.getTickingPolicy(tctxt) != TickingPolicy.RANDOM)
|
if (tickable.getTickingPolicy(tileContext) != TickingPolicy.RANDOM)
|
||||||
return;
|
return;
|
||||||
tickable.tick(tctxt);
|
tickable.tick(tileContext);
|
||||||
});
|
|
||||||
|
tileContext.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private float computeRandomTicks(Server server) {
|
private float computeRandomTicks(Server server) {
|
||||||
@ -184,6 +196,18 @@ public class TickChunk extends Evaluation {
|
|||||||
server.getTickLength());
|
server.getTickLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ServerBlockContext contextPushBiC(
|
||||||
|
ServerWorldContext context,
|
||||||
|
ChunkGenericRO<?, ?, ?, ?, ?> chunk,
|
||||||
|
Vec3i blockInChunk
|
||||||
|
) {
|
||||||
|
Vec3i blockInWorld = Vectors.grab3i();
|
||||||
|
Coordinates.getInWorld(chunk.getPosition(), blockInChunk, blockInWorld);
|
||||||
|
ServerBlockContext blockContext = context.push(blockInWorld);
|
||||||
|
Vectors.release(blockInWorld);
|
||||||
|
return blockContext;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void getRelevantChunk(Vec3i output) {
|
public void getRelevantChunk(Vec3i output) {
|
||||||
Vec3i p = chunk.getData().getPosition();
|
Vec3i p = chunk.getData().getPosition();
|
||||||
|
@ -25,7 +25,6 @@ import ru.windcorp.progressia.common.world.Coordinates;
|
|||||||
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
import ru.windcorp.progressia.common.world.rels.AbsFace;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.TickAndUpdateUtil;
|
import ru.windcorp.progressia.server.world.TickAndUpdateUtil;
|
||||||
import ru.windcorp.progressia.server.world.DefaultWorldLogic;
|
|
||||||
|
|
||||||
class TileTriggeredUpdate extends CachedEvaluation {
|
class TileTriggeredUpdate extends CachedEvaluation {
|
||||||
|
|
||||||
@ -40,17 +39,15 @@ class TileTriggeredUpdate extends CachedEvaluation {
|
|||||||
public void evaluate(Server server) {
|
public void evaluate(Server server) {
|
||||||
Vec3i cursor = new Vec3i(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
Vec3i cursor = new Vec3i(blockInWorld.x, blockInWorld.y, blockInWorld.z);
|
||||||
|
|
||||||
DefaultWorldLogic world = server.getWorld();
|
// Update facemates (also self)
|
||||||
|
TickAndUpdateUtil.updateTiles(server, cursor, face);
|
||||||
TickAndUpdateUtil.updateTiles(world, cursor, face); // Update facemates
|
// Update block on one side
|
||||||
// (also self)
|
TickAndUpdateUtil.updateBlock(server, cursor);
|
||||||
TickAndUpdateUtil.updateBlock(world, cursor); // Update block on one
|
|
||||||
// side
|
|
||||||
cursor.add(face.getVector());
|
cursor.add(face.getVector());
|
||||||
TickAndUpdateUtil.updateBlock(world, cursor); // Update block on the
|
// Update block on the other side
|
||||||
// other side
|
TickAndUpdateUtil.updateBlock(server, cursor);
|
||||||
TickAndUpdateUtil.updateTiles(world, cursor, face.getCounter()); // Update
|
// Update complement
|
||||||
// complement
|
TickAndUpdateUtil.updateTiles(server, cursor, face.getCounter());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(Vec3i blockInWorld, AbsFace face) {
|
public void init(Vec3i blockInWorld, AbsFace face) {
|
||||||
|
@ -21,17 +21,19 @@ package ru.windcorp.progressia.server.world.tasks;
|
|||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
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.util.MultiLOC;
|
||||||
import ru.windcorp.progressia.common.world.block.BlockData;
|
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.entity.EntityData;
|
||||||
|
import ru.windcorp.progressia.common.world.generic.EntityGeneric;
|
||||||
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
import ru.windcorp.progressia.common.world.rels.BlockFace;
|
||||||
import ru.windcorp.progressia.common.world.tile.TileData;
|
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.Server;
|
||||||
|
import ru.windcorp.progressia.server.world.context.impl.ReportingServerContext;
|
||||||
import ru.windcorp.progressia.server.world.ticking.TickerTask;
|
import ru.windcorp.progressia.server.world.ticking.TickerTask;
|
||||||
|
|
||||||
public class WorldAccessor {
|
public class WorldAccessor implements ReportingServerContext.ChangeListener {
|
||||||
|
|
||||||
private final MultiLOC cache;
|
private final MultiLOC cache;
|
||||||
{
|
{
|
||||||
@ -54,38 +56,52 @@ public class WorldAccessor {
|
|||||||
this.server = server;
|
this.server = server;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlock(Vec3i blockInWorld, BlockData block) {
|
@Override
|
||||||
|
public void onBlockSet(Vec3i blockInWorld, BlockData block) {
|
||||||
SetBlock change = cache.grab(SetBlock.class);
|
SetBlock change = cache.grab(SetBlock.class);
|
||||||
change.getPacket().set(block, blockInWorld);
|
change.getPacket().set(block, blockInWorld);
|
||||||
server.requestChange(change);
|
server.requestChange(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBlock(Vec3i blockInWorld, String id) {
|
@Override
|
||||||
setBlock(blockInWorld, BlockDataRegistry.getInstance().get(id));
|
public void onTileAdded(Vec3i blockInWorld, BlockFace face, TileData tile) {
|
||||||
}
|
|
||||||
|
|
||||||
public void addTile(Vec3i blockInWorld, BlockFace face, TileData tile) {
|
|
||||||
AddTile change = cache.grab(AddTile.class);
|
AddTile change = cache.grab(AddTile.class);
|
||||||
change.getPacket().set(tile, blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)));
|
change.getPacket().set(tile, blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)));
|
||||||
server.requestChange(change);
|
server.requestChange(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addTile(Vec3i blockInWorld, BlockFace face, String id) {
|
@Override
|
||||||
addTile(blockInWorld, face, TileDataRegistry.getInstance().get(id));
|
public void onTileRemoved(Vec3i blockInWorld, BlockFace face, int tag) {
|
||||||
}
|
|
||||||
|
|
||||||
public void removeTile(Vec3i blockInWorld, BlockFace face, int tag) {
|
|
||||||
RemoveTile change = cache.grab(RemoveTile.class);
|
RemoveTile change = cache.grab(RemoveTile.class);
|
||||||
change.getPacket().set(blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)), tag);
|
change.getPacket().set(blockInWorld, face.resolve(server.getWorld().getUp(blockInWorld)), tag);
|
||||||
server.requestChange(change);
|
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 <T extends EntityData> void changeEntity(
|
@Override
|
||||||
T entity,
|
public <SE extends StatefulObject & EntityGeneric> void onEntityChanged(
|
||||||
StateChange<T> stateChange
|
SE entity,
|
||||||
|
StateChange<SE> stateChange
|
||||||
) {
|
) {
|
||||||
ChangeEntity change = cache.grab(ChangeEntity.class);
|
ChangeEntity change = cache.grab(ChangeEntity.class);
|
||||||
change.set(entity, stateChange);
|
change.set((EntityData) entity, stateChange);
|
||||||
server.requestChange(change);
|
server.requestChange(change);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
package ru.windcorp.progressia.server.world.tile;
|
package ru.windcorp.progressia.server.world.tile;
|
||||||
|
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContextRO;
|
||||||
|
|
||||||
public class HangingTileLogic extends TileLogic implements UpdateableTile {
|
public class HangingTileLogic extends TileLogic implements UpdateableTile {
|
||||||
|
|
||||||
@ -27,15 +29,15 @@ public class HangingTileLogic extends TileLogic implements UpdateableTile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(TileTickContext context) {
|
public void update(ServerTileContext context) {
|
||||||
if (!canOccupyFace(context)) {
|
if (!canOccupyFace(context)) {
|
||||||
context.removeThisTile();
|
context.removeTile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canOccupyFace(TileTickContext context) {
|
public boolean canOccupyFace(ServerTileContextRO context) {
|
||||||
BlockLogic host = context.getBlock();
|
BlockLogic host = context.logic().getBlock();
|
||||||
if (host == null)
|
if (host == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -45,13 +47,14 @@ public class HangingTileLogic extends TileLogic implements UpdateableTile {
|
|||||||
if (canBeSquashed(context))
|
if (canBeSquashed(context))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return context.evalComplementary(ctxt -> {
|
context.pushOpposite();
|
||||||
BlockLogic complHost = ctxt.getBlock();
|
BlockLogic complHost = context.logic().getBlock();
|
||||||
return complHost == null || !complHost.isSolid(ctxt, context.getFace());
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<TileTickContext> 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> R evalComplementary(Function<TSTickContext, R> action) {
|
|
||||||
Objects.requireNonNull(action, "action");
|
|
||||||
return action.apply(getComplementary());
|
|
||||||
}
|
|
||||||
|
|
||||||
default void forComplementary(Consumer<TSTickContext> action) {
|
|
||||||
Objects.requireNonNull(action, "action");
|
|
||||||
evalComplementary((Function<TSTickContext, Void>) ctxt -> {
|
|
||||||
action.accept(ctxt);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -18,12 +18,14 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.server.world.tile;
|
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;
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
|
|
||||||
public interface TickableTile {
|
public interface TickableTile {
|
||||||
|
|
||||||
void tick(TileTickContext context);
|
void tick(ServerTileContext context);
|
||||||
|
|
||||||
TickingPolicy getTickingPolicy(TileTickContext context);
|
TickingPolicy getTickingPolicy(ServerTileContextRO context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ package ru.windcorp.progressia.server.world.tile;
|
|||||||
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
import ru.windcorp.progressia.common.util.namespaces.Namespaced;
|
||||||
import ru.windcorp.progressia.common.world.generic.TileGeneric;
|
import ru.windcorp.progressia.common.world.generic.TileGeneric;
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContextRO;
|
||||||
|
|
||||||
public class TileLogic extends Namespaced implements TileGeneric {
|
public class TileLogic extends Namespaced implements TileGeneric {
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ public class TileLogic extends Namespaced implements TileGeneric {
|
|||||||
super(id);
|
super(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canOccupyFace(TileTickContext context) {
|
public boolean canOccupyFace(ServerTileContextRO context) {
|
||||||
return canOccupyFace(context.getFace());
|
return canOccupyFace(context.getFace());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ public class TileLogic extends Namespaced implements TileGeneric {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSolid(TileTickContext context) {
|
public boolean isSolid(ServerTileContextRO context) {
|
||||||
return isSolid();
|
return isSolid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -18,8 +18,10 @@
|
|||||||
|
|
||||||
package ru.windcorp.progressia.server.world.tile;
|
package ru.windcorp.progressia.server.world.tile;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.server.world.context.ServerTileContext;
|
||||||
|
|
||||||
public interface UpdateableTile {
|
public interface UpdateableTile {
|
||||||
|
|
||||||
void update(TileTickContext context);
|
void update(ServerTileContext context);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -383,7 +383,7 @@ public class TestContent {
|
|||||||
ru.windcorp.progressia.server.comms.Client client
|
ru.windcorp.progressia.server.comms.Client client
|
||||||
) {
|
) {
|
||||||
Vec3i blockInWorld = ((ControlBreakBlockData) packet.getControl()).getBlockInWorld();
|
Vec3i blockInWorld = ((ControlBreakBlockData) packet.getControl()).getBlockInWorld();
|
||||||
server.getWorldAccessor().setBlock(blockInWorld, BlockDataRegistry.getInstance().get("Test:Air"));
|
server.createContext().setBlock(blockInWorld, BlockDataRegistry.getInstance().get("Test:Air"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void onBlockPlaceTrigger(ControlData control) {
|
private static void onBlockPlaceTrigger(ControlData control) {
|
||||||
@ -403,7 +403,7 @@ public class TestContent {
|
|||||||
Vec3i blockInWorld = controlData.getBlockInWorld();
|
Vec3i blockInWorld = controlData.getBlockInWorld();
|
||||||
if (server.getWorld().getData().getChunkByBlock(blockInWorld) == null)
|
if (server.getWorld().getData().getChunkByBlock(blockInWorld) == null)
|
||||||
return;
|
return;
|
||||||
server.getWorldAccessor().setBlock(blockInWorld, block);
|
server.createContext().setBlock(blockInWorld, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void onTilePlaceTrigger(ControlData control) {
|
private static void onTilePlaceTrigger(ControlData control) {
|
||||||
@ -428,7 +428,7 @@ public class TestContent {
|
|||||||
return;
|
return;
|
||||||
if (server.getWorld().getData().getTiles(blockInWorld, face).isFull())
|
if (server.getWorld().getData().getTiles(blockInWorld, face).isFull())
|
||||||
return;
|
return;
|
||||||
server.getWorldAccessor().addTile(blockInWorld, face, tile);
|
server.createContext().addTile(blockInWorld, face, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void registerMisc() {
|
private static void registerMisc() {
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
package ru.windcorp.progressia.test;
|
package ru.windcorp.progressia.test;
|
||||||
|
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
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;
|
import ru.windcorp.progressia.server.world.entity.EntityLogic;
|
||||||
|
|
||||||
public class TestEntityLogicStatie extends EntityLogic {
|
public class TestEntityLogicStatie extends EntityLogic {
|
||||||
@ -29,13 +29,13 @@ public class TestEntityLogicStatie extends EntityLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(EntityData entity, TickContext context) {
|
public void tick(EntityData entity, ServerWorldContext context) {
|
||||||
super.tick(entity, context);
|
super.tick(entity, context);
|
||||||
|
|
||||||
TestEntityDataStatie statie = (TestEntityDataStatie) entity;
|
TestEntityDataStatie statie = (TestEntityDataStatie) entity;
|
||||||
|
|
||||||
int size = (int) (18 + 6 * Math.sin(entity.getAge()));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,11 @@ package ru.windcorp.progressia.test;
|
|||||||
|
|
||||||
import ru.windcorp.progressia.common.world.rels.RelFace;
|
import ru.windcorp.progressia.common.world.rels.RelFace;
|
||||||
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
import ru.windcorp.progressia.server.world.block.BlockLogic;
|
||||||
import ru.windcorp.progressia.server.world.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.ticking.TickingPolicy;
|
||||||
import ru.windcorp.progressia.server.world.tile.HangingTileLogic;
|
import ru.windcorp.progressia.server.world.tile.HangingTileLogic;
|
||||||
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
||||||
import ru.windcorp.progressia.server.world.tile.TileTickContext;
|
|
||||||
|
|
||||||
public class TestTileLogicGrass extends HangingTileLogic implements TickableTile {
|
public class TestTileLogicGrass extends HangingTileLogic implements TickableTile {
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canOccupyFace(TileTickContext context) {
|
public boolean canOccupyFace(ServerTileContextRO context) {
|
||||||
return context.getFace() != RelFace.DOWN && super.canOccupyFace(context);
|
return context.getFace() != RelFace.DOWN && super.canOccupyFace(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,34 +43,31 @@ public class TestTileLogicGrass extends HangingTileLogic implements TickableTile
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TickingPolicy getTickingPolicy(TileTickContext context) {
|
public TickingPolicy getTickingPolicy(ServerTileContextRO context) {
|
||||||
return TickingPolicy.RANDOM;
|
return TickingPolicy.RANDOM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick(TileTickContext context) {
|
public void tick(ServerTileContext context) {
|
||||||
if (!isLocationSuitable(context)) {
|
if (!isLocationSuitable(context)) {
|
||||||
// context.removeThisTile();
|
// context.removeThisTile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canBeSquashed(TileTickContext context) {
|
public boolean canBeSquashed(ServerTileContextRO context) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLocationSuitable(TileTickContext context) {
|
private boolean isLocationSuitable(ServerTileContextRO context) {
|
||||||
return canOccupyFace(context) && isBlockAboveTransparent(context);
|
return canOccupyFace(context) && isBlockAboveTransparent(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isBlockAboveTransparent(BlockTickContext context) {
|
private boolean isBlockAboveTransparent(ServerTileContextRO context) {
|
||||||
return context.evalNeighbor(RelFace.UP, bctxt -> {
|
// TODO rework
|
||||||
BlockLogic block = bctxt.getBlock();
|
context.pushRelative(RelFace.UP.resolve(context.getServer().getWorld().getUp(context.getLocation())));
|
||||||
if (block == null)
|
BlockLogic block = context.logic().getBlock();
|
||||||
return true;
|
return context.popAndReturn(block == null || block.isTransparent(context));
|
||||||
|
|
||||||
return block.isTransparent(bctxt);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user