package net.minecraftforge.fml.common.network.internal; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import java.io.IOException; import java.util.List; import org.apache.logging.log4j.Level; import com.google.common.base.Throwables; import net.minecraft.entity.DataWatcher; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.network.PacketBuffer; import net.minecraft.util.MathHelper; import net.minecraftforge.fml.common.FMLLog; import net.minecraftforge.fml.common.ModContainer; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData; import net.minecraftforge.fml.common.registry.IThrowableEntity; import net.minecraftforge.fml.common.registry.EntityRegistry.EntityRegistration; import net.minecraftforge.fml.relauncher.Side; public abstract class FMLMessage { public static class CompleteHandshake extends FMLMessage { Side target; public CompleteHandshake() { } public CompleteHandshake(Side target) { this.target = target; } @Override void fromBytes(ByteBuf buf) { target = Side.values()[buf.readByte()]; } @Override void toBytes(ByteBuf buf) { buf.writeByte(target.ordinal()); } } public static class OpenGui extends FMLMessage { int windowId; String modId; int modGuiId; int x; int y; int z; public OpenGui() {} OpenGui(int windowId, String modId, int modGuiId, int x, int y, int z) { this.windowId = windowId; this.modId = modId; this.modGuiId = modGuiId; this.x = x; this.y = y; this.z = z; } @Override void toBytes(ByteBuf buf) { buf.writeInt(windowId); ByteBufUtils.writeUTF8String(buf, modId); buf.writeInt(modGuiId); buf.writeInt(x); buf.writeInt(y); buf.writeInt(z); } @Override void fromBytes(ByteBuf buf) { windowId = buf.readInt(); modId = ByteBufUtils.readUTF8String(buf); modGuiId = buf.readInt(); x = buf.readInt(); y = buf.readInt(); z = buf.readInt(); } } public abstract static class EntityMessage extends FMLMessage { Entity entity; int entityId; public EntityMessage() { } EntityMessage(Entity entity) { this.entity = entity; } @Override void toBytes(ByteBuf buf) { buf.writeInt(entity.getEntityId()); } @Override void fromBytes(ByteBuf buf) { entityId = buf.readInt(); } } public static class EntityAdjustMessage extends EntityMessage { int serverX; int serverY; int serverZ; public EntityAdjustMessage() {} public EntityAdjustMessage(Entity entity, int serverX, int serverY, int serverZ) { super(entity); this.serverX = serverX; this.serverY = serverY; this.serverZ = serverZ; } @Override void toBytes(ByteBuf buf) { super.toBytes(buf); buf.writeInt(serverX); buf.writeInt(serverY); buf.writeInt(serverZ); } @Override void fromBytes(ByteBuf buf) { super.fromBytes(buf); serverX = buf.readInt(); serverY = buf.readInt(); serverZ = buf.readInt(); } } public static class EntitySpawnMessage extends EntityMessage { String modId; int modEntityTypeId; int rawX; int rawY; int rawZ; double scaledX; double scaledY; double scaledZ; float scaledYaw; float scaledPitch; float scaledHeadYaw; int throwerId; double speedScaledX; double speedScaledY; double speedScaledZ; @SuppressWarnings("rawtypes") List dataWatcherList; ByteBuf dataStream; public EntitySpawnMessage() {} public EntitySpawnMessage(EntityRegistration er, Entity entity, ModContainer modContainer) { super(entity); modId = modContainer.getModId(); modEntityTypeId = er.getModEntityId(); } @Override void toBytes(ByteBuf buf) { super.toBytes(buf); ByteBufUtils.writeUTF8String(buf, modId); buf.writeInt(modEntityTypeId); // posX, posY, posZ buf.writeInt(MathHelper.floor_double(entity.posX * 32D)); buf.writeInt(MathHelper.floor_double(entity.posY * 32D)); buf.writeInt(MathHelper.floor_double(entity.posZ * 32D)); // yaw, pitch buf.writeByte((byte)(entity.rotationYaw * 256.0F / 360.0F)); buf.writeByte((byte) (entity.rotationPitch * 256.0F / 360.0F)); // head yaw if (entity instanceof EntityLivingBase) { buf.writeByte((byte) (((EntityLivingBase)entity).rotationYawHead * 256.0F / 360.0F)); } else { buf.writeByte(0); } ByteBuf tmpBuf = Unpooled.buffer(); PacketBuffer pb = new PacketBuffer(tmpBuf); try { entity.getDataWatcher().writeTo(pb); } catch (IOException e) { FMLLog.log(Level.FATAL,e,"Encountered fatal exception trying to send entity spawn data watchers"); throw Throwables.propagate(e); } buf.writeBytes(tmpBuf); if (entity instanceof IThrowableEntity) { Entity owner = ((IThrowableEntity)entity).getThrower(); buf.writeInt(owner == null ? entity.getEntityId() : owner.getEntityId()); double maxVel = 3.9D; double mX = entity.motionX; double mY = entity.motionY; double mZ = entity.motionZ; if (mX < -maxVel) mX = -maxVel; if (mY < -maxVel) mY = -maxVel; if (mZ < -maxVel) mZ = -maxVel; if (mX > maxVel) mX = maxVel; if (mY > maxVel) mY = maxVel; if (mZ > maxVel) mZ = maxVel; buf.writeInt((int)(mX * 8000D)); buf.writeInt((int)(mY * 8000D)); buf.writeInt((int)(mZ * 8000D)); } else { buf.writeInt(0); } if (entity instanceof IEntityAdditionalSpawnData) { tmpBuf = Unpooled.buffer(); ((IEntityAdditionalSpawnData)entity).writeSpawnData(tmpBuf); buf.writeBytes(tmpBuf); } } @Override void fromBytes(ByteBuf dat) { super.fromBytes(dat); modId = ByteBufUtils.readUTF8String(dat); modEntityTypeId = dat.readInt(); rawX = dat.readInt(); rawY = dat.readInt(); rawZ = dat.readInt(); scaledX = rawX / 32D; scaledY = rawY / 32D; scaledZ = rawZ / 32D; scaledYaw = dat.readByte() * 360F / 256F; scaledPitch = dat.readByte() * 360F / 256F; scaledHeadYaw = dat.readByte() * 360F / 256F; try { dataWatcherList = DataWatcher.readWatchedListFromPacketBuffer(new PacketBuffer(dat)); } catch (IOException e) { FMLLog.log(Level.FATAL, e, "There was a critical error decoding the datawatcher stream for a mod entity."); throw Throwables.propagate(e); } throwerId = dat.readInt(); if (throwerId != 0) { speedScaledX = dat.readInt() / 8000D; speedScaledY = dat.readInt() / 8000D; speedScaledZ = dat.readInt() / 8000D; } this.dataStream = dat; } } abstract void toBytes(ByteBuf buf); abstract void fromBytes(ByteBuf buf); }