add: Persistent gamerule per world.

Signed-off-by: 秋雨落 <i@rain.cx>
This commit is contained in:
秋雨落 committed 2024-09-18 14:45:16 +08:00
1 parent a7e564d709
commit 40d3e8cf54
3 files changed
+63 -17

No files matched your search

@@ -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();
}
@@ -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<RegistryKey<World>, 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<ServerCommandSource> serverCommandSourceCommandDispatcher, CommandRegistryAccess commandRegistryAccess, CommandManager.RegistrationEnvironment registrationEnvironment) {
serverCommandSourceCommandDispatcher.register(
LiteralArgumentBuilder.<ServerCommandSource>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> 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<World> key){
return RoomWorldDataLoader.get(serverSupplier.get().getWorld(key)).getGameRules();
}
}
@@ -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<RoomWorldDataLoader> 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();
}
}