Added more generic Contexts. WIP.
This commit is contained in:
parent
0264e512ab
commit
d7afe39f00
@ -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 -> {
|
||||
* 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<BlockContext> 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();
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
@ -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);
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user