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>
<artifactId>orebfuscator</artifactId>
<version>4.4.1-SNAPSHOT</version>
<version>4.4.2-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Orebfuscator4</name>

View File

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

View File

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

View File

@ -48,7 +48,7 @@ public class Calculations {
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;
byte[] output;
@ -67,7 +67,7 @@ public class Calculations {
removedEntities = new ArrayList<>();
output = obfuscate(worldConfig, chunkData, player, proximityBlocks, removedEntities);
if (cache != null) {
// If cache is still allowed
if(chunkData.useCache) {
@ -137,7 +137,7 @@ public class Calculations {
Player player,
ArrayList<BlockCoord> proximityBlocks,
ArrayList<BlockCoord> removedEntities
) throws IOException
) throws Exception
{
ProximityHiderConfig proximityHider = worldConfig.getProximityHiderConfig();
int initialRadius = Orebfuscator.config.getInitialRadius();
@ -149,7 +149,6 @@ public class Calculations {
int engineMode = Orebfuscator.config.getEngineMode();
int maxChance = worldConfig.getAirGeneratorMaxChance();
int incrementMax = maxChance;
int randomBlocksLength = worldConfig.getRandomBlocks().length;
boolean randomAlternate = false;
@ -157,132 +156,133 @@ public class Calculations {
int startX = chunkData.chunkX << 4;
int startZ = chunkData.chunkZ << 4;
ChunkMapManager manager = new ChunkMapManager(chunkData);
manager.init();
byte[] output;
for(int i = 0; i < manager.getSectionCount(); i++) {
worldConfig.shuffleRandomBlocks();
try (ChunkMapManager manager = ChunkMapManager.create(chunkData)) {
for (int i = 0; i < manager.getSectionCount(); i++) {
worldConfig.shuffleRandomBlocks();
for(int offsetY = 0; offsetY < 16; offsetY++) {
for(int offsetZ = 0; offsetZ < 16; offsetZ++) {
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;
for (int offsetY = 0; offsetY < 16; offsetY++) {
for (int offsetZ = 0; offsetZ < 16; offsetZ++) {
int incrementMax = (maxChance + random(maxChance)) / 2;
// Initialize data
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;
for (int offsetX = 0; offsetX < 16; offsetX++) {
int blockData = manager.readNextBlock();
int x = startX | offsetX;
int y = manager.getY();
int z = startZ | offsetZ;
boolean obfuscate = false;
boolean specialObfuscate = false;
// Initialize data
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
if (obfuscateFlag) {
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)) {
boolean obfuscate = false;
boolean specialObfuscate = false;
// Check if the block should be obfuscated for the default engine modes
if (obfuscateFlag) {
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;
}
} else {
// Obfuscate all blocks
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 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 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();
// 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
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) {
removedEntities.add(new BlockCoord(x, y, z));
}
manager.finalizeOutput();
if(offsetY == 0 && offsetZ == 0 && offsetX == 0) {
manager.finalizeOutput();
manager.initOutputPalette();
addBlocksToPalette(manager, worldConfig);
manager.initOutputSection();
}
manager.writeOutputBlock(blockData);
}
}
}
}
manager.finalizeOutput();
byte[] output = manager.createOutput();
output = manager.createOutput();
}
ProximityHider.addProximityBlocks(player, chunkData.chunkX, chunkData.chunkZ, proximityBlocks);
//Orebfuscator.log("Create new chunk data for x = " + chunkData.chunkX + ", z = " + chunkData.chunkZ);/*debug*/
return output;