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 }