Skip to content

Commit

Permalink
Volume and regeneration rejigging
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Naylor committed Jul 24, 2021
1 parent 80fb05a commit 6216cd7
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 42 deletions.
36 changes: 32 additions & 4 deletions src/main/java/org/spongepowered/api/world/server/ChunkManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,47 +175,75 @@ default <T> Collection<Ticket<T>> findTickets(final DefaultedRegistryReference<T
/**
* Regenerates a chunk at the given chunk coordinate position.
*
* <p>Care should be taken to check the result of the future, as an
* exception may be provided if the regeneration was not successful.</p>
*
* <p><strong>Users must not use {@link CompletableFuture#get() get} or
* {@link CompletableFuture#join() join} on this future.</strong> Doing so
* may end up causing a deadlock on the server.</p>
*
* @param chunkPosition The chunk position to regenerate
* @return The regenerated chunk, if available
*/
default CompletableFuture<WorldChunk> regenerateChunk(final Vector3i chunkPosition) {
default CompletableFuture<Boolean> regenerateChunk(final Vector3i chunkPosition) {
Objects.requireNonNull(chunkPosition, "chunkPosition");
return this.regenerateChunk(chunkPosition.x(), chunkPosition.y(), chunkPosition.z(), ChunkRegenerateFlags.ALL.get());
}

/**
* Regenerates a chunk at the given chunk coordinates.
*
* <p>Care should be taken to check the result of the future, as an
* exception may be provided if the regeneration was not successful.</p>
*
* <p><strong>Users must not use {@link CompletableFuture#get() get} or
* {@link CompletableFuture#join() join} on this future.</strong> Doing so
* may end up causing a deadlock on the server.</p>
*
* @param cx The chunk x coordinate
* @param cy The chunk y coordinate
* @param cz The chunk z coordinate
* @return The regenerated chunk, if available
*/
default CompletableFuture<WorldChunk> regenerateChunk(final int cx, final int cy, final int cz) {
default CompletableFuture<Boolean> regenerateChunk(final int cx, final int cy, final int cz) {
return this.regenerateChunk(cx, cy, cz, ChunkRegenerateFlags.ALL.get());
}

/**
* Regenerates a chunk at the given chunk coordinate position.
*
* <p>Care should be taken to check the result of the future, as an
* exception may be provided if the regeneration was not successful.</p>
*
* <p><strong>Users must not use {@link CompletableFuture#get() get} or
* {@link CompletableFuture#join() join} on this future.</strong> Doing so
* may end up causing a deadlock on the server.</p>
*
* @param chunkPosition The chunk position to regenerate
* @param flag The chunk regenerate flag to use
* @return The regenerated chunk, if available
*/
default CompletableFuture<WorldChunk> regenerateChunk(final Vector3i chunkPosition, final ChunkRegenerateFlag flag) {
default CompletableFuture<Boolean> regenerateChunk(final Vector3i chunkPosition, final ChunkRegenerateFlag flag) {
Objects.requireNonNull(chunkPosition, "chunkPosition");
return this.regenerateChunk(chunkPosition.x(), chunkPosition.y(), chunkPosition.z(), Objects.requireNonNull(flag, "flag"));
}

/**
* Regenerates a chunk at the given chunk coordinates.
*
* <p>Care should be taken to check the result of the future, as an
* exception may be provided if the regeneration was not successful.</p>
*
* <p><strong>Users must not use {@link CompletableFuture#get() get} or
* {@link CompletableFuture#join() join} on this future.</strong> Doing so
* may end up causing a deadlock on the server.</p>
*
* @param cx The chunk x coordinate
* @param cy The chunk y coordinate
* @param cz The chunk z coordinate
* @param flag The chunk regenerate flag to use
* @return The regenerated chunk, if available
*/
CompletableFuture<WorldChunk> regenerateChunk(int cx, int cy, int cz, ChunkRegenerateFlag flag);
CompletableFuture<Boolean> regenerateChunk(int cx, int cy, int cz, ChunkRegenerateFlag flag);

}
59 changes: 31 additions & 28 deletions src/main/java/org/spongepowered/api/world/volume/Volume.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,85 +30,88 @@

import java.util.Objects;

/**
* A volume is a bounded cuboid that is a view to some collection of objects
* with position. Such a cuboid is always aligned along the cartesian axes
* in 3D space with the bounds specified in block-position space.
*/
public interface Volume {

/**
* The minimum valid block position in this volume.
* The minimum valid position in this volume.
*
* @return The minimum valid block position
* @return The minimum valid position
*/
Vector3i blockMin();
Vector3i min();

/**
* The maximum valid block position in this volume.
* The maximum valid position in this volume.
*
* @return The maximum valid block position
* @return The maximum valid position
*/
Vector3i blockMax();
Vector3i max();

/**
* The size of this region, defined as the difference
* between {@link #blockMax()} and {@link #blockMin()},
* plus {@link Vector3i#ONE}.
* The size of this region, defined as the difference between {@link #max()}
* and {@link #min()}, plus {@link Vector3i#ONE}.
*
* @return The size of the volume.
*/
default Vector3i blockSize() {
return this.blockMax().sub(this.blockMin()).add(Vector3i.ONE);
default Vector3i size() {
return this.max().sub(this.min()).add(Vector3i.ONE);
}

/**
* Returns true if the block volume contains a block at the specified
* position. This is defined as <code>{{@link #blockMin()} &lt;= position &lt;=
* {@link #blockMax()}</code>
* Returns true if the supplied co-ordinate is valid within this
* volume. This is defined as <code>{{@link #min()} &lt;= (x, y, z)
* &gt;= {@link #max()}</code>
*
* @param position The position to check
* @return Whether or not the position has a block in this volume
* @return Whether or not the position is within this volume
*/
default boolean containsBlock(final Vector3i position) {
default boolean contains(final Vector3i position) {
Objects.requireNonNull(position, "position");

return this.containsBlock(position.x(), position.y(), position.z());
return this.contains(position.x(), position.y(), position.z());
}

/**
* Returns true if the block volume contains a block at the specified
* position. This is defined as <code>{{@link #blockMin()} &lt;= (x, y, z)
* &gt;= {@link #blockMax()}</code>
* Returns true if the supplied co-ordinate is valid within this
* volume. This is defined as <code>{{@link #min()} &lt;= (x, y, z)
* &gt;= {@link #max()}</code>
*
* @param x The X coordinate to check
* @param y The Y coordinate to check
* @param z The Z coordinate to check
* @return Whether or not the position has a block in this volume
* @return Whether or not the position is within this volume
*/
boolean containsBlock(int x, int y, int z);
boolean contains(int x, int y, int z);

/**
* Returns true if {@link #containsBlock(Vector3i)} is true and the
* Returns true if {@link #contains(Vector3i)} is true and the
* backing data is actually loaded - e.g. for a {@link ServerWorld}, this
* will only return true if the {@link WorldChunk} that contains this co-ordinate
* is fully loaded.
*
* @param position The position to check
* @return Whether or not the position has a block in this volume
* @return Whether or not the position is within this volume
* <strong>and</strong> the location is loaded.
*/
default boolean isAreaAvailable(final Vector3i position) {
default boolean available(final Vector3i position) {
Objects.requireNonNull(position, "position");

return this.isAreaAvailable(position.x(), position.y(), position.z());
}

/**
* Returns true if {@link #containsBlock(int, int, int)} is true and the
* Returns true if {@link #contains(int, int, int)} is true and the
* backing data is actually loaded - e.g. for a {@link ServerWorld}, this
* will only return true if the {@link WorldChunk} that contains this co-ordinate
* is fully loaded.
*
* @param x The X coordinate to check
* @param y The Y coordinate to check
* @param z The Z coordinate to check
* @return Whether or not the position has a block in this volume
* @return Whether or not the position is within this volume
* <strong>and</strong> the location is loaded.
*/
boolean isAreaAvailable(int x, int y, int z);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public interface ArchetypeVolume extends BlockVolume.Modifiable<ArchetypeVolume>
* @return The logical center of the volume
*/
default Vector3d logicalCenter() {
return this.blockMin().toDouble().add(this.blockSize().toDouble().div(2));
return this.min().toDouble().add(this.size().toDouble().div(2));
}

/**
Expand All @@ -79,27 +79,27 @@ default void applyToWorld(final ServerWorld target, final Vector3i placement, fi
Objects.requireNonNull(target, "Target world cannot be null");
Objects.requireNonNull(placement, "Target position cannot be null");
try (final CauseStackManager.StackFrame frame = Sponge.server().causeStackManager().pushCauseFrame()) {
this.blockStateStream(this.blockMin(), this.blockMax(), StreamOptions.lazily())
this.blockStateStream(this.min(), this.max(), StreamOptions.lazily())
.apply(VolumeCollectors.of(
target,
VolumePositionTranslators.relativeTo(placement),
VolumeApplicators.applyBlocks(BlockChangeFlags.DEFAULT_PLACEMENT)
));

this.biomeStream(this.blockMin(), this.blockMax(), StreamOptions.lazily())
this.biomeStream(this.min(), this.max(), StreamOptions.lazily())
.apply(VolumeCollectors.of(
target,
VolumePositionTranslators.relativeTo(placement),
VolumeApplicators.applyBiomes()
));
this.blockEntityArchetypeStream(this.blockMin(), this.blockMax(), StreamOptions.lazily())
this.blockEntityArchetypeStream(this.min(), this.max(), StreamOptions.lazily())
.apply(VolumeCollectors.of(
target,
VolumePositionTranslators.relativeTo(placement),
VolumeApplicators.applyBlockEntityArchetype()
));
frame.addContext(EventContextKeys.SPAWN_TYPE, spawnContext);
this.entityArchetypeStream(this.blockMin(), this.blockMax(), StreamOptions.lazily())
this.entityArchetypeStream(this.min(), this.max(), StreamOptions.lazily())
.apply(VolumeCollectors.of(
target,
VolumePositionTranslators.relativeTo(placement),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.spongepowered.api.world.chunk.Chunk;
import org.spongepowered.api.world.server.ServerLocation;
import org.spongepowered.api.world.storage.ChunkLayout;
import org.spongepowered.api.world.volume.Volume;
import org.spongepowered.api.world.volume.block.BlockVolume;
import org.spongepowered.math.vector.Vector3i;

Expand All @@ -40,7 +41,7 @@
* Presents a volume of {@link Chunk}s that can exist
* without a {@link WorldLike} volume.
*/
public interface ChunkVolume extends BlockVolume {
public interface ChunkVolume extends Volume {

/**
* Returns information about the chunk layout used by this volume's
Expand Down Expand Up @@ -138,7 +139,7 @@ public interface ChunkVolume extends BlockVolume {
* @param allowEmpty Whether to allow empty chunks
* @return Whether a chunk is loaded or not
*/
default boolean isChunkLoadedAtBlock(int bx, int by, int bz, boolean allowEmpty) {
default boolean isChunkLoadedAtBlock(final int bx, final int by, final int bz, final boolean allowEmpty) {
return this.isChunkLoaded(this.chunkLayout().forceToChunk(bx, by, bz), allowEmpty);
}

Expand Down Expand Up @@ -196,7 +197,7 @@ default boolean isChunkLoadedAtBlock(final Vector3i position, final boolean allo
* @param bz The block z coordinate
* @return Whether a chunk exists
*/
default boolean hasChunkAtBlock(int bx, int by, int bz) {
default boolean hasChunkAtBlock(final int bx, final int by, final int bz) {
return this.hasChunk(this.chunkLayout().forceToChunk(bx, by, bz));
}

Expand All @@ -209,7 +210,7 @@ default boolean hasChunkAtBlock(int bx, int by, int bz) {
* @param chunkPosition The chunk coordinates
* @return Whether a chunk exists
*/
default boolean hasChunk(Vector3i chunkPosition) {
default boolean hasChunk(final Vector3i chunkPosition) {
return this.hasChunk(chunkPosition.x(), chunkPosition.y(), chunkPosition.z());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ default boolean hasBlockState(Vector3i pos, Predicate<? super BlockState> predic
boolean hasBlockState(int x, int y, int z, Predicate<? super BlockState> predicate);

default int maximumHeight() {
return this instanceof World ? ((World) this).blockMax().y() : 256;
return this instanceof World ? ((World) this).max().y() : 256;
}

interface Mutable extends GenerationVolume, MutableGameVolume {
Expand Down

0 comments on commit 6216cd7

Please sign in to comment.