001 package cpw.mods.fml.common.network; 002 003 import java.io.ByteArrayInputStream; 004 import java.io.ByteArrayOutputStream; 005 import java.io.DataInputStream; 006 import java.io.DataOutputStream; 007 import java.io.IOException; 008 import java.util.List; 009 import java.util.logging.Level; 010 011 import net.minecraft.entity.*; 012 import net.minecraft.network.INetworkManager; 013 import net.minecraft.network.packet.NetHandler; 014 import net.minecraft.util.MathHelper; 015 016 import com.google.common.io.ByteArrayDataInput; 017 import com.google.common.io.ByteArrayDataOutput; 018 import com.google.common.io.ByteStreams; 019 020 import cpw.mods.fml.common.FMLCommonHandler; 021 import cpw.mods.fml.common.FMLLog; 022 import cpw.mods.fml.common.ModContainer; 023 import cpw.mods.fml.common.registry.EntityRegistry; 024 import cpw.mods.fml.common.registry.EntityRegistry.EntityRegistration; 025 import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData; 026 import cpw.mods.fml.common.registry.IThrowableEntity; 027 028 public class EntitySpawnPacket extends FMLPacket 029 { 030 031 public int networkId; 032 public int modEntityId; 033 public int entityId; 034 public double scaledX; 035 public double scaledY; 036 public double scaledZ; 037 public float scaledYaw; 038 public float scaledPitch; 039 public float scaledHeadYaw; 040 public List metadata; 041 public int throwerId; 042 public double speedScaledX; 043 public double speedScaledY; 044 public double speedScaledZ; 045 public ByteArrayDataInput dataStream; 046 public int rawX; 047 public int rawY; 048 public int rawZ; 049 050 public EntitySpawnPacket() 051 { 052 super(Type.ENTITYSPAWN); 053 } 054 055 @Override 056 public byte[] generatePacket(Object... data) 057 { 058 EntityRegistration er = (EntityRegistration) data[0]; 059 Entity ent = (Entity) data[1]; 060 NetworkModHandler handler = (NetworkModHandler) data[2]; 061 ByteArrayDataOutput dat = ByteStreams.newDataOutput(); 062 063 dat.writeInt(handler.getNetworkId()); 064 dat.writeInt(er.getModEntityId()); 065 // entity id 066 dat.writeInt(ent.entityId); 067 068 // entity pos x,y,z 069 dat.writeInt(MathHelper.floor_double(ent.posX * 32D)); 070 dat.writeInt(MathHelper.floor_double(ent.posY * 32D)); 071 dat.writeInt(MathHelper.floor_double(ent.posZ * 32D)); 072 073 // yaw, pitch 074 dat.writeByte((byte) (ent.rotationYaw * 256.0F / 360.0F)); 075 dat.writeByte((byte) (ent.rotationPitch * 256.0F / 360.0F)); 076 077 // head yaw 078 if (ent instanceof EntityLiving) 079 { 080 dat.writeByte((byte) (((EntityLiving)ent).rotationYawHead * 256.0F / 360.0F)); 081 } 082 else 083 { 084 dat.writeByte(0); 085 } 086 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 087 DataOutputStream dos = new DataOutputStream(bos); 088 try 089 { 090 ent.getDataWatcher().writeWatchableObjects(dos); 091 } 092 catch (IOException e) 093 { 094 // unpossible 095 } 096 097 dat.write(bos.toByteArray()); 098 099 if (ent instanceof IThrowableEntity) 100 { 101 Entity owner = ((IThrowableEntity)ent).getThrower(); 102 dat.writeInt(owner == null ? ent.entityId : owner.entityId); 103 double maxVel = 3.9D; 104 double mX = ent.motionX; 105 double mY = ent.motionY; 106 double mZ = ent.motionZ; 107 if (mX < -maxVel) mX = -maxVel; 108 if (mY < -maxVel) mY = -maxVel; 109 if (mZ < -maxVel) mZ = -maxVel; 110 if (mX > maxVel) mX = maxVel; 111 if (mY > maxVel) mY = maxVel; 112 if (mZ > maxVel) mZ = maxVel; 113 dat.writeInt((int)(mX * 8000D)); 114 dat.writeInt((int)(mY * 8000D)); 115 dat.writeInt((int)(mZ * 8000D)); 116 } 117 else 118 { 119 dat.writeInt(0); 120 } 121 if (ent instanceof IEntityAdditionalSpawnData) 122 { 123 ((IEntityAdditionalSpawnData)ent).writeSpawnData(dat); 124 } 125 126 return dat.toByteArray(); 127 } 128 129 @Override 130 public FMLPacket consumePacket(byte[] data) 131 { 132 ByteArrayDataInput dat = ByteStreams.newDataInput(data); 133 networkId = dat.readInt(); 134 modEntityId = dat.readInt(); 135 entityId = dat.readInt(); 136 rawX = dat.readInt(); 137 rawY = dat.readInt(); 138 rawZ = dat.readInt(); 139 scaledX = rawX / 32D; 140 scaledY = rawY / 32D; 141 scaledZ = rawZ / 32D; 142 scaledYaw = dat.readByte() * 360F / 256F; 143 scaledPitch = dat.readByte() * 360F / 256F; 144 scaledHeadYaw = dat.readByte() * 360F / 256F; 145 ByteArrayInputStream bis = new ByteArrayInputStream(data, 27, data.length - 27); 146 DataInputStream dis = new DataInputStream(bis); 147 try 148 { 149 metadata = DataWatcher.readWatchableObjects(dis); 150 } 151 catch (IOException e) 152 { 153 // Nope 154 } 155 dat.skipBytes(data.length - bis.available() - 27); 156 throwerId = dat.readInt(); 157 if (throwerId != 0) 158 { 159 speedScaledX = dat.readInt() / 8000D; 160 speedScaledY = dat.readInt() / 8000D; 161 speedScaledZ = dat.readInt() / 8000D; 162 } 163 164 this.dataStream = dat; 165 return this; 166 } 167 168 @Override 169 public void execute(INetworkManager network, FMLNetworkHandler handler, NetHandler netHandler, String userName) 170 { 171 NetworkModHandler nmh = handler.findNetworkModHandler(networkId); 172 ModContainer mc = nmh.getContainer(); 173 174 EntityRegistration registration = EntityRegistry.instance().lookupModSpawn(mc, modEntityId); 175 Class<? extends Entity> cls = registration.getEntityClass(); 176 if (cls == null) 177 { 178 FMLLog.log(Level.WARNING, "Missing mod entity information for %s : %d", mc.getModId(), modEntityId); 179 return; 180 } 181 182 183 Entity entity = FMLCommonHandler.instance().spawnEntityIntoClientWorld(registration, this); 184 } 185 186 }