Added more generic Contexts. WIP.

This commit is contained in:
OLEGSHA 2021-07-15 22:26:20 +03:00
parent 0264e512ab
commit d7afe39f00
Signed by: OLEGSHA
GPG Key ID: E57A4B08D64AFF7A
10 changed files with 902 additions and 0 deletions

View File

@ -0,0 +1,105 @@
/*
* 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.common.world.context;
/**
* A cursor-like object for retrieving information about an in-game environment.
* A context object typically holds a reference to some sort of data structure
* and a cursor pointing to a location in that data structure. The exact meaning
* of "environment" and "location" is defined by extending interfaces.
* <p>
* Context objects are intended to be the primary way of interacting for in-game
* content. Wherever possible, context objects should be preferred over other
* means of accessing game structures.
* <h2 id="validity">Context Validity</h2>
* Context objects may only be used while they are valid to avoid undefined
* behavior. There exists no programmatic way to determine a context's validity;
* it is the responsibility of the programmer to avoid interacting with invalid
* contexts.
* <p>
* Contexts are usually acquired as method parameters. Unless stated otherwise,
* the context is valid until the invoked method returns; the only exception to
* this rule is subcontexting (see below). Consequently, contexts should never
* be stored outside their intended methods.
* <p>
* In practice, context objects are typically highly volatile. They are <em>not
* thread-safe</em> and are often pooled and reused.
* <p>
* <h2 id="subcontexting">Subcontexting</h2>
* <em>Subcontexting</em> is the invocation of user-provided code with a context
* object derived from an existing one. For example, block context provides a
* convenience method for referencing the block's neighbor:
*
* <pre>
* blockContextA.forNeighbor(RelFace.UP, blockContextB -&gt; {
* foo(blockContextA); // undefined behavior!
* foo(blockContextB); // correct
* });
* </pre>
*
* In this example, {@code forNeighbor} is a subcontexting method,
* {@code blockContextA} is the parent context, {@code blockContextB} is the
* subcontext, and the lambda is the context consumer.
* <p>
* <em>Parent contexts are invalid while the subcontexting method is
* running.</em> Referencing {@code blockContextA} from inside the lambda
* creates undefined behavior.
* <p>
* This restriction exists because some implementations of contexts may
* implement subcontexting by simply modifying the parent context for the
* duration of the call and presenting the temporarily modified parent context
* as the subcontext:
*
* <pre>
* public void forNeighbor(BlockFace face, Consumer&lt;BlockContext&gt; action) {
* this.position.add(face);
* action.accept(this);
* this.position.sub(face);
* }
* </pre>
*/
public interface Context {
/**
* Tests whether the environment is "real". Any actions carried out in an
* environment that is not "real" should not have any side effects outside
* of the environment.
* <p>
* A typical "real" environment is the world of the client that is actually
* displayed or a world of the server that the clients actually interact
* with. An example of a non-"real" environment is a fake world used by
* developer tools to query the properties or behaviors of in-game content.
* While in-game events may well trigger global-scope actions, such as
* writing files, this may become an unintended or even harmful byproduct in
* some scenarios that are not actually linked to an actual in-game world.
* <p>
* This flag should generally only be consulted before taking action through
* means other than a provided changer object. The interactions with the
* context should otherwise remain unaltered.
* <p>
* When querying game content for purposes other than directly applying
* results in-game, {@code isReal()} should return {@code false}. In all
* other cases, where possible, the call should be delegated to a provided
* context object.
*
* @return {@code false} iff side effects outside the environment should be
* suppressed
*/
boolean isReal();
}

View File

@ -0,0 +1,119 @@
/*
* 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.common.world.generic.context;
import glm.vec._3.i.Vec3i;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
import ru.windcorp.progressia.common.world.rels.BlockFace;
/**
* A {@link Context} referencing a world with a block location specified. The
* location may or may not be loaded.
*/
//@formatter:off
public interface GenericROBlockContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROWorldContext<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Returns the location of the block.
* <p>
* The coordinate system in use is not specified, but it is consistent
* across all methods of this context.
* <p>
* The object returned by this method must not be modified. It is only valid
* while the context is {@linkplain valid}.
*
* @return a vector describing the block's position
*/
Vec3i getLocation();
/**
* Determines whether the location relevant to this context is currently
* loaded.
*
* @return {@code true} iff the location is loaded
*/
default boolean isLoaded() {
return isBlockLoaded(getLocation());
}
/**
* Gets the block relevant in this context.
*
* @return the block or {@code null} if the location is not loaded
*/
default B getBlock() {
return getBlock(getLocation());
}
/**
* Gets the tile stack at the specified position; block location is implied
* by the context.
*
* @return the specified tile stack or {@code null} if the location is not
* loaded or the tile stack does not exist
*/
default TS getTilesOrNull(BlockFace face) {
return getTilesOrNull(getLocation(), face);
}
/**
* Determines whether the location relevant to this context has a tile stack
* at the specified side.
*
* @return {@code true} iff the tile stack exists
*/
default boolean hasTiles(BlockFace face) {
return hasTiles(getLocation(), face);
}
/**
* Determines whether the specified position has a tile; block location is
* implied by the context.
*
* @return {@code true} iff the tile exists
*/
default boolean hasTile(BlockFace face, int layer) {
return hasTile(getLocation(), face, layer);
}
/**
* Gets the tile at the specified position; block location is implied by the
* context.
*
* @return the specified tile or {@code null} if the location is not loaded
* or the tile does not exist
*/
default T getTile(BlockFace face, int layer) {
return getTile(getLocation(), face, layer);
}
}

View File

@ -0,0 +1,93 @@
/*
* 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.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
import ru.windcorp.progressia.common.world.rels.RelFace;
/**
* A {@link Context} referencing a world with a block location and a block face
* specified, effectively pointing to a tile stack. The tile stack may or may
* not actually exist.
*/
//@formatter:off
public interface GenericROBlockFaceContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROBlockContext<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Returns the face relevant to this context.
*
* @return the block face
*/
RelFace getFace();
/**
* Gets the tile stack at the relevant position.
*
* @return the specified tile stack or {@code null} if the location is not
* loaded or the tile stack does not exist
*/
default TS getTilesOrNull() {
return getTilesOrNull(getLocation(), getFace());
}
/**
* Determines whether the location relevant to this context has a tile
* stack.
*
* @return {@code true} iff the tile stack exists
*/
default boolean hasTiles() {
return hasTiles(getLocation(), getFace());
}
/**
* Determines whether the specified position has a tile; block location and
* face are implied by the context.
*
* @return {@code true} iff the tile exists
*/
default boolean hasTile(int layer) {
return hasTile(getLocation(), getFace(), layer);
}
/**
* Gets the tile at the specified position; block location and face are
* implied by the context.
*
* @return the specified tile or {@code null} if the location is not loaded
* or the tile does not exist
*/
default T getTile(int layer) {
return getTile(getLocation(), getFace(), layer);
}
}

View File

@ -0,0 +1,85 @@
/*
* 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.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
/**
* A {@link Context} referencing a world with a block location, a block face and
* a tile layer specified, effectively pointing to a single tile. The tile may
* or may not actually exist.
*/
//@formatter:off
public interface GenericROTileContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROBlockFaceContext<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Returns the tile layer relevant to this context.
*
* @return the tile layer
*/
int getLayer();
/**
* Determines whether the location relevant to this context has a tile.
*
* @return {@code true} iff the tile exists
*/
default boolean hasTile() {
return hasTile(getLocation(), getFace(), getLayer());
}
/**
* Gets the tile at the relevant position.
*
* @return the specified tile or {@code null} if the location is not loaded
* or the tile does not exist
*/
default T getTile() {
return getTile(getLocation(), getFace(), getLayer());
}
/**
* Gets the tag of the tile at the relevant position.
*
* @return the tag of the tile or {@code -1} if the location is not loaded
* or the tile does not exist
*/
default int getTag() {
TS tileStack = getTilesOrNull();
if (tileStack == null) {
return -1;
}
return tileStack.getTagByIndex(getLayer());
}
}

View File

@ -0,0 +1,45 @@
/*
* 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.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.GenericBlock;
import ru.windcorp.progressia.common.world.generic.GenericROChunk;
import ru.windcorp.progressia.common.world.generic.GenericEntity;
import ru.windcorp.progressia.common.world.generic.GenericTile;
import ru.windcorp.progressia.common.world.generic.GenericROTileReference;
import ru.windcorp.progressia.common.world.generic.GenericROTileStack;
import ru.windcorp.progressia.common.world.generic.GenericROWorld;
/**
* A {@link Context} with a world instance.
*/
// @formatter:off
public interface GenericROWorldContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericROTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericROChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends Context, GenericROWorld<B, T, TS, TR, C, E> {
// @formatter:on
// currently empty
}

View File

@ -0,0 +1,92 @@
/*
* 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.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.*;
import ru.windcorp.progressia.common.world.rels.BlockFace;
/**
* A writable {@link Context} referencing a world with a block location
* specified. This context provides methods for affecting the world. The
* application of requested changes may or may not be immediate, see
* {@link #isImmediate()}. The location may or may not be loaded.
*/
//@formatter:off
public interface GenericRWBlockContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericRWTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericRWWorldContext<B, T, TS, TR, C, E>, GenericROBlockContext<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Requests that a block is changed. The object provided may be stored until
* the change is applied. The location of the block is implied by the
* context.
*
* @param block the new block
* @see #isImmediate()
*/
default void setBlock(B block) {
setBlock(getLocation(), block);
}
/**
* Requests that a tile is added to the top of the tile stack at the given
* location. The object provided may be stored until the change is applied.
* If the tile could not be added at the time of application this method
* fails silently. The location of the block is implied by the context.
*
* @param face the face of the block to add the tile to
* @param tile the tile to add
*/
default void addTile(BlockFace face, T tile) {
addTile(getLocation(), face, tile);
}
/**
* Requests that a tile identified by its tag is removed from the specified
* tile stack. If the tile could not be found at the time of application
* this method fails silently. The location of the block is implied by the
* context.
*
* @param face the of the block to remove the tile from
* @param tag the tag of the tile to remove
*/
default void removeTile(BlockFace face, int tag) {
removeTile(getLocation(), face, tag);
}
/**
* Requests that the referenced tile is removed from the specified tile
* stack. If the tile could not be found at the time of application this
* method fails silently. The location of the block is implied by the
* context.
*
* @param face the of the block to remove the tile from
* @param tileReference a reference to the tile
*/
default void removeTile(BlockFace face, TR tileReference) {
removeTile(getLocation(), face, tileReference.getTag());
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.*;
/**
* A writable {@link Context} referencing a world with a block location and a
* block face specified, effectively pointing to a tile stack. This context
* provides methods for affecting the world. The application of requested
* changes may or may not be immediate, see {@link #isImmediate()}. The tile
* stack may or may not actually exist.
*/
//@formatter:off
public interface GenericRWBlockFaceContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericRWTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericRWBlockContext<B, T, TS, TR, C, E>, GenericROBlockFaceContext<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Requests that a tile is added to the top of the tile stack at the given
* location. The object provided may be stored until the change is applied.
* If the tile could not be added at the time of application this method
* fails silently. The location and the face of the block are implied by the
* context.
*
* @param tile the tile to add
*/
default void addTile(T tile) {
addTile(getLocation(), getFace(), tile);
}
/**
* Requests that a tile identified by its tag is removed from the specified
* tile stack. If the tile could not be found at the time of application
* this method fails silently. The location and the face of the block are
* implied by the context.
*
* @param tag the tag of the tile to remove
*/
default void removeTile(int tag) {
removeTile(getLocation(), getFace(), tag);
}
/**
* Requests that the referenced tile is removed from the specified tile
* stack. If the tile could not be found at the time of application this
* method fails silently. The location and the face of the block are implied
* by the context.
*
* @param tileReference a reference to the tile
*/
default void removeTile(TR tileReference) {
removeTile(getLocation(), getFace(), tileReference.getTag());
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.common.world.generic.context;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.common.world.generic.*;
/**
* A writable {@link Context} referencing a world with a block location, a block
* face and a tile layer specified, effectively pointing to a single tile. This
* context provides methods for affecting the world. The application of
* requested changes may or may not be immediate, see {@link #isImmediate()}.
* The tile may or may not actually exist.
*/
//@formatter:off
public interface GenericRWTileContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericRWTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericRWBlockFaceContext<B, T, TS, TR, C, E>, GenericROTileContext<B, T, TS, TR, C, E> {
//@formatter:on
/**
* Requests that the tile relevant to this context be removed from its tile
* stack. If the tile could not be found at the time of application this
* method fails silently.
*/
default void removeTile() {
removeTile(getLocation(), getFace(), getTag());
}
}

View File

@ -0,0 +1,151 @@
/*
* 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.common.world.generic.context;
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.world.context.Context;
import ru.windcorp.progressia.common.world.generic.*;
import ru.windcorp.progressia.common.world.rels.BlockFace;
/**
* A writable {@link Context} with a world instance. This context provides
* methods for affecting the world. The application of requested changes may or
* may not be immediate, see {@link #isImmediate()}.
*/
// @formatter:off
public interface GenericRWWorldContext<
B extends GenericBlock,
T extends GenericTile,
TS extends GenericRWTileStack <B, T, TS, TR, C>,
TR extends GenericROTileReference <B, T, TS, TR, C>,
C extends GenericRWChunk <B, T, TS, TR, C>,
E extends GenericEntity
> extends GenericROWorldContext<B, T, TS, TR, C, E>, GenericRWWorld<B, T, TS, TR, C, E> {
// @formatter:on
/**
* Queries whether changes requested with this context are guaranteed to be
* applied immediately.
* <p>
* When the changes are applied immediately, all subsequent queries will
* reflect the change. When the changes are not applied immediately, none of
* the subsequent queries will be affected by the requests while the context
* is {@linkplain Context#validity valid}. Immediate mode does not change
* while the context is valid.
*
* @return {@code true} iff changes are visible immediately
*/
boolean isImmediate();
/**
* Requests that a block is changed. The object provided may be stored until
* the change is applied.
*
* @param location the location of the change
* @param block the new block
* @see #isImmediate()
*/
default void setBlock(Vec3i location, B block) {
setBlock(location, block);
}
/**
* Requests that a tile is added to the top of the tile stack at the given
* location. The object provided may be stored until the change is applied.
* If the tile could not be added at the time of application this method
* fails silently.
*
* @param location the location of the block to which the tile is to be
* added
* @param face the face of the block to add the tile to
* @param tile the tile to add
*/
void addTile(Vec3i location, BlockFace face, T tile);
/**
* Requests that a tile identified by its tag is removed from the specified
* tile stack. If the tile could not be found at the time of application
* this method fails silently.
*
* @param location the location of the block from which the tile is to be
* removed
* @param face the of the block to remove the tile from
* @param tag the tag of the tile to remove
*/
void removeTile(Vec3i location, BlockFace face, int tag);
/**
* Requests that the referenced tile is removed from the specified tile
* stack. If the tile could not be found at the time of application this
* method fails silently.
*
* @param location the location of the block from which the tile is to
* be removed
* @param face the of the block to remove the tile from
* @param tileReference a reference to the tile
*/
default void removeTile(Vec3i location, BlockFace face, TR tileReference) {
removeTile(location, face, tileReference.getTag());
}
/**
* Requests that an entity is added to the world. The object provided may be
* stored until the change is applied. If the entity was already added to
* the world at the time of application this method does nothing.
*
* @param entity the entity to add
* @see #isImmediate()
*/
@Override
void addEntity(E entity);
/**
* Requests that an entity with the given entity ID is removed from the
* world. If the entity did not exist at the time of application this method
* fails silently.
*
* @param entityId the ID of the entity to remove
* @see #isImmediate()
* @see #removeEntity(GenericEntity)
*/
@Override
void removeEntity(long entityId);
/**
* Requests that the entity is removed from the world. If the entity did not
* exist at the time of application this method fails silently.
*
* @param entity the entity to remove
* @see #isImmediate()
* @see #removeEntity(long)
*/
@Override
void removeEntity(E entity);
/**
* Requests that the specified change is applied to the given entity. The {@code change} object provided may be stored until the change is applied.
*
* @param entity the entity to change
* @param change the change to apply
*/
@Override
<SE extends StatefulObject & GenericEntity> void changeEntity(SE entity, StateChange<SE> change);
}

View File

@ -0,0 +1,84 @@
/*
* Progressia
* Copyright (C) 2020-2021 Wind Corporation and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package ru.windcorp.progressia.server.world.context;
import java.util.Random;
import ru.windcorp.progressia.common.world.context.Context;
import ru.windcorp.progressia.server.Server;
import ru.windcorp.progressia.server.ServerState;
/**
* A server-side {@link Context}. This context has a {@link Server} instance.
*/
public interface ServerContext extends Context {
/**
* Gets the {@link Server} instance relevant to this context. This method
* should always be preferred to {@link ServerState#getInstance()} when
* possible.
*
* @return the server instance
*/
Server getServer();
/**
* Retrieves a context-appropriate source of randomness. This source should
* always be preferred to any other when possible.
*
* @return an intended {@link Random} instance
*/
Random getRandom();
/**
* 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
*/
default double getTickLength() {
return getServer().getTickLength();
}
/**
* Adjusts the provided value according to tick length assuming the value
* scales linearly. The call {@code ctxt.adjustValue(x)} is equivalent to
* {@code ((float) ctxt.getTickLength()) * x}.
*
* @param valueForOneSecond the value to adjust, normalized to one second
* @return the value adjust to account for the actual tick length
* @see #getTickLength()
*/
default float adjustTime(float valueForOneSecond) {
return ((float) getTickLength()) * valueForOneSecond;
}
/**
* Adjusts the provided value according to tick length assuming the value
* scales linearly. The call {@code ctxt.adjustValue(x)} is equivalent to
* {@code ctxt.getTickLength() * x}.
*
* @param valueForOneSecond the value to adjust, normalized to one second
* @return the value adjust to account for the actual tick length
* @see #getTickLength()
*/
default double adjustTime(double valueForOneSecond) {
return getTickLength() * valueForOneSecond;
}
}