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.NetworkManager; 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(NetworkManager 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 }