Skip to content

Commit e406ca9

Browse files
committed
change: fail a bit more gracefully
1 parent 5b02a68 commit e406ca9

File tree

2 files changed

+41
-40
lines changed

2 files changed

+41
-40
lines changed

lib/src/main/java/dev/galacticraft/dynworlds/api/DynamicLevelRegistry.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import net.minecraft.world.level.dimension.DimensionType;
2727
import net.minecraft.world.level.dimension.LevelStem;
2828
import net.minecraft.world.level.levelgen.WorldGenSettings;
29+
import org.jetbrains.annotations.NotNull;
2930

3031
/**
3132
* The registry for dynamic levels.
@@ -45,7 +46,7 @@ public interface DynamicLevelRegistry {
4546
* @param type The dimension type of the level.
4647
* @since 0.1.0
4748
*/
48-
void addDynamicLevel(ResourceLocation id, LevelStem stem, DimensionType type);
49+
boolean addDynamicLevel(@NotNull ResourceLocation id, @NotNull LevelStem stem, @NotNull DimensionType type);
4950

5051
/**
5152
* Tests if a level with the given ID exists.
@@ -55,7 +56,7 @@ public interface DynamicLevelRegistry {
5556
* If the level exists, you should not call {@link #addDynamicLevel(ResourceLocation, LevelStem, DimensionType)} with the same ID.
5657
* @since 0.1.0
5758
*/
58-
boolean levelExists(ResourceLocation id);
59+
boolean levelExists(@NotNull ResourceLocation id);
5960

6061
/**
6162
* Returns whether a level with the given ID can be created.
@@ -64,7 +65,7 @@ public interface DynamicLevelRegistry {
6465
* @return {@code true} if the level can be created, {@code false} otherwise.
6566
* @since 0.1.0
6667
*/
67-
boolean canCreateLevel(ResourceLocation id);
68+
boolean canCreateLevel(@NotNull ResourceLocation id);
6869

6970
/**
7071
* Returns whether a level with the given ID can be deleted.
@@ -73,7 +74,7 @@ public interface DynamicLevelRegistry {
7374
* @return {@code true} if the level can be deleted, {@code false} otherwise.
7475
* @since 0.1.0
7576
*/
76-
boolean canDestroyLevel(ResourceLocation id);
77+
boolean canDestroyLevel(@NotNull ResourceLocation id);
7778

7879
/**
7980
* Erases a dynamic level from existence.
@@ -83,5 +84,5 @@ public interface DynamicLevelRegistry {
8384
* @param remover The method to remove players from the level.
8485
* @since 0.1.0
8586
*/
86-
void removeDynamicLevel(ResourceLocation id, PlayerRemover remover);
87+
boolean removeDynamicLevel(@NotNull ResourceLocation id, @NotNull PlayerRemover remover);
8788
}

lib/src/main/java/dev/galacticraft/dynworlds/impl/mixin/MinecraftServerMixin.java

+35-35
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@
5858
import net.minecraft.world.level.storage.WorldData;
5959
import org.apache.commons.io.FileUtils;
6060
import org.jetbrains.annotations.NotNull;
61-
import org.jetbrains.annotations.Nullable;
6261
import org.spongepowered.asm.mixin.Final;
6362
import org.spongepowered.asm.mixin.Mixin;
6463
import org.spongepowered.asm.mixin.Shadow;
@@ -221,21 +220,19 @@ private void removeWorlds(BooleanSupplier shouldKeepTicking, CallbackInfo ci) {
221220
}
222221

223222
@Override
224-
public void addDynamicLevel(ResourceLocation id, @NotNull LevelStem stem, DimensionType type) {
225-
if (!this.canCreateLevel(id)) {
226-
throw new IllegalArgumentException("World already exists!?");
227-
}
223+
public boolean addDynamicLevel(@NotNull ResourceLocation id, @NotNull LevelStem stem, @NotNull DimensionType type) {
224+
if (!this.canCreateLevel(id)) return false;
228225
((WritableRegistry<LevelStem>) this.getWorldData().worldGenSettings().dimensions()).register(ResourceKey.create(Registry.LEVEL_STEM_REGISTRY, id), stem, Lifecycle.stable());
229226
((ImmutableRegistryAccessAccessor) this.registryAccess()).unfreezeTypes(reg -> reg.register(ResourceKey.create(Registry.DIMENSION_TYPE_REGISTRY, id), type, Lifecycle.stable()));
230227

231-
ResourceKey<Level> worldKey = ResourceKey.create(Registry.DIMENSION_REGISTRY, id);
232-
DerivedLevelData properties = new DerivedLevelData(this.getWorldData(), this.getWorldData().overworldData());
233-
ServerLevel world = new ServerLevel(
228+
ResourceKey<Level> key = ResourceKey.create(Registry.DIMENSION_REGISTRY, id);
229+
DerivedLevelData data = new DerivedLevelData(this.getWorldData(), this.getWorldData().overworldData());
230+
ServerLevel level = new ServerLevel(
234231
(MinecraftServer) (Object) this,
235232
this.executor,
236233
this.storageSource,
237-
properties,
238-
worldKey,
234+
data,
235+
key,
239236
stem.typeHolder(),
240237
progressListenerFactory.create(10),
241238
stem.generator(),
@@ -246,71 +243,74 @@ public void addDynamicLevel(ResourceLocation id, @NotNull LevelStem stem, Dimens
246243
);
247244
ServerLevel overworld = this.overworld();
248245
assert overworld != null;
249-
overworld.getWorldBorder().addListener(new BorderChangeListener.DelegateBorderChangeListener(world.getWorldBorder()));
250-
world.getChunkSource().setSimulationDistance(((DistanceManagerAccessor) ((ServerChunkCacheAccessor) overworld.getChunkSource()).getDistanceManager()).getSimulationDistance());
251-
world.getChunkSource().setViewDistance(((ChunkMapAccessor) overworld.getChunkSource().chunkMap).getViewDistance());
246+
overworld.getWorldBorder().addListener(new BorderChangeListener.DelegateBorderChangeListener(level.getWorldBorder()));
247+
level.getChunkSource().setSimulationDistance(((DistanceManagerAccessor) ((ServerChunkCacheAccessor) overworld.getChunkSource()).getDistanceManager()).getSimulationDistance());
248+
level.getChunkSource().setViewDistance(((ChunkMapAccessor) overworld.getChunkSource().chunkMap).getViewDistance());
252249
if (stem.typeHolder() instanceof Holder.Reference<DimensionType>
253250
&& (stem.typeHolder().unwrap().right().isEmpty()
254251
|| stem.typeHolder().value() != type)) {
255252
((HolderReferenceInvoker<DimensionType>) stem.typeHolder()).callBind(stem.typeHolder().unwrapKey().get(), type);
256253
}
257254
((PrimaryLevelDataAccessor) this.getWorldData()).addDynamicLevel(id, stem);
258-
this.enqueuedCreatedWorlds.put(worldKey, world); //prevent comodification
255+
this.enqueuedCreatedWorlds.put(key, level); //prevent comodification
259256

260257
FriendlyByteBuf packetByteBuf = PacketByteBufs.create();
261258
packetByteBuf.writeResourceLocation(id);
262259
packetByteBuf.writeInt(this.registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).getId(type));
263260
packetByteBuf.writeNbt((CompoundTag) DimensionType.DIRECT_CODEC.encode(type, NbtOps.INSTANCE, new CompoundTag()).get().orThrow());
264261
this.getPlayerList().broadcastAll(new ClientboundCustomPayloadPacket(Constant.id("create_world"), packetByteBuf));
265262
this.reloadTags();
263+
return true;
266264
}
267265

268266
@Override
269-
public boolean levelExists(ResourceLocation id) {
267+
public boolean levelExists(@NotNull ResourceLocation id) {
270268
return this.levels.containsKey(ResourceKey.create(Registry.DIMENSION_REGISTRY, id))
271269
&& this.registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY).containsKey(id)
272270
|| this.getWorldData().worldGenSettings().dimensions().containsKey(id)
273271
|| ((PrimaryLevelDataAccessor) this.getWorldData()).getDynamicWorlds().containsKey(id);
274272
}
275273

276274
@Override
277-
public boolean canCreateLevel(ResourceLocation id) {
275+
public boolean canCreateLevel(@NotNull ResourceLocation id) {
278276
return Constant.CONFIG.allowWorldCreation() && !this.levelExists(id);
279277
}
280278

281279
@Override
282-
public boolean canDestroyLevel(ResourceLocation id) {
280+
public boolean canDestroyLevel(@NotNull ResourceLocation id) {
283281
return this.levelExists(id) && (Constant.CONFIG.deleteWorldsWithPlayers() || this.levels.get(ResourceKey.create(Registry.DIMENSION_REGISTRY, id)).players().size() == 0);
284282
}
285283

286284
@Override
287-
public void removeDynamicLevel(ResourceLocation id, @Nullable PlayerRemover remover) {
288-
if (!this.canDestroyLevel(id)) {
289-
throw new IllegalArgumentException("Cannot destroy world!");
290-
}
285+
public boolean removeDynamicLevel(@NotNull ResourceLocation id, @NotNull PlayerRemover remover) {
286+
if (!this.canDestroyLevel(id)) return false;
291287

292-
((PrimaryLevelDataAccessor) this.getWorldData()).removeDynamicLevel(id); //worst case, it'll just be gone on reload
293-
ResourceKey<Level> of = ResourceKey.create(Registry.DIMENSION_REGISTRY, id);
294-
for (ServerPlayer serverPlayerEntity : this.getPlayerList().getPlayers()) {
295-
if (serverPlayerEntity.level.dimension().equals(of)) {
296-
if (remover == null) {
297-
throw new IllegalArgumentException("Cannot remove world as it is currently loaded by a player!");
298-
} else {
299-
remover.removePlayer((MinecraftServer) (Object) this, serverPlayerEntity);
288+
ResourceKey<Level> key = ResourceKey.create(Registry.DIMENSION_REGISTRY, id);
289+
List<ServerPlayer> players = new ArrayList<>(this.levels.get(key).players()); // prevent comod
290+
if (!players.isEmpty()) {
291+
if (Constant.CONFIG.deleteWorldsWithPlayers()) {
292+
for (ServerPlayer player : players) {
293+
if (player.level.dimension().equals(key)) {
294+
remover.removePlayer((MinecraftServer) (Object) this, player);
295+
}
300296
}
297+
} else {
298+
return false;
301299
}
302300
}
303301

304-
this.enqueuedDestroyedWorlds.add(of);
302+
((PrimaryLevelDataAccessor) this.getWorldData()).removeDynamicLevel(id);
303+
this.enqueuedDestroyedWorlds.add(key);
304+
return true;
305305
}
306306

307307
private void reloadTags() {
308-
for (TagManager.LoadResult<?> registryTag : ((ReloadableServerResourcesAccessor) this.resources.managers()).getTagManager().getResult()) {
309-
if (registryTag.key() == Registry.DIMENSION_TYPE_REGISTRY) {
310-
Registry<DimensionType> dimensionTypes = this.registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
311-
dimensionTypes.resetTags();
308+
for (TagManager.LoadResult<?> result : ((ReloadableServerResourcesAccessor) this.resources.managers()).getTagManager().getResult()) {
309+
if (result.key() == Registry.DIMENSION_TYPE_REGISTRY) {
310+
Registry<DimensionType> types = this.registryAccess().registryOrThrow(Registry.DIMENSION_TYPE_REGISTRY);
311+
types.resetTags();
312312
//noinspection unchecked - we know that the registry is a registry of dimension types as the key is correct
313-
dimensionTypes.bindTags(((TagManager.LoadResult<DimensionType>) registryTag).tags().entrySet()
313+
types.bindTags(((TagManager.LoadResult<DimensionType>) result).tags().entrySet()
314314
.stream()
315315
.collect(Collectors.toUnmodifiableMap(entry -> TagKey.create(Registry.DIMENSION_TYPE_REGISTRY, entry.getKey()), entry -> (entry.getValue()).getValues())));
316316
break;

0 commit comments

Comments
 (0)