mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-27 23:10:16 +01:00
cbf630d5b5
Came across this in my complete utter failure to use the commands to apply patches properly
615 lines
39 KiB
Diff
615 lines
39 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: stonar96 <minecraft.stonar96@gmail.com>
|
|
Date: Thu, 25 Nov 2021 13:27:51 +0100
|
|
Subject: [PATCH] Anti-Xray
|
|
|
|
|
|
diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java
|
|
index 81ff677e970ffbe7ad5381e56852e33cf7a8ea45..184e6c6fe2ba522d0ea0774604839320c4152371 100644
|
|
--- a/io/papermc/paper/FeatureHooks.java
|
|
+++ b/io/papermc/paper/FeatureHooks.java
|
|
@@ -37,20 +37,25 @@ public final class FeatureHooks {
|
|
}
|
|
|
|
public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) {
|
|
- return new LevelChunkSection(biomeRegistry);
|
|
+ return new LevelChunkSection(biomeRegistry, level, chunkPos, chunkSection); // Paper - Anti-Xray - Add parameters
|
|
}
|
|
|
|
public static void sendChunkRefreshPackets(final List<ServerPlayer> playersInRange, final LevelChunk chunk) {
|
|
- final ClientboundLevelChunkWithLightPacket refreshPacket = new ClientboundLevelChunkWithLightPacket(chunk, chunk.level.getLightEngine(), null, null);
|
|
+ // Paper start - Anti-Xray
|
|
+ final Map<Object, ClientboundLevelChunkWithLightPacket> refreshPackets = new HashMap<>();
|
|
for (final ServerPlayer player : playersInRange) {
|
|
if (player.connection == null) continue;
|
|
|
|
- player.connection.send(refreshPacket);
|
|
+ final Boolean shouldModify = chunk.getLevel().chunkPacketBlockController.shouldModify(player, chunk);
|
|
+ player.connection.send(refreshPackets.computeIfAbsent(shouldModify, s -> { // Use connection to prevent creating firing event
|
|
+ return new ClientboundLevelChunkWithLightPacket(chunk, chunk.level.getLightEngine(), null, null, (Boolean) s);
|
|
+ }));
|
|
}
|
|
+ // Paper end - Anti-Xray
|
|
}
|
|
|
|
public static PalettedContainer<BlockState> emptyPalettedBlockContainer() {
|
|
- return new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
|
+ return new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, null); // Paper - Anti-Xray - Add preset block states
|
|
}
|
|
|
|
public static Set<Long> getSentChunkKeys(final ServerPlayer player) {
|
|
diff --git a/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java b/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java
|
|
index d4872b7f4e9591b3b1c67406312905851303f521..cb41460e94161675e2ab43f4b1b5286ee38e2e13 100644
|
|
--- a/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java
|
|
+++ b/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java
|
|
@@ -70,8 +70,10 @@ public record ClientboundChunksBiomesPacket(List<ClientboundChunksBiomesPacket.C
|
|
}
|
|
|
|
public static void extractChunkData(FriendlyByteBuf buffer, LevelChunk chunk) {
|
|
+ int chunkSectionIndex = 0; // Paper - Anti-Xray
|
|
for (LevelChunkSection levelChunkSection : chunk.getSections()) {
|
|
- levelChunkSection.getBiomes().write(buffer);
|
|
+ levelChunkSection.getBiomes().write(buffer, null, chunkSectionIndex); // Paper - Anti-Xray
|
|
+ chunkSectionIndex++; // Paper - Anti-Xray
|
|
}
|
|
}
|
|
|
|
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
|
index 5d1943d37dfad0c12e77179f0866851532d983e9..3aea76690bc3e35758d3bf274777130af17d8a0f 100644
|
|
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
|
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData.java
|
|
@@ -28,7 +28,13 @@ public class ClientboundLevelChunkPacketData {
|
|
private final byte[] buffer;
|
|
private final List<ClientboundLevelChunkPacketData.BlockEntityInfo> blockEntitiesData;
|
|
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public ClientboundLevelChunkPacketData(LevelChunk levelChunk) {
|
|
+ this(levelChunk, null);
|
|
+ }
|
|
+ public ClientboundLevelChunkPacketData(LevelChunk levelChunk, io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
|
|
+ // Paper end
|
|
this.heightmaps = new CompoundTag();
|
|
|
|
for (Entry<Heightmap.Types, Heightmap> entry : levelChunk.getHeightmaps()) {
|
|
@@ -38,7 +44,11 @@ public class ClientboundLevelChunkPacketData {
|
|
}
|
|
|
|
this.buffer = new byte[calculateChunkSize(levelChunk)];
|
|
- extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk);
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ if (chunkPacketInfo != null) {
|
|
+ chunkPacketInfo.setBuffer(this.buffer);
|
|
+ }
|
|
+ extractChunkData(new FriendlyByteBuf(this.getWriteBuffer()), levelChunk, chunkPacketInfo);
|
|
this.blockEntitiesData = Lists.newArrayList();
|
|
|
|
for (Entry<BlockPos, BlockEntity> entryx : levelChunk.getBlockEntities().entrySet()) {
|
|
@@ -85,9 +95,17 @@ public class ClientboundLevelChunkPacketData {
|
|
return byteBuf;
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public static void extractChunkData(FriendlyByteBuf buffer, LevelChunk chunk) {
|
|
+ ClientboundLevelChunkPacketData.extractChunkData(buffer, chunk, null);
|
|
+ }
|
|
+ public static void extractChunkData(FriendlyByteBuf buffer, LevelChunk chunk, io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo) {
|
|
+ int chunkSectionIndex = 0;
|
|
for (LevelChunkSection levelChunkSection : chunk.getSections()) {
|
|
- levelChunkSection.write(buffer);
|
|
+ levelChunkSection.write(buffer, chunkPacketInfo, chunkSectionIndex);
|
|
+ chunkSectionIndex++;
|
|
+ // Paper end - Anti-Xray - Add chunk packet info
|
|
}
|
|
}
|
|
|
|
diff --git a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
|
|
index 3a384175f8e7f204234bbaf3081bdc20c47a0d4b..5699bc15eba92e22433a20cb8326b59f2ebd3036 100644
|
|
--- a/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
|
|
+++ b/net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket.java
|
|
@@ -18,18 +18,31 @@ public class ClientboundLevelChunkWithLightPacket implements Packet<ClientGamePa
|
|
private final int z;
|
|
private final ClientboundLevelChunkPacketData chunkData;
|
|
private final ClientboundLightUpdatePacketData lightData;
|
|
- // Paper start - Anti-Xray
|
|
+ // Paper start - Async-Anti-Xray - Ready flag for the connection, add chunk packet info
|
|
+ private volatile boolean ready;
|
|
+
|
|
+ @Override
|
|
+ public boolean isReady() {
|
|
+ return this.ready;
|
|
+ }
|
|
+
|
|
public void setReady(final boolean ready) {
|
|
- // Empty hook, updated by feature patch
|
|
+ this.ready = ready;
|
|
}
|
|
- // Paper end - Anti-Xray
|
|
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public ClientboundLevelChunkWithLightPacket(LevelChunk chunk, LevelLightEngine lightEngine, @Nullable BitSet skyLight, @Nullable BitSet blockLight) {
|
|
+ this(chunk, lightEngine, skyLight, blockLight, true);
|
|
+ }
|
|
+ public ClientboundLevelChunkWithLightPacket(LevelChunk chunk, LevelLightEngine lightEngine, @Nullable BitSet skyLight, @Nullable BitSet blockLight, boolean modifyBlocks) {
|
|
+ // Paper end - Anti-Xray
|
|
ChunkPos pos = chunk.getPos();
|
|
this.x = pos.x;
|
|
this.z = pos.z;
|
|
- this.chunkData = new ClientboundLevelChunkPacketData(chunk);
|
|
+ io.papermc.paper.antixray.ChunkPacketInfo<net.minecraft.world.level.block.state.BlockState> chunkPacketInfo = modifyBlocks ? chunk.getLevel().chunkPacketBlockController.getChunkPacketInfo(this, chunk) : null; // Paper - Ant-Xray
|
|
+ this.chunkData = new ClientboundLevelChunkPacketData(chunk, chunkPacketInfo); // Paper - Anti-Xray
|
|
this.lightData = new ClientboundLightUpdatePacketData(pos, lightEngine, skyLight, blockLight);
|
|
+ chunk.getLevel().chunkPacketBlockController.modifyBlocks(this, chunkPacketInfo); // Paper - Anti-Xray - Modify blocks
|
|
}
|
|
|
|
private ClientboundLevelChunkWithLightPacket(RegistryFriendlyByteBuf buffer) {
|
|
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
|
index da8848e2a3e3745949eb2356a049451d30f763a7..192977dd661ee795ada13db895db770293e9b402 100644
|
|
--- a/net/minecraft/server/level/ServerLevel.java
|
|
+++ b/net/minecraft/server/level/ServerLevel.java
|
|
@@ -348,7 +348,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
|
org.bukkit.generator.BiomeProvider biomeProvider // CraftBukkit
|
|
) {
|
|
// CraftBukkit start
|
|
- super(serverLevelData, dimension, server.registryAccess(), levelStem.type(), false, isDebug, biomeZoomSeed, server.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> server.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(levelStorageAccess.levelDirectory.path(), serverLevelData.getLevelName(), dimension.location(), spigotConfig, server.registryAccess(), serverLevelData.getGameRules()))); // Paper - create paper world configs
|
|
+ super(serverLevelData, dimension, server.registryAccess(), levelStem.type(), false, isDebug, biomeZoomSeed, server.getMaxChainedNeighborUpdates(), gen, biomeProvider, env, spigotConfig -> server.paperConfigurations.createWorldConfig(io.papermc.paper.configuration.PaperConfigurations.createWorldContextMap(levelStorageAccess.levelDirectory.path(), serverLevelData.getLevelName(), dimension.location(), spigotConfig, server.registryAccess(), serverLevelData.getGameRules())), dispatcher); // Paper - create paper world configs; Async-Anti-Xray: Pass executor
|
|
this.pvpMode = server.isPvpAllowed();
|
|
this.levelStorageAccess = levelStorageAccess;
|
|
this.uuid = org.bukkit.craftbukkit.util.WorldUUID.getUUID(levelStorageAccess.levelDirectory.path().toFile());
|
|
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
index 47ed3ad5c0b4753f58e0bafff5e5e70b2f0bb40b..623c069f1fe079e020c6391a3db1a3d95cd3dbf5 100644
|
|
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
@@ -299,6 +299,7 @@ public class ServerPlayerGameMode {
|
|
org.bukkit.craftbukkit.event.CraftEventFactory.callBlockDamageAbortEvent(this.player, pos, this.player.getInventory().getSelected()); // CraftBukkit
|
|
}
|
|
}
|
|
+ this.level.chunkPacketBlockController.onPlayerLeftClickBlock(this, pos, action, face, maxBuildHeight, sequence); // Paper - Anti-Xray
|
|
}
|
|
|
|
public void destroyAndAck(BlockPos pos, int sequence, String message) {
|
|
diff --git a/net/minecraft/server/network/PlayerChunkSender.java b/net/minecraft/server/network/PlayerChunkSender.java
|
|
index 342bc843c384761e883de861044f4f8930ae8763..14878690a88fd4de3e2c127086607e6c819c636c 100644
|
|
--- a/net/minecraft/server/network/PlayerChunkSender.java
|
|
+++ b/net/minecraft/server/network/PlayerChunkSender.java
|
|
@@ -78,8 +78,11 @@ public class PlayerChunkSender {
|
|
}
|
|
}
|
|
|
|
- private static void sendChunk(ServerGamePacketListenerImpl packetListener, ServerLevel level, LevelChunk chunk) {
|
|
- packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null));
|
|
+ // Paper start - Anti-Xray
|
|
+ public static void sendChunk(ServerGamePacketListenerImpl packetListener, ServerLevel level, LevelChunk chunk) {
|
|
+ final boolean shouldModify = level.chunkPacketBlockController.shouldModify(packetListener.player, chunk);
|
|
+ packetListener.send(new ClientboundLevelChunkWithLightPacket(chunk, level.getLightEngine(), null, null, shouldModify));
|
|
+ // Paper end - Anti-Xray
|
|
// Paper start - PlayerChunkLoadEvent
|
|
if (io.papermc.paper.event.packet.PlayerChunkLoadEvent.getHandlerList().getRegisteredListeners().length > 0) {
|
|
new io.papermc.paper.event.packet.PlayerChunkLoadEvent(new org.bukkit.craftbukkit.CraftChunk(chunk), packetListener.getPlayer().getBukkitEntity()).callEvent();
|
|
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
|
|
index 600a08d6b45cb19dbe551cefbf726e68684a0837..ff0315cffdb282fdc0a1ffd15e2954caa76835c9 100644
|
|
--- a/net/minecraft/server/players/PlayerList.java
|
|
+++ b/net/minecraft/server/players/PlayerList.java
|
|
@@ -403,7 +403,7 @@ public abstract class PlayerList {
|
|
.getOrThrow(net.minecraft.world.level.biome.Biomes.PLAINS);
|
|
player.connection.send(new net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket(
|
|
new net.minecraft.world.level.chunk.EmptyLevelChunk(serverLevel, player.chunkPosition(), plains),
|
|
- serverLevel.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null)
|
|
+ serverLevel.getLightEngine(), (java.util.BitSet)null, (java.util.BitSet) null, true) // Paper - Anti-Xray
|
|
);
|
|
}
|
|
// Paper end - Send empty chunk
|
|
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
|
|
index 0f346faa82b988e86834c38837f6f11bea7f31c6..771d6ed6a7c889c09efd4ff6e20298c851eaa79f 100644
|
|
--- a/net/minecraft/world/level/Level.java
|
|
+++ b/net/minecraft/world/level/Level.java
|
|
@@ -168,6 +168,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
}
|
|
// Paper end - add paper world config
|
|
|
|
+ public final io.papermc.paper.antixray.ChunkPacketBlockController chunkPacketBlockController; // Paper - Anti-Xray
|
|
public static BlockPos lastPhysicsProblem; // Spigot
|
|
private org.spigotmc.TickLimiter entityLimiter;
|
|
private org.spigotmc.TickLimiter tileLimiter;
|
|
@@ -214,7 +215,8 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
org.bukkit.generator.BiomeProvider biomeProvider, // CraftBukkit
|
|
org.bukkit.World.Environment env, // CraftBukkit
|
|
java.util.function.Function<org.spigotmc.SpigotWorldConfig, // Spigot - create per world config
|
|
- io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator // Paper - create paper world config
|
|
+ io.papermc.paper.configuration.WorldConfiguration> paperWorldConfigCreator, // Paper - create paper world config
|
|
+ java.util.concurrent.Executor executor // Paper - Anti-Xray
|
|
) {
|
|
this.spigotConfig = new org.spigotmc.SpigotWorldConfig(((net.minecraft.world.level.storage.PrimaryLevelData) levelData).getLevelName()); // Spigot
|
|
this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config
|
|
@@ -295,6 +297,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
// CraftBukkit end
|
|
this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime);
|
|
this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime);
|
|
+ this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new io.papermc.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : io.papermc.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray
|
|
}
|
|
|
|
// Paper start - Cancel hit for vanished players
|
|
@@ -495,6 +498,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
// CraftBukkit end
|
|
|
|
BlockState blockState = chunkAt.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag
|
|
+ this.chunkPacketBlockController.onBlockChange(this, pos, state, blockState, flags, recursionLeft); // Paper - Anti-Xray
|
|
|
|
if (blockState == null) {
|
|
// CraftBukkit start - remove blockstate if failed (or the same)
|
|
diff --git a/net/minecraft/world/level/chunk/ChunkAccess.java b/net/minecraft/world/level/chunk/ChunkAccess.java
|
|
index 809b3c37d3749c76c3c243cd91c593d03693e9b3..860d1c9729c4ee97ec6f40f7aa969829070b27c0 100644
|
|
--- a/net/minecraft/world/level/chunk/ChunkAccess.java
|
|
+++ b/net/minecraft/world/level/chunk/ChunkAccess.java
|
|
@@ -114,14 +114,14 @@ public abstract class ChunkAccess implements BiomeManager.NoiseBiomeSource, Ligh
|
|
}
|
|
}
|
|
|
|
- replaceMissingSections(biomeRegistry, this.sections);
|
|
+ this.replaceMissingSections(biomeRegistry, this.sections); // Paper - Anti-Xray - make it a non-static method
|
|
this.biomeRegistry = biomeRegistry; // CraftBukkit
|
|
}
|
|
|
|
- private static void replaceMissingSections(Registry<Biome> biomeRegistry, LevelChunkSection[] sections) {
|
|
+ private void replaceMissingSections(Registry<Biome> biomeRegistry, LevelChunkSection[] sections) { // Paper - Anti-Xray - make it a non-static method
|
|
for (int i = 0; i < sections.length; i++) {
|
|
if (sections[i] == null) {
|
|
- sections[i] = new LevelChunkSection(biomeRegistry);
|
|
+ sections[i] = new LevelChunkSection(biomeRegistry, this.levelHeightAccessor instanceof net.minecraft.world.level.Level ? (net.minecraft.world.level.Level) this.levelHeightAccessor : null, this.chunkPos, this.levelHeightAccessor.getSectionYFromSectionIndex(i)); // Paper - Anti-Xray - Add parameters
|
|
}
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
|
|
index 51a136cf015de730ca0d1b48cf618a2ed69ea89f..96b0342ab7b922aa16d07b6c00542e6cb66c974a 100644
|
|
--- a/net/minecraft/world/level/chunk/LevelChunk.java
|
|
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
|
|
@@ -109,7 +109,7 @@ public class LevelChunk extends ChunkAccess {
|
|
@Nullable LevelChunk.PostLoadProcessor postLoad,
|
|
@Nullable BlendingData blendingData
|
|
) {
|
|
- super(pos, data, level, level.registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData);
|
|
+ super(pos, data, level, net.minecraft.server.MinecraftServer.getServer().registryAccess().lookupOrThrow(Registries.BIOME), inhabitedTime, sections, blendingData); // Paper - Anti-Xray - The world isn't ready yet, use server singleton for registry
|
|
this.level = (net.minecraft.server.level.ServerLevel) level; // CraftBukkit - type
|
|
this.gameEventListenerRegistrySections = new Int2ObjectOpenHashMap<>();
|
|
|
|
diff --git a/net/minecraft/world/level/chunk/LevelChunkSection.java b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
|
index baa9f3e2e6e45c250930658e82bad70a3a292b05..fc21c3268c4b4fda2933d71f0913db28e3796653 100644
|
|
--- a/net/minecraft/world/level/chunk/LevelChunkSection.java
|
|
+++ b/net/minecraft/world/level/chunk/LevelChunkSection.java
|
|
@@ -38,9 +38,15 @@ public class LevelChunkSection {
|
|
this.recalcBlockCounts();
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray - Add parameters
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public LevelChunkSection(Registry<Biome> biomeRegistry) {
|
|
- this.states = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
|
- this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
|
+ this(biomeRegistry, null, null, 0);
|
|
+ }
|
|
+ public LevelChunkSection(Registry<Biome> biomeRegistry, net.minecraft.world.level.Level level, net.minecraft.world.level.ChunkPos chunkPos, int chunkSectionY) {
|
|
+ // Paper end - Anti-Xray
|
|
+ this.states = new PalettedContainer<>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, level == null || level.chunkPacketBlockController == null ? null : level.chunkPacketBlockController.getPresetBlockStates(level, chunkPos, chunkSectionY)); // Paper - Anti-Xray - Add preset block states
|
|
+ this.biomes = new PalettedContainer<>(biomeRegistry.asHolderIdMap(), biomeRegistry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null); // Paper - Anti-Xray - Add preset biomes
|
|
}
|
|
|
|
public BlockState getBlockState(int x, int y, int z) {
|
|
@@ -168,10 +174,16 @@ public class LevelChunkSection {
|
|
this.biomes = palettedContainer;
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public void write(FriendlyByteBuf buffer) {
|
|
+ this.write(buffer, null, 0);
|
|
+ }
|
|
+ public void write(FriendlyByteBuf buffer, io.papermc.paper.antixray.ChunkPacketInfo<BlockState> chunkPacketInfo, int chunkSectionIndex) {
|
|
buffer.writeShort(this.nonEmptyBlockCount);
|
|
- this.states.write(buffer);
|
|
- this.biomes.write(buffer);
|
|
+ this.states.write(buffer, chunkPacketInfo, chunkSectionIndex);
|
|
+ this.biomes.write(buffer, null, chunkSectionIndex);
|
|
+ // Paper end - Anti-Xray
|
|
}
|
|
|
|
public int getSerializedSize() {
|
|
diff --git a/net/minecraft/world/level/chunk/PalettedContainer.java b/net/minecraft/world/level/chunk/PalettedContainer.java
|
|
index e8ec28ce3fe13561b45c4654e174776d9d2d7b71..a6028a54c75de068515e95913b21160ab4326985 100644
|
|
--- a/net/minecraft/world/level/chunk/PalettedContainer.java
|
|
+++ b/net/minecraft/world/level/chunk/PalettedContainer.java
|
|
@@ -28,6 +28,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
private static final int MIN_PALETTE_BITS = 0;
|
|
private final PaletteResize<T> dummyPaletteResize = (bits, objectAdded) -> 0;
|
|
public final IdMap<T> registry;
|
|
+ private final T @org.jetbrains.annotations.Nullable [] presetValues; // Paper - Anti-Xray - Add preset values
|
|
private volatile PalettedContainer.Data<T> data;
|
|
private final PalettedContainer.Strategy strategy;
|
|
//private final ThreadingDetector threadingDetector = new ThreadingDetector("PalettedContainer"); // Paper - unused
|
|
@@ -40,13 +41,21 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
// this.threadingDetector.checkAndUnlock(); // Paper - disable this - use proper synchronization
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray - Add preset values
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public static <T> Codec<PalettedContainer<T>> codecRW(IdMap<T> registry, Codec<T> codec, PalettedContainer.Strategy strategy, T value) {
|
|
- PalettedContainerRO.Unpacker<T, PalettedContainer<T>> unpacker = PalettedContainer::unpack;
|
|
+ return PalettedContainer.codecRW(registry, codec, strategy, value, null);
|
|
+ }
|
|
+ public static <T> Codec<PalettedContainer<T>> codecRW(IdMap<T> registry, Codec<T> codec, PalettedContainer.Strategy strategy, T value, T @org.jetbrains.annotations.Nullable [] presetValues) {
|
|
+ PalettedContainerRO.Unpacker<T, PalettedContainer<T>> unpacker = (idListx, paletteProviderx, serialized) -> {
|
|
+ return unpack(idListx, paletteProviderx, serialized, value, presetValues);
|
|
+ };
|
|
+ // Paper end
|
|
return codec(registry, codec, strategy, value, unpacker);
|
|
}
|
|
|
|
public static <T> Codec<PalettedContainerRO<T>> codecRO(IdMap<T> registry, Codec<T> codec, PalettedContainer.Strategy strategy, T value) {
|
|
- PalettedContainerRO.Unpacker<T, PalettedContainerRO<T>> unpacker = (registry1, strategy1, packedData) -> unpack(registry1, strategy1, packedData)
|
|
+ PalettedContainerRO.Unpacker<T, PalettedContainerRO<T>> unpacker = (registry1, strategy1, packedData) -> unpack(registry1, strategy1, packedData, value, null) // Paper - Anti-Xray - Add preset values
|
|
.map(container -> (PalettedContainerRO<T>)container);
|
|
return codec(registry, codec, strategy, value, unpacker);
|
|
}
|
|
@@ -66,27 +75,66 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
);
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray - Add preset values
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
+ public PalettedContainer(IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainer.Configuration<T> configuration, BitStorage storage, List<T> values) {
|
|
+ this(registry, strategy, configuration, storage, values, null, null);
|
|
+ }
|
|
public PalettedContainer(
|
|
- IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainer.Configuration<T> configuration, BitStorage storage, List<T> values
|
|
+ IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainer.Configuration<T> configuration, BitStorage storage, List<T> values, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues
|
|
) {
|
|
+ this.presetValues = presetValues;
|
|
this.registry = registry;
|
|
this.strategy = strategy;
|
|
this.data = new PalettedContainer.Data<>(configuration, storage, configuration.factory().create(configuration.bits(), registry, this, values));
|
|
+ if (presetValues != null && (configuration.factory() == PalettedContainer.Strategy.SINGLE_VALUE_PALETTE_FACTORY ? this.data.palette.valueFor(0) != defaultValue : configuration.factory() != PalettedContainer.Strategy.GLOBAL_PALETTE_FACTORY)) {
|
|
+ // In 1.18 Mojang unfortunately removed code that already handled possible resize operations on read from disk for us
|
|
+ // We readd this here but in a smarter way than it was before
|
|
+ int maxSize = 1 << configuration.bits();
|
|
+
|
|
+ for (T presetValue : presetValues) {
|
|
+ if (this.data.palette.getSize() >= maxSize) {
|
|
+ java.util.Set<T> allValues = new java.util.HashSet<>(values);
|
|
+ allValues.addAll(Arrays.asList(presetValues));
|
|
+ int newBits = Mth.ceillog2(allValues.size());
|
|
+
|
|
+ if (newBits > configuration.bits()) {
|
|
+ this.onResize(newBits, null);
|
|
+ }
|
|
+
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ this.data.palette.idFor(presetValue);
|
|
+ }
|
|
+ }
|
|
+ // Paper end
|
|
}
|
|
|
|
- private PalettedContainer(IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainer.Data<T> data) {
|
|
+ // Paper start - Anti-Xray - Add preset values
|
|
+ private PalettedContainer(IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainer.Data<T> data, T @org.jetbrains.annotations.Nullable [] presetValues) {
|
|
+ this.presetValues = presetValues;
|
|
+ // Paper end - Anti-Xray
|
|
this.registry = registry;
|
|
this.strategy = strategy;
|
|
this.data = data;
|
|
}
|
|
|
|
- private PalettedContainer(PalettedContainer<T> other) {
|
|
+ private PalettedContainer(PalettedContainer<T> other, T @org.jetbrains.annotations.Nullable [] presetValues) { // Paper - Anti-Xray - Add preset values
|
|
+ this.presetValues = presetValues; // Paper - Anti-Xray - Add preset values
|
|
this.registry = other.registry;
|
|
this.strategy = other.strategy;
|
|
this.data = other.data.copy(this);
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray - Add preset values
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
public PalettedContainer(IdMap<T> registry, T palette, PalettedContainer.Strategy strategy) {
|
|
+ this(registry, palette, strategy, null);
|
|
+ }
|
|
+ public PalettedContainer(IdMap<T> registry, T palette, PalettedContainer.Strategy strategy, T @org.jetbrains.annotations.Nullable [] presetValues) {
|
|
+ this.presetValues = presetValues;
|
|
+ // Paper end - Anti-Xray
|
|
this.strategy = strategy;
|
|
this.registry = registry;
|
|
this.data = this.createOrReuseData(null, 0);
|
|
@@ -101,11 +149,30 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
@Override
|
|
public synchronized int onResize(int bits, T objectAdded) { // Paper - synchronize
|
|
PalettedContainer.Data<T> data = this.data;
|
|
+ // Paper start - Anti-Xray - Add preset values
|
|
+ if (this.presetValues != null && objectAdded != null && data.configuration().factory() == PalettedContainer.Strategy.SINGLE_VALUE_PALETTE_FACTORY) {
|
|
+ int duplicates = 0;
|
|
+ List<T> presetValues = Arrays.asList(this.presetValues);
|
|
+ duplicates += presetValues.contains(objectAdded) ? 1 : 0;
|
|
+ duplicates += presetValues.contains(data.palette.valueFor(0)) ? 1 : 0;
|
|
+ bits = Mth.ceillog2((1 << this.strategy.calculateBitsForSerialization(this.registry, 1 << bits)) + presetValues.size() - duplicates);
|
|
+ }
|
|
+ // Paper end - Anti-Xray
|
|
PalettedContainer.Data<T> data1 = this.createOrReuseData(data, bits);
|
|
data1.copyFrom(data.palette, data.storage);
|
|
this.data = data1;
|
|
- return data1.palette.idFor(objectAdded);
|
|
+ // Paper start - Anti-Xray
|
|
+ this.addPresetValues();
|
|
+ return objectAdded == null ? -1 : data1.palette.idFor(objectAdded);
|
|
+ }
|
|
+ private void addPresetValues() {
|
|
+ if (this.presetValues != null && this.data.configuration().factory() != PalettedContainer.Strategy.GLOBAL_PALETTE_FACTORY) {
|
|
+ for (T presetValue : this.presetValues) {
|
|
+ this.data.palette.idFor(presetValue);
|
|
+ }
|
|
+ }
|
|
}
|
|
+ // Paper end - Anti-Xray
|
|
|
|
public synchronized T getAndSet(int x, int y, int z, T state) { // Paper - synchronize
|
|
this.acquire();
|
|
@@ -172,24 +239,35 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
data.palette.read(buffer);
|
|
buffer.readLongArray(data.storage.getRaw());
|
|
this.data = data;
|
|
+ this.addPresetValues(); // Paper - Anti-Xray - Add preset values (inefficient, but this isn't used by the server)
|
|
} finally {
|
|
this.release();
|
|
}
|
|
}
|
|
|
|
+ // Paper start - Anti-Xray; Add chunk packet info
|
|
@Override
|
|
- public synchronized void write(FriendlyByteBuf buffer) { // Paper - synchronize
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse
|
|
+ public void write(FriendlyByteBuf buffer) {
|
|
+ this.write(buffer, null, 0);
|
|
+ }
|
|
+ @Override
|
|
+ public synchronized void write(FriendlyByteBuf buffer, @Nullable io.papermc.paper.antixray.ChunkPacketInfo<T> chunkPacketInfo, int chunkSectionIndex) { // Paper - Synchronize
|
|
this.acquire();
|
|
|
|
try {
|
|
- this.data.write(buffer);
|
|
+ this.data.write(buffer, chunkPacketInfo, chunkSectionIndex);
|
|
+ if (chunkPacketInfo != null) {
|
|
+ chunkPacketInfo.setPresetValues(chunkSectionIndex, this.presetValues);
|
|
+ }
|
|
+ // Paper end - Anti-Xray
|
|
} finally {
|
|
this.release();
|
|
}
|
|
}
|
|
|
|
private static <T> DataResult<PalettedContainer<T>> unpack(
|
|
- IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainerRO.PackedData<T> packedData
|
|
+ IdMap<T> registry, PalettedContainer.Strategy strategy, PalettedContainerRO.PackedData<T> packedData, T defaultValue, T @org.jetbrains.annotations.Nullable [] presetValues // Paper - Anti-Xray - Add preset values
|
|
) {
|
|
List<T> list = packedData.paletteEntries();
|
|
int size = strategy.size();
|
|
@@ -222,7 +300,7 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
}
|
|
}
|
|
|
|
- return DataResult.success(new PalettedContainer<>(registry, strategy, configuration, bitStorage, list));
|
|
+ return DataResult.success(new PalettedContainer<>(registry, strategy, configuration, bitStorage, list, defaultValue, presetValues)); // Paper - Anti-Xray - Add preset values
|
|
}
|
|
|
|
@Override
|
|
@@ -280,12 +358,12 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
|
|
@Override
|
|
public PalettedContainer<T> copy() {
|
|
- return new PalettedContainer<>(this);
|
|
+ return new PalettedContainer<>(this, this.presetValues); // Paper - Anti-Xray - Add preset values
|
|
}
|
|
|
|
@Override
|
|
public PalettedContainer<T> recreate() {
|
|
- return new PalettedContainer<>(this.registry, this.data.palette.valueFor(0), this.strategy);
|
|
+ return new PalettedContainer<>(this.registry, this.data.palette.valueFor(0), this.strategy, this.presetValues); // Paper - Anti-Xray - Add preset values
|
|
}
|
|
|
|
@Override
|
|
@@ -324,9 +402,16 @@ public class PalettedContainer<T> implements PaletteResize<T>, PalettedContainer
|
|
return 1 + this.palette.getSerializedSize() + VarInt.getByteSize(this.storage.getRaw().length) + this.storage.getRaw().length * 8;
|
|
}
|
|
|
|
- public void write(FriendlyByteBuf buffer) {
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ public void write(FriendlyByteBuf buffer, @Nullable io.papermc.paper.antixray.ChunkPacketInfo<T> chunkPacketInfo, int chunkSectionIndex) {
|
|
buffer.writeByte(this.storage.getBits());
|
|
this.palette.write(buffer);
|
|
+ if (chunkPacketInfo != null) {
|
|
+ chunkPacketInfo.setBits(chunkSectionIndex, this.configuration.bits());
|
|
+ chunkPacketInfo.setPalette(chunkSectionIndex, this.palette);
|
|
+ chunkPacketInfo.setIndex(chunkSectionIndex, buffer.writerIndex() + VarInt.getByteSize(this.storage.getRaw().length));
|
|
+ }
|
|
+ // Paper end
|
|
buffer.writeLongArray(this.storage.getRaw());
|
|
}
|
|
|
|
diff --git a/net/minecraft/world/level/chunk/PalettedContainerRO.java b/net/minecraft/world/level/chunk/PalettedContainerRO.java
|
|
index bfbb1a2bb4abbb369a24f2f01439e9ea3e16794b..8d6ed8be4d93f7d4e6ea80c351020d88ee98aa4d 100644
|
|
--- a/net/minecraft/world/level/chunk/PalettedContainerRO.java
|
|
+++ b/net/minecraft/world/level/chunk/PalettedContainerRO.java
|
|
@@ -14,7 +14,10 @@ public interface PalettedContainerRO<T> {
|
|
|
|
void getAll(Consumer<T> consumer);
|
|
|
|
- void write(FriendlyByteBuf buffer);
|
|
+ // Paper start - Anti-Xray - Add chunk packet info
|
|
+ @Deprecated @io.papermc.paper.annotation.DoNotUse void write(FriendlyByteBuf buffer);
|
|
+ void write(FriendlyByteBuf buffer, @javax.annotation.Nullable io.papermc.paper.antixray.ChunkPacketInfo<T> chunkPacketInfo, int chunkSectionIndex);
|
|
+ // Paper end
|
|
|
|
int getSerializedSize();
|
|
|
|
diff --git a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
|
index 37437a86d74291fab1de9495008aafb15dfadce0..cf6e2053d81f7b0f8c8e58b9c0fad3285ebc047d 100644
|
|
--- a/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
|
+++ b/net/minecraft/world/level/chunk/storage/SerializableChunkData.java
|
|
@@ -94,7 +94,7 @@ public record SerializableChunkData(
|
|
, @Nullable net.minecraft.nbt.Tag persistentDataContainer // CraftBukkit - persistentDataContainer
|
|
) {
|
|
public static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codecRW(
|
|
- Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState()
|
|
+ Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), null // Paper - Anti-Xray
|
|
);
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
private static final String TAG_UPGRADE_DATA = "UpgradeData";
|
|
@@ -128,6 +128,7 @@ public record SerializableChunkData(
|
|
|
|
@Nullable
|
|
public static SerializableChunkData parse(LevelHeightAccessor levelHeightAccessor, RegistryAccess registries, CompoundTag tag) {
|
|
+ net.minecraft.server.level.ServerLevel serverLevel = (net.minecraft.server.level.ServerLevel) levelHeightAccessor; // Paper - Anti-Xray This is is seemingly only called from ChunkMap, where, we have a server level. We'll fight this later if needed.
|
|
if (!tag.contains("Status", 8)) {
|
|
return null;
|
|
} else {
|
|
@@ -212,18 +213,21 @@ public record SerializableChunkData(
|
|
Codec<PalettedContainer<Holder<Biome>>> codec = makeBiomeCodecRW(registry); // CraftBukkit - read/write
|
|
|
|
for (int i2 = 0; i2 < list7.size(); i2++) {
|
|
- CompoundTag compound2 = list7.getCompound(i2);
|
|
+ CompoundTag compound2 = list7.getCompound(i2); final CompoundTag sectionData = compound2; // Paper - Anti-Xray - OBFHELPER
|
|
int _byte = compound2.getByte("Y");
|
|
LevelChunkSection levelChunkSection;
|
|
if (_byte >= levelHeightAccessor.getMinSectionY() && _byte <= levelHeightAccessor.getMaxSectionY()) {
|
|
+ // Paper start - Anti-Xray - Add preset block states
|
|
+ BlockState[] presetBlockStates = serverLevel.chunkPacketBlockController.getPresetBlockStates(serverLevel, chunkPos, _byte);
|
|
PalettedContainer<BlockState> palettedContainer;
|
|
if (compound2.contains("block_states", 10)) {
|
|
- palettedContainer = BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, compound2.getCompound("block_states"))
|
|
+ Codec<PalettedContainer<BlockState>> blockStateCodec = presetBlockStates == null ? BLOCK_STATE_CODEC : PalettedContainer.codecRW(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState(), presetBlockStates); // Paper - Anti-Xray
|
|
+ palettedContainer = blockStateCodec.parse(NbtOps.INSTANCE, sectionData.getCompound("block_states")) // Paper - Anti-Xray
|
|
.promotePartial(string -> logErrors(chunkPos, _byte, string))
|
|
.getOrThrow(SerializableChunkData.ChunkReadException::new);
|
|
} else {
|
|
palettedContainer = new PalettedContainer<>(
|
|
- Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES
|
|
+ Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES, presetBlockStates // Paper - Anti-Xray
|
|
);
|
|
}
|
|
|
|
@@ -234,7 +238,7 @@ public record SerializableChunkData(
|
|
.getOrThrow(SerializableChunkData.ChunkReadException::new);
|
|
} else {
|
|
palettedContainerRo = new PalettedContainer<>(
|
|
- registry.asHolderIdMap(), registry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES
|
|
+ registry.asHolderIdMap(), registry.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES, null // Paper - Anti-Xray - Add preset biomes
|
|
);
|
|
}
|
|
|
|
@@ -414,7 +418,7 @@ public record SerializableChunkData(
|
|
|
|
// CraftBukkit start - read/write
|
|
private static Codec<PalettedContainer<Holder<Biome>>> makeBiomeCodecRW(Registry<Biome> iregistry) {
|
|
- return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS));
|
|
+ return PalettedContainer.codecRW(iregistry.asHolderIdMap(), iregistry.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, iregistry.getOrThrow(Biomes.PLAINS), null); // Paper - Anti-Xray - Add preset biomes
|
|
}
|
|
// CraftBukkit end
|
|
|