From 2ea17752249feea9a7f3552bf5f8986b40d27b4f Mon Sep 17 00:00:00 2001 From: LexManos Date: Fri, 10 Feb 2012 03:06:08 -0800 Subject: [PATCH] Created a Entity tracking ans spawning system. Mod creators should call MinecraftForge.registerEntity to register a entity. All entity ID numbers are Mod Unique. Meaning two mods can have Entity #1. Added client and server side packet handlers for the 'Forge' channel. For use in internal packets such as the new Spawn packet. Updated the build scripts to copy over unique server source files now that there actually are some. For modders: If you have a entity that used MLMP's 'owner' system, you should have your entity implement IThrowableEntity If you have a entity that implments MLMLP's ISpawnable, you should implement ISpawnHandler. They provide the same functionality, just in a cleaner, more orginized way and will be the method used when we eventually drop MLMP. --- forge/build.bat | 1 + forge/build.sh | 1 + .../src/forge/MinecraftForgeClient.java | 16 +++ .../src/forge/PacketHandlerClient.java | 99 ++++++++++++++ .../src/forge/EntityTrackerInfo.java | 21 +++ .../net/minecraft/src/forge/ForgeHooks.java | 122 +++++++++++++----- .../minecraft/src/forge/ISpawnHandler.java | 27 ++++ .../minecraft/src/forge/IThrowableEntity.java | 22 ++++ .../minecraft/src/forge/MessageManager.java | 12 +- .../minecraft/src/forge/MinecraftForge.java | 107 ++++++++++++++- .../src/forge/PacketEntitySpawn.java | 89 +++++++++++++ .../minecraft/src/forge/ForgeHooksServer.java | 45 +++++++ .../src/forge/PacketHandlerServer.java | 11 ++ .../minecraft/src/NetClientHandler.java.patch | 12 +- .../minecraft/src/EntityTracker.java.patch | 21 +++ .../src/EntityTrackerEntry.java.patch | 25 ++++ .../minecraft/src/NetLoginHandler.java.patch | 11 +- 17 files changed, 587 insertions(+), 55 deletions(-) create mode 100644 forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java create mode 100644 forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java create mode 100644 forge/forge_common/net/minecraft/src/forge/ISpawnHandler.java create mode 100644 forge/forge_common/net/minecraft/src/forge/IThrowableEntity.java create mode 100644 forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java create mode 100644 forge/forge_server/src/net/minecraft/src/forge/ForgeHooksServer.java create mode 100644 forge/forge_server/src/net/minecraft/src/forge/PacketHandlerServer.java create mode 100644 forge/patches/minecraft_server/net/minecraft/src/EntityTracker.java.patch create mode 100644 forge/patches/minecraft_server/net/minecraft/src/EntityTrackerEntry.java.patch diff --git a/forge/build.bat b/forge/build.bat index a1bbcca96f..3037e63e48 100755 --- a/forge/build.bat +++ b/forge/build.bat @@ -4,6 +4,7 @@ @mkdir src xcopy /Y /E src_work\* src\ xcopy /Y /E forge\forge_client\src\net\* src\minecraft\net +xcopy /Y /E forge\forge_server\src\net\* src\minecraft_server\net xcopy /Y /E forge\forge_common\net\* src\minecraft\net xcopy /Y /E forge\forge_common\net\* src\minecraft_server\net diff --git a/forge/build.sh b/forge/build.sh index bac689442a..111a63bbeb 100755 --- a/forge/build.sh +++ b/forge/build.sh @@ -7,6 +7,7 @@ rm -rf src bin src_forge cp -a src_work src_forge cp -a forge/forge_client/src/net/* src_forge/minecraft/net/ +cp -a forge/forge_server/src/net/* src_forge/minecraft_server/net/ cp -a forge/forge_common/net/* src_forge/minecraft/net/ cp -a forge/forge_common/net/* src_forge/minecraft_server/net/ diff --git a/forge/forge_client/src/net/minecraft/src/forge/MinecraftForgeClient.java b/forge/forge_client/src/net/minecraft/src/forge/MinecraftForgeClient.java index 8c5d270e9c..bbefddf77e 100755 --- a/forge/forge_client/src/net/minecraft/src/forge/MinecraftForgeClient.java +++ b/forge/forge_client/src/net/minecraft/src/forge/MinecraftForgeClient.java @@ -87,4 +87,20 @@ public class MinecraftForgeClient { public static ICustomItemRenderer getCustomItemRenderer (int itemID) { return customItemRenderers [itemID]; } + + private static boolean hasInit = false; + public static void init() + { + if (hasInit) + { + return; + } + hasInit = true; + ForgeHooks.setPacketHandler(new PacketHandlerClient()); + } + + static + { + init(); + } } diff --git a/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java b/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java new file mode 100644 index 0000000000..5ddf23d6e6 --- /dev/null +++ b/forge/forge_client/src/net/minecraft/src/forge/PacketHandlerClient.java @@ -0,0 +1,99 @@ +package net.minecraft.src.forge; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.IOException; +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; + +public class PacketHandlerClient implements IPacketHandler +{ + @Override + public void onPacketData(NetworkManager network, String channel, byte[] bytes) + { + DataInputStream data = new DataInputStream(new ByteArrayInputStream(bytes)); + try + { + int packetID = data.read(); + switch(packetID) + { + case ForgeHooks.FORGE_PACKET_SPAWN: + PacketEntitySpawn pkt = new PacketEntitySpawn(); + pkt.readData(data); + onEntitySpawnPacket(pkt, data, ModLoader.getMinecraftInstance().theWorld); + break; + } + } + catch(IOException e) + { + ModLoader.getLogger().log(Level.SEVERE, "Exception in PacketHandlerClient.onPacketData", e); + e.printStackTrace(); + } + } + + public void onEntitySpawnPacket(PacketEntitySpawn packet, DataInputStream data, World world) + { + Class cls = MinecraftForge.getEntityClass(packet.modID, packet.typeID); + if (cls == null) + { + System.out.println("Could not find entity info for " + Integer.toHexString(packet.modID) + " : " + packet.typeID); + return; + } + + double posX = (double)packet.posX / 32D; + double posY = (double)packet.posY / 32D; + double posZ = (double)packet.posZ / 32D; + try + { + Entity entity = (Entity)(cls.getConstructor(World.class, double.class, double.class, double.class).newInstance(world, posX, posY, posZ)); + if (entity instanceof IThrowableEntity) + { + Minecraft mc = ModLoader.getMinecraftInstance(); + Entity thrower = (mc.thePlayer.entityId == packet.throwerID ? mc.thePlayer : ((WorldClient)world).getEntityByID(packet.throwerID)); + ((IThrowableEntity)entity).setThrower(thrower); + } + + entity.serverPosX = packet.posX; + entity.serverPosY = packet.posX; + entity.serverPosZ = packet.posZ; + entity.rotationYaw = 0.0F; + entity.rotationPitch = 0.0F; + + Entity parts[] = entity.getParts(); + if (parts != null) + { + int i = packet.entityID - entity.entityId; + for (int j = 0; j < parts.length; j++) + { + parts[j].entityId += i; + } + } + + entity.entityId = packet.entityID; + + if (packet.throwerID > 0) + { + entity.setVelocity(packet.speedX / 8000D, packet.speedY / 8000D, packet.speedZ / 8000D); + } + + if (entity instanceof ISpawnHandler) + { + ((ISpawnHandler)entity).readSpawnData(data); + } + + ((WorldClient)world).addEntityToWorld(packet.entityID, entity); + } + catch (Exception e) + { + e.printStackTrace(); + ModLoader.getLogger().throwing("ForgeHooksClient", "onEntitySpawnPacket", e); + ModLoader.ThrowException(String.format("Error spawning entity of type %d for %s.", packet.typeID, MinecraftForge.getModByID(packet.modID)), e); + } + } +} diff --git a/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java b/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java new file mode 100644 index 0000000000..1e88261e0b --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/EntityTrackerInfo.java @@ -0,0 +1,21 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.BaseMod; + +public class EntityTrackerInfo +{ + public final BaseMod 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) + { + Mod = mod; + this.ID = ID; + Range = range; + UpdateFrequancy = updateFrequancy; + SendVelocityInfo = sendVelocityInfo; + } +} diff --git a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java index f391051ddc..eb65a73766 100644 --- a/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java +++ b/forge/forge_common/net/minecraft/src/forge/ForgeHooks.java @@ -15,9 +15,15 @@ import net.minecraft.src.Item; import net.minecraft.src.EnumStatus; import net.minecraft.src.ModLoader; import net.minecraft.src.NetworkManager; +import net.minecraft.src.Packet; import net.minecraft.src.Packet1Login; +import net.minecraft.src.Packet250CustomPayload; import net.minecraft.src.World; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; import java.util.*; public class ForgeHooks { @@ -165,37 +171,33 @@ public class ForgeHooks { static int seedGrassWeight; static { - plantGrassList=new ArrayList(); - plantGrassList.add(new ProbableItem( - Block.plantYellow.blockID,0,1,0,20)); - plantGrassList.add(new ProbableItem( - Block.plantRed.blockID,0,1,20,30)); - plantGrassWeight=30; + plantGrassList = new ArrayList(); + plantGrassList.add(new ProbableItem(Block.plantYellow.blockID, 0, 1, 0, 20)); + plantGrassList.add(new ProbableItem(Block.plantRed.blockID, 0, 1, 20, 30)); + plantGrassWeight = 30; - seedGrassList=new ArrayList(); - seedGrassList.add(new ProbableItem( - Item.seeds.shiftedIndex,0,1,0,10)); - seedGrassWeight=10; + seedGrassList = new ArrayList(); + seedGrassList.add(new ProbableItem(Item.seeds.shiftedIndex, 0, 1, 0, 10)); + seedGrassWeight = 10; } public static void plantGrassPlant(World world, int i, int j, int k) { - int n=world.rand.nextInt(plantGrassWeight); - ProbableItem pi=getRandomItem(plantGrassList,n); - if(pi==null) return; - world.setBlockAndMetadataWithNotify(i,j,k,pi.itemid,pi.meta); + int n = world.rand.nextInt(plantGrassWeight); + ProbableItem pi = getRandomItem(plantGrassList, n); + if (pi == null) return; + world.setBlockAndMetadataWithNotify(i, j, k, pi.itemid, pi.meta); } public static void addPlantGrass(int item, int md, int prop) { - plantGrassList.add(new ProbableItem( - item,md,1,plantGrassWeight,plantGrassWeight+prop)); - plantGrassWeight+=prop; + plantGrassList.add(new ProbableItem(item, md, 1, plantGrassWeight, plantGrassWeight + prop)); + plantGrassWeight += prop; } public static ItemStack getGrassSeed(World world) { - int n=world.rand.nextInt(seedGrassWeight); - ProbableItem pi=getRandomItem(seedGrassList,n); - if(pi==null) return null; - return new ItemStack(pi.itemid,pi.qty,pi.meta); + int n = world.rand.nextInt(seedGrassWeight); + ProbableItem pi = getRandomItem(seedGrassList,n); + if (pi == null) return null; + return new ItemStack(pi.itemid, pi.qty, pi.meta); } public static void addGrassSeed(int item, int md, int qty, int prop) { @@ -206,22 +208,21 @@ public class ForgeHooks { // Tool Path // ------------------------------------------------------------ - public static boolean canHarvestBlock(Block bl, - EntityPlayer player, int md) { + public static boolean canHarvestBlock(Block bl, EntityPlayer player, int md) { if(bl.blockMaterial.getIsHarvestable()) return true; ItemStack itemstack = player.inventory.getCurrentItem(); - if(itemstack == null) return false; + if (itemstack == null) return false; - List tc=(List)toolClasses.get(itemstack.itemID); - if(tc==null) return itemstack.canHarvestBlock(bl); - Object[] ta=tc.toArray(); - String cls=(String)ta[0]; int hvl=(Integer)ta[1]; + List tc = (List)toolClasses.get(itemstack.itemID); + if (tc == null) return itemstack.canHarvestBlock(bl); + Object[] ta = tc.toArray(); + String cls = (String)ta[0]; + int hvl = (Integer)ta[1]; - Integer bhl=(Integer)toolHarvestLevels.get(Arrays.asList( - bl.blockID,md,cls)); - if(bhl==null) return itemstack.canHarvestBlock(bl); - if(bhl>hvl) return false; + Integer bhl = (Integer)toolHarvestLevels.get(Arrays.asList(bl.blockID, md, cls)); + if(bhl == null) return itemstack.canHarvestBlock(bl); + if(bhl > hvl) return false; return true; } @@ -326,6 +327,46 @@ public class ForgeHooks { } } + + public static HashMap entityTrackerMap = new HashMap(); + + /** + * Builds the 'Spawn' packet using the Custom Payload packet on the 'Forge' channel. + * Supports entities that have custom spawn data, as well as the generic 'Owner' construct. + * + * @param entity The entity instance to spawn + * @return The spawn packet, or null if we arn't spawning it. + */ + public static Packet getEntitySpawnPacket(Entity entity) + { + EntityTrackerInfo info = MinecraftForge.getEntityTrackerInfo(entity, false); + if (info == null) + { + 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; + } public static final int majorVersion=0; public static final int minorVersion=0; @@ -340,5 +381,22 @@ public class ForgeHooks { static HashMap toolClasses=new HashMap(); static HashMap toolHarvestLevels=new HashMap(); static HashSet toolEffectiveness=new HashSet(); + + private static IPacketHandler forgePacketHandler = null; + public static void setPacketHandler(IPacketHandler handler) + { + if (forgePacketHandler != null) + { + throw new RuntimeException("Attempted to set Forge's Internal packet handler after it was already set"); + } + forgePacketHandler = handler; + } + public static IPacketHandler getPacketHandler() + { + 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/ISpawnHandler.java b/forge/forge_common/net/minecraft/src/forge/ISpawnHandler.java new file mode 100644 index 0000000000..d902d675a3 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/ISpawnHandler.java @@ -0,0 +1,27 @@ +package net.minecraft.src.forge; + +import java.io.DataInputStream; +import java.io.DataOutputStream; + +/** + * A interface for Entities that need extra information to be communicated + * between the server and client when they are spawned. + */ +public interface ISpawnHandler +{ + /** + * Called by the server when constructing the spawn packet. + * Data should be added to the provided stream. + * + * @param data The packet data stream + */ + public void writeSpawnData(DataOutputStream data); + + /** + * Called by the client when it receives a Entity spawn packet. + * Data should be read out of the stream in the same way as it was written. + * + * @param data The packet data stream + */ + public void readSpawnData(DataInputStream data); +} diff --git a/forge/forge_common/net/minecraft/src/forge/IThrowableEntity.java b/forge/forge_common/net/minecraft/src/forge/IThrowableEntity.java new file mode 100644 index 0000000000..bb54bdebc5 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/IThrowableEntity.java @@ -0,0 +1,22 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.Entity; + +/** + * This interface should be implemented by an Entity that can be 'thrown', like snowballs. + * This was created to mimic ModLoaderMP's 'owner' functionality. + */ +public interface IThrowableEntity +{ + /** + * Gets the entity that threw/created this entity. + * @return The owner instance, Null if none. + */ + public Entity getThrower(); + + /** + * Sets the entity that threw/created this entity. + * @param entity The new thrower/creator. + */ + public void setThrower(Entity entity); +} diff --git a/forge/forge_common/net/minecraft/src/forge/MessageManager.java b/forge/forge_common/net/minecraft/src/forge/MessageManager.java index 0c3cd71f3b..f4b0df35ff 100644 --- a/forge/forge_common/net/minecraft/src/forge/MessageManager.java +++ b/forge/forge_common/net/minecraft/src/forge/MessageManager.java @@ -408,12 +408,12 @@ public class MessageManager { if (channel.equals("Forge")) { - /* Currently Forge has no custom tasks, but will eventually have - * Mod list testing, and whatever, when we remove ModLoaderMP - * - byte[] tmpData = new byte[data.length]; - System.arraycopy(data, 0, tmpData, 0, data.length); - */ + if (ForgeHooks.getPacketHandler() != null) + { + byte[] tmpData = new byte[data.length]; + System.arraycopy(data, 0, tmpData, 0, data.length); + ForgeHooks.getPacketHandler().onPacketData(manager, channel, tmpData); + } } if (connections.contains(manager)) diff --git a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java index 85c8770273..9dee1ae194 100755 --- a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java +++ b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java @@ -5,10 +5,13 @@ package net.minecraft.src.forge; +import net.minecraft.src.BaseMod; import net.minecraft.src.Block; +import net.minecraft.src.Entity; import net.minecraft.src.EntityMinecart; import net.minecraft.src.Item; import net.minecraft.src.ItemStack; +import net.minecraft.src.ModLoader; import net.minecraft.src.World; import java.util.*; @@ -382,17 +385,25 @@ public class MinecraftForge { * mods that use recent, new, or unstable APIs to prevent * incompatibilities. */ - public static void versionDetectStrict(String modname, - int major, int minor, int revision) { - if(major!=ForgeHooks.majorVersion) { + public static void versionDetectStrict(String modname, int major, int minor, int revision) + { + if(major!=ForgeHooks.majorVersion) + { killMinecraft(modname,"MinecraftForge Major Version Mismatch, expecting "+major+".x.x"); - } else if(minor!=ForgeHooks.minorVersion) { - if(minor>ForgeHooks.minorVersion) { + } + else if(minor!=ForgeHooks.minorVersion) + { + if(minor>ForgeHooks.minorVersion) + { killMinecraft(modname,"MinecraftForge Too Old, need at least "+major+"."+minor+"."+revision); - } else { + } + else + { killMinecraft(modname,"MinecraftForge minor version mismatch, expecting "+major+"."+minor+".x"); } - } else if(revision>ForgeHooks.revisionVersion) { + } + else if(revision>ForgeHooks.revisionVersion) + { killMinecraft(modname,"MinecraftForge Too Old, need at least "+major+"."+minor+"."+revision); } } @@ -775,6 +786,88 @@ public class MinecraftForge { } return ret; } + + /** + * Registers a Entity class tracking information. Used for sendingEntity + * information over the network. + * + * @param entityClass The class for the Entity + * @param mod The BaseMod that provides this Entity. + * @param ID The ID for the Entity. Needs to be unique combination of Mod and ID. + * @param range How close a player has to be to be informed this Entity exists. + * @param updateFrequancy How many ticks between checking and sending information updates for this Entity. + * @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) + { + if (ForgeHooks.entityTrackerMap.containsKey(entityClass)) + { + return false; + } + ForgeHooks.entityTrackerMap.put(entityClass, new EntityTrackerInfo(mod, ID, range, updateFrequancy, sendVelocityInfo)); + return true; + } + + /** + * Retrieves the tracker info for input Entity. + * + * @param entity The Entity to find tracking info for. + * @param checkSupers If we should check the super-classes for a match. + * @return The information, or Null if not found. + */ + public static EntityTrackerInfo getEntityTrackerInfo(Entity entity, boolean checkSupers) + { + for (Map.Entry entry : ForgeHooks.entityTrackerMap.entrySet()) + { + if (entry.getKey().isInstance(entity)) + { + if (!checkSupers || entry.getKey() == entry.getClass()) + { + return entry.getValue(); + } + } + } + return null; + } + + /** + * Retrieves the Class for a registered Entity based on ModID and Entity Type. + * + * @param modID The ID of the mod (mod.toString().hashCode()) + * @param type The ID for the Entity + * @return The entity Class, or null if not found. + */ + public static Class getEntityClass(int modID, int type) + { + for (Map.Entry entry : ForgeHooks.entityTrackerMap.entrySet()) + { + EntityTrackerInfo info = entry.getValue(); + if (type == info.ID && modID == info.Mod.toString().hashCode()) + { + return entry.getKey(); + } + } + return null; + } + + /** + * Retrieves a mod instance based on it's ID. (toString().hashCode()) + * + * @param id The mod ID + * @return The mod, or null if not found + */ + public static BaseMod getModByID(int id) + { + for(BaseMod mod : (List)ModLoader.getLoadedMods()) + { + if (mod.toString().hashCode() == id) + { + return mod; + } + } + return null; + } static diff --git a/forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java b/forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java new file mode 100644 index 0000000000..5d55fff76c --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/PacketEntitySpawn.java @@ -0,0 +1,89 @@ +package net.minecraft.src.forge; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import net.minecraft.src.BaseMod; +import net.minecraft.src.Entity; +import net.minecraft.src.MathHelper; + +public class PacketEntitySpawn +{ + + public int entityID; + public int posX; + public int posY; + public int posZ; + public int speedX; + public int speedY; + public int speedZ; + public int typeID; + public int modID; + public int throwerID; + + public PacketEntitySpawn(){} + public PacketEntitySpawn(Entity ent, BaseMod mod, int type) + { + entityID = ent.entityId; + + posX = MathHelper.floor_double(ent.posX * 32D); + posY = MathHelper.floor_double(ent.posY * 32D); + posZ = MathHelper.floor_double(ent.posZ * 32D); + + typeID = type; + modID = mod.toString().hashCode(); + + if (ent instanceof IThrowableEntity) + { + Entity owner = ((IThrowableEntity)ent).getThrower(); + throwerID = (owner == null ? ent.entityId : owner.entityId); + double maxVel = 3.9D; + double mX = ent.motionX; + double mY = ent.motionY; + double mZ = ent.motionZ; + if (mX < -maxVel) mX = -maxVel; + if (mY < -maxVel) mY = -maxVel; + if (mZ < -maxVel) mZ = -maxVel; + if (mX > maxVel) mX = maxVel; + if (mY > maxVel) mY = maxVel; + if (mZ > maxVel) mZ = maxVel; + speedX = (int)(mX * 8000D); + speedY = (int)(mY * 8000D); + speedZ = (int)(mZ * 8000D); + } + } + public void writeData(DataOutputStream data) throws IOException + { + data.writeInt(modID); + data.writeInt(entityID); + data.writeByte(typeID); + data.writeInt(posX); + data.writeInt(posY); + data.writeInt(posZ); + data.writeInt(throwerID); + if (throwerID != 0) + { + data.writeShort(speedX); + data.writeShort(speedY); + data.writeShort(speedZ); + } + } + + public void readData(DataInputStream data) throws IOException + { + modID = data.readInt(); + entityID = data.readInt(); + typeID = data.readByte(); + posX = data.readInt(); + posY = data.readInt(); + posZ = data.readInt(); + throwerID = data.readInt(); + if (throwerID != 0) + { + speedX = data.readShort(); + speedY = data.readShort(); + speedX = data.readShort(); + } + } +} diff --git a/forge/forge_server/src/net/minecraft/src/forge/ForgeHooksServer.java b/forge/forge_server/src/net/minecraft/src/forge/ForgeHooksServer.java new file mode 100644 index 0000000000..cf60baf9a1 --- /dev/null +++ b/forge/forge_server/src/net/minecraft/src/forge/ForgeHooksServer.java @@ -0,0 +1,45 @@ +package net.minecraft.src.forge; + +import java.util.Map; + +import net.minecraft.src.Entity; +import net.minecraft.src.EntityTracker; + +public class ForgeHooksServer +{ + /** + * Called when a Entity is being added to a EntityTracker. + * If we have valid info, register the entity. + * + * @param tracker The EntityTracker instance + * @param entity The Entity to add + * @return True if we registered the Entity + */ + public static boolean OnTrackEntity(EntityTracker tracker, Entity entity) + { + EntityTrackerInfo info = MinecraftForge.getEntityTrackerInfo(entity, true); + if (info != null) + { + tracker.trackEntity(entity, info.Range, info.UpdateFrequancy, info.SendVelocityInfo); + return true; + } + return false; + } + + + private static boolean hasInit = false; + public static void init() + { + if (hasInit) + { + return; + } + hasInit = true; + ForgeHooks.setPacketHandler(new PacketHandlerServer()); + } + + static + { + init(); + } +} diff --git a/forge/forge_server/src/net/minecraft/src/forge/PacketHandlerServer.java b/forge/forge_server/src/net/minecraft/src/forge/PacketHandlerServer.java new file mode 100644 index 0000000000..13a3c53ca6 --- /dev/null +++ b/forge/forge_server/src/net/minecraft/src/forge/PacketHandlerServer.java @@ -0,0 +1,11 @@ +package net.minecraft.src.forge; + +import net.minecraft.src.NetworkManager; + +public class PacketHandlerServer implements IPacketHandler +{ + @Override + public void onPacketData(NetworkManager network, String channel, byte[] data) + { + } +} diff --git a/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch b/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch index 6cc4548126..46105316b0 100644 --- a/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch +++ b/forge/patches/minecraft/net/minecraft/src/NetClientHandler.java.patch @@ -53,7 +53,7 @@ - addToSendQueue(new Packet1Login(mc.session.username, 23)); + /** + * We use some of the unused fields in Packet 001 Login to identify the user as having Forge installed. -+ * This allows modded clients to connect to Vinella server without crashing. ++ * This allows modded clients to connect to Vanilla server without crashing. + * It also allows unmodded clients to connect to Forge server without crashing. + * Its a bit of a dirty hack, but it doesnt interrupt the login flow, and its unused data. + * The C->S serverMode is set to the hash code of the string "Forge", this should provide a fairly unique @@ -61,8 +61,8 @@ + * 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 = 0x040E9B47; //"Forge".hashCode(); -+ pkt.mapSeed = ForgeHooks.buildVersion; ++ pkt.serverMode = ForgeHooks.FORGE_ID; ++ pkt.mapSeed = ForgeHooks.buildVersion; + addToSendQueue(pkt); } else @@ -74,7 +74,7 @@ - addToSendQueue(new Packet1Login(mc.session.username, 23)); + /** + * We use some of the unused fields in Packet 001 Login to identify the user as having Forge installed. -+ * This allows modded clients to connect to Vinella server without crashing. ++ * This allows modded clients to connect to Vanilla server without crashing. + * It also allows unmodded clients to connect to Forge server without crashing. + * Its a bit of a dirty hack, but it doesnt interrupt the login flow, and its unused data. + * The C->S serverMode is set to the hash code of the string "Forge", this should provide a fairly unique @@ -82,8 +82,8 @@ + * 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 = 0x040E9B47; //"Forge".hashCode(); -+ pkt.mapSeed = ForgeHooks.buildVersion; ++ pkt.serverMode = ForgeHooks.FORGE_ID; ++ pkt.mapSeed = ForgeHooks.buildVersion; + addToSendQueue(pkt); } else diff --git a/forge/patches/minecraft_server/net/minecraft/src/EntityTracker.java.patch b/forge/patches/minecraft_server/net/minecraft/src/EntityTracker.java.patch new file mode 100644 index 0000000000..eb442023c9 --- /dev/null +++ b/forge/patches/minecraft_server/net/minecraft/src/EntityTracker.java.patch @@ -0,0 +1,21 @@ +--- ../src_base/minecraft_server/net/minecraft/src/EntityTracker.java 0000-00-00 00:00:00.000000000 -0000 ++++ ../src_work/minecraft_server/net/minecraft/src/EntityTracker.java 0000-00-00 00:00:00.000000000 -0000 +@@ -2,6 +2,7 @@ + + import java.util.*; + import net.minecraft.server.MinecraftServer; ++import net.minecraft.src.forge.ForgeHooksServer; + + public class EntityTracker + { +@@ -22,6 +23,10 @@ + + public void trackEntity(Entity entity) + { ++ if (ForgeHooksServer.OnTrackEntity(this, entity)) ++ { ++ return; ++ } + if (entity instanceof EntityPlayerMP) + { + trackEntity(entity, 512, 2); diff --git a/forge/patches/minecraft_server/net/minecraft/src/EntityTrackerEntry.java.patch b/forge/patches/minecraft_server/net/minecraft/src/EntityTrackerEntry.java.patch new file mode 100644 index 0000000000..4d6f6600b3 --- /dev/null +++ b/forge/patches/minecraft_server/net/minecraft/src/EntityTrackerEntry.java.patch @@ -0,0 +1,25 @@ +--- ../src_base/minecraft_server/net/minecraft/src/EntityTrackerEntry.java 0000-00-00 00:00:00.000000000 -0000 ++++ ../src_work/minecraft_server/net/minecraft/src/EntityTrackerEntry.java 0000-00-00 00:00:00.000000000 -0000 +@@ -5,6 +5,8 @@ + import java.util.*; + import java.util.logging.Logger; + ++import net.minecraft.src.forge.ForgeHooks; ++ + public class EntityTrackerEntry + { + public Entity trackedEntity; +@@ -250,6 +252,13 @@ + { + System.out.println("Fetching addPacket for removed entity"); + } ++ ++ Packet pkt = ForgeHooks.getEntitySpawnPacket(trackedEntity); ++ if (pkt != null) ++ { ++ return pkt; ++ } ++ + EntityTrackerEntry2 entitytrackerentry2 = ModLoaderMp.HandleEntityTrackerEntries(trackedEntity); + if (entitytrackerentry2 != null) + { 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 58c3aa5c1c..1dad01427d 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,13 @@ +@@ -1,10 +1,14 @@ package net.minecraft.src; import java.io.IOException; @@ -10,11 +10,12 @@ import java.util.logging.Logger; import net.minecraft.server.MinecraftServer; +import net.minecraft.src.forge.ForgeHooks; ++import net.minecraft.src.forge.ForgeHooksServer; +import net.minecraft.src.forge.MessageManager; public class NetLoginHandler extends NetHandler { -@@ -29,6 +32,7 @@ +@@ -29,6 +33,7 @@ mcServer = minecraftserver; netManager = new NetworkManager(socket, s, this); netManager.chunkDataSendCounter = 0; @@ -22,14 +23,16 @@ } public void tryLogin() -@@ -129,7 +133,37 @@ +@@ -129,7 +134,39 @@ } entityplayermp.func_20057_k(); - ModLoaderMp.HandleAllLogins(entityplayermp); + -+ if (packet1login.serverMode == 0x040E9B47) //"Forge".hashCode(); ++ if (packet1login.serverMode == ForgeHooks.FORGE_ID) + { ++ //Pretty hackish place to put it, but it needs to go somewhere ++ ForgeHooksServer.init(); + //pkt.mapSeed = ForgeHooks.buildVersion; + ForgeHooks.onLogin(netManager, packet1login); +