9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2026-01-06 15:51:33 +00:00

Player operation limiter

This commit is contained in:
violetc
2022-12-11 19:16:32 +08:00
parent 3f5a80efa3
commit e9a13299b5
4 changed files with 216 additions and 0 deletions

View File

@@ -26,6 +26,7 @@ Leaves Modification
- Remove Player Chat sign (can instead of NoChatReport Mod server side)
- Instant BlockUpdater reintroduced
- Random flatten triangular distribution (like Carpet-TIS-Addition)
- Player operation limiter (can disable auto break bedrock mod)
## Performance

View File

@@ -26,6 +26,7 @@ Leaves Modification
- 删除玩家聊天内的签名 (可以替代NoChatReportMod的服务器侧)
- 重新引入更新抑制机制
- 扁平化随机数三角分布 (类似Carpet-TIS-Addition)
- 玩家操作限制器 (可禁止自动破基岩mod)
## 性能

View File

@@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Sun, 11 Dec 2022 18:43:36 +0800
Subject: [PATCH] Player operation limiter
diff --git a/src/main/java/top/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java b/src/main/java/top/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c55d8e105aebb269b05f9df68daaf48352391cb
--- /dev/null
+++ b/src/main/java/top/leavesmc/leaves/event/player/PlayerOperationLimitEvent.java
@@ -0,0 +1,56 @@
+package top.leavesmc.leaves.event.player;
+
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Called when a player operation is limited
+ */
+public class PlayerOperationLimitEvent extends PlayerEvent {
+ private static final HandlerList handlers = new HandlerList();
+
+ private final Block block;
+ private final Operation operation;
+
+ public PlayerOperationLimitEvent(@NotNull Player who, Operation operation, Block block) {
+ super(who);
+ this.block = block;
+ this.operation = operation;
+ }
+
+ /**
+ * Gets the operated block
+ *
+ * @return block
+ */
+ public Block getBlock() {
+ return block;
+ }
+
+ /**
+ * Gets the type of operation
+ *
+ * @return operation type
+ */
+ public Operation getOperation() {
+ return operation;
+ }
+
+ @NotNull
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @NotNull
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public enum Operation {
+ MINE, PLACE
+ }
+}

View File

@@ -0,0 +1,146 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Sun, 11 Dec 2022 18:43:35 +0800
Subject: [PATCH] Player operation limiter
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java
index 3ed09fe9693b64105466e6102062bce500da0486..fdc64e99738f1940115be06758a2bcb240da5e09 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayer.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java
@@ -271,6 +271,10 @@ public class ServerPlayer extends Player {
public final com.destroystokyo.paper.util.misc.PooledLinkedHashSets.PooledObjectLinkedOpenHashSet<ServerPlayer> cachedSingleHashSet; // Paper
public PlayerNaturallySpawnCreaturesEvent playerNaturallySpawnedEvent; // Paper
public org.bukkit.event.player.PlayerQuitEvent.QuitReason quitReason = null; // Paper - there are a lot of changes to do if we change all methods leading to the event
+ // Leaves start - player operation limiter
+ private int instaBreakCountPerTick = 0;
+ private int placeBlockCountPerTick = 0;
+ // Leaves end - player operation limiter
public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile) {
super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile);
@@ -663,6 +667,7 @@ public class ServerPlayer extends Player {
this.joining = false;
}
// CraftBukkit end
+ this.resetOperationCountPerTick(); // Leaves - player operation limiter
this.gameMode.tick();
this.wardenSpawnTracker.tick();
--this.spawnInvulnerableTime;
@@ -2557,5 +2562,32 @@ public class ServerPlayer extends Player {
public CraftPlayer getBukkitEntity() {
return (CraftPlayer) super.getBukkitEntity();
}
+
+ // Leaves start - player operation limiter
+ private void resetOperationCountPerTick() {
+ instaBreakCountPerTick = 0;
+ placeBlockCountPerTick = 0;
+ }
+
+ public int getInstaBreakCountPerTick() {
+ return instaBreakCountPerTick;
+ }
+
+ public int getPlaceBlockCountPerTick() {
+ return placeBlockCountPerTick;
+ }
+
+ public void addInstaBreakCountPerTick() {
+ ++instaBreakCountPerTick;
+ }
+
+ public void addPlaceBlockCountPerTick() {
+ ++placeBlockCountPerTick;
+ }
+
+ public boolean allowOperation() {
+ return (instaBreakCountPerTick == 0 || placeBlockCountPerTick == 0) && (instaBreakCountPerTick <= 1 && placeBlockCountPerTick <= 2);
+ }
+ // Leaves end - player operation limiter
// CraftBukkit end
}
diff --git a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
index 58b093bb1de78ee3b3b2ea364aa50474883f443a..a59cf7c1a34ee54b3a64047498ce4e090648df86 100644
--- a/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/src/main/java/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -44,6 +44,7 @@ import org.bukkit.event.Event;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerGameModeChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
+import top.leavesmc.leaves.event.player.PlayerOperationLimitEvent;
// CraftBukkit end
public class ServerPlayerGameMode {
@@ -325,6 +326,19 @@ public class ServerPlayerGameMode {
}
public void destroyAndAck(BlockPos pos, int sequence, String reason) {
+ // Leaves start - player operation limiter
+ if (top.leavesmc.leaves.LeavesConfig.playerOperationLimiter) {
+ if (reason.equals("insta mine")) {
+ player.addInstaBreakCountPerTick();
+ if (!player.allowOperation()) {
+ MinecraftServer.getServer().server.getPluginManager().callEvent(new PlayerOperationLimitEvent(player.getBukkitEntity(), PlayerOperationLimitEvent.Operation.MINE, CraftBlock.at(level, pos)));
+ this.player.connection.send(new ClientboundBlockUpdatePacket(pos, this.level.getBlockState(pos)));
+ this.debugLogging(pos, false, sequence, reason);
+ return;
+ }
+ }
+ }
+ // Leaves end - player operation limiter
if (this.destroyBlock(pos)) {
this.debugLogging(pos, true, sequence, reason);
} else {
diff --git a/src/main/java/net/minecraft/world/item/BlockItem.java b/src/main/java/net/minecraft/world/item/BlockItem.java
index 3ab714721b51b039291b8e8a4b4da5118e18f5b7..1aedc8e019fb9d5307a5a2c6c2cc8e8646d51428 100644
--- a/src/main/java/net/minecraft/world/item/BlockItem.java
+++ b/src/main/java/net/minecraft/world/item/BlockItem.java
@@ -32,9 +32,12 @@ import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.shapes.CollisionContext;
+import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.block.CraftBlock;
+import org.bukkit.craftbukkit.block.CraftBlockState;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.event.block.BlockCanBuildEvent;
+import top.leavesmc.leaves.event.player.PlayerOperationLimitEvent;
// CraftBukkit end
public class BlockItem extends Item {
@@ -83,6 +86,18 @@ public class BlockItem extends Item {
final org.bukkit.block.BlockState oldBlockstate = blockstate != null ? blockstate : org.bukkit.craftbukkit.block.CraftBlockStates.getBlockState(blockactioncontext1.getLevel(), blockactioncontext1.getClickedPos()); // Paper
// CraftBukkit end
+ // Leaves start - player operation limiter
+ if (top.leavesmc.leaves.LeavesConfig.playerOperationLimiter && !context.getLevel().isClientSide()) {
+ ServerPlayer player = (ServerPlayer) context.getPlayer();
+ if (player != null && iblockdata != null) {
+ player.addPlaceBlockCountPerTick();
+ if (!player.allowOperation()) {
+ MinecraftServer.getServer().server.getPluginManager().callEvent(new PlayerOperationLimitEvent(player.getBukkitEntity(), PlayerOperationLimitEvent.Operation.PLACE, blockstate.getBlock()));
+ return InteractionResult.FAIL;
+ }
+ }
+ }
+ // Leaves end - player operation limiter
if (iblockdata == null) {
return InteractionResult.FAIL;
} else if (!this.placeBlock(blockactioncontext1, iblockdata)) {
diff --git a/src/main/java/top/leavesmc/leaves/LeavesConfig.java b/src/main/java/top/leavesmc/leaves/LeavesConfig.java
index 43b0083d51e8d78092595a93755ed2e1b84c4694..d63907fbf908cf6c83c727889abe37058a673f6a 100644
--- a/src/main/java/top/leavesmc/leaves/LeavesConfig.java
+++ b/src/main/java/top/leavesmc/leaves/LeavesConfig.java
@@ -432,6 +432,11 @@ public final class LeavesConfig {
}
}
+ public static boolean playerOperationLimiter = false;
+ private static void playerOperationLimiter() {
+ playerOperationLimiter = getBoolean("settings.modify.player-operation-limiter", playerOperationLimiter);
+ }
+
public static final class WorldConfig {
public final String worldName;