mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 12:27:59 +01:00
Make engine-mode 2 truly random
Up to now a simple counter variable was used to iterate through the hidden-blocks in engine-mode 2 while obfuscating. This results in low quality obfuscation. One could for example easily write a hack, which bypasses Anti-Xray by not showing ores, which have a certain pattern. Furthermore, engine-mode 1 is slightly optimized by this commit. However, engine-mode 2 is probably somewhat slower. I did some tests but I wasn't able to get stable results for some reason. Therefore this needs further testing. An optimized random algorithm is utilized to pick random blocks from the hidden-blocks list. This implementation uses xorshift and integer multiplication for bounding. The resulting distribution is negligibly biased because xorshift doesn't generate 0 and integer multiplication also implies biased results.
This commit is contained in:
parent
cd06ca5eb8
commit
0bad695802
@ -98,10 +98,10 @@ 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
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c1456ca57be1
|
||||
index 0000000000000000000000000000000000000000..70b854c2619551df1f1984204010fa15b743234a
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/com/destroystokyo/paper/antixray/ChunkPacketBlockControllerAntiXray.java
|
||||
@@ -0,0 +1,622 @@
|
||||
@@ -0,0 +1,604 @@
|
||||
+package com.destroystokyo.paper.antixray;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
@ -109,6 +109,8 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+import java.util.List;
|
||||
+import java.util.Set;
|
||||
+import java.util.concurrent.Executor;
|
||||
+import java.util.concurrent.ThreadLocalRandom;
|
||||
+import java.util.function.IntSupplier;
|
||||
+
|
||||
+import net.minecraft.server.*;
|
||||
+import org.bukkit.Bukkit;
|
||||
@ -290,7 +292,25 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ boolean[] obfuscateTemp = null;
|
||||
+ dataBitsReader.setDataBits(chunkPacketInfoAntiXray.getData());
|
||||
+ dataBitsWriter.setDataBits(chunkPacketInfoAntiXray.getData());
|
||||
+ int counter = 0;
|
||||
+ int numberOfBlocks = predefinedBlockDataBits.length;
|
||||
+ // Keep the lambda expressions as simple as possible. They are used very frequently.
|
||||
+ IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() {
|
||||
+ private int state;
|
||||
+
|
||||
+ {
|
||||
+ while ((state = ThreadLocalRandom.current().nextInt()) == 0);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public int getAsInt() {
|
||||
+ // https://en.wikipedia.org/wiki/Xorshift
|
||||
+ state ^= state << 13;
|
||||
+ state ^= state >>> 17;
|
||||
+ state ^= state << 5;
|
||||
+ // https://www.pcg-random.org/posts/bounded-rands.html
|
||||
+ return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32);
|
||||
+ }
|
||||
+ };
|
||||
+
|
||||
+ for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) {
|
||||
+ if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPredefinedObjects(chunkSectionIndex) != null) {
|
||||
@ -328,7 +348,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+
|
||||
+ // Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section
|
||||
+ dataBitsWriter.setBitsPerObject(0);
|
||||
+ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, counter);
|
||||
+ obfuscateLayer(-1, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, emptyNearbyChunkSections, random);
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.setBitsPerObject(chunkPacketInfoAntiXray.getBitsPerObject(chunkSectionIndex));
|
||||
@ -343,7 +363,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ current = next;
|
||||
+ next = nextNext;
|
||||
+ nextNext = temp;
|
||||
+ counter = obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, counter);
|
||||
+ obfuscateLayer(y, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random);
|
||||
+ }
|
||||
+
|
||||
+ // Check if the chunk section above doesn't need obfuscation
|
||||
@ -368,7 +388,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ // There is nothing to read anymore
|
||||
+ dataBitsReader.setBitsPerObject(0);
|
||||
+ solid[0] = true;
|
||||
+ counter = obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, counter);
|
||||
+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solid, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random);
|
||||
+ }
|
||||
+ } else {
|
||||
+ // If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section
|
||||
@ -380,7 +400,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ current = next;
|
||||
+ next = nextNext;
|
||||
+ nextNext = temp;
|
||||
+ counter = obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, counter);
|
||||
+ obfuscateLayer(15, dataBitsReader, dataBitsWriter, solidTemp, obfuscateTemp, predefinedBlockDataBitsTemp, current, next, nextNext, nearbyChunkSections, random);
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.finish();
|
||||
@ -390,7 +410,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ chunkPacketInfoAntiXray.getPacketPlayOutMapChunk().setReady(true);
|
||||
+ }
|
||||
+
|
||||
+ private int obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, ChunkSection[] nearbyChunkSections, int counter) {
|
||||
+ private void obfuscateLayer(int y, DataBitsReader dataBitsReader, DataBitsWriter dataBitsWriter, boolean[] solid, boolean[] obfuscate, int[] predefinedBlockDataBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, ChunkSection[] nearbyChunkSections, IntSupplier random) {
|
||||
+ // First block of first line
|
||||
+ int dataBits = dataBitsReader.read();
|
||||
+
|
||||
@ -402,11 +422,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(0, y, 15))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 0))] || current[0][0]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -427,11 +443,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(x, y, 15))] || current[0][x]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -451,11 +463,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[2] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[2].getType(15, y, 15))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 0))] || current[0][15]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -477,11 +485,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, z))] || current[z][0]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -503,11 +507,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (current[z][x]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -528,11 +528,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, z))] || current[z][15]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -552,11 +548,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(0, y, 0))] || nearbyChunkSections[0] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[0].getType(15, y, 15))] || current[15][0]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -577,11 +569,7 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(x, y, 0))] || current[15][x]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
@ -601,19 +589,13 @@ index 0000000000000000000000000000000000000000..f475427af03a0bcd69a215daf3d0c145
|
||||
+ if (nearbyChunkSections[3] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[3].getType(15, y, 0))] || nearbyChunkSections[1] == Chunk.EMPTY_CHUNK_SECTION || !solidGlobal[ChunkSection.GLOBAL_PALETTE.getOrCreateIdFor(nearbyChunkSections[1].getType(0, y, 15))] || current[15][15]) {
|
||||
+ dataBitsWriter.skip();
|
||||
+ } else {
|
||||
+ if (counter >= predefinedBlockDataBits.length) {
|
||||
+ counter = 0;
|
||||
+ }
|
||||
+
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[counter++]);
|
||||
+ dataBitsWriter.write(predefinedBlockDataBits[random.getAsInt()]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!obfuscate[dataBits]) {
|
||||
+ next[15][15] = true;
|
||||
+ }
|
||||
+
|
||||
+ return counter;
|
||||
+ }
|
||||
+
|
||||
+ private boolean[] readDataPalette(DataPalette<IBlockData> dataPalette, boolean[] temp, boolean[] global) {
|
||||
|
Loading…
Reference in New Issue
Block a user