From caa16ca9f3e5f7ae477759103baefadab9dfe649 Mon Sep 17 00:00:00 2001 From: ABKQPO <93412322+ABKQPO@users.noreply.github.com> Date: Sun, 7 Jun 2026 22:23:31 +0800 Subject: [PATCH] fix permission --- .../GuideNhClientBridgeController.java | 16 +++++++- .../guidenh/guide/internal/GuideCommand.java | 7 ++++ .../GuideNhServerStructureAccess.java | 37 +++++++++++++++++++ ...hAe2BaseTileNetworkBatchServerHandler.java | 9 ++++- .../GuideNhAe2CableBatchServerHandler.java | 9 ++++- .../network/GuideNhCustomPayloadLimits.java | 2 + .../GuideNhRegionExportRequestMessage.java | 12 +++++- .../GuideNhRegionExportServerHandler.java | 11 ++++++ .../GuideNhStructureChunkAssembler.java | 14 +++++++ .../GuideNhStructureRequestHandler.java | 24 +++++++++++- 10 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/hfstudio/guidenh/guide/internal/structure/GuideNhServerStructureAccess.java diff --git a/src/main/java/com/hfstudio/guidenh/client/command/GuideNhClientBridgeController.java b/src/main/java/com/hfstudio/guidenh/client/command/GuideNhClientBridgeController.java index 1c9b352c..03c1923a 100644 --- a/src/main/java/com/hfstudio/guidenh/client/command/GuideNhClientBridgeController.java +++ b/src/main/java/com/hfstudio/guidenh/client/command/GuideNhClientBridgeController.java @@ -148,9 +148,23 @@ public CompletableFuture requestRegionExport(int x, int y, int z, int si int requestId = nextRegionExportRequestId.getAndIncrement(); CompletableFuture future = new CompletableFuture<>(); pendingRegionExports.put(requestId, future); + Minecraft minecraft = Minecraft.getMinecraft(); + EntityPlayer player = minecraft.thePlayer; + int dimensionId = player != null && player.worldObj != null && player.worldObj.provider != null + ? player.worldObj.provider.dimensionId + : 0; GuideNhNetwork.channel() .sendToServer( - new GuideNhRegionExportRequestMessage(requestId, x, y, z, sizeX, sizeY, sizeZ, includeEntities)); + new GuideNhRegionExportRequestMessage( + requestId, + dimensionId, + x, + y, + z, + sizeX, + sizeY, + sizeZ, + includeEntities)); return future; } diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideCommand.java b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideCommand.java index e3b6d25d..e3bfeeca 100644 --- a/src/main/java/com/hfstudio/guidenh/guide/internal/GuideCommand.java +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/GuideCommand.java @@ -11,6 +11,7 @@ import net.minecraft.util.ResourceLocation; import com.hfstudio.guidenh.guide.Guide; +import com.hfstudio.guidenh.guide.internal.structure.GuideNhServerStructureAccess; public class GuideCommand extends CommandBase { @@ -59,6 +60,12 @@ public void processCommand(ICommandSender sender, String[] args) throws CommandE .openGuide(player, guideId, null); } case "reload" -> { + if (!sender.canCommandSenderUseCommand( + GuideNhServerStructureAccess.STRUCTURE_PERMISSION_LEVEL, + getCommandName())) { + send(sender, GuidebookText.CommandStructurePermissionDenied); + return; + } boolean ok = GuideMEProxy.instance() .reloadResources(); if (ok) { diff --git a/src/main/java/com/hfstudio/guidenh/guide/internal/structure/GuideNhServerStructureAccess.java b/src/main/java/com/hfstudio/guidenh/guide/internal/structure/GuideNhServerStructureAccess.java new file mode 100644 index 00000000..781747fe --- /dev/null +++ b/src/main/java/com/hfstudio/guidenh/guide/internal/structure/GuideNhServerStructureAccess.java @@ -0,0 +1,37 @@ +package com.hfstudio.guidenh.guide.internal.structure; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.server.MinecraftServer; + +import com.hfstudio.guidenh.config.ModConfig; + +public class GuideNhServerStructureAccess { + + public static final String STRUCTURE_COMMAND_NAME = "guidenh"; + public static final int STRUCTURE_PERMISSION_LEVEL = 3; + + private GuideNhServerStructureAccess() {} + + public static boolean canUseSceneExport(EntityPlayerMP player) { + return isSceneExportEnabled() && (isSinglePlayerServer() || hasStructurePermission(player)); + } + + public static boolean hasStructurePermission(EntityPlayerMP player) { + return player != null && player.canCommandSenderUseCommand(STRUCTURE_PERMISSION_LEVEL, STRUCTURE_COMMAND_NAME); + } + + public static boolean isSceneExportEnabled() { + return ModConfig.ui.sceneExportEnabled; + } + + public static boolean isSameDimension(EntityPlayerMP player, int dimensionId) { + return player != null && player.worldObj != null + && player.worldObj.provider != null + && player.worldObj.provider.dimensionId == dimensionId; + } + + private static boolean isSinglePlayerServer() { + MinecraftServer server = MinecraftServer.getServer(); + return server != null && server.isSinglePlayer(); + } +} diff --git a/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2BaseTileNetworkBatchServerHandler.java b/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2BaseTileNetworkBatchServerHandler.java index 33f6698a..a20fc30b 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2BaseTileNetworkBatchServerHandler.java +++ b/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2BaseTileNetworkBatchServerHandler.java @@ -1,9 +1,11 @@ package com.hfstudio.guidenh.integration.ae2.network; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.WorldServer; +import com.hfstudio.guidenh.guide.internal.structure.GuideNhServerStructureAccess; import com.hfstudio.guidenh.integration.Mods; import com.hfstudio.guidenh.integration.ae2.Ae2BaseTileNetworkStreamPreview; @@ -17,6 +19,7 @@ public class GuideNhAe2BaseTileNetworkBatchServerHandler @Override public IMessage onMessage(GuideNhAe2BaseTileNetworkBatchRequestMessage message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; long corr = message.getCorrId(); int dim = message.getDim(); int[] xyz = message.getXyz(); @@ -25,7 +28,11 @@ public IMessage onMessage(GuideNhAe2BaseTileNetworkBatchRequestMessage message, n = Math.max(0, xyz.length / 3); } - if (!Mods.AE2.isModLoaded() || n <= 0 || n > GuideNhAe2BaseTileNetworkBatchRequestMessage.MAX_POSITIONS) { + if (player == null || !Mods.AE2.isModLoaded() + || !GuideNhServerStructureAccess.canUseSceneExport(player) + || !GuideNhServerStructureAccess.isSameDimension(player, dim) + || n <= 0 + || n > GuideNhAe2BaseTileNetworkBatchRequestMessage.MAX_POSITIONS) { return new GuideNhAe2BaseTileNetworkBatchReplyMessage(corr, new byte[0][]); } diff --git a/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2CableBatchServerHandler.java b/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2CableBatchServerHandler.java index 1ae3e3bb..8cc468bd 100644 --- a/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2CableBatchServerHandler.java +++ b/src/main/java/com/hfstudio/guidenh/integration/ae2/network/GuideNhAe2CableBatchServerHandler.java @@ -2,11 +2,13 @@ import java.io.IOException; +import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.WorldServer; import net.minecraftforge.common.util.ForgeDirection; +import com.hfstudio.guidenh.guide.internal.structure.GuideNhServerStructureAccess; import com.hfstudio.guidenh.integration.Mods; import com.hfstudio.guidenh.integration.ae2.Ae2CableBusPartStreamCodec; import com.hfstudio.guidenh.integration.ae2.Ae2CableBusSideStreams; @@ -25,6 +27,7 @@ public class GuideNhAe2CableBatchServerHandler @Override public IMessage onMessage(GuideNhAe2CableBatchRequestMessage message, MessageContext ctx) { + EntityPlayerMP player = ctx.getServerHandler().playerEntity; long corr = message.getCorrId(); int dim = message.getDim(); int[] xyz = message.getXyz(); @@ -33,7 +36,11 @@ public IMessage onMessage(GuideNhAe2CableBatchRequestMessage message, MessageCon n = Math.max(0, xyz.length / 3); } - if (!Mods.AE2.isModLoaded() || n <= 0 || n > GuideNhAe2CableBatchRequestMessage.MAX_POSITIONS) { + if (player == null || !Mods.AE2.isModLoaded() + || !GuideNhServerStructureAccess.canUseSceneExport(player) + || !GuideNhServerStructureAccess.isSameDimension(player, dim) + || n <= 0 + || n > GuideNhAe2CableBatchRequestMessage.MAX_POSITIONS) { return new GuideNhAe2CableBatchReplyMessage(corr, new byte[0], new byte[0], new int[0], new byte[0][]); } diff --git a/src/main/java/com/hfstudio/guidenh/network/GuideNhCustomPayloadLimits.java b/src/main/java/com/hfstudio/guidenh/network/GuideNhCustomPayloadLimits.java index f7d9557e..e199fb14 100644 --- a/src/main/java/com/hfstudio/guidenh/network/GuideNhCustomPayloadLimits.java +++ b/src/main/java/com/hfstudio/guidenh/network/GuideNhCustomPayloadLimits.java @@ -4,6 +4,8 @@ public class GuideNhCustomPayloadLimits { public static final int MAX_PAYLOAD_BYTES = 28 * 1024; public static final int MAX_STRUCTURE_BYTES_PER_PACKET = 27 * 1024; + public static final int MAX_STRUCTURE_TRANSFER_BYTES = 8 * 1024 * 1024; + public static final long STRUCTURE_TRANSFER_TTL_MILLIS = 30_000L; private GuideNhCustomPayloadLimits() {} } diff --git a/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportRequestMessage.java b/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportRequestMessage.java index 5fd33485..45ef69d8 100644 --- a/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportRequestMessage.java +++ b/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportRequestMessage.java @@ -6,6 +6,7 @@ public class GuideNhRegionExportRequestMessage implements IMessage { private int requestId; + private int dimensionId; private int x; private int y; private int z; @@ -16,9 +17,10 @@ public class GuideNhRegionExportRequestMessage implements IMessage { public GuideNhRegionExportRequestMessage() {} - public GuideNhRegionExportRequestMessage(int requestId, int x, int y, int z, int sizeX, int sizeY, int sizeZ, - boolean includeEntities) { + public GuideNhRegionExportRequestMessage(int requestId, int dimensionId, int x, int y, int z, int sizeX, int sizeY, + int sizeZ, boolean includeEntities) { this.requestId = requestId; + this.dimensionId = dimensionId; this.x = x; this.y = y; this.z = z; @@ -32,6 +34,10 @@ public int getRequestId() { return requestId; } + public int getDimensionId() { + return dimensionId; + } + public int getX() { return x; } @@ -63,6 +69,7 @@ public boolean isIncludeEntities() { @Override public void fromBytes(ByteBuf buf) { requestId = buf.readInt(); + dimensionId = buf.readInt(); x = buf.readInt(); y = buf.readInt(); z = buf.readInt(); @@ -75,6 +82,7 @@ public void fromBytes(ByteBuf buf) { @Override public void toBytes(ByteBuf buf) { buf.writeInt(requestId); + buf.writeInt(dimensionId); buf.writeInt(x); buf.writeInt(y); buf.writeInt(z); diff --git a/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportServerHandler.java b/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportServerHandler.java index 23ddce79..63f7805a 100644 --- a/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportServerHandler.java +++ b/src/main/java/com/hfstudio/guidenh/network/GuideNhRegionExportServerHandler.java @@ -8,6 +8,7 @@ import net.minecraft.util.AxisAlignedBB; import com.hfstudio.guidenh.guide.internal.item.RegionWandItem; +import com.hfstudio.guidenh.guide.internal.structure.GuideNhServerStructureAccess; import com.hfstudio.guidenh.guide.internal.structure.GuideStructureVolume; import cpw.mods.fml.common.network.simpleimpl.IMessage; @@ -22,6 +23,13 @@ public IMessage onMessage(GuideNhRegionExportRequestMessage message, MessageCont if (player == null) { return null; } + if (!GuideNhServerStructureAccess.canUseSceneExport(player)) { + GuideNhNetwork.channel() + .sendTo( + GuideNhRegionExportReplyMessage.error(message.getRequestId(), "Scene export is not allowed"), + player); + return null; + } try { String structureText = exportRegion(player, message); if (structureText == null) { @@ -50,6 +58,9 @@ private String exportRegion(EntityPlayerMP player, GuideNhRegionExportRequestMes || GuideStructureVolume.exceedsLimit(sizeX, sizeY, sizeZ, RegionWandItem.MAX_EXPORT_BLOCKS)) { return null; } + if (!GuideNhServerStructureAccess.isSameDimension(player, message.getDimensionId())) { + return null; + } int x = message.getX(); int y = message.getY(); int z = message.getZ(); diff --git a/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureChunkAssembler.java b/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureChunkAssembler.java index 5af965d4..d0ceaa16 100644 --- a/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureChunkAssembler.java +++ b/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureChunkAssembler.java @@ -8,6 +8,8 @@ public class GuideNhStructureChunkAssembler { private final byte[][] chunks; + private final long expiresAtMillis; + private boolean discarded; private int received; private int totalBytes; @@ -16,10 +18,14 @@ public GuideNhStructureChunkAssembler(int chunkCount) { throw new IllegalArgumentException("Invalid structure chunk count: " + chunkCount); } this.chunks = new byte[chunkCount][]; + this.expiresAtMillis = System.currentTimeMillis() + GuideNhCustomPayloadLimits.STRUCTURE_TRANSFER_TTL_MILLIS; } @Nullable public synchronized String accept(GuideNhStructureRequestMessage message) { + if (isExpired()) { + return null; + } int index = message.getChunkIndex(); if (message.getChunkCount() != chunks.length || index < 0 || index >= chunks.length) { return null; @@ -32,6 +38,10 @@ public synchronized String accept(GuideNhStructureRequestMessage message) { chunks[index] = bytes; received++; totalBytes += bytes.length; + if (totalBytes > GuideNhCustomPayloadLimits.MAX_STRUCTURE_TRANSFER_BYTES) { + discarded = true; + return null; + } } if (received != chunks.length) { return null; @@ -46,4 +56,8 @@ public synchronized String accept(GuideNhStructureRequestMessage message) { } return out.toString(StandardCharsets.UTF_8); } + + public boolean isExpired() { + return discarded || System.currentTimeMillis() > expiresAtMillis; + } } diff --git a/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureRequestHandler.java b/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureRequestHandler.java index 3bc50917..65556fd8 100644 --- a/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureRequestHandler.java +++ b/src/main/java/com/hfstudio/guidenh/network/GuideNhStructureRequestHandler.java @@ -7,6 +7,7 @@ import net.minecraft.util.ChatComponentTranslation; import com.hfstudio.guidenh.guide.internal.GuidebookText; +import com.hfstudio.guidenh.guide.internal.structure.GuideNhServerStructureAccess; import com.hfstudio.guidenh.guide.internal.structure.GuideNhStructureRuntime; import com.hfstudio.guidenh.guide.internal.structure.GuideStructureMemoryStore; import com.hfstudio.guidenh.guide.internal.structure.GuideStructureWorldPlacementTarget; @@ -25,6 +26,7 @@ public IMessage onMessage(GuideNhStructureRequestMessage message, MessageContext if (player == null) { return null; } + pruneExpiredTransfers(); var playerId = player.getUniqueID(); var sessionStore = GuideNhStructureRuntime.getServerSessionStore(); @@ -32,11 +34,18 @@ public IMessage onMessage(GuideNhStructureRequestMessage message, MessageContext byte action = message.getAction(); String structureText = message.getStructureText(); if (message.isChunkedStructureTransfer()) { + if (!GuideNhServerStructureAccess.canUseSceneExport(player)) { + send(player, GuidebookText.CommandStructurePermissionDenied); + return null; + } TransferKey key = new TransferKey(playerId, message.getAction(), message.getTransferId()); GuideNhStructureChunkAssembler assembler = CHUNK_TRANSFERS .computeIfAbsent(key, ignored -> new GuideNhStructureChunkAssembler(message.getChunkCount())); structureText = assembler.accept(message); if (structureText == null) { + if (assembler.isExpired()) { + CHUNK_TRANSFERS.remove(key, assembler); + } return null; } CHUNK_TRANSFERS.remove(key); @@ -45,10 +54,14 @@ public IMessage onMessage(GuideNhStructureRequestMessage message, MessageContext switch (action) { case GuideNhStructureRequestMessage.ACTION_CACHE: + if (!GuideNhServerStructureAccess.canUseSceneExport(player)) { + send(player, GuidebookText.CommandStructurePermissionDenied); + break; + } sessionStore.remember(playerId, "client-cache", structureText); break; case GuideNhStructureRequestMessage.ACTION_IMPORT_AND_PLACE: - if (!player.canCommandSenderUseCommand(3, "guidenh")) { + if (!GuideNhServerStructureAccess.hasStructurePermission(player)) { send(player, GuidebookText.CommandStructurePermissionDenied); break; } @@ -69,7 +82,7 @@ public IMessage onMessage(GuideNhStructureRequestMessage message, MessageContext message.getZ()); break; case GuideNhStructureRequestMessage.ACTION_PLACE_ALL: - if (!player.canCommandSenderUseCommand(3, "guidenh")) { + if (!GuideNhServerStructureAccess.hasStructurePermission(player)) { send(player, GuidebookText.CommandStructurePermissionDenied); break; } @@ -112,6 +125,13 @@ public static String getErrorMessage(Throwable throwable) { .getSimpleName(); } + private static void pruneExpiredTransfers() { + CHUNK_TRANSFERS.entrySet() + .removeIf( + entry -> entry.getValue() + .isExpired()); + } + private static final class TransferKey { private final UUID playerId;