From e4d8a6279cbcbd748a769a104e592e7189477944 Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Wed, 6 Jan 2021 00:35:50 -0800 Subject: [PATCH] Implement Keyed on World --- .../0281-Implement-Keyed-on-World.patch | 164 ++++++++++++++++++ .../0693-Implement-Keyed-on-World.patch | 110 ++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 Spigot-API-Patches/0281-Implement-Keyed-on-World.patch create mode 100644 Spigot-Server-Patches/0693-Implement-Keyed-on-World.patch diff --git a/Spigot-API-Patches/0281-Implement-Keyed-on-World.patch b/Spigot-API-Patches/0281-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..73d4fbf49e --- /dev/null +++ b/Spigot-API-Patches/0281-Implement-Keyed-on-World.patch @@ -0,0 +1,164 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:10 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java +index 68101a322ffab8ec28843386b79b8079576fa720..5f7208196684d9c8373df28b7cfb5f9e21baa41e 100644 +--- a/src/main/java/org/bukkit/Bukkit.java ++++ b/src/main/java/org/bukkit/Bukkit.java +@@ -639,6 +639,18 @@ public final class Bukkit { + public static World getWorld(@NotNull UUID uid) { + return server.getWorld(uid); + } ++ // Paper start ++ /** ++ * Gets the world from the given NamespacedKey ++ * ++ * @param worldKey the NamespacedKey of the world to retrieve ++ * @return a world with the given NamespacedKey, or null if none exists ++ */ ++ @Nullable ++ public static World getWorld(@NotNull NamespacedKey worldKey) { ++ return server.getWorld(worldKey); ++ } ++ // Paper end + + /** + * Gets the map from the given item ID. +diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java +index a79fa08b9e6fb924b2da933eb6e4b365d14d938d..f3e27d2d02a9407bb1b091b8c1125ad5abf99e55 100644 +--- a/src/main/java/org/bukkit/Server.java ++++ b/src/main/java/org/bukkit/Server.java +@@ -541,6 +541,17 @@ public interface Server extends PluginMessageRecipient, net.kyori.adventure.audi + @Nullable + public World getWorld(@NotNull UUID uid); + ++ // Paper start ++ /** ++ * Gets the world from the given NamespacedKey ++ * ++ * @param worldKey the NamespacedKey of the world to retrieve ++ * @return a world with the given NamespacedKey, or null if none exists ++ */ ++ @Nullable ++ public World getWorld(@NotNull NamespacedKey worldKey); ++ // Paper end ++ + /** + * Gets the map from the given item ID. + * +diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java +index 3c50a10fda033c139993ed5465a92f95d5b10c17..064497506e6a5ab89ca43b99968ca79d51d67c46 100644 +--- a/src/main/java/org/bukkit/World.java ++++ b/src/main/java/org/bukkit/World.java +@@ -43,7 +43,7 @@ import org.jetbrains.annotations.Nullable; + /** + * Represents a world, which may contain entities, chunks and blocks + */ +-public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience { // Paper ++public interface World extends PluginMessageRecipient, Metadatable, net.kyori.adventure.audience.ForwardingAudience, Keyed { // Paper + + // Paper start + /** +@@ -829,6 +829,15 @@ public interface World extends PluginMessageRecipient, Metadatable, net.kyori.ad + + @NotNull + java.util.concurrent.CompletableFuture getChunkAtAsync(int x, int z, boolean gen, boolean urgent); ++ ++ /** ++ * Get the world's key ++ * ++ * @return the world's key ++ */ ++ @NotNull ++ @Override ++ NamespacedKey getKey(); + // Paper end + + /** +diff --git a/src/main/java/org/bukkit/WorldCreator.java b/src/main/java/org/bukkit/WorldCreator.java +index 6e6945dd4c770be04ec09da3958fae751717527a..3802bf39c2b8330ab64f90f91c88741500caaa64 100644 +--- a/src/main/java/org/bukkit/WorldCreator.java ++++ b/src/main/java/org/bukkit/WorldCreator.java +@@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; + * Represents various types of options that may be used to create a world. + */ + public class WorldCreator { ++ private final NamespacedKey key; // Paper + private final String name; + private long seed; + private World.Environment environment = World.Environment.NORMAL; +@@ -26,13 +27,67 @@ public class WorldCreator { + * @param name Name of the world that will be created + */ + public WorldCreator(@NotNull String name) { +- if (name == null) { +- throw new IllegalArgumentException("World name cannot be null"); +- } ++ // Paper start ++ this(name, NamespacedKey.minecraft(name)); ++ } + +- this.name = name; ++ /** ++ * Creates an empty WorldCreator for the given world name and key ++ * ++ * @param levelName LevelName of the world that will be created ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ public WorldCreator(@NotNull String levelName, @NotNull NamespacedKey worldKey) { ++ if (levelName == null || worldKey == null) { ++ throw new IllegalArgumentException("World name and key cannot be null"); ++ } ++ this.name = levelName; + this.seed = (new Random()).nextLong(); ++ this.key = worldKey; ++ } ++ ++ /** ++ * Creates an empty WorldCreator for the given key. ++ * LevelName will be the Key part of the NamespacedKey. ++ * ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ public WorldCreator(@NotNull NamespacedKey worldKey) { ++ this(worldKey.getKey(), worldKey); ++ } ++ ++ /** ++ * Gets the key for this WorldCreator ++ * ++ * @return the key ++ */ ++ @NotNull ++ public NamespacedKey key() { ++ return key; ++ } ++ ++ /** ++ * Creates an empty WorldCreator for the given world name and key ++ * ++ * @param levelName LevelName of the world that will be created ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ @NotNull ++ public static WorldCreator ofNameAndKey(@NotNull String levelName, @NotNull NamespacedKey worldKey) { ++ return new WorldCreator(levelName, worldKey); ++ } ++ ++ /** ++ * Creates an empty WorldCreator for the given key. ++ * LevelName will be the Key part of the NamespacedKey. ++ * ++ * @param worldKey NamespacedKey of the world that will be created ++ */ ++ @NotNull ++ public static WorldCreator ofKey(@NotNull NamespacedKey worldKey) { ++ return new WorldCreator(worldKey); + } ++ // Paper end + + /** + * Copies the options from the specified world diff --git a/Spigot-Server-Patches/0693-Implement-Keyed-on-World.patch b/Spigot-Server-Patches/0693-Implement-Keyed-on-World.patch new file mode 100644 index 0000000000..192466a7f3 --- /dev/null +++ b/Spigot-Server-Patches/0693-Implement-Keyed-on-World.patch @@ -0,0 +1,110 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Wed, 6 Jan 2021 00:34:04 -0800 +Subject: [PATCH] Implement Keyed on World + + +diff --git a/src/main/java/net/minecraft/server/IRegistry.java b/src/main/java/net/minecraft/server/IRegistry.java +index 6c7caef36b484a16b62977b5495247588c34dc2b..eb578c2f3e0193f18143d7cc0e38edc2e4a32d7a 100644 +--- a/src/main/java/net/minecraft/server/IRegistry.java ++++ b/src/main/java/net/minecraft/server/IRegistry.java +@@ -57,7 +57,7 @@ public abstract class IRegistry implements Codec, Keyable, Registry { + public static final ResourceKey> I = a("loot_function_type"); + public static final ResourceKey> J = a("loot_condition_type"); + public static final ResourceKey> K = a("dimension_type"); +- public static final ResourceKey> L = a("dimension"); ++ public static final ResourceKey> L = a("dimension"); public static final ResourceKey> getWorldRegistry() { return L; } // Paper - OBFHELPER + public static final ResourceKey> M = a("dimension"); + public static final IRegistry SOUND_EVENT = a(IRegistry.g, () -> { + return SoundEffects.ENTITY_ITEM_PICKUP; +@@ -266,9 +266,9 @@ public abstract class IRegistry implements Codec, Keyable, Registry { + MinecraftKey minecraftkey = resourcekey.a(); + + IRegistry.a.put(minecraftkey, supplier); +- IRegistryWritable iregistrywritable = IRegistry.e; ++ IRegistryWritable iregistrywritable = IRegistry.e; // Paper - decompile fix + +- return (IRegistryWritable) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); ++ return (R) iregistrywritable.a(resourcekey, (Object) r0, lifecycle); // Paper - decompile fix + } + + protected IRegistry(ResourceKey> resourcekey, Lifecycle lifecycle) { +@@ -355,11 +355,11 @@ public abstract class IRegistry implements Codec, Keyable, Registry { + } + + public static T a(IRegistry iregistry, MinecraftKey minecraftkey, T t0) { +- return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); ++ return ((IRegistryWritable) iregistry).a(ResourceKey.a(iregistry.b, minecraftkey), t0, Lifecycle.stable()); // Paper - decompile fix + } + + public static T a(IRegistry iregistry, int i, String s, T t0) { +- return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); ++ return ((IRegistryWritable) iregistry).a(i, ResourceKey.a(iregistry.b, new MinecraftKey(s)), t0, Lifecycle.stable()); // Paper - decompile fix + } + + static { +diff --git a/src/main/java/net/minecraft/server/ResourceKey.java b/src/main/java/net/minecraft/server/ResourceKey.java +index b35f0340b15fb22e979eb4343537b105281295f4..09781906d1a15560836392ebb8eacb6f3db94958 100644 +--- a/src/main/java/net/minecraft/server/ResourceKey.java ++++ b/src/main/java/net/minecraft/server/ResourceKey.java +@@ -11,6 +11,7 @@ public class ResourceKey { + private final MinecraftKey b; + private final MinecraftKey c; + ++ public static ResourceKey newResourceKey(ResourceKey> registryKey, MinecraftKey minecraftKey) { return a(registryKey, minecraftKey); } // Paper - OBFHELPER + public static ResourceKey a(ResourceKey> resourcekey, MinecraftKey minecraftkey) { + return a(resourcekey.c, minecraftkey); + } +@@ -40,6 +41,7 @@ public class ResourceKey { + return this.b.equals(resourcekey.a()); + } + ++ public MinecraftKey getLocation() { return a(); } // Paper - OBFHELPER + public MinecraftKey a() { + return this.c; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index f84d879ef982ee4adcaa43e7c3db1f1003961983..1398b18409db3b3741ce199ee7156a2dfe2cc96c 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -1154,7 +1154,7 @@ public final class CraftServer implements Server { + chunkgenerator = worlddimension.c(); + } + +- ResourceKey worldKey = ResourceKey.a(IRegistry.L, new MinecraftKey(name.toLowerCase(java.util.Locale.ENGLISH))); ++ ResourceKey worldKey = ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), new MinecraftKey(creator.key().getNamespace().toLowerCase(java.util.Locale.ENGLISH), creator.key().getKey().toLowerCase(java.util.Locale.ENGLISH))); // Paper + + WorldServer internal = (WorldServer) new WorldServer(console, console.executorService, worldSession, worlddata, worldKey, dimensionmanager, getServer().worldLoadListenerFactory.create(11), + chunkgenerator, worlddata.getGeneratorSettings().isDebugWorld(), j, creator.environment() == Environment.NORMAL ? list : ImmutableList.of(), true, creator.environment(), generator); +@@ -1245,6 +1245,15 @@ public final class CraftServer implements Server { + return null; + } + ++ // Paper start ++ @Override ++ public World getWorld(NamespacedKey worldKey) { ++ WorldServer worldServer = console.getWorldServer(ResourceKey.newResourceKey(IRegistry.getWorldRegistry(), CraftNamespacedKey.toMinecraft(worldKey))); ++ if (worldServer == null) return null; ++ return worldServer.getWorld(); ++ } ++ // Paper end ++ + public void addWorld(World world) { + // Check if a World already exists with the UID. + if (getWorld(world.getUID()) != null) { +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index d9b683264da17ba65409e2b976c885875fe09c89..cade3ed6079011f44eba613dece3d69ec18f8f04 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -2585,6 +2585,11 @@ public class CraftWorld implements World { + return CompletableFuture.completedFuture(chunk == null ? null : chunk.getBukkitChunk()); + }, MinecraftServer.getServer()); + } ++ ++ @Override ++ public org.bukkit.NamespacedKey getKey() { ++ return org.bukkit.craftbukkit.util.CraftNamespacedKey.fromMinecraft(world.getDimensionKey().getLocation()); ++ } + // Paper end + + // Spigot start