From 40d3e8cf54cce868919354da8d6d46fb891394f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A7=8B=E9=9B=A8=E8=90=BD?= Date: Wed, 18 Sep 2024 14:45:16 +0800 Subject: [PATCH] add: Persistent gamerule per world. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 秋雨落 --- .../mixin/server/subserver/WorldMixin.java | 6 +- .../io/ib67/sfcraft/module/RoomModule.java | 18 ++---- .../room/data/RoomWorldDataLoader.java | 56 +++++++++++++++++++ 3 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 src/main/java/io/ib67/sfcraft/room/data/RoomWorldDataLoader.java diff --git a/src/main/java/io/ib67/sfcraft/mixin/server/subserver/WorldMixin.java b/src/main/java/io/ib67/sfcraft/mixin/server/subserver/WorldMixin.java index cc333e6..ee735c8 100644 --- a/src/main/java/io/ib67/sfcraft/mixin/server/subserver/WorldMixin.java +++ b/src/main/java/io/ib67/sfcraft/mixin/server/subserver/WorldMixin.java @@ -1,7 +1,5 @@ package io.ib67.sfcraft.mixin.server.subserver; -import com.llamalad7.mixinextras.sugar.Local; -import com.llamalad7.mixinextras.sugar.ref.LocalRef; import io.ib67.sfcraft.SFCraft; import io.ib67.sfcraft.module.RoomModule; import net.minecraft.registry.DynamicRegistryManager; @@ -12,13 +10,11 @@ import net.minecraft.world.GameRules; import net.minecraft.world.MutableWorldProperties; import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.level.LevelProperties; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.function.Supplier; @@ -40,7 +36,7 @@ public abstract class WorldMixin { int maxChainedNeighborUpdates, CallbackInfo ci) { var id = registryRef.getValue(); if (id.getNamespace().equals("sfcraft")) { // room - customGameRule = SFCraft.getInjector().getInstance(RoomModule.class).readGameRuleForRoom(id); + customGameRule = SFCraft.getInjector().getInstance(RoomModule.class).readGameRuleForRoom(registryRef); } else { customGameRule = properties.getGameRules(); } diff --git a/src/main/java/io/ib67/sfcraft/module/RoomModule.java b/src/main/java/io/ib67/sfcraft/module/RoomModule.java index 73e8189..ef7ca42 100644 --- a/src/main/java/io/ib67/sfcraft/module/RoomModule.java +++ b/src/main/java/io/ib67/sfcraft/module/RoomModule.java @@ -10,6 +10,7 @@ import io.ib67.sfcraft.config.SFConfig; import io.ib67.sfcraft.inject.MinecraftServerSupplier; import io.ib67.sfcraft.room.RequestedRoom; import io.ib67.sfcraft.registry.RoomRegistry; +import io.ib67.sfcraft.room.data.RoomWorldDataLoader; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import lombok.SneakyThrows; @@ -73,18 +74,13 @@ public class RoomModule extends ServerModule { for (Pair, BlockPos> registryKeyBlockPosPair : pregenQueue) { var world = serverSupplier.get().getWorld(registryKeyBlockPosPair.getLeft()); if (world == null) { - log.warn("Cannot find world " + registryKeyBlockPosPair.getLeft()); + log.warn("Cannot find world {}", registryKeyBlockPosPair.getLeft()); continue; } world.getChunkManager().addTicket(ChunkTicketType.START, new ChunkPos(registryKeyBlockPosPair.getRight()), 64, Unit.INSTANCE); } } - @Override - public void onDisable() { - //todo persistence of gameRulesPerRoom - } - private void registerCommand(CommandDispatcher serverCommandSourceCommandDispatcher, CommandRegistryAccess commandRegistryAccess, CommandManager.RegistrationEnvironment registrationEnvironment) { serverCommandSourceCommandDispatcher.register( LiteralArgumentBuilder.literal("reco") @@ -103,7 +99,7 @@ public class RoomModule extends ServerModule { networkHandler.send(new StoreCookieS2CPacket(ROOM_COOKIE, EMPTY), PacketCallbacks.always(() -> { networkHandler.sendPacket(new ServerTransferS2CPacket(config.domain, serverSupplier.get().getServerPort())); })); - return 0; + return 1; } @SneakyThrows @@ -160,9 +156,7 @@ public class RoomModule extends ServerModule { private static SecretKey getKeyFromPassword(String password, String salt) { SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256); - SecretKey secret = new SecretKeySpec(factory.generateSecret(spec) - .getEncoded(), "AES"); - return secret; + return new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES"); } public void enqueuePregen(RegistryKey world, BlockPos spawnPos) { @@ -184,7 +178,7 @@ public class RoomModule extends ServerModule { return uuidMapper.get(virtual); } - public GameRules readGameRuleForRoom(Identifier identifier){ - return gameRulesPerRoom.computeIfAbsent(identifier, k -> new GameRules()); + public GameRules readGameRuleForRoom(RegistryKey key){ + return RoomWorldDataLoader.get(serverSupplier.get().getWorld(key)).getGameRules(); } } diff --git a/src/main/java/io/ib67/sfcraft/room/data/RoomWorldDataLoader.java b/src/main/java/io/ib67/sfcraft/room/data/RoomWorldDataLoader.java new file mode 100644 index 0000000..f99fae9 --- /dev/null +++ b/src/main/java/io/ib67/sfcraft/room/data/RoomWorldDataLoader.java @@ -0,0 +1,56 @@ +package io.ib67.sfcraft.room.data; + +import com.mojang.serialization.Dynamic; +import lombok.Getter; +import net.minecraft.datafixer.DataFixTypes; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtOps; +import net.minecraft.registry.RegistryWrapper; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.Identifier; +import net.minecraft.world.GameRules; +import net.minecraft.world.PersistentState; + +import java.util.Objects; + +@Getter +public class RoomWorldDataLoader extends PersistentState { + + private static final Identifier ID = Identifier.of("sfcraft", "room_data"); + private static final Type TYPE = new Type<>(RoomWorldDataLoader::new, RoomWorldDataLoader::readNbt, DataFixTypes.LEVEL); + + private static final String TAG_GAME_RULES = "gameRules"; + + private final GameRules gameRules; + + public RoomWorldDataLoader() { + this(new GameRules()); + } + + public RoomWorldDataLoader(GameRules gameRules) { + this.gameRules = gameRules; + } + + public static RoomWorldDataLoader get(ServerWorld world) { + Objects.requireNonNull(world); + var state = world.getPersistentStateManager().getOrCreate(TYPE, ID.toString()); + state.markDirty(); + return state; + } + + @Override + public NbtCompound writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registry) { + nbt.put(TAG_GAME_RULES, gameRules.toNbt()); + return nbt; + } + + private static RoomWorldDataLoader readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup registry) { + if (nbt.contains(TAG_GAME_RULES)) { + var c = nbt.getCompound(TAG_GAME_RULES); + var dynamic = new Dynamic<>(NbtOps.INSTANCE, c); + var rule = new GameRules(dynamic); + return new RoomWorldDataLoader(rule); + } + return new RoomWorldDataLoader(); + } +}