Skip to content

Commit 73982f7

Browse files
committed
chore: improve project documentation
* rename some methods to be more intuitive * bump version to 0.7 * remove some config options * should be decided by library users instead
1 parent cafb6ac commit 73982f7

21 files changed

+631
-444
lines changed

README.md

+141-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,142 @@
11
# DynamicDimensions
2-
Library to facilitate the runtime addition and removal of minecraft dimensions.
2+
Library to facilitate the runtime addition and removal of Minecraft dimensions.
3+
4+
## Adding DynamicDimensions to your project
5+
Add the Galacticraft maven to your project
6+
```groovy
7+
repositories {
8+
maven {
9+
url = "https://maven.galacticraft.net/repository/maven-releases"
10+
}
11+
}
12+
```
13+
14+
Then add the appropriate dependency:
15+
### Fabric
16+
```groovy
17+
dependencies {
18+
modImplementation("dev.galacticraft.dynamicdimensions-fabric:$dynDims")
19+
}
20+
```
21+
22+
### NeoForge
23+
```groovy
24+
dependencies {
25+
implementation(fg.deobf("dev.galacticraft.dynamicdimensions-neoforge:$dynDims"))
26+
}
27+
```
28+
29+
### Multiplatform
30+
```groovy
31+
// Common
32+
dependencies {
33+
implementation("dev.galacticraft.dynamicdimensions-common:$dynDims")
34+
}
35+
// Fabric
36+
dependencies {
37+
modRuntimeOnly("dev.galacticraft.dynamicdimensions-fabric:$dynDims")
38+
}
39+
40+
// NeoForge
41+
dependencies {
42+
runtimeOnly(fg.deobf("dev.galacticraft.dynamicdimensions-neoforge:$dynDims"))
43+
}
44+
```
45+
46+
## Using the API
47+
All APIs dealing with the addition and removal of dynamic dimensions go through the
48+
`dev.galacticraft.dynamicdimensions.api.DynamicDimensionRegistry`
49+
class.
50+
51+
To obtain an instance, simply call
52+
`DynamicDimensionRegistry#from(MinecraftServer)`
53+
54+
Note that this library does *not* keep track of what dynamic dimensions have been created when the server restarts.
55+
You will need to track this yourself and then
56+
[load the dimension](#loading-a-dimension-reads-or-creates-new-level-data)
57+
again.
58+
59+
### Creating a *new* dimension (overwrites level data)
60+
Call
61+
`DynamicDimensionRegistry::createDynamicDimension`
62+
with the ID of your dimension, a chunk generator, and a dimension type.
63+
64+
```java
65+
ChunkGenerator generator;
66+
DimensionType type;
67+
68+
// ... initialize chunk generator and dimension type ...
69+
70+
DynamicDimensionRegistry registry = DynamicDimensionRegistry.from(server);
71+
ServerLevel level = registry.createDynamicDimension(new ResourceLocation("mymod", "dynamic"), generator, type);
72+
73+
if (level == null) {
74+
// failed to create level
75+
} else { /*...*/ }
76+
```
77+
78+
This will create a new dimension with the given ID, discarding data from any previous dimensions with the same ID.
79+
If you want world data to be loaded, see
80+
[the next section](#loading-a-dimension-reads-or-creates-new-level-data)
81+
.
82+
83+
#### Caveats
84+
85+
* `createDynamicDimension` will delete all previous dimension data.
86+
* The `DimensionType` and ID of your dimension cannot already be in use.
87+
* There may be a one-tick delay before the dimension is registered with the server.
88+
89+
### Loading a dimension (reads or creates new level data)
90+
Call
91+
`DynamicDimensionRegistry::loadDynamicDimension`
92+
with the ID of your dimension, a chunk generator, and a dimension type.
93+
```java
94+
ChunkGenerator generator;
95+
DimensionType type;
96+
97+
// ... initialize chunk generator and dimension type ...
98+
99+
DynamicDimensionRegistry registry = DynamicDimensionRegistry.from(server);
100+
ServerLevel level = registry.loadDynamicDimension(new ResourceLocation("mymod", "dynamic"), generator, type);
101+
102+
if (level == null) {
103+
// failed to create level
104+
} else { /*...*/ }
105+
```
106+
107+
This will create a dimension with the given ID, loading previous region/level data from disk.
108+
109+
#### Caveats
110+
111+
* The `DimensionType` and ID of your dimension cannot already be in use.
112+
* There may be a one-tick delay before the dimension is registered with the server.
113+
114+
### Unloading a dimension
115+
Call
116+
`DynamicDimensionRegistry::unloadDynamicDimension`
117+
with the ID of your dimension and (optionally) a callback to move connected players off-world.
118+
```java
119+
DynamicDimensionRegistry registry = DynamicDimensionRegistry.from(server);
120+
registry.unloadDynamicDimension(new ResourceLocation("mymod", "dynamic"), null);
121+
```
122+
The dimension will be saved to disk before being unloaded. You can use
123+
`loadDynamicDimension`
124+
to create the dimension again (loading the same world data).
125+
126+
#### Caveats
127+
* There may be a one-tick delay before the dimension is removed from the server.
128+
129+
### Deleting a dimension
130+
Call
131+
`DynamicDimensionRegistry::deleteDynamicDimension`
132+
with the ID of your dimension and (optionally) a callback to move connected players off-world.
133+
```java
134+
DynamicDimensionRegistry registry = DynamicDimensionRegistry.from(server);
135+
registry.deleteDynamicDimension(new ResourceLocation("mymod", "dynamic"), null);
136+
```
137+
The dimension will be unloaded, then all the dimension files will be deleted.
138+
139+
#### Caveats
140+
141+
* There may be a one-tick delay before the dimension is removed from the server.
142+
* Once deleted, dimension files are not recoverable

build.gradle.kts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
plugins {
2-
id("org.ajoberstar.grgit.service") version ("5.2.1")
2+
id("org.ajoberstar.grgit.service") version("5.2.1")
33
id("org.cadixdev.licenser") version("0.6.1") apply(false)
4-
id("fabric-loom") version ("1.5-SNAPSHOT") apply (false)
5-
id("org.jetbrains.gradle.plugin.idea-ext") version ("1.1.7") // required for neoforge
4+
id("fabric-loom") version("1.5-SNAPSHOT") apply(false)
5+
id("org.jetbrains.gradle.plugin.idea-ext") version("1.1.7") // required for neoforge
66
}
77

88
val minecraft = project.property("minecraft.version").toString()

common/src/main/java/dev/galacticraft/dynamicdimensions/api/DynamicDimensionRegistry.java

+34-18
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import net.minecraft.resources.ResourceLocation;
2626
import net.minecraft.server.MinecraftServer;
27+
import net.minecraft.server.level.ServerLevel;
2728
import net.minecraft.world.level.chunk.ChunkGenerator;
2829
import net.minecraft.world.level.dimension.DimensionType;
2930
import org.jetbrains.annotations.Contract;
@@ -35,7 +36,7 @@
3536
* It is not possible to access the registry from the client.
3637
*
3738
* @since 0.1.0
38-
* @see #from(MinecraftServer) to get an instance.
39+
* @see #from(MinecraftServer)
3940
*/
4041
public interface DynamicDimensionRegistry {
4142
/**
@@ -69,8 +70,8 @@ public interface DynamicDimensionRegistry {
6970
/**
7071
* Returns whether a level and dimension with the given ID can be deleted.
7172
*
72-
* @param id The ID of the level/dimension.
73-
* @return {@code true} if the level and dimension are dynamic and can be deleted, {@code false} otherwise.
73+
* @param id The ID of the dimension.
74+
* @return {@code true} if the dimension is dynamic and can be deleted, {@code false} otherwise.
7475
* @since 0.1.0
7576
*/
7677
boolean canDeleteDimension(@NotNull ResourceLocation id);
@@ -79,48 +80,63 @@ public interface DynamicDimensionRegistry {
7980
* Returns whether a level and dimension with the given ID can be created.
8081
*
8182
* @param id The ID of the level/dimension.
82-
* @return {@code true} if the level and dimension are dynamic and can be created, {@code false} otherwise.
83+
* @return {@code true} if a dynamic dimension can be created with the given id, {@code false} otherwise.
8384
* @since 0.6.0
8485
*/
8586
boolean canCreateDimension(@NotNull ResourceLocation id);
8687

8788
/**
8889
* Registers a new dimension and updates all clients with the new dimension.
89-
* If world data already exists for this dimension it may be deleted
90-
* NOTE: The dimension may not be loaded until the next tick.
90+
* If world data already exists for this dimension it will be overwritten.
9191
*
9292
* @param chunkGenerator The chunk generator.
9393
* @param id The ID of the dimension.
9494
* This ID must be unique and unused in the {@link net.minecraft.core.registries.Registries#DIMENSION_TYPE} registry and the {@link net.minecraft.world.level.levelgen.WorldDimensions#dimensions()} registry.
9595
* @param type The dimension type.
96-
* @return whether a dimension with the given id was created
96+
* @return the server level of the new dimension if successful, {@code null} otherwise.
97+
* @see #loadDynamicDimension(ResourceLocation, ChunkGenerator, DimensionType) if you want to load previous data
98+
* @implNote The dimension may not be loaded until the next tick.
9799
* @since 0.6.0
98100
*/
99-
boolean createDynamicDimension(@NotNull ResourceLocation id, @NotNull ChunkGenerator chunkGenerator, @NotNull DimensionType type);
101+
@Nullable ServerLevel createDynamicDimension(@NotNull ResourceLocation id, @NotNull ChunkGenerator chunkGenerator, @NotNull DimensionType type);
100102

101103
/**
102104
* Registers a new dimension and updates all clients with the new dimension.
103-
* If world data already exists for this dimension it will be used, otherwise it will be generated
104-
* NOTE: The dimension will not be loaded until the next tick.
105+
* If world data already exists for this dimension it will be used, otherwise it will be created.
105106
*
106107
* @param chunkGenerator The chunk generator.
107108
* @param id The ID of the dimension.
108-
* This ID must be unique and unused in the {@link net.minecraft.core.registries.Registries#DIMENSION_TYPE} registry and the {@link net.minecraft.world.level.levelgen.WorldDimensions#dimensions()} registry.
109+
* This ID must be unique and unused in the {@link net.minecraft.core.registries.Registries#DIMENSION_TYPE dimension type} registry
110+
* and the {@link net.minecraft.world.level.levelgen.WorldDimensions#dimensions() dimensions} registry.
109111
* @param type The dimension type.
110-
* @return whether a dimension with the given id was created
112+
* @return the server level of the new dimension if successful, {@code null} otherwise.
113+
* @implNote The dimension may not be loaded until the next tick.
111114
* @since 0.6.0
112115
*/
113-
boolean loadDynamicDimension(@NotNull ResourceLocation id, @NotNull ChunkGenerator chunkGenerator, @NotNull DimensionType type);
116+
@Nullable ServerLevel loadDynamicDimension(@NotNull ResourceLocation id, @NotNull ChunkGenerator chunkGenerator, @NotNull DimensionType type);
114117

115118
/**
116-
* Removes a dynamic dimension from the server.
119+
* Deletes a dynamic dimension from the server.
117120
* This may delete the dimension files permanently.
118-
* Players will be removed from the dimension using the provided player remover.
121+
* Remaining players will be removed from the dimension using the provided player remover.
119122
*
120123
* @param id The ID of the dimension.
121124
* @param remover The method to remove players from the dimension.
122-
* @return whether a dimension with the given id was removed
123-
* @since 0.1.0
125+
* @return whether a dimension with the given id was deleted
126+
* @implNote The dimension may not be deleted until the next tick.
127+
* @since 0.7.0
128+
*/
129+
boolean deleteDynamicDimension(@NotNull ResourceLocation id, @Nullable PlayerRemover remover);
130+
131+
/**
132+
* Removes a dynamic dimension from the server, saving the level to disk.
133+
* Remaining players will be removed from the dimension using the provided player remover.
134+
*
135+
* @param id The ID of the dimension.
136+
* @param remover The method to remove players from the dimension.
137+
* @return whether a dimension with the given id was unloaded
138+
* @implNote The dimension may not be unloaded until the next tick.
139+
* @since 0.7.0
124140
*/
125-
boolean removeDynamicDimension(@NotNull ResourceLocation id, @Nullable PlayerRemover remover);
141+
boolean unloadDynamicDimension(@NotNull ResourceLocation id, @Nullable PlayerRemover remover);
126142
}

common/src/main/java/dev/galacticraft/dynamicdimensions/api/PlayerRemover.java

+26
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,40 @@
2222

2323
package dev.galacticraft.dynamicdimensions.api;
2424

25+
import net.minecraft.core.BlockPos;
26+
import net.minecraft.network.chat.Component;
2527
import net.minecraft.server.MinecraftServer;
28+
import net.minecraft.server.level.ServerLevel;
2629
import net.minecraft.server.level.ServerPlayer;
30+
import net.minecraft.world.level.storage.LevelData;
2731

2832
/**
2933
* Removes players from a {@link net.minecraft.world.level.Level}.
3034
*/
3135
@FunctionalInterface
3236
public interface PlayerRemover {
37+
/**
38+
* Attempts to bring players to their personal spawn point, otherwise to the default (overworld) spawn point.
39+
*/
40+
PlayerRemover DEFAULT = (server, player) -> {
41+
player.sendSystemMessage(Component.translatable("command.dynamicdimensions.delete.removed", player.serverLevel().dimension().location()), true);
42+
ServerLevel level = server.getLevel(player.getRespawnDimension());
43+
if (level != null && level != player.serverLevel()) {
44+
BlockPos pos = player.getRespawnPosition();
45+
if (pos != null) {
46+
player.teleportTo(level, pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, player.getYRot(), player.getXRot());
47+
} else {
48+
LevelData levelData = level.getLevelData();
49+
player.teleportTo(level, levelData.getXSpawn() + 0.5, levelData.getYSpawn(), levelData.getZSpawn() + 0.5, player.getYRot(), player.getXRot());
50+
}
51+
} else {
52+
level = server.overworld();
53+
LevelData levelData = level.getLevelData();
54+
player.teleportTo(level, levelData.getXSpawn() + 0.5, levelData.getYSpawn(), levelData.getZSpawn() + 0.5, player.getYRot(), player.getXRot());
55+
}
56+
player.setDeltaMovement(0.0, 0.0, 0.0);
57+
};
58+
3359
/**
3460
* Called when a player must be removed from the level.
3561
* May cause unexpected behaviour if the player is not actually removed from the level.

common/src/main/java/dev/galacticraft/dynamicdimensions/impl/Constants.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,6 @@ public interface Constants {
3333
Logger LOGGER = LoggerFactory.getLogger(MOD_ID);
3434
DynamicDimensionsConfig CONFIG = Services.PLATFORM.getConfig();
3535

36-
ResourceLocation CREATE_WORLD_PACKET = new ResourceLocation(MOD_ID, "create_world");
37-
ResourceLocation DELETE_WORLD_PACKET = new ResourceLocation(MOD_ID, "delete_world");
36+
ResourceLocation CREATE_DIMENSION_PACKET = new ResourceLocation(MOD_ID, "create_dimension");
37+
ResourceLocation REMOVE_DIMENSION_PACKET = new ResourceLocation(MOD_ID, "remove_dimension");
3838
}

common/src/main/java/dev/galacticraft/dynamicdimensions/impl/accessor/PrimaryLevelDataAccessor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@
3434
*/
3535
@ApiStatus.Internal
3636
public interface PrimaryLevelDataAccessor {
37-
void setDynamicList(@NotNull List<ResourceKey<Level>> dynamicDimensions);
37+
void dynamicDimensions$setDynamicList(@NotNull List<ResourceKey<Level>> dynamicDimensions);
3838
}

common/src/main/java/dev/galacticraft/dynamicdimensions/impl/client/network/DynamicDimensionsS2CPacketReceivers.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@
3737

3838
public final class DynamicDimensionsS2CPacketReceivers {
3939
public static void registerReceivers() {
40-
PlayPackets.registerClientReceiver(Constants.CREATE_WORLD_PACKET, (client, handler, buf, responseSender) -> createDynamicWorld(client, handler, buf));
41-
PlayPackets.registerClientReceiver(Constants.DELETE_WORLD_PACKET, (client, handler, buf, responseSender) -> deleteDynamicWorld(client, handler, buf));
40+
PlayPackets.registerClientReceiver(Constants.CREATE_DIMENSION_PACKET, (client, handler, buf, responseSender) -> createDynamicDimension(client, handler, buf));
41+
PlayPackets.registerClientReceiver(Constants.REMOVE_DIMENSION_PACKET, (client, handler, buf, responseSender) -> removeDynamicDimension(client, handler, buf));
4242
}
4343

44-
private static void createDynamicWorld(@NotNull Minecraft client, @NotNull ClientPacketListener handler, @NotNull FriendlyByteBuf buf) {
44+
private static void createDynamicDimension(@NotNull Minecraft client, @NotNull ClientPacketListener handler, @NotNull FriendlyByteBuf buf) {
4545
ResourceLocation id = buf.readResourceLocation();
4646
int rawId = buf.readInt();
4747
DimensionType type = DimensionType.DIRECT_CODEC.decode(NbtOps.INSTANCE, buf.readNbt()).get().orThrow().getFirst();
@@ -51,7 +51,7 @@ private static void createDynamicWorld(@NotNull Minecraft client, @NotNull Clien
5151
});
5252
}
5353

54-
private static void deleteDynamicWorld(@NotNull Minecraft client, @NotNull ClientPacketListener handler, @NotNull FriendlyByteBuf buf) {
54+
private static void removeDynamicDimension(@NotNull Minecraft client, @NotNull ClientPacketListener handler, @NotNull FriendlyByteBuf buf) {
5555
ResourceLocation id = buf.readResourceLocation();
5656
client.execute(() -> {
5757
RegistryUtil.unregister(handler.registryAccess().registryOrThrow(Registries.DIMENSION_TYPE), id);

0 commit comments

Comments
 (0)