mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-28 03:48:01 +01:00
624 lines
39 KiB
Diff
624 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 1e5d94cdcdffb4d2940f17bacdf0e6a488e84318..d3aebc7f833764351c8e5fe1fad1aa2f8718ca37 100644
|
|
--- a/io/papermc/paper/FeatureHooks.java
|
|
+++ b/io/papermc/paper/FeatureHooks.java
|
|
@@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.longs.LongSets;
|
|
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
|
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
import it.unimi.dsi.fastutil.objects.ObjectSets;
|
|
+import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
@@ -36,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 7702004b68b7735043914f93b54b4413cd21ba41..4d20bda4cba578c47216d450c99389b744a59008 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 23d241e98f37979701f80fb6f7b76954bd699ad6..fd7ad2b1bffe3880def0f0c9a7ed8de5088ecd71 100644
|
|
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
|
|
@@ -298,6 +298,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 8a93d1034eb0dab4b4010d52ddbb0caa5697416d..bafeeab3edbc73f6f86474e18ab4a3d96ce17157 100644
|
|
--- a/net/minecraft/server/players/PlayerList.java
|
|
+++ b/net/minecraft/server/players/PlayerList.java
|
|
@@ -404,7 +404,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 13dbd0da80b2199519370ac6e993ace53f42c1ea..0e4ab448755632696c4326f1df9f3855cd38a64d 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
|
|
|