From c307ff5387f0bc951b2f60a8da2a5ba10fd6a96c Mon Sep 17 00:00:00 2001 From: shsa Date: Thu, 29 Jan 2015 15:22:58 +0700 Subject: [PATCH] base version --- java/Orebfuscator/BlockChange.java | 110 ++++++++++++++++++++++++++++ java/Orebfuscator/ChunkInfo.java | 74 ++++++++++++++----- java/Orebfuscator/Fields.java | 22 ++++++ java/Orebfuscator/MapChunkBulk.java | 62 +++++++++------- java/Orebfuscator/ProxyChannel.java | 17 ++++- 5 files changed, 238 insertions(+), 47 deletions(-) create mode 100644 java/Orebfuscator/BlockChange.java diff --git a/java/Orebfuscator/BlockChange.java b/java/Orebfuscator/BlockChange.java new file mode 100644 index 0000000..cf6adc9 --- /dev/null +++ b/java/Orebfuscator/BlockChange.java @@ -0,0 +1,110 @@ +package Orebfuscator; + +import io.netty.channel.Channel; + +import java.lang.reflect.Field; +import java.util.HashSet; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; +import net.minecraft.network.play.server.S23PacketBlockChange; +import net.minecraft.world.World; + +public class BlockChange +{ + public static Field fieldPositionX = null; + public static Field fieldPositionY = null; + public static Field fieldPositionZ = null; + public static HashSet list = new HashSet(); + + public static int baseX; + public static int baseY; + public static int baseZ; + + public static byte offset = 2; + public static int startPos; + + public static void parse(World world, Channel channel, S23PacketBlockChange packet) + { + if (fieldPositionX == null) + { + fieldPositionX = Fields.getField(packet, "field_148887_a"); + fieldPositionY = Fields.getField(packet, "field_148885_b"); + fieldPositionZ = Fields.getField(packet, "field_148886_c"); + } + + int x = (Integer) Fields.getValue(packet, fieldPositionX); + int y = (Integer) Fields.getValue(packet, fieldPositionY); + int z = (Integer) Fields.getValue(packet, fieldPositionZ); + + // используем базовую точку, чтобы в дальнейшем высчитывать смещения обновляемых блоков + // смещения будем сводить в один int и хранить в HashSet + baseX = x - offset; + baseY = y - offset; + baseZ = z - offset; + + x = offset; + y = offset; + z = offset; + + startPos = (offset << 16) | (offset << 8) | offset; + + list.clear(); + updateAjacentBlocks(world, offset, offset, offset, offset + 1); + for (int pos : list) + { + x = baseX + (pos >> 16 & 255); + y = baseY + (pos >> 8 & 255); + z = baseZ + (pos & 255); + + world.markBlockForUpdate(x, y, z); + } + } + + public static boolean isTransparent(World world, int x, int y, int z) + { + int pos = (x << 16) | (y << 8) | z; + if (pos == startPos) + return false; + + Block block = world.getBlock(baseX + x, baseY + y, baseZ + z); + return Orebfuscator.isBlockTransparent(Block.getIdFromBlock(block)); + } + + public static boolean needUpdate(World world, int x, int y, int z) + { + int pos = (x << 16) | (y << 8) | z; + if (pos == startPos) + return false; + + return !( + isTransparent(world, x - 1, y, z) || isTransparent(world, x + 1, y, z) || + isTransparent(world, x, y - 1, z) || isTransparent(world, x, y + 1, z) || + isTransparent(world, x, y, z - 1) || isTransparent(world, x, y, z + 1) + ); + } + + public static boolean updateAjacentBlocks(World world, int x, int y, int z, int step) + { + if (step == 0) + return false; + + int pos = (x << 16) | (y << 8) | z; + if (list.contains(pos)) + return false; + + if (needUpdate(world, x, y, z)) + list.add(pos); + + step--; + updateAjacentBlocks(world, x - 1, y, z, step); + updateAjacentBlocks(world, x + 1, y, z, step); + updateAjacentBlocks(world, x, y - 1, z, step); + updateAjacentBlocks(world, x, y + 1, z, step); + updateAjacentBlocks(world, x, y, z - 1, step); + updateAjacentBlocks(world, x, y, z + 1, step); + + return true; + } +} diff --git a/java/Orebfuscator/ChunkInfo.java b/java/Orebfuscator/ChunkInfo.java index 4955c67..7a61439 100644 --- a/java/Orebfuscator/ChunkInfo.java +++ b/java/Orebfuscator/ChunkInfo.java @@ -1,7 +1,9 @@ package Orebfuscator; +import net.minecraft.block.Block; import net.minecraft.network.play.server.S26PacketMapChunkBulk; import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; public class ChunkInfo { @@ -10,7 +12,7 @@ public class ChunkInfo //public boolean[] listLSB = new boolean[16]; //public boolean[] listMSB = new boolean[16]; - // offsetsLSB[] - содержит список позиций, с которых начинаются блоки размером 16x16x16 содержащие первые 8 бит BlockID + // offsetsLSB[] - содержит список секций, с которых начинаются блоки размером 16x16x16 содержащие первые 8 бит BlockID // размер секции 16*16*16 = 4096 байт public int[] offsetsLSB = new int[16]; @@ -24,11 +26,18 @@ public class ChunkInfo // NibbleArray ExtendedBlockStorage.blockMSBArray public int[] offsetsMSB = new int[16]; + public int chunkX; + public int chunkZ; + + // Максимальный индекс+1 секции public int len; public byte[] data; - public void parse(World world, byte[] data, int sectionLSB, int sectionMSB) + public void parse(World world, int chunkX, int chunkZ, int sectionLSB, int sectionMSB, byte[] data) { + this.chunkX = chunkX; + this.chunkZ = chunkZ; + this.data = data; int countLSB = 0; len = 0; @@ -61,15 +70,6 @@ public class ChunkInfo } } - for (i = 0; i < len; i++) - { - if (offsetsLSB[i] > -1) - { - offsetsMetadata[i] = pos; - pos += 2048; - } - } - for (i = 0; i < len; i++) { if (offsetsLSB[i] > -1) @@ -110,16 +110,17 @@ public class ChunkInfo { for (int z = 0; z < 16; z++) { + /* if ((x > 0 && x < 16) && (y == 0 || y == 15) && (z == 0 || z == 15)) setBlockID(x, y, z, 1); if ((x == 0 || x == 15) && (y > 0 || y < 16) && (z == 0 || z == 15)) setBlockID(x, y, z, 1); if ((x == 0 || x == 15) && (y == 0 || y == 15) && (z > 0 || z < 16)) setBlockID(x, y, z, 1); - - if (!Orebfuscator.isBlockTransparent(getBlockID(x, y, z))) + */ + if (neetObfuscate(world, x, i << 4 | y, z)) { - //data[pos + n] = 1; + setBlockID(x, i << 4 | y, z, 57); } } } @@ -131,14 +132,14 @@ public class ChunkInfo /** * Returns the block corresponding to the given coordinates inside a chunk. */ - public int getBlockID(int x, int y, int z) + public int getBlockID(World world, int x, int y, int z) { int section = y >> 4; if (this.offsetsLSB[section] > -1) { y = y & 15; - int id = this.data[this.offsetsLSB[section] + y << 8 | z << 4 | x] & 255; + int id = this.data[this.offsetsLSB[section] + (y << 8 | z << 4 | x)] & 255; if (this.offsetsMSB[section] > -1) { int l = y << 4 | z << 4 | x; @@ -146,8 +147,10 @@ public class ChunkInfo int j1 = l & 1; id |= j1 == 0 ? this.data[this.offsetsMSB[section] + i1] & 15 : this.data[this.offsetsMSB[section] + i1] >> 4 & 15; } + + return id; } - + return 0; } @@ -158,7 +161,7 @@ public class ChunkInfo { y = y & 15; - this.data[this.offsetsLSB[section] + y << 8 | z << 4 | x] = (byte) (blockID & 255); + this.data[this.offsetsLSB[section] + (y << 8 | z << 4 | x)] = (byte) (blockID & 255); if (this.offsetsMSB[section] > -1) { int l = y << 4 | z << 4 | x; @@ -176,4 +179,39 @@ public class ChunkInfo } } } + + public boolean isTransparent(World world, int x, int y, int z) + { + if (y < 0 || y > 255) + return true; + + if (x < 0 || x > 15 || z < 0 || z > 15) + { + /* + Block block = world.getBlock((this.chunkX << 4) | x, y, (this.chunkZ << 4) | z); + return Orebfuscator.isBlockTransparent(Block.getIdFromBlock(block)); + */ + return true; + } + + + return Orebfuscator.isBlockTransparent(getBlockID(world, x, y, z)); + } + + public boolean neetObfuscate(World world, int x, int y, int z) + { + if (isTransparent(world, x, y, z)) + { + return false; + } + + return !( + isTransparent(world, x - 1, y, z) || + isTransparent(world, x + 1, y, z) || + isTransparent(world, x, y - 1, z) || + isTransparent(world, x, y + 1, z) || + isTransparent(world, x, y, z - 1) || + isTransparent(world, x, y, z + 1) + ); + } } diff --git a/java/Orebfuscator/Fields.java b/java/Orebfuscator/Fields.java index 10dd42e..4812448 100644 --- a/java/Orebfuscator/Fields.java +++ b/java/Orebfuscator/Fields.java @@ -39,6 +39,28 @@ public class Fields return null; } + public static Object getValue(Object instance, Field field) + { + try { + return field.get(instance); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Field getField(Object instance, String name) + { + try { + Field field = instance.getClass().getDeclaredField(name); + field.setAccessible(true); + return field; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + public static void setValue(Object instance, int index, Object value) { try { diff --git a/java/Orebfuscator/MapChunkBulk.java b/java/Orebfuscator/MapChunkBulk.java index daf8e46..e6ab044 100644 --- a/java/Orebfuscator/MapChunkBulk.java +++ b/java/Orebfuscator/MapChunkBulk.java @@ -1,42 +1,52 @@ package Orebfuscator; +import java.lang.reflect.Field; + import net.minecraft.network.play.server.S26PacketMapChunkBulk; import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; public class MapChunkBulk { - public int offsetLSB; - public int offsetMSB; - public int offsetMetadata; - public int offsetBlocklight; - public int len; - public int lenLSB; - public int lenMSB; - public int[] bufLSB; - public int[] bufMSB; - public byte[][] dataArray; - public byte[] data; + public static Field fieldChunkX; + public static Field fieldChunkZ; - public MapChunkBulk(S26PacketMapChunkBulk packet, World world) + + // 1110011 - набор блоков (ExtendedBlockStorage.blockLSBArray) по высоте (1 - есть блок, 0 - нет блока) + public static Field fieldStatusLSB = null; + + // 0001110 - набор блоков (ExtendedBlockStorage.blockMSBArray) по высоте (1 - есть блок, 0 - нет блока) + public static Field fieldStatusMSB; + + // -- массив данных + public static Field fieldData; + + public static ChunkInfo info; + + public static void parse(World world, S26PacketMapChunkBulk packet) { - int k = 0; - int l; + if (fieldStatusLSB == null) + { + fieldChunkX = Fields.getField(packet, "field_149266_a"); + fieldChunkZ = Fields.getField(packet, "field_149264_b"); - bufLSB = (int[]) Fields.getValue(packet, "field_149265_c"); // 1110011 - набор блоков (ExtendedBlockStorage.blockLSBArray) по высоте (1 - есть блок, 0 - нет блока) - bufMSB = (int[]) Fields.getValue(packet, "field_149262_d"); // 0001110 - набор блоков (ExtendedBlockStorage.blockMSBArray) по высоте (1 - есть блок, 0 - нет блока) - dataArray = (byte[][]) Fields.getValue(packet, "field_149260_f"); // -- массив данных + fieldStatusLSB = Fields.getField(packet, "field_149265_c"); + fieldStatusMSB = Fields.getField(packet, "field_149262_d"); + fieldData = Fields.getField(packet, "field_149260_f"); + + info = new ChunkInfo(); + } + - ChunkInfo info = new ChunkInfo(); - - int lsb; - int msb; - int pos; - int len; - - for (int i = 0; i < bufLSB.length; i++) + int[] chunkX = (int[]) Fields.getValue(packet, fieldChunkX); + int[] chunkZ = (int[]) Fields.getValue(packet, fieldChunkZ); + int[] statusLSB = (int[]) Fields.getValue(packet, fieldStatusLSB); + int[] statusMSB = (int[]) Fields.getValue(packet, fieldStatusMSB); + byte[][] dataArray = (byte[][]) Fields.getValue(packet, fieldData); + + for (int i = 0; i < statusLSB.length; i++) { - info.parse(world, dataArray[i], bufLSB[i], bufMSB[i]); + info.parse(world, chunkX[i], chunkZ[i], statusLSB[i], statusMSB[i], dataArray[i]); } } } diff --git a/java/Orebfuscator/ProxyChannel.java b/java/Orebfuscator/ProxyChannel.java index d7e95fb..0dfec06 100644 --- a/java/Orebfuscator/ProxyChannel.java +++ b/java/Orebfuscator/ProxyChannel.java @@ -3,6 +3,7 @@ package Orebfuscator; import java.net.SocketAddress; import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.play.server.S23PacketBlockChange; import net.minecraft.network.play.server.S26PacketMapChunkBulk; import io.netty.buffer.ByteBufAllocator; import io.netty.channel.Channel; @@ -32,11 +33,21 @@ public class ProxyChannel implements Channel if (msg instanceof S26PacketMapChunkBulk) { S26PacketMapChunkBulk packet = (S26PacketMapChunkBulk)msg; - MapChunkBulk chunk = new MapChunkBulk(packet, player.worldObj); - - //Log.msg("%d", field_149260_f[0].length); + MapChunkBulk.parse(player.worldObj, packet); + return; + } + if (msg instanceof MyPacketBlockChange) + { + return; + } + if (msg instanceof S23PacketBlockChange) + { + S23PacketBlockChange packet = (S23PacketBlockChange)msg; + BlockChange.parse(player.worldObj, channel, packet); + return; } + //world.scheduleBlockUpdate(x, y, z, this, tickRate); //Log.msg("%s", msg.getClass().getName()); }