Fix for PaperSpigot and issue #188

master
Aleksey-Terzi 2018-10-24 18:00:08 +03:00
parent 972286af6c
commit b5fd5c57e7
5 changed files with 176 additions and 152 deletions

View File

@ -4,7 +4,7 @@
<groupId>com.lishid</groupId> <groupId>com.lishid</groupId>
<artifactId>orebfuscator</artifactId> <artifactId>orebfuscator</artifactId>
<version>4.4.1-SNAPSHOT</version> <version>4.4.2-SNAPSHOT</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Orebfuscator4</name> <name>Orebfuscator4</name>

View File

@ -7,17 +7,26 @@ package com.lishid.orebfuscator.chunkmap;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Stack;
import com.lishid.orebfuscator.NmsInstance; import com.lishid.orebfuscator.NmsInstance;
public class ChunkMapManager { public class ChunkMapManager implements AutoCloseable {
private static final ThreadLocal<ChunkMapBuffer> _buffer = new ThreadLocal<ChunkMapBuffer>() { private static final Object _lock = new Object();
@Override private static final Stack<ChunkMapBuffer> _bufferStack = new Stack<>();
protected ChunkMapBuffer initialValue() {
return new ChunkMapBuffer(); private static ChunkMapBuffer popBuffer() {
} synchronized(_lock) {
}; return _bufferStack.isEmpty() ? new ChunkMapBuffer() : _bufferStack.pop();
}
}
private static void pushBuffer(ChunkMapBuffer buffer) {
synchronized(_lock) {
_bufferStack.push(buffer);
}
}
private ChunkMapBuffer buffer; private ChunkMapBuffer buffer;
private ChunkData chunkData; private ChunkData chunkData;
private ChunkReader reader; private ChunkReader reader;
@ -42,43 +51,51 @@ public class ChunkMapManager {
return this.chunkData; return this.chunkData;
} }
public ChunkMapManager(ChunkData chunkData) { private ChunkMapManager() {
this.buffer = _buffer.get();
this.chunkData = chunkData; }
}
public static ChunkMapManager create(ChunkData chunkData) throws IOException {
public void init() throws IOException { ChunkMapManager manager = new ChunkMapManager();
this.reader = new ChunkReader(this.chunkData.data); manager.chunkData = chunkData;
this.sectionCount = 0; manager.buffer = popBuffer();
this.sectionIndex = -1; manager.reader = new ChunkReader(chunkData.data);
this.minX = this.chunkData.chunkX << 4; manager.sectionCount = 0;
this.maxX = this.minX + 15; manager.sectionIndex = -1;
this.minZ = this.chunkData.chunkZ << 4; manager.minX = chunkData.chunkX << 4;
this.maxZ = this.minZ + 15; manager.maxX = manager.minX + 15;
manager.minZ = chunkData.chunkZ << 4;
this.buffer.lightArrayLength = 2048; manager.maxZ = manager.minZ + 15;
manager.buffer.lightArrayLength = 2048;
if(this.chunkData.isOverworld) { if(chunkData.isOverworld) {
this.buffer.lightArrayLength <<= 1; manager.buffer.lightArrayLength <<= 1;
} }
manager.buffer.writer.init();
this.buffer.writer.init(); int mask = chunkData.primaryBitMask;
int mask = this.chunkData.primaryBitMask;
while(mask != 0) { while(mask != 0) {
if((mask & 0x1) != 0) { if((mask & 0x1) != 0) {
this.sectionCount++; manager.sectionCount++;
} }
mask >>>= 1; mask >>>= 1;
} }
this.buffer.clearLayers();
moveToNextLayer(); manager.buffer.clearLayers();
manager.moveToNextLayer();
return manager;
} }
public void close() throws Exception {
pushBuffer(this.buffer);
}
public boolean inputHasNonAirBlock() { public boolean inputHasNonAirBlock() {
return this.buffer.paletteLength > 1 || NmsInstance.current.isAir(this.buffer.palette[0]); return this.buffer.paletteLength > 1 || NmsInstance.current.isAir(this.buffer.palette[0]);
} }

View File

@ -59,7 +59,7 @@ public class ChunkReader {
private void readLong() throws IOException { private void readLong() throws IOException {
if(this.byteIndex + 7 >= this.data.length) { if(this.byteIndex + 7 >= this.data.length) {
throw new IOException("No data to read."); throw new IOException("No data to read. byteIndex = " + this.byteIndex);
} }
this.buffer = ((this.data[this.byteIndex] & 0xffL) << 56) this.buffer = ((this.data[this.byteIndex] & 0xffL) << 56)
@ -83,7 +83,7 @@ public class ChunkReader {
value |= (b & 0x7F) << (size++ * 7); value |= (b & 0x7F) << (size++ * 7);
if(size > 5) { if(size > 5) {
throw new IOException("Invalid VarInt."); throw new IOException("Invalid VarInt. byteIndex = " + this.byteIndex + ", value = " + value + ", size = " + size);
} }
} }
@ -92,7 +92,7 @@ public class ChunkReader {
public int readByte() throws IOException { public int readByte() throws IOException {
if(this.byteIndex >= this.data.length) { if(this.byteIndex >= this.data.length) {
throw new IOException("No data to read."); throw new IOException("No data to read. byteIndex = " + this.byteIndex);
} }
return this.data[this.byteIndex++] & 0xff; return this.data[this.byteIndex++] & 0xff;

View File

@ -18,6 +18,7 @@ package com.lishid.orebfuscator.hook;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -50,6 +51,8 @@ public class ProtocolLibHook {
this.manager.addPacketListener(new PacketAdapter(plugin, PacketType.Play.Server.MAP_CHUNK) { this.manager.addPacketListener(new PacketAdapter(plugin, PacketType.Play.Server.MAP_CHUNK) {
@Override @Override
public void onPacketSending(PacketEvent event) { public void onPacketSending(PacketEvent event) {
ChunkData chunkData = null;
try { try {
Player player = event.getPlayer(); Player player = event.getPlayer();
@ -72,7 +75,7 @@ public class ProtocolLibHook {
List nmsTags = list.read(0); List nmsTags = list.read(0);
ChunkData chunkData = new ChunkData(); chunkData = new ChunkData();
chunkData.chunkX = ints.read(0); chunkData.chunkX = ints.read(0);
chunkData.chunkZ = ints.read(1); chunkData.chunkZ = ints.read(1);
chunkData.groundUpContinuous = bools.read(0); chunkData.groundUpContinuous = bools.read(0);
@ -83,7 +86,7 @@ public class ProtocolLibHook {
Calculations.Result result = Calculations.obfuscateOrUseCache(chunkData, player, worldConfig); Calculations.Result result = Calculations.obfuscateOrUseCache(chunkData, player, worldConfig);
if(result.output != null) { if(result != null && result.output != null) {
byteArray.write(0, result.output); byteArray.write(0, result.output);
if(nmsTags != null) { if(nmsTags != null) {
@ -92,6 +95,10 @@ public class ProtocolLibHook {
} }
} }
} catch (Exception e) { } catch (Exception e) {
if(chunkData != null) {
Orebfuscator.logger.log(Level.SEVERE, "ChunkX = " + chunkData.chunkX + ", chunkZ = " + chunkData.chunkZ);
}
e.printStackTrace(); e.printStackTrace();
} }
} }
@ -147,7 +154,7 @@ public class ProtocolLibHook {
} }
} }
/* /*
private static boolean _isSaved; private static boolean _isSaved;
private void saveTestData(ChunkData chunkData) { private void saveTestData(ChunkData chunkData) {
if(_isSaved) return; if(_isSaved) return;
@ -156,7 +163,7 @@ public class ProtocolLibHook {
FileOutputStream fos; FileOutputStream fos;
try { try {
fos = new FileOutputStream("D:\\Temp\\chunk.dat"); fos = new FileOutputStream("D:\\Temp\\chunk_X" + chunkData.chunkX + "_Z" + chunkData.chunkZ + ".dat");
fos.write(chunkData.chunkX & 0xff); fos.write(chunkData.chunkX & 0xff);
fos.write((chunkData.chunkX >> 8) & 0xff); fos.write((chunkData.chunkX >> 8) & 0xff);
fos.write(chunkData.chunkZ & 0xff); fos.write(chunkData.chunkZ & 0xff);

View File

@ -48,7 +48,7 @@ public class Calculations {
private static Random random = new Random(); private static Random random = new Random();
public static Result obfuscateOrUseCache(ChunkData chunkData, Player player, WorldConfig worldConfig) throws IOException { public static Result obfuscateOrUseCache(ChunkData chunkData, Player player, WorldConfig worldConfig) throws Exception {
if(chunkData.primaryBitMask == 0) return null; if(chunkData.primaryBitMask == 0) return null;
byte[] output; byte[] output;
@ -67,7 +67,7 @@ public class Calculations {
removedEntities = new ArrayList<>(); removedEntities = new ArrayList<>();
output = obfuscate(worldConfig, chunkData, player, proximityBlocks, removedEntities); output = obfuscate(worldConfig, chunkData, player, proximityBlocks, removedEntities);
if (cache != null) { if (cache != null) {
// If cache is still allowed // If cache is still allowed
if(chunkData.useCache) { if(chunkData.useCache) {
@ -137,7 +137,7 @@ public class Calculations {
Player player, Player player,
ArrayList<BlockCoord> proximityBlocks, ArrayList<BlockCoord> proximityBlocks,
ArrayList<BlockCoord> removedEntities ArrayList<BlockCoord> removedEntities
) throws IOException ) throws Exception
{ {
ProximityHiderConfig proximityHider = worldConfig.getProximityHiderConfig(); ProximityHiderConfig proximityHider = worldConfig.getProximityHiderConfig();
int initialRadius = Orebfuscator.config.getInitialRadius(); int initialRadius = Orebfuscator.config.getInitialRadius();
@ -149,7 +149,6 @@ public class Calculations {
int engineMode = Orebfuscator.config.getEngineMode(); int engineMode = Orebfuscator.config.getEngineMode();
int maxChance = worldConfig.getAirGeneratorMaxChance(); int maxChance = worldConfig.getAirGeneratorMaxChance();
int incrementMax = maxChance;
int randomBlocksLength = worldConfig.getRandomBlocks().length; int randomBlocksLength = worldConfig.getRandomBlocks().length;
boolean randomAlternate = false; boolean randomAlternate = false;
@ -157,132 +156,133 @@ public class Calculations {
int startX = chunkData.chunkX << 4; int startX = chunkData.chunkX << 4;
int startZ = chunkData.chunkZ << 4; int startZ = chunkData.chunkZ << 4;
ChunkMapManager manager = new ChunkMapManager(chunkData); byte[] output;
manager.init();
for(int i = 0; i < manager.getSectionCount(); i++) { try (ChunkMapManager manager = ChunkMapManager.create(chunkData)) {
worldConfig.shuffleRandomBlocks(); for (int i = 0; i < manager.getSectionCount(); i++) {
worldConfig.shuffleRandomBlocks();
for(int offsetY = 0; offsetY < 16; offsetY++) { for (int offsetY = 0; offsetY < 16; offsetY++) {
for(int offsetZ = 0; offsetZ < 16; offsetZ++) { for (int offsetZ = 0; offsetZ < 16; offsetZ++) {
incrementMax = (maxChance + random(maxChance)) / 2; int incrementMax = (maxChance + random(maxChance)) / 2;
for(int offsetX = 0; offsetX < 16; offsetX++) {
int blockData = manager.readNextBlock();
int x = startX | offsetX;
int y = manager.getY();
int z = startZ | offsetZ;
// Initialize data for (int offsetX = 0; offsetX < 16; offsetX++) {
int obfuscateBits = worldConfig.getObfuscatedBits(blockData); int blockData = manager.readNextBlock();
boolean obfuscateFlag = (obfuscateBits & Globals.MASK_OBFUSCATE) != 0; int x = startX | offsetX;
boolean proximityHiderFlag = (obfuscateBits & Globals.MASK_PROXIMITYHIDER) != 0; int y = manager.getY();
boolean darknessBlockFlag = (obfuscateBits & Globals.MASK_DARKNESSBLOCK) != 0; int z = startZ | offsetZ;
boolean tileEntityFlag = (obfuscateBits & Globals.MASK_TILEENTITY) != 0;
boolean obfuscate = false; // Initialize data
boolean specialObfuscate = false; int obfuscateBits = worldConfig.getObfuscatedBits(blockData);
boolean obfuscateFlag = (obfuscateBits & Globals.MASK_OBFUSCATE) != 0;
boolean proximityHiderFlag = (obfuscateBits & Globals.MASK_PROXIMITYHIDER) != 0;
boolean darknessBlockFlag = (obfuscateBits & Globals.MASK_DARKNESSBLOCK) != 0;
boolean tileEntityFlag = (obfuscateBits & Globals.MASK_TILEENTITY) != 0;
// Check if the block should be obfuscated for the default engine modes boolean obfuscate = false;
if (obfuscateFlag) { boolean specialObfuscate = false;
if (initialRadius == 0) {
// Do not interfere with PH // Check if the block should be obfuscated for the default engine modes
if (proximityHiderFlag && proximityHider.isEnabled() && proximityHider.isProximityObfuscated(y, blockData)) { if (obfuscateFlag) {
if (!areAjacentBlocksTransparent(manager, player.getWorld(), false, x, y, z, 1)) { if (initialRadius == 0) {
// Do not interfere with PH
if (proximityHiderFlag && proximityHider.isEnabled() && proximityHider.isProximityObfuscated(y, blockData)) {
if (!areAjacentBlocksTransparent(manager, player.getWorld(), false, x, y, z, 1)) {
obfuscate = true;
}
} else {
// Obfuscate all blocks
obfuscate = true; obfuscate = true;
} }
} else { } else {
// Obfuscate all blocks // Check if any nearby blocks are transparent
obfuscate = true; if (!areAjacentBlocksTransparent(manager, player.getWorld(), false, x, y, z, initialRadius)) {
} obfuscate = true;
} else {
// Check if any nearby blocks are transparent
if (!areAjacentBlocksTransparent(manager, player.getWorld(), false, x, y, z, initialRadius)) {
obfuscate = true;
}
}
}
// Check if the block should be obfuscated because of proximity check
if (!obfuscate && proximityHiderFlag && proximityHider.isEnabled() && proximityHider.isProximityObfuscated(y, blockData)) {
BlockCoord block = new BlockCoord(x, y, z);
if (block != null) {
proximityBlocks.add(block);
}
obfuscate = true;
if (proximityHider.isUseSpecialBlock()) {
specialObfuscate = true;
}
}
// Check if the block is obfuscated
if (obfuscate && (!worldConfig.isBypassObfuscationForSignsWithText() || canObfuscate(chunkData, x, y, z, blockData))) {
if (specialObfuscate) {
// Proximity hider
blockData = proximityHider.getSpecialBlockID();
} else {
if (engineMode == 1) {
// Engine mode 1, replace with stone
blockData = worldConfig.getMode1BlockId();
} else if (engineMode == 2) {
// Ending mode 2, replace with random block
if (randomBlocksLength > 1) {
randomIncrement = CalculationsUtil.increment(randomIncrement, randomBlocksLength);
}
blockData = worldConfig.getRandomBlock(randomIncrement, randomAlternate);
randomAlternate = !randomAlternate;
}
// Anti texturepack and freecam
if (worldConfig.isAntiTexturePackAndFreecam()) {
// Add random air blocks
randomIncrement2 = random(incrementMax);
if (randomIncrement2 == 0) {
randomCave = 1 + random(3);
}
if (randomCave > 0) {
blockData = NmsInstance.current.getCaveAirBlockId();
randomCave--;
} }
} }
} }
}
// Check if the block should be obfuscated because of the darkness // Check if the block should be obfuscated because of proximity check
if (!obfuscate && darknessBlockFlag && worldConfig.isDarknessHideBlocks()) { if (!obfuscate && proximityHiderFlag && proximityHider.isEnabled() && proximityHider.isProximityObfuscated(y, blockData)) {
if (!areAjacentBlocksBright(player.getWorld(), x, y, z, 1)) { BlockCoord block = new BlockCoord(x, y, z);
// Hide block, setting it to air if (block != null) {
blockData = NmsInstance.current.getCaveAirBlockId(); proximityBlocks.add(block);
}
obfuscate = true; obfuscate = true;
if (proximityHider.isUseSpecialBlock()) {
specialObfuscate = true;
}
} }
// Check if the block is obfuscated
if (obfuscate && (!worldConfig.isBypassObfuscationForSignsWithText() || canObfuscate(chunkData, x, y, z, blockData))) {
if (specialObfuscate) {
// Proximity hider
blockData = proximityHider.getSpecialBlockID();
} else {
if (engineMode == 1) {
// Engine mode 1, replace with stone
blockData = worldConfig.getMode1BlockId();
} else if (engineMode == 2) {
// Ending mode 2, replace with random block
if (randomBlocksLength > 1) {
randomIncrement = CalculationsUtil.increment(randomIncrement, randomBlocksLength);
}
blockData = worldConfig.getRandomBlock(randomIncrement, randomAlternate);
randomAlternate = !randomAlternate;
}
// Anti texturepack and freecam
if (worldConfig.isAntiTexturePackAndFreecam()) {
// Add random air blocks
randomIncrement2 = random(incrementMax);
if (randomIncrement2 == 0) {
randomCave = 1 + random(3);
}
if (randomCave > 0) {
blockData = NmsInstance.current.getCaveAirBlockId();
randomCave--;
}
}
}
}
// Check if the block should be obfuscated because of the darkness
if (!obfuscate && darknessBlockFlag && worldConfig.isDarknessHideBlocks()) {
if (!areAjacentBlocksBright(player.getWorld(), x, y, z, 1)) {
// Hide block, setting it to air
blockData = NmsInstance.current.getCaveAirBlockId();
obfuscate = true;
}
}
if (obfuscate && tileEntityFlag) {
removedEntities.add(new BlockCoord(x, y, z));
}
if (offsetY == 0 && offsetZ == 0 && offsetX == 0) {
manager.finalizeOutput();
manager.initOutputPalette();
addBlocksToPalette(manager, worldConfig);
manager.initOutputSection();
}
manager.writeOutputBlock(blockData);
} }
}
}
}
if (obfuscate && tileEntityFlag) { manager.finalizeOutput();
removedEntities.add(new BlockCoord(x, y, z));
}
if(offsetY == 0 && offsetZ == 0 && offsetX == 0) { output = manager.createOutput();
manager.finalizeOutput(); }
manager.initOutputPalette();
addBlocksToPalette(manager, worldConfig);
manager.initOutputSection();
}
manager.writeOutputBlock(blockData);
}
}
}
}
manager.finalizeOutput();
byte[] output = manager.createOutput();
ProximityHider.addProximityBlocks(player, chunkData.chunkX, chunkData.chunkZ, proximityBlocks); ProximityHider.addProximityBlocks(player, chunkData.chunkX, chunkData.chunkZ, proximityBlocks);
//Orebfuscator.log("Create new chunk data for x = " + chunkData.chunkX + ", z = " + chunkData.chunkZ);/*debug*/ //Orebfuscator.log("Create new chunk data for x = " + chunkData.chunkX + ", z = " + chunkData.chunkZ);/*debug*/
return output; return output;