diff --git a/README.md b/README.md index 45f626b..862341b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # orebfuscator orebfuscator for mcpc+ 1.7.10 + +original idea https://github.com/Shevchik/Orebfuscator diff --git a/java/Orebfuscator/AsyncPacketQueue.java b/java/Orebfuscator/AsyncPacketQueue.java new file mode 100644 index 0000000..ffa525a --- /dev/null +++ b/java/Orebfuscator/AsyncPacketQueue.java @@ -0,0 +1,124 @@ +package Orebfuscator; + +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Queue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; + +public class AsyncPacketQueue implements Iterable, Collection, Queue +{ + + public Queue queue; + public EntityPlayerMP player; + + public AsyncPacketQueue(EntityPlayerMP player, Queue queue) + { + this.player = player; + this.queue = queue; + } + + @Override + public boolean add(E arg0) { + //Packet packet = (Packet) Fields.getValue(arg0, Fields.InboundHandlerTuplePacketListener.getPacketIndex()); + //Log.msg("%s", packet.getClass().getName()); + Log.msg("%s", arg0.getClass().getName()); + return this.queue.add(arg0); + } + + public void cleanup() { + this.player = null; + } + + @Override + public E element() { + return (E) this.queue.element(); + } + + @Override + public boolean offer(E arg0) { + return this.queue.offer(arg0); + } + + @Override + public E peek() { + return (E) this.queue.peek(); + } + + @Override + public E poll() { + return (E) this.queue.poll(); + } + + @Override + public E remove() { + return (E) this.queue.remove(); + } + + @Override + public boolean addAll(Collection arg0) { + Log.error("Queue.addAll"); + return this.queue.addAll(arg0); + } + + @Override + public void clear() { + this.queue.clear(); + } + + @Override + public boolean contains(Object arg0) { + return this.queue.contains(arg0); + } + + @Override + public boolean containsAll(Collection arg0) { + return this.queue.containsAll(arg0); + } + + @Override + public boolean isEmpty() { + return this.queue.isEmpty(); + } + + @Override + public boolean remove(Object arg0) { + return this.queue.remove(arg0); + } + + @Override + public boolean removeAll(Collection arg0) { + return this.queue.removeAll(arg0); + } + + @Override + public boolean retainAll(Collection arg0) { + return this.queue.removeAll(arg0); + } + + @Override + public int size() { + return this.queue.size(); + } + + @Override + public Object[] toArray() { + return this.queue.toArray(); + } + + @Override + public T[] toArray(T[] arg0) { + return (T[]) this.queue.toArray(arg0); + } + + @Override + public Iterator iterator() { + return this.queue.iterator(); + } +} diff --git a/java/Orebfuscator/Fields.java b/java/Orebfuscator/Fields.java new file mode 100644 index 0000000..10dd42e --- /dev/null +++ b/java/Orebfuscator/Fields.java @@ -0,0 +1,84 @@ +package Orebfuscator; + +import java.lang.reflect.Field; + +public class Fields +{ + public static int findFieldIndex(Class clazz, String fieldName) + { + Field[] fields = clazz.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) + { + if (fields[i].getName().equals(fieldName)) + return i; + } + return -1; + } + + public static Object getValue(Object instance, int index) + { + try { + Field field = instance.getClass().getDeclaredFields()[index]; + field.setAccessible(true); + return field.get(instance); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static Object getValue(Object instance, String name) + { + try { + Field field = instance.getClass().getDeclaredField(name); + field.setAccessible(true); + return field.get(instance); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + public static void setValue(Object instance, int index, Object value) + { + try { + Field field = instance.getClass().getDeclaredFields()[index]; + field.setAccessible(true); + field.set(instance, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static class NetworkManager + { + public static String getOutboundPacketsQueueName() + { + return "outboundPacketsQueue"; + } + + public static int getReceivedPacketsQueueIndex() + { + return 10; + } + + public static int getOutboundPacketsQueueIndex() + { + return 11; + } + + public static int getChannelIndex() + { + return 12; + } + } + + + public static class InboundHandlerTuplePacketListener + { + public static int getPacketIndex() + { + return 0; + } + } +} diff --git a/java/Orebfuscator/Log.java b/java/Orebfuscator/Log.java new file mode 100644 index 0000000..9b69e43 --- /dev/null +++ b/java/Orebfuscator/Log.java @@ -0,0 +1,42 @@ +package Orebfuscator; + +import java.util.Locale; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.ThreadContext; + +import cpw.mods.fml.common.TracingPrintStream; +import cpw.mods.fml.relauncher.FMLRelaunchLog; + +public class Log +{ + private static boolean configured; + private static Logger myLog; + + private static void configureLogging() + { + myLog = LogManager.getLogger(Orebfuscator.MODID); + configured = true; + } + + public static void log(Level level, String format, Object... data) + { + if (!configured) + { + configureLogging(); + } + myLog.log(level, String.format(format, data)); + } + + public static void msg(String format, Object... data) + { + log(Level.INFO, format, data); + } + + public static void error(String format, Object... data) + { + log(Level.ERROR, format, data); + } +} diff --git a/java/Orebfuscator/MapChunkBulk.java b/java/Orebfuscator/MapChunkBulk.java new file mode 100644 index 0000000..a522f03 --- /dev/null +++ b/java/Orebfuscator/MapChunkBulk.java @@ -0,0 +1,115 @@ +package Orebfuscator; + +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 MapChunkBulk(S26PacketMapChunkBulk packet, World world) + { + int k = 0; + int l; + + 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"); // -- массив данных + + int lsb; + int msb; + int pos; + int len; + + for (int i = 0; i < bufLSB.length; i++) + { + lenLSB = 0; + lenMSB = 0; + len = 0; + for (int j = 0; j < 16; ++j) + { + l = bufLSB[i] >> j & 1; + + if (l == 1) + { + lenLSB++; + len = j + 1; + l = bufMSB[i] >> j & 1; + lenMSB++; + } + } + + offsetLSB = 0; // с этой позиции начинаются блоки размером 16x16x16 содержащие первые 8 бит BlockID + // размер блока 16*16*16 = 4096 байт + offsetMetadata = offsetLSB + lenLSB * 4096; // начало NibbleArrays содержащих ExtendedBlockStorage.blockMetadataArray + // размер массива (16*16*16)/2 = 2048 (делим попалам, т.к. в одном байте содержится два значения по 4 бита) + offsetBlocklight = offsetMetadata + lenLSB * 2048; // начало NibbleArray содержащего ExtendedBlockStorage.blocklightArray + + // NibbleArray ExtendedBlockStorage.blockMSBArray + if (world.provider.hasNoSky) + { + offsetMSB = offsetBlocklight + lenLSB * 2048; + } + else + { + offsetMSB = offsetBlocklight + 2 * lenLSB * 2048; // если есть небо, то в буфере будет массив ExtendedBlockStorage.skylightArray + } + + pos = 0; + data = dataArray[i]; + for (int j = 0; j < 16; ++j) + { + l = bufLSB[i] >> j & 1; + + if (l == 1) + { + for (int x = 0; x < 16; x++) + { + for (int y = 0; y < 16; y++) + { + for (int z = 0; z < 16; z++) + { + if (!Orebfuscator.isBlockTransparent(getBlockID(x, y, z))) + { + //data[pos + n] = 1; + } + } + } + } + pos += 4096; + } + } + } + } + + public int getBlockID(int x, int y, int z) + { + if (y >> 4 < this.lenLSB) + { + y = y & 15; + /* + int l = this.blockLSBArray[y << 8 | z << 4 | x] & 255; + + if (this.blockMSBArray != null) + { + l |= this.blockMSBArray.get(p_150819_1_, p_150819_2_, p_150819_3_) << 8; + } + + return Block.getBlockById(l); + */ + } + + return 0; + } +} diff --git a/java/Orebfuscator/Orebfuscator.java b/java/Orebfuscator/Orebfuscator.java new file mode 100644 index 0000000..f7800a0 --- /dev/null +++ b/java/Orebfuscator/Orebfuscator.java @@ -0,0 +1,89 @@ +package Orebfuscator; + +import java.util.HashSet; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetHandlerPlayServer; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.Mod; +import cpw.mods.fml.common.Mod.EventHandler; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.event.FMLPreInitializationEvent; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent; +import cpw.mods.fml.common.network.FMLNetworkEvent; +import cpw.mods.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import cpw.mods.fml.relauncher.ReflectionHelper; + +@Mod(modid = Orebfuscator.MODID, version = Orebfuscator.VERSION, acceptableRemoteVersions = "*") +public class Orebfuscator +{ + public static final String MODID = "Orebfuscator"; + public static final String VERSION = "0.1"; + + @EventHandler + public void init(FMLInitializationEvent event) + { + } + + @EventHandler + public void preInit(FMLPreInitializationEvent event) + { + FMLCommonHandler.instance().bus().register(this); + } + + @SubscribeEvent + public void onPlayerLogged(PlayerEvent.PlayerLoggedInEvent event) + { + PlayerInjector.hookPlayer((EntityPlayerMP)event.player); + } + + @SubscribeEvent + public void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) + { + PlayerInjector.cleanupPlayer((EntityPlayerMP) event.player); + } + + @SubscribeEvent + public void onClientConnect(FMLNetworkEvent.ServerConnectionFromClientEvent event) + { + /* + NetHandlerPlayServer handler = (NetHandlerPlayServer)event.handler; + PlayerInjector.hookPlayer(handler.playerEntity, handler.netManager); + */ + } + + private static HashSet forcedTransparentBlocks = new HashSet(); + private static boolean[] TransparentBlocks = new boolean[4096]; + private static boolean TransparentCached = false; + public static boolean isBlockTransparent(int id) + { + if (id < 0) + return true; + if (!TransparentCached) + { + // Generate TransparentBlocks by reading them from Minecraft + for (int i = 0; i < TransparentBlocks.length; i++) { + if (forcedTransparentBlocks.contains(i)) + { + TransparentBlocks[i] = true; + } + else + { + Block block = Block.getBlockById(i); + if (block == null) + { + TransparentBlocks[i] = true; + } + else + { + TransparentBlocks[i] = !block.isNormalCube(); + } + } + } + TransparentCached = true; + } + return TransparentBlocks[id]; + } +} diff --git a/java/Orebfuscator/PlayerInjector.java b/java/Orebfuscator/PlayerInjector.java new file mode 100644 index 0000000..a82d287 --- /dev/null +++ b/java/Orebfuscator/PlayerInjector.java @@ -0,0 +1,49 @@ +package Orebfuscator; + +import io.netty.channel.Channel; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Queue; + +import cpw.mods.fml.relauncher.ReflectionHelper; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.NetHandlerPlayServer; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.Packet; + +public class PlayerInjector { + + @SuppressWarnings("unchecked") + public static void hookPlayer(EntityPlayerMP player) + { + /* + NetworkManager nm = player.playerNetServerHandler.netManager; + Queue queue = (Queue)Fields.getValue(nm, Fields.NetworkManager.getReceivedPacketsQueueIndex()); + queue = new AsyncPacketQueue(player, queue); + Fields.setValue(nm, Fields.NetworkManager.getReceivedPacketsQueueIndex(), queue); + */ + /* + Queue queue = (Queue)Fields.getValue(nm, Fields.NetworkManager.getOutboundPacketsQueueIndex()); + queue = new AsyncPacketQueue(player, queue); + Fields.setValue(nm, Fields.NetworkManager.getOutboundPacketsQueueIndex(), queue); + */ + + NetworkManager nm = player.playerNetServerHandler.netManager; + Channel channel = (Channel)Fields.getValue(nm, Fields.NetworkManager.getChannelIndex()); + channel = new ProxyChannel(channel, player); + Fields.setValue(nm, Fields.NetworkManager.getChannelIndex(), channel); + } + + public static void cleanupPlayer(EntityPlayerMP player) + { + /* + NetworkManager nm = player.playerNetServerHandler.netManager; + ((AsyncPacketQueue)Fields.getValue(nm, Fields.NetworkManager.getReceivedPacketsQueueIndex())).cleanup(); + */ + /* + NetworkManager nm = player.playerNetServerHandler.netManager; + ((AsyncPacketQueue)Fields.getValue(nm, Fields.NetworkManager.getOutboundPacketsQueueIndex())).cleanup(); + */ + } +} diff --git a/java/Orebfuscator/ProxyChannel.java b/java/Orebfuscator/ProxyChannel.java new file mode 100644 index 0000000..d7e95fb --- /dev/null +++ b/java/Orebfuscator/ProxyChannel.java @@ -0,0 +1,239 @@ +package Orebfuscator; + +import java.net.SocketAddress; + +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.play.server.S26PacketMapChunkBulk; +import io.netty.buffer.ByteBufAllocator; +import io.netty.channel.Channel; +import io.netty.channel.ChannelConfig; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelMetadata; +import io.netty.channel.ChannelPipeline; +import io.netty.channel.ChannelProgressivePromise; +import io.netty.channel.ChannelPromise; +import io.netty.channel.EventLoop; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; + +public class ProxyChannel implements Channel +{ + public Channel channel; + public EntityPlayerMP player; + + public ProxyChannel(Channel channel, EntityPlayerMP player) + { + this.channel = channel; + this.player = player; + } + + public void updateMsg(Object msg) + { + if (msg instanceof S26PacketMapChunkBulk) + { + S26PacketMapChunkBulk packet = (S26PacketMapChunkBulk)msg; + MapChunkBulk chunk = new MapChunkBulk(packet, player.worldObj); + + //Log.msg("%d", field_149260_f[0].length); + } + + //Log.msg("%s", msg.getClass().getName()); + } + + @Override + public Attribute attr(AttributeKey key) { + return this.channel.attr(key); + } + + @Override + public ChannelFuture bind(SocketAddress localAddress) { + return this.channel.bind(localAddress); + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress) { + return this.channel.connect(remoteAddress); + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) { + return this.channel.connect(remoteAddress, localAddress); + } + + @Override + public ChannelFuture disconnect() { + return this.channel.disconnect(); + } + + @Override + public ChannelFuture close() { + return this.channel.close(); + } + + @Override + public ChannelFuture deregister() { + return this.channel.deregister(); + } + + @Override + public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) { + return this.channel.bind(localAddress, promise); + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) { + return this.channel.connect(remoteAddress, promise); + } + + @Override + public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) { + return this.channel.connect(remoteAddress, localAddress, promise); + } + + @Override + public ChannelFuture disconnect(ChannelPromise promise) { + return this.channel.disconnect(promise); + } + + @Override + public ChannelFuture close(ChannelPromise promise) { + return this.channel.close(promise); + } + + @Override + public ChannelFuture deregister(ChannelPromise promise) { + return this.channel.deregister(promise); + } + + @Override + public ChannelFuture write(Object msg) { + return this.channel.write(msg); + } + + @Override + public ChannelFuture write(Object msg, ChannelPromise promise) { + return this.channel.write(msg, promise); + } + + @Override + public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) { + this.updateMsg(msg); + return this.channel.writeAndFlush(msg, promise); + } + + @Override + public ChannelFuture writeAndFlush(Object msg) { + this.updateMsg(msg); + return this.channel.writeAndFlush(msg); + } + + @Override + public ChannelPipeline pipeline() { + return this.channel.pipeline(); + } + + @Override + public ByteBufAllocator alloc() { + return this.channel.alloc(); + } + + @Override + public ChannelPromise newPromise() { + return this.channel.newPromise(); + } + + @Override + public ChannelProgressivePromise newProgressivePromise() { + return this.channel.newProgressivePromise(); + } + + @Override + public ChannelFuture newSucceededFuture() { + return this.channel.newSucceededFuture(); + } + + @Override + public ChannelFuture newFailedFuture(Throwable cause) { + return this.channel.newFailedFuture(cause); + } + + @Override + public ChannelPromise voidPromise() { + return this.channel.voidPromise(); + } + + @Override + public int compareTo(Channel arg0) { + return this.channel.compareTo(arg0); + } + + @Override + public EventLoop eventLoop() { + return this.channel.eventLoop(); + } + + @Override + public Channel parent() { + return this.channel.parent(); + } + + @Override + public ChannelConfig config() { + return this.channel.config(); + } + + @Override + public boolean isOpen() { + return this.channel.isOpen(); + } + + @Override + public boolean isRegistered() { + return this.channel.isRegistered(); + } + + @Override + public boolean isActive() { + return this.channel.isActive(); + } + + @Override + public ChannelMetadata metadata() { + return this.channel.metadata(); + } + + @Override + public SocketAddress localAddress() { + return this.channel.localAddress(); + } + + @Override + public SocketAddress remoteAddress() { + return this.channel.remoteAddress(); + } + + @Override + public ChannelFuture closeFuture() { + return this.channel.closeFuture(); + } + + @Override + public boolean isWritable() { + return this.channel.isWritable(); + } + + @Override + public Channel flush() { + return this.channel.flush(); + } + + @Override + public Channel read() { + return this.channel.read(); + } + + @Override + public Unsafe unsafe() { + return this.channel.unsafe(); + } +} diff --git a/resources/mcmod.info b/resources/mcmod.info new file mode 100644 index 0000000..2535d81 --- /dev/null +++ b/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "Orebfuscator", + "name": "Example Mod", + "description": "", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "", + "updateUrl": "", + "authorList": ["ExampleDude"], + "credits": "The Forge and FML guys, for making this example", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +]