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