    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    }