Preserve order and allow multiple equal blocks in hidden-blocks of Anti-Xray (#4072)

* Preserve order of hidden-blocks in Anti-Xray

This small change allows to specify and predict the order in which
Anti-Xray uses the hidden-blocks in engine-mode 2. The order is
preserved as specified in the hidden-blocks list. This can be useful,
for example, when adding air to the hidden-blocks to predict which fake
ores should be exposed to fake air.

* Allow to add equal blocks multiple times to hidden-blocks

This adds the ability to add equal blocks multiple times to the
hidden-blocks of Anti-Xray in engine-mode 2. Thus it is possible to give
certain blocks different priorities in Anti-Xray. For example if air and
diamond_ore are added twice, the obfuscated chunk will contain twice as
many air and diamond_ore blocks as other blocks in the list.
This commit is contained in:
stonar96 2020-11-24 17:59:04 +01:00 committed by GitHub
parent 8535eca3bf
commit 83f377be8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -100,14 +100,15 @@ index 0000000000000000000000000000000000000000..df7e4183d8842f5be8ae9d0698f8fa90
+} +}
diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java diff --git a/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java
new file mode 100644 new file mode 100644
index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c9270d1589d index 0000000000000000000000000000000000000000..ac2dd0841dc849c3ceabb5ea899594ae73fb52fc
--- /dev/null --- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java +++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java
@@ -0,0 +1,605 @@ @@ -0,0 +1,615 @@
+package com.destroystokyo.paper.antixray; +package com.destroystokyo.paper.antixray;
+ +
+import java.util.ArrayList; +import java.util.ArrayList;
+import java.util.HashSet; +import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List; +import java.util.List;
+import java.util.Set; +import java.util.Set;
+import java.util.concurrent.Executor; +import java.util.concurrent.Executor;
@ -127,6 +128,7 @@ index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c92
+ private final int maxChunkSectionIndex; + private final int maxChunkSectionIndex;
+ private final int updateRadius; + private final int updateRadius;
+ private final IBlockData[] predefinedBlockData; + private final IBlockData[] predefinedBlockData;
+ private final IBlockData[] predefinedBlockDataFull;
+ private final IBlockData[] predefinedBlockDataStone; + private final IBlockData[] predefinedBlockDataStone;
+ private final IBlockData[] predefinedBlockDataNetherrack; + private final IBlockData[] predefinedBlockDataNetherrack;
+ private final IBlockData[] predefinedBlockDataEndStone; + private final IBlockData[] predefinedBlockDataEndStone;
@ -152,6 +154,7 @@ index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c92
+ if (engineMode == EngineMode.HIDE) { + if (engineMode == EngineMode.HIDE) {
+ toObfuscate = paperWorldConfig.hiddenBlocks; + toObfuscate = paperWorldConfig.hiddenBlocks;
+ predefinedBlockData = null; + predefinedBlockData = null;
+ predefinedBlockDataFull = null;
+ predefinedBlockDataStone = new IBlockData[] {Blocks.STONE.getBlockData()}; + predefinedBlockDataStone = new IBlockData[] {Blocks.STONE.getBlockData()};
+ predefinedBlockDataNetherrack = new IBlockData[] {Blocks.NETHERRACK.getBlockData()}; + predefinedBlockDataNetherrack = new IBlockData[] {Blocks.NETHERRACK.getBlockData()};
+ predefinedBlockDataEndStone = new IBlockData[] {Blocks.END_STONE.getBlockData()}; + predefinedBlockDataEndStone = new IBlockData[] {Blocks.END_STONE.getBlockData()};
@ -161,25 +164,30 @@ index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c92
+ predefinedBlockDataBitsEndStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.END_STONE.getBlockData())}; + predefinedBlockDataBitsEndStoneGlobal = new int[] {ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(Blocks.END_STONE.getBlockData())};
+ } else { + } else {
+ toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks); + toObfuscate = new ArrayList<>(paperWorldConfig.replacementBlocks);
+ Set<IBlockData> predefinedBlockDataSet = new HashSet<IBlockData>(); + List<IBlockData> predefinedBlockDataList = new LinkedList<IBlockData>();
+ +
+ for (String id : paperWorldConfig.hiddenBlocks) { + for (String id : paperWorldConfig.hiddenBlocks) {
+ Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null); + Block block = IRegistry.BLOCK.getOptional(new MinecraftKey(id)).orElse(null);
+ +
+ if (block != null && !block.isTileEntity()) { + if (block != null && !block.isTileEntity()) {
+ toObfuscate.add(id); + toObfuscate.add(id);
+ predefinedBlockDataSet.add(block.getBlockData()); + predefinedBlockDataList.add(block.getBlockData());
+ } + }
+ } + }
+ +
+ // The doc of the LinkedHashSet(Collection<? extends E> c) constructor doesn't specify that the insertion order is the predictable iteration order of the specified Collection, although it is in the implementation
+ Set<IBlockData> predefinedBlockDataSet = new LinkedHashSet<IBlockData>();
+ // Therefore addAll(Collection<? extends E> c) is used, which guarantees this order in the doc
+ predefinedBlockDataSet.addAll(predefinedBlockDataList);
+ predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataSet.toArray(new IBlockData[0]); + predefinedBlockData = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataSet.toArray(new IBlockData[0]);
+ predefinedBlockDataFull = predefinedBlockDataSet.size() == 0 ? new IBlockData[] {Blocks.DIAMOND_ORE.getBlockData()} : predefinedBlockDataList.toArray(new IBlockData[0]);
+ predefinedBlockDataStone = null; + predefinedBlockDataStone = null;
+ predefinedBlockDataNetherrack = null; + predefinedBlockDataNetherrack = null;
+ predefinedBlockDataEndStone = null; + predefinedBlockDataEndStone = null;
+ predefinedBlockDataBitsGlobal = new int[predefinedBlockData.length]; + predefinedBlockDataBitsGlobal = new int[predefinedBlockDataFull.length];
+ +
+ for (int i = 0; i < predefinedBlockData.length; i++) { + for (int i = 0; i < predefinedBlockDataFull.length; i++) {
+ predefinedBlockDataBitsGlobal[i] = ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(predefinedBlockData[i]); + predefinedBlockDataBitsGlobal[i] = ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(predefinedBlockDataFull[i]);
+ } + }
+ +
+ predefinedBlockDataBitsStoneGlobal = null; + predefinedBlockDataBitsStoneGlobal = null;
@ -213,8 +221,8 @@ index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c92
+ this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1; + this.maxBlockYUpdatePosition = (maxChunkSectionIndex + 1) * 16 + updateRadius - 1;
+ } + }
+ +
+ private int getPredefinedBlockDataLength() { + private int getPredefinedBlockDataFullLength() {
+ return engineMode == EngineMode.HIDE ? 1 : predefinedBlockData.length; + return engineMode == EngineMode.HIDE ? 1 : predefinedBlockDataFull.length;
+ } + }
+ +
+ @Override + @Override
@ -272,7 +280,7 @@ index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c92
+ +
+ // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal) + // Actually these fields should be variables inside the obfuscate method but in sync mode or with SingleThreadExecutor in async mode it's okay (even without ThreadLocal)
+ // If an ExecutorService with multiple threads is used, ThreadLocal must be used here + // If an ExecutorService with multiple threads is used, ThreadLocal must be used here
+ private final ThreadLocal<int[]> predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataLength()]); + private final ThreadLocal<int[]> predefinedBlockDataBits = ThreadLocal.withInitial(() -> new int[getPredefinedBlockDataFullLength()]);
+ private static final ThreadLocal<boolean[]> solid = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); + private static final ThreadLocal<boolean[]> solid = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]);
+ private static final ThreadLocal<boolean[]> obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]); + private static final ThreadLocal<boolean[]> obfuscate = ThreadLocal.withInitial(() -> new boolean[Block.REGISTRY_ID.size()]);
+ // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate + // These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate
@ -322,10 +330,12 @@ index 0000000000000000000000000000000000000000..b879f1796912bb8467202e946ccf0c92
+ if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == ChunkSection.GLOBAL_PALETTE) { + if (chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex) == ChunkSection.GLOBAL_PALETTE) {
+ predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal; + predefinedBlockDataBitsTemp = engineMode == EngineMode.HIDE ? chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.NETHER ? predefinedBlockDataBitsNetherrackGlobal : chunkPacketInfoAntiXray.getChunk().world.getWorld().getEnvironment() == Environment.THE_END ? predefinedBlockDataBitsEndStoneGlobal : predefinedBlockDataBitsStoneGlobal : predefinedBlockDataBitsGlobal;
+ } else { + } else {
+ // If it's this.predefinedBlockData, use this.predefinedBlockDataFull instead
+ IBlockData[] predefinedBlockDataFull = chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) == predefinedBlockData ? this.predefinedBlockDataFull : chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex);
+ predefinedBlockDataBitsTemp = predefinedBlockDataBits; + predefinedBlockDataBitsTemp = predefinedBlockDataBits;
+ +
+ for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) { + for (int i = 0; i < predefinedBlockDataBitsTemp.length; i++) {
+ predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex)[i]); + predefinedBlockDataBitsTemp[i] = chunkPacketInfoAntiXray.getDataPalette(chunkSectionIndex).getOrCreateIdFor(predefinedBlockDataFull[i]);
+ } + }
+ } + }
+ +