diff --git a/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java b/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java index 5ddf23d6e6..57a8093aca 100644 --- a/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java +++ b/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java @@ -1,16 +1,18 @@ package net.minecraft.src.forge; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.DataInputStream; +import java.io.DataOutputStream; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map.Entry; import java.util.logging.Level; import net.minecraft.client.Minecraft; -import net.minecraft.src.Entity; -import net.minecraft.src.ModLoader; -import net.minecraft.src.NetworkManager; -import net.minecraft.src.World; -import net.minecraft.src.WorldClient; +import net.minecraft.src.*; +import net.minecraft.src.forge.packets.*; public class PacketHandlerClient implements IPacketHandler { @@ -20,13 +22,16 @@ public class PacketHandlerClient implements IPacketHandler DataInputStream data = new DataInputStream(new ByteArrayInputStream(bytes)); try { + ForgePacket pkt = null; + NetClientHandler net = (NetClientHandler)network.getNetHandler(); + int packetID = data.read(); switch(packetID) { - case ForgeHooks.FORGE_PACKET_SPAWN: - PacketEntitySpawn pkt = new PacketEntitySpawn(); + case ForgePacket.SPAWN: + pkt = new PacketEntitySpawn(); pkt.readData(data); - onEntitySpawnPacket(pkt, data, ModLoader.getMinecraftInstance().theWorld); + onEntitySpawnPacket((PacketEntitySpawn)pkt, data, ModLoader.getMinecraftInstance().theWorld); break; } } @@ -36,7 +41,14 @@ public class PacketHandlerClient implements IPacketHandler e.printStackTrace(); } } - + + /** + * Processes the Entity Spawn packet. And spawns an entity in world as needed. + * If the client has the required client mod. + * @param packet The Spawn Packet + * @param data A stream holding extra data for the entity to read + * @param world The world to spawn the entity in + */ public void onEntitySpawnPacket(PacketEntitySpawn packet, DataInputStream data, World world) { Class cls = MinecraftForge.getEntityClass(packet.modID, packet.typeID); @@ -96,4 +108,21 @@ public class PacketHandlerClient implements IPacketHandler ModLoader.ThrowException(String.format("Error spawning entity of type %d for %s.", packet.typeID, MinecraftForge.getModByID(packet.modID)), e); } } + + /** + * Sends a list of all loaded mods to the server. + * For now, it it simple a String[] of mod.toString() + * @param network The network connection to send the packet on. + */ + private void onModListCheck(NetClientHandler net) + { + PacketModList pkt = new PacketModList(false); + pkt.Mods = new String[ModLoader.getLoadedMods().size()]; + int x = 0; + for(BaseMod mod : (List)ModLoader.getLoadedMods()) + { + pkt.Mods[x++] = mod.toString(); + } + net.addToSendQueue(pkt.getPacket()); + } } diff --git a/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java b/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java index 1e88261e0b..e9444f1b7e 100644 --- a/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java +++ b/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java @@ -4,13 +4,13 @@ import net.minecraft.src.BaseMod; public class EntityTrackerInfo { - public final BaseMod Mod; + public final NetworkMod Mod; public final int ID; public final int Range; public final int UpdateFrequancy; public final boolean SendVelocityInfo; - public EntityTrackerInfo(BaseMod mod, int ID, int range, int updateFrequancy, boolean sendVelocityInfo) + public EntityTrackerInfo(NetworkMod mod, int ID, int range, int updateFrequancy, boolean sendVelocityInfo) { Mod = mod; this.ID = ID; diff --git a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java index eadfefaa9f..e1544c3bf2 100644 --- a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java +++ b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java @@ -5,6 +5,7 @@ package net.minecraft.src.forge; +import net.minecraft.src.BaseMod; import net.minecraft.src.Block; import net.minecraft.src.Entity; import net.minecraft.src.EntityItem; @@ -20,6 +21,7 @@ import net.minecraft.src.Packet; import net.minecraft.src.Packet1Login; import net.minecraft.src.Packet250CustomPayload; import net.minecraft.src.World; +import net.minecraft.src.forge.packets.PacketEntitySpawn; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; @@ -360,29 +362,12 @@ public class ForgeHooks { { return null; } - ByteArrayOutputStream bytes = new ByteArrayOutputStream(); - DataOutputStream data = new DataOutputStream(bytes); - try - { - data.writeByte(FORGE_PACKET_SPAWN); - PacketEntitySpawn spawn = new PacketEntitySpawn(entity, info.Mod, info.ID); - spawn.writeData(data); - if (entity instanceof ISpawnHandler) - { - ((ISpawnHandler)entity).writeSpawnData(data); - } - } - catch (IOException e) - { - e.printStackTrace(); - } - Packet250CustomPayload pkt = new Packet250CustomPayload(); - pkt.channel = "Forge"; - pkt.data = bytes.toByteArray(); - pkt.length = pkt.data.length; - return pkt; + PacketEntitySpawn pkt = new PacketEntitySpawn(entity, info.Mod, info.ID); + return pkt.getPacket(); } + + public static Hashtable networkMods = new Hashtable(); public static final int majorVersion=0; public static final int minorVersion=0; @@ -411,8 +396,5 @@ public class ForgeHooks { { return forgePacketHandler; } - //Forge Packet ID Constants. - public static final int FORGE_ID = 0x040E9B47; //"Forge".hashCode(); - public static final int FORGE_PACKET_SPAWN = 1; } diff --git a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java index 7c7d28ae2b..9df81093ac 100755 --- a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java +++ b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java @@ -15,6 +15,7 @@ import net.minecraft.src.ModLoader; import net.minecraft.src.World; import java.util.*; +import java.util.Map.Entry; public class MinecraftForge { @@ -808,7 +809,7 @@ public class MinecraftForge { * @param sendVelocityInfo If velocity information should be included in the update information. * @return True, if successfully registered. False if the class is already registered. */ - public static boolean registerEntity(Class entityClass, BaseMod mod, int ID, int range, int updateFrequancy, boolean sendVelocityInfo) + public static boolean registerEntity(Class entityClass, NetworkMod mod, int ID, int range, int updateFrequancy, boolean sendVelocityInfo) { if (ForgeHooks.entityTrackerMap.containsKey(entityClass)) { @@ -866,16 +867,44 @@ public class MinecraftForge { * @param id The mod ID * @return The mod, or null if not found */ - public static BaseMod getModByID(int id) + public static NetworkMod getModByID(int id) { - for(BaseMod mod : (List)ModLoader.getLoadedMods()) + return ForgeHooks.networkMods.get(id); + } + + /** + * Returns a unique index number for the specific mod. + * + * @param mod The mod to find + * @return The index number, -1 if no index found + */ + public static int getModID(NetworkMod mod) + { + for (Entry entry : ForgeHooks.networkMods.entrySet()) { - if (mod.toString().hashCode() == id) + if (entry.getValue() == mod) { - return mod; + return entry.getKey(); } } - return null; + return -1; + } + + /** + * Returns a list of mods that are designed to be used over the network. + * @return + */ + public static NetworkMod[] getNetworkMods() + { + ArrayList ret = new ArrayList(); + for(BaseMod mod : (List)ModLoader.getLoadedMods()) + { + if (mod instanceof NetworkMod) + { + ret.add((NetworkMod)mod); + } + } + return ret.toArray(new NetworkMod[0]); } diff --git a/forge/forge_common/net/minecraft/src/forge/NetworkMod.java b/forge/forge_common/net/minecraft/src/forge/NetworkMod.java new file mode 100644 index 0000000000..a7aa76d9e5 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/NetworkMod.java @@ -0,0 +1,25 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.BaseMod; + +/** + * This is for mods that are designed to be used on the server side alone, + * or both the client and server side. This class is used when registering + * various things relating to network traffic. Entity ID's, GUI Id's, etc.. + */ +public abstract class NetworkMod extends BaseMod +{ + /** + * Returns true if every client is required to have this + * mod installed when it is installed on a server. + * @return True if client is required, false if not. + */ + public abstract boolean clientSideRequired(); + + /** + * Returns true if the server is required to have this + * mod when it is installed on the client. + * @return True if server is required, false if not. + */ + public abstract boolean serverSideRequired(); +} diff --git a/forge/forge_common/net/minecraft/src/forge/packets/ForgePacket.java b/forge/forge_common/net/minecraft/src/forge/packets/ForgePacket.java new file mode 100644 index 0000000000..c650a2337e --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/packets/ForgePacket.java @@ -0,0 +1,49 @@ +package net.minecraft.src.forge.packets; + +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import net.minecraft.src.BaseMod; +import net.minecraft.src.ModLoader; +import net.minecraft.src.Packet; +import net.minecraft.src.Packet250CustomPayload; +import net.minecraft.src.forge.ForgeHooks; + +public abstract class ForgePacket +{ + //Forge Packet ID Constants. + public static final int FORGE_ID = 0x040E9B47; //"Forge".hashCode(); + public static final int SPAWN = 1; + public static final int MODLIST = 2; + public static final int MOD_MISSING = 3; + public static final int MOD_IDS = 4; + public static final int OPEN_GUI = 5; + + public Packet getPacket() + { + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream data = new DataOutputStream(bytes); + try + { + data.writeByte(getID()); + writeData(data); + } + catch (IOException e) + { + e.printStackTrace(); + } + Packet250CustomPayload pkt = new Packet250CustomPayload(); + pkt.channel = "Forge"; + pkt.data = bytes.toByteArray(); + pkt.length = pkt.data.length; + return pkt; + } + + public abstract void writeData(DataOutputStream data) throws IOException; + public abstract void readData(DataInputStream data) throws IOException; + public abstract int getID(); +} diff --git a/forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java b/forge/forge_common/net/minecraft/src/forge/packets/PacketEntitySpawn.java similarity index 74% rename from forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java rename to forge/forge_common/net/minecraft/src/forge/packets/PacketEntitySpawn.java index 5d55fff76c..2a29ba47cf 100644 --- a/forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java +++ b/forge/forge_common/net/minecraft/src/forge/packets/PacketEntitySpawn.java @@ -1,4 +1,4 @@ -package net.minecraft.src.forge; +package net.minecraft.src.forge.packets; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -7,10 +7,13 @@ import java.io.IOException; import net.minecraft.src.BaseMod; import net.minecraft.src.Entity; import net.minecraft.src.MathHelper; +import net.minecraft.src.forge.ISpawnHandler; +import net.minecraft.src.forge.IThrowableEntity; +import net.minecraft.src.forge.MinecraftForge; +import net.minecraft.src.forge.NetworkMod; -public class PacketEntitySpawn +public class PacketEntitySpawn extends ForgePacket { - public int entityID; public int posX; public int posY; @@ -21,9 +24,10 @@ public class PacketEntitySpawn public int typeID; public int modID; public int throwerID; + private ISpawnHandler handler; public PacketEntitySpawn(){} - public PacketEntitySpawn(Entity ent, BaseMod mod, int type) + public PacketEntitySpawn(Entity ent, NetworkMod mod, int type) { entityID = ent.entityId; @@ -32,7 +36,7 @@ public class PacketEntitySpawn posZ = MathHelper.floor_double(ent.posZ * 32D); typeID = type; - modID = mod.toString().hashCode(); + modID = MinecraftForge.getModID(mod); if (ent instanceof IThrowableEntity) { @@ -52,6 +56,10 @@ public class PacketEntitySpawn speedY = (int)(mY * 8000D); speedZ = (int)(mZ * 8000D); } + if (ent instanceof ISpawnHandler) + { + handler = (ISpawnHandler)ent; + } } public void writeData(DataOutputStream data) throws IOException { @@ -68,6 +76,10 @@ public class PacketEntitySpawn data.writeShort(speedY); data.writeShort(speedZ); } + if (handler != null) + { + handler.writeSpawnData(data); + } } public void readData(DataInputStream data) throws IOException @@ -86,4 +98,9 @@ public class PacketEntitySpawn speedX = data.readShort(); } } + @Override + public int getID() + { + return ForgePacket.SPAWN; + } } diff --git a/forge/forge_common/net/minecraft/src/forge/packets/PacketModList.java b/forge/forge_common/net/minecraft/src/forge/packets/PacketModList.java new file mode 100644 index 0000000000..47191f67a0 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/packets/PacketModList.java @@ -0,0 +1,58 @@ +package net.minecraft.src.forge.packets; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.List; + +import net.minecraft.src.BaseMod; +import net.minecraft.src.ModLoader; + +public class PacketModList extends ForgePacket +{ + private boolean isServer = false; + public String[] Mods; + public int Length = -1; + + public PacketModList(boolean server) + { + isServer = server; + } + + @Override + public void writeData(DataOutputStream data) throws IOException + { + if (!isServer) + { + data.writeInt(Mods.length); + for(String mod : Mods) + { + data.writeUTF(mod); + } + } + } + + @Override + public void readData(DataInputStream data) throws IOException + { + if (isServer) + { + Length = data.readInt(); + if (Length >= 0) + { + Mods = new String[Length]; + for (int x = 0; x < Length; x++) + { + Mods[x] = data.readUTF(); + } + } + } + } + + @Override + public int getID() + { + return ForgePacket.MODLIST; + } + +} diff --git a/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch b/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch index 46105316b0..8c70a3751c 100644 --- a/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch +++ b/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch @@ -1,15 +1,16 @@ --- ../src_base/minecraft/net/minecraft/src/NetClientHandler.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft/net/minecraft/src/NetClientHandler.java 0000-00-00 00:00:00.000000000 -0000 -@@ -7,6 +7,8 @@ +@@ -7,6 +7,9 @@ import java.util.*; import java.util.logging.Logger; import net.minecraft.client.Minecraft; +import net.minecraft.src.forge.ForgeHooks; +import net.minecraft.src.forge.MessageManager; ++import net.minecraft.src.forge.packets.ForgePacket; public class NetClientHandler extends NetHandler { -@@ -35,6 +37,8 @@ +@@ -35,6 +38,8 @@ mc = minecraft; Socket socket = new Socket(InetAddress.getByName(s), i); netManager = new NetworkManager(socket, "Client", this); @@ -18,7 +19,7 @@ } public void processReadPackets() -@@ -58,6 +62,27 @@ +@@ -58,6 +63,27 @@ mc.thePlayer.entityId = packet1login.protocolVersion; currentServerMaxPlayers = packet1login.maxPlayers; ((PlayerControllerMP)mc.playerController).setCreative(packet1login.serverMode == 1); @@ -46,7 +47,7 @@ } public void handlePickupSpawn(Packet21PickupSpawn packet21pickupspawn) -@@ -608,7 +633,19 @@ +@@ -608,7 +634,19 @@ } else if (packet2handshake.username.equals("-")) { @@ -61,13 +62,13 @@ + * The C->S mapSeed is set to the current Forge build number, in case we need to do any quick version checks. + */ + Packet1Login pkt = new Packet1Login(mc.session.username, 23); -+ pkt.serverMode = ForgeHooks.FORGE_ID; ++ pkt.serverMode = ForgePacket.FORGE_ID; + pkt.mapSeed = ForgeHooks.buildVersion; + addToSendQueue(pkt); } else { -@@ -620,7 +657,19 @@ +@@ -620,7 +658,19 @@ bufferedreader.close(); if (s1.equalsIgnoreCase("ok")) { @@ -82,13 +83,13 @@ + * The C->S mapSeed is set to the current Forge build number, in case we need to do any quick version checks. + */ + Packet1Login pkt = new Packet1Login(mc.session.username, 23); -+ pkt.serverMode = ForgeHooks.FORGE_ID; ++ pkt.serverMode = ForgePacket.FORGE_ID; + pkt.mapSeed = ForgeHooks.buildVersion; + addToSendQueue(pkt); } else { -@@ -1017,4 +1066,44 @@ +@@ -1017,4 +1067,44 @@ { addToSendQueue(new Packet0KeepAlive(packet0keepalive.randomId)); } diff --git a/forge/patches/minecraft_server/net/minecraft/src/ModLoader.java.patch b/forge/patches/minecraft_server/net/minecraft/src/ModLoader.java.patch index 045abcab87..97c3e29808 100644 --- a/forge/patches/minecraft_server/net/minecraft/src/ModLoader.java.patch +++ b/forge/patches/minecraft_server/net/minecraft/src/ModLoader.java.patch @@ -1,6 +1,33 @@ --- ../src_base/minecraft_server/net/minecraft/src/ModLoader.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft_server/net/minecraft/src/ModLoader.java 0000-00-00 00:00:00.000000000 -0000 -@@ -1325,6 +1325,7 @@ +@@ -10,6 +10,8 @@ + import java.util.zip.ZipEntry; + import java.util.zip.ZipInputStream; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.src.forge.ForgeHooks; ++import net.minecraft.src.forge.NetworkMod; + + public final class ModLoader + { +@@ -626,6 +628,17 @@ + readFromClassPath(file); + System.out.println("Done."); + props.setProperty("loggingLevel", cfgLoggingLevel.getName()); ++ /* ++ * Gather up a list of network mods and assign them an id ++ */ ++ int x = 0; ++ for (BaseMod mod : (List)modList) ++ { ++ if (mod instanceof NetworkMod) ++ { ++ ForgeHooks.networkMods.put(x++, (NetworkMod)mod); ++ } ++ } + Iterator iterator = modList.iterator(); + do + { +@@ -1325,6 +1338,7 @@ { method_getNextWindowId.invoke(entityplayermp, new Object[0]); int j = field_currentWindowId.getInt(entityplayermp); diff --git a/forge/patches/minecraft_server/net/minecraft/src/NetLoginHandler.java.patch b/forge/patches/minecraft_server/net/minecraft/src/NetLoginHandler.java.patch index 1dad01427d..9f3d6603f3 100644 --- a/forge/patches/minecraft_server/net/minecraft/src/NetLoginHandler.java.patch +++ b/forge/patches/minecraft_server/net/minecraft/src/NetLoginHandler.java.patch @@ -1,6 +1,6 @@ --- ../src_base/minecraft_server/net/minecraft/src/NetLoginHandler.java 0000-00-00 00:00:00.000000000 -0000 +++ ../src_work/minecraft_server/net/minecraft/src/NetLoginHandler.java 0000-00-00 00:00:00.000000000 -0000 -@@ -1,10 +1,14 @@ +@@ -1,10 +1,15 @@ package net.minecraft.src; import java.io.IOException; @@ -12,10 +12,11 @@ +import net.minecraft.src.forge.ForgeHooks; +import net.minecraft.src.forge.ForgeHooksServer; +import net.minecraft.src.forge.MessageManager; ++import net.minecraft.src.forge.packets.ForgePacket; public class NetLoginHandler extends NetHandler { -@@ -29,6 +33,7 @@ +@@ -29,6 +34,7 @@ mcServer = minecraftserver; netManager = new NetworkManager(socket, s, this); netManager.chunkDataSendCounter = 0; @@ -23,13 +24,13 @@ } public void tryLogin() -@@ -129,7 +134,39 @@ +@@ -129,7 +135,39 @@ } entityplayermp.func_20057_k(); - ModLoaderMp.HandleAllLogins(entityplayermp); + -+ if (packet1login.serverMode == ForgeHooks.FORGE_ID) ++ if (packet1login.serverMode == ForgePacket.FORGE_ID) + { + //Pretty hackish place to put it, but it needs to go somewhere + ForgeHooksServer.init(); @@ -53,7 +54,7 @@ + } + pkt.length = pkt.data.length; + netserverhandler.sendPacket(pkt); -+ ++ ForgeHooksServer.sendModListRequest(netManager); + ModLoaderMp.HandleAllLogins(entityplayermp); + } + else