Fixed #3 - implemented random ticks, refactored Ticking* interfaces
- Random ticks now happen - Ticking* interfaces now have a single getTickingPolicy method instead of two doesTick* methods. This makes more sense since an object cannot both tick randomly and regularly. - Added Server.stop - Added some convenience methods related to setting blocks and tiles - Documented some stuff
This commit is contained in:
parent
377241c529
commit
f8e763c0d6
@ -35,10 +35,21 @@ public final class BlockFace extends BlockRelation {
|
|||||||
private static final ImmutableList<BlockFace> ALL_FACES =
|
private static final ImmutableList<BlockFace> ALL_FACES =
|
||||||
ImmutableList.of(TOP, BOTTOM, NORTH, SOUTH, WEST, EAST);
|
ImmutableList.of(TOP, BOTTOM, NORTH, SOUTH, WEST, EAST);
|
||||||
|
|
||||||
|
static {
|
||||||
|
link(TOP, BOTTOM);
|
||||||
|
link(NORTH, SOUTH);
|
||||||
|
link(WEST, EAST);
|
||||||
|
}
|
||||||
|
|
||||||
private static final ImmutableList<BlockFace> PRIMARY_FACES =
|
private static final ImmutableList<BlockFace> PRIMARY_FACES =
|
||||||
ImmutableList.of(TOP, NORTH, WEST);
|
ALL_FACES.stream().filter(BlockFace::isPrimary).collect(ImmutableList.toImmutableList());
|
||||||
|
|
||||||
|
private static final ImmutableList<BlockFace> SECONDARY_FACES =
|
||||||
|
ALL_FACES.stream().filter(BlockFace::isSecondary).collect(ImmutableList.toImmutableList());
|
||||||
|
|
||||||
public static final int BLOCK_FACE_COUNT = ALL_FACES.size();
|
public static final int BLOCK_FACE_COUNT = ALL_FACES.size();
|
||||||
|
public static final int PRIMARY_BLOCK_FACE_COUNT = PRIMARY_FACES.size();
|
||||||
|
public static final int SECONDARY_BLOCK_FACE_COUNT = SECONDARY_FACES.size();
|
||||||
|
|
||||||
public static ImmutableList<BlockFace> getFaces() {
|
public static ImmutableList<BlockFace> getFaces() {
|
||||||
return ALL_FACES;
|
return ALL_FACES;
|
||||||
@ -48,10 +59,8 @@ public final class BlockFace extends BlockRelation {
|
|||||||
return PRIMARY_FACES;
|
return PRIMARY_FACES;
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
public static ImmutableList<BlockFace> getSecondaryFaces() {
|
||||||
link(TOP, BOTTOM);
|
return SECONDARY_FACES;
|
||||||
link(NORTH, SOUTH);
|
|
||||||
link(WEST, EAST);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void link(BlockFace a, BlockFace b) {
|
private static void link(BlockFace a, BlockFace b) {
|
||||||
@ -108,6 +117,10 @@ public final class BlockFace extends BlockRelation {
|
|||||||
return counterFace;
|
return counterFace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSecondary() {
|
||||||
|
return !isPrimary;
|
||||||
|
}
|
||||||
|
|
||||||
public BlockFace getSecondary() {
|
public BlockFace getSecondary() {
|
||||||
if (isPrimary) return counterFace;
|
if (isPrimary) return counterFace;
|
||||||
else return this;
|
else return this;
|
||||||
|
@ -5,6 +5,8 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
|
||||||
import ru.windcorp.jputil.functions.ThrowingRunnable;
|
import ru.windcorp.jputil.functions.ThrowingRunnable;
|
||||||
import ru.windcorp.progressia.common.util.TaskQueue;
|
import ru.windcorp.progressia.common.util.TaskQueue;
|
||||||
import ru.windcorp.progressia.common.world.WorldData;
|
import ru.windcorp.progressia.common.world.WorldData;
|
||||||
@ -16,6 +18,10 @@ import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
|||||||
|
|
||||||
public class Server {
|
public class Server {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Server} instance whose main thread is the current thread.
|
||||||
|
* @return the server that operates in this thread
|
||||||
|
*/
|
||||||
public static Server getCurrentServer() {
|
public static Server getCurrentServer() {
|
||||||
return ServerThread.getCurrentServer();
|
return ServerThread.getCurrentServer();
|
||||||
}
|
}
|
||||||
@ -30,6 +36,8 @@ public class Server {
|
|||||||
private final TaskQueue taskQueue = new TaskQueue(this::isServerThread);
|
private final TaskQueue taskQueue = new TaskQueue(this::isServerThread);
|
||||||
private final Collection<Consumer<Server>> repeatingTasks = Collections.synchronizedCollection(new ArrayList<>());
|
private final Collection<Consumer<Server>> repeatingTasks = Collections.synchronizedCollection(new ArrayList<>());
|
||||||
|
|
||||||
|
private final TickingSettings tickingSettings = new TickingSettings();
|
||||||
|
|
||||||
public Server(WorldData world) {
|
public Server(WorldData world) {
|
||||||
this.world = new WorldLogic(world, this);
|
this.world = new WorldLogic(world, this);
|
||||||
this.serverThread = new ServerThread(this);
|
this.serverThread = new ServerThread(this);
|
||||||
@ -37,6 +45,10 @@ public class Server {
|
|||||||
invokeEveryTick(this::scheduleChunkTicks);
|
invokeEveryTick(this::scheduleChunkTicks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns this server's world.
|
||||||
|
* @return this server's {@link WorldLogic}
|
||||||
|
*/
|
||||||
public WorldLogic getWorld() {
|
public WorldLogic getWorld() {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
@ -110,29 +122,70 @@ public class Server {
|
|||||||
serverThread.getTicker().requestEvaluation(evaluation);
|
serverThread.getTicker().requestEvaluation(evaluation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the duration of the last server tick. Server logic should assume that this much in-world time has passed.
|
||||||
|
* @return the length of the last server tick
|
||||||
|
*/
|
||||||
public double getTickLength() {
|
public double getTickLength() {
|
||||||
return this.serverThread.getTicker().getTickLength();
|
return this.serverThread.getTicker().getTickLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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() {
|
public WorldAccessor getWorldAccessor() {
|
||||||
return worldAccessor;
|
return worldAccessor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ticking settings for this server.
|
||||||
|
* @return a {@link TickingSettings} object
|
||||||
|
*/
|
||||||
|
public TickingSettings getTickingSettings() {
|
||||||
|
return tickingSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the server. This method blocks until the server enters normal operation or fails to start.
|
||||||
|
*/
|
||||||
public void start() {
|
public void start() {
|
||||||
this.serverThread.start();
|
this.serverThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the tasks from tasks queues and repeating tasks.
|
||||||
|
*/
|
||||||
public void tick() {
|
public void tick() {
|
||||||
taskQueue.runTasks();
|
taskQueue.runTasks();
|
||||||
repeatingTasks.forEach(t -> t.accept(this));
|
repeatingTasks.forEach(t -> t.accept(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shuts the server down, disconnecting the clients with the provided message.
|
||||||
|
* This method blocks until the shutdown is complete.
|
||||||
|
* @param message the message to send to the clients as the disconnect reason
|
||||||
|
*/
|
||||||
public void shutdown(String message) {
|
public void shutdown(String message) {
|
||||||
// Do nothing
|
LogManager.getLogger().warn("Server.shutdown() is not yet implemented");
|
||||||
|
serverThread.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scheduleChunkTicks(Server server) {
|
private void scheduleChunkTicks(Server server) {
|
||||||
server.getWorld().getChunks().forEach(chunk -> requestEvaluation(chunk.getTickTask()));
|
server.getWorld().getChunks().forEach(chunk -> requestEvaluation(chunk.getTickTask()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an instance of {@link java.util.Random Random} that can be used as a source of indeterministic
|
||||||
|
* randomness. World generation and other algorithms that must have random but reproducible results should
|
||||||
|
* not use this.
|
||||||
|
* @return a thread-safe indeterministic instance of {@link java.util.Random}.
|
||||||
|
*/
|
||||||
|
public java.util.Random getAdHocRandom() {
|
||||||
|
return java.util.concurrent.ThreadLocalRandom.current();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,16 @@ public class ServerThread implements Runnable {
|
|||||||
LogManager.getLogger(getClass()).error("Got an exception in server thread", e);
|
LogManager.getLogger(getClass()).error("Got an exception in server thread", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
executor.awaitTermination(10, TimeUnit.MINUTES);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LogManager.getLogger().warn("Received interrupt in ServerThread.stop(), aborting wait");
|
||||||
|
}
|
||||||
|
|
||||||
|
getTicker().stop();
|
||||||
|
}
|
||||||
|
|
||||||
public Server getServer() {
|
public Server getServer() {
|
||||||
return server;
|
return server;
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package ru.windcorp.progressia.server;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.common.Units;
|
||||||
|
|
||||||
|
public class TickingSettings {
|
||||||
|
|
||||||
|
private float randomTickFrequency = Units.get("1 min^-1");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the average rate of random ticks in a single block.
|
||||||
|
* @return ticking frequency
|
||||||
|
*/
|
||||||
|
public float getRandomTickFrequency() {
|
||||||
|
return randomTickFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,7 @@ import ru.windcorp.progressia.server.world.block.TickableBlock;
|
|||||||
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.tasks.TickChunk;
|
import ru.windcorp.progressia.server.world.tasks.TickChunk;
|
||||||
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
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.TileLogicRegistry;
|
import ru.windcorp.progressia.server.world.tile.TileLogicRegistry;
|
||||||
@ -63,7 +64,7 @@ public class ChunkLogic {
|
|||||||
Coordinates.getInWorld(getData().getPosition(), blockInChunk, null)
|
Coordinates.getInWorld(getData().getPosition(), blockInChunk, null)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (((TickableBlock) block).doesTickRegularly(blockTickContext)) {
|
if (((TickableBlock) block).getTickingPolicy(blockTickContext) == TickingPolicy.REGULAR) {
|
||||||
tickingBlocks.add(new Vec3i(blockInChunk));
|
tickingBlocks.add(new Vec3i(blockInChunk));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,7 +81,7 @@ public class ChunkLogic {
|
|||||||
loc.layer
|
loc.layer
|
||||||
);
|
);
|
||||||
|
|
||||||
if (((TickableTile) tile).doesTickRegularly(tileTickContext)) {
|
if (((TickableTile) tile).getTickingPolicy(tileTickContext) == TickingPolicy.REGULAR) {
|
||||||
tickingTiles.add(new TileLocation(loc));
|
tickingTiles.add(new TileLocation(loc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,4 +20,16 @@ public interface BlockTickContext extends ChunkTickContext {
|
|||||||
return getWorldData().getBlock(getBlockInWorld());
|
return getWorldData().getBlock(getBlockInWorld());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convenience methods - changes
|
||||||
|
*/
|
||||||
|
|
||||||
|
default void setThisBlock(BlockData block) {
|
||||||
|
getAccessor().setBlock(getBlockInWorld(), block);
|
||||||
|
}
|
||||||
|
|
||||||
|
default void setThisBlock(String id) {
|
||||||
|
getAccessor().setBlock(getBlockInWorld(), id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
package ru.windcorp.progressia.server.world.block;
|
package ru.windcorp.progressia.server.world.block;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
|
|
||||||
public interface TickableBlock {
|
public interface TickableBlock {
|
||||||
|
|
||||||
void tick(BlockTickContext context);
|
void tick(BlockTickContext context);
|
||||||
|
|
||||||
default boolean doesTickRegularly(BlockTickContext context) {
|
TickingPolicy getTickingPolicy(BlockTickContext context);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean doesTickRandomly(BlockTickContext context) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,20 +1,49 @@
|
|||||||
package ru.windcorp.progressia.server.world.tasks;
|
package ru.windcorp.progressia.server.world.tasks;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
|
import ru.windcorp.progressia.common.util.FloatMathUtils;
|
||||||
|
import ru.windcorp.progressia.common.world.ChunkData;
|
||||||
import ru.windcorp.progressia.common.world.Coordinates;
|
import ru.windcorp.progressia.common.world.Coordinates;
|
||||||
|
import ru.windcorp.progressia.common.world.block.BlockFace;
|
||||||
|
import ru.windcorp.progressia.common.world.tile.TileData;
|
||||||
import ru.windcorp.progressia.server.Server;
|
import ru.windcorp.progressia.server.Server;
|
||||||
import ru.windcorp.progressia.server.world.ChunkLogic;
|
import ru.windcorp.progressia.server.world.ChunkLogic;
|
||||||
import ru.windcorp.progressia.server.world.MutableBlockTickContext;
|
import ru.windcorp.progressia.server.world.MutableBlockTickContext;
|
||||||
import ru.windcorp.progressia.server.world.MutableTileTickContext;
|
import ru.windcorp.progressia.server.world.MutableTileTickContext;
|
||||||
import ru.windcorp.progressia.server.world.TickAndUpdateUtil;
|
import ru.windcorp.progressia.server.world.TickAndUpdateUtil;
|
||||||
|
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.ticking.Evaluation;
|
import ru.windcorp.progressia.server.world.ticking.Evaluation;
|
||||||
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
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.TileLogicRegistry;
|
||||||
|
|
||||||
|
import static ru.windcorp.progressia.common.world.ChunkData.BLOCKS_PER_CHUNK;
|
||||||
|
|
||||||
public class TickChunk extends Evaluation {
|
public class TickChunk extends Evaluation {
|
||||||
|
|
||||||
|
private static final int CHUNK_VOLUME =
|
||||||
|
ChunkData.BLOCKS_PER_CHUNK *
|
||||||
|
ChunkData.BLOCKS_PER_CHUNK *
|
||||||
|
ChunkData.BLOCKS_PER_CHUNK;
|
||||||
|
|
||||||
|
private final List<Consumer<Server>> randomTickMethods = ImmutableList.of(
|
||||||
|
s -> this.tickRandomBlock(s),
|
||||||
|
s -> this.tickRandomTile(s, BlockFace.NORTH),
|
||||||
|
s -> this.tickRandomTile(s, BlockFace.TOP),
|
||||||
|
s -> this.tickRandomTile(s, BlockFace.WEST)
|
||||||
|
);
|
||||||
|
|
||||||
private final ChunkLogic chunk;
|
private final ChunkLogic chunk;
|
||||||
|
|
||||||
public TickChunk(ChunkLogic chunk) {
|
public TickChunk(ChunkLogic chunk) {
|
||||||
this.chunk = chunk;
|
this.chunk = chunk;
|
||||||
}
|
}
|
||||||
@ -62,7 +91,90 @@ public class TickChunk extends Evaluation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void tickRandom(Server server) {
|
private void tickRandom(Server server) {
|
||||||
// TODO Implement
|
float ticks = computeRandomTicks(server);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are expected to run 3.25 random ticks per tick
|
||||||
|
* on average, then run 3 random ticks unconditionally
|
||||||
|
* and run one extra random tick with 0.25 chance
|
||||||
|
*/
|
||||||
|
float unconditionalTicks = FloatMathUtils.floor(ticks);
|
||||||
|
float extraTickChance = ticks - unconditionalTicks;
|
||||||
|
|
||||||
|
for (int i = 0; i < unconditionalTicks; ++i) {
|
||||||
|
tickRandomOnce(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (server.getAdHocRandom().nextFloat() < extraTickChance) {
|
||||||
|
tickRandomOnce(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickRandomOnce(Server server) {
|
||||||
|
// Pick a target at random: a block or one of 3 primary block faces
|
||||||
|
randomTickMethods.get(
|
||||||
|
server.getAdHocRandom().nextInt(randomTickMethods.size())
|
||||||
|
).accept(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickRandomBlock(Server server) {
|
||||||
|
Random random = server.getAdHocRandom();
|
||||||
|
|
||||||
|
Vec3i blockInChunk = new Vec3i(
|
||||||
|
random.nextInt(BLOCKS_PER_CHUNK),
|
||||||
|
random.nextInt(BLOCKS_PER_CHUNK),
|
||||||
|
random.nextInt(BLOCKS_PER_CHUNK)
|
||||||
|
);
|
||||||
|
|
||||||
|
BlockLogic block = this.chunk.getBlock(blockInChunk);
|
||||||
|
|
||||||
|
if (!(block instanceof TickableBlock)) return;
|
||||||
|
TickableBlock tickable = (TickableBlock) block;
|
||||||
|
|
||||||
|
BlockTickContext context = TickAndUpdateUtil.getBlockTickContext(
|
||||||
|
server,
|
||||||
|
Coordinates.getInWorld(this.chunk.getPosition(), blockInChunk, null)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (tickable.getTickingPolicy(context) != TickingPolicy.RANDOM) return;
|
||||||
|
tickable.tick(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickRandomTile(Server server, BlockFace face) {
|
||||||
|
Random random = server.getAdHocRandom();
|
||||||
|
|
||||||
|
Vec3i blockInChunk = new Vec3i(
|
||||||
|
random.nextInt(BLOCKS_PER_CHUNK),
|
||||||
|
random.nextInt(BLOCKS_PER_CHUNK),
|
||||||
|
random.nextInt(BLOCKS_PER_CHUNK)
|
||||||
|
);
|
||||||
|
|
||||||
|
List<TileData> tiles = this.chunk.getData().getTilesOrNull(blockInChunk, face);
|
||||||
|
if (tiles == null) return;
|
||||||
|
|
||||||
|
MutableTileTickContext context = new MutableTileTickContext();
|
||||||
|
Vec3i blockInWorld = Coordinates.getInWorld(this.chunk.getPosition(), blockInChunk, null);
|
||||||
|
|
||||||
|
for (int layer = 0; layer < tiles.size(); ++layer) {
|
||||||
|
TileData data = tiles.get(layer);
|
||||||
|
|
||||||
|
TileLogic logic = TileLogicRegistry.getInstance().get(data.getId());
|
||||||
|
if (!(logic instanceof TickableTile)) return;
|
||||||
|
TickableTile tickable = (TickableTile) logic;
|
||||||
|
|
||||||
|
context.init(server, blockInWorld, face, layer);
|
||||||
|
|
||||||
|
if (tickable.getTickingPolicy(context) != TickingPolicy.RANDOM) return;
|
||||||
|
tickable.tick(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private float computeRandomTicks(Server server) {
|
||||||
|
return (float) (
|
||||||
|
server.getTickingSettings().getRandomTickFrequency() *
|
||||||
|
CHUNK_VOLUME * randomTickMethods.size() *
|
||||||
|
server.getTickLength()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tickEntities(Server server) {
|
private void tickEntities(Server server) {
|
||||||
|
@ -5,9 +5,11 @@ import java.util.function.Consumer;
|
|||||||
import glm.vec._3.i.Vec3i;
|
import glm.vec._3.i.Vec3i;
|
||||||
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.block.BlockFace;
|
import ru.windcorp.progressia.common.world.block.BlockFace;
|
||||||
import ru.windcorp.progressia.common.world.entity.EntityData;
|
import ru.windcorp.progressia.common.world.entity.EntityData;
|
||||||
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.ticking.TickerTask;
|
import ru.windcorp.progressia.server.world.ticking.TickerTask;
|
||||||
|
|
||||||
@ -38,12 +40,20 @@ public class WorldAccessor {
|
|||||||
change.initialize(blockInWorld, block);
|
change.initialize(blockInWorld, block);
|
||||||
server.requestChange(change);
|
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) {
|
public void addTile(Vec3i blockInWorld, BlockFace face, TileData tile) {
|
||||||
AddOrRemoveTile change = cache.grab(AddOrRemoveTile.class);
|
AddOrRemoveTile change = cache.grab(AddOrRemoveTile.class);
|
||||||
change.initialize(blockInWorld, face, tile, true);
|
change.initialize(blockInWorld, face, tile, true);
|
||||||
server.requestChange(change);
|
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, TileData tile) {
|
public void removeTile(Vec3i blockInWorld, BlockFace face, TileData tile) {
|
||||||
AddOrRemoveTile change = cache.grab(AddOrRemoveTile.class);
|
AddOrRemoveTile change = cache.grab(AddOrRemoveTile.class);
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
package ru.windcorp.progressia.server.world.ticking;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.server.world.block.TickableBlock;
|
||||||
|
import ru.windcorp.progressia.server.world.tile.TickableTile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Various ticking policies that {@link TickableBlock} or {@link TickableTile} can have.
|
||||||
|
* Ticking policy determines when, and if, the block or tile is ticked.
|
||||||
|
* @author javapony
|
||||||
|
*/
|
||||||
|
public enum TickingPolicy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ticking policy that requests that no ticks happen.
|
||||||
|
* This is typically used for blocks or tiles that only tick under certain conditions,
|
||||||
|
* which are not meant at the moment.
|
||||||
|
*/
|
||||||
|
NONE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ticking policy that requests that the object is ticked every server tick exactly once.
|
||||||
|
* This should not be used for objects that only change rarely; consider using {@link RANDOM}
|
||||||
|
* instead.
|
||||||
|
*/
|
||||||
|
REGULAR,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ticking policy that requests that the object is ticked only once every
|
||||||
|
* <pre>
|
||||||
|
* Server.getTickingSettings().getRandomTickFrequency()</pre>
|
||||||
|
* seconds on average (this value is only determined at runtime). Note that
|
||||||
|
* the block might sometimes tick more than once per single server tick.
|
||||||
|
*/
|
||||||
|
RANDOM;
|
||||||
|
|
||||||
|
}
|
@ -1,15 +1,11 @@
|
|||||||
package ru.windcorp.progressia.server.world.tile;
|
package ru.windcorp.progressia.server.world.tile;
|
||||||
|
|
||||||
|
import ru.windcorp.progressia.server.world.ticking.TickingPolicy;
|
||||||
|
|
||||||
public interface TickableTile {
|
public interface TickableTile {
|
||||||
|
|
||||||
void tick(TileTickContext context);
|
void tick(TileTickContext context);
|
||||||
|
|
||||||
default boolean doesTickRegularly(TileTickContext context) {
|
TickingPolicy getTickingPolicy(TileTickContext context);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean doesTickRandomly(TileTickContext context) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user