package com.flansmod.common.network;
import java.util.ArrayList;
import java.util.List;
import com.flansmod.common.FlansMod;
import com.flansmod.common.PlayerData;
import com.flansmod.common.PlayerHandler;
import com.flansmod.common.guns.BulletType;
import com.flansmod.common.guns.GunType;
import com.flansmod.common.guns.ItemGun;
import com.flansmod.common.guns.ItemGun;
import com.flansmod.common.guns.ShootableType;
import com.flansmod.common.guns.ShotData;
import com.flansmod.common.guns.ShotData.InstantShotData;
import com.flansmod.common.guns.ShotData.SpawnEntityShotData;
import com.flansmod.common.guns.raytracing.FlansModRaytracer;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.BulletHit;
import com.flansmod.common.types.InfoType;
import com.flansmod.common.vector.Vector3f;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class PacketShotData extends PacketBase
{
private List<ShotData> shotData;
public PacketShotData() {}
public PacketShotData(List<ShotData> shotData)
{
this.shotData = shotData;
}
public PacketShotData(ShotData shotData)
{
this.shotData = new ArrayList<ShotData>();
this.shotData.add(shotData);
}
@Override
public void encodeInto(ChannelHandlerContext ctx, ByteBuf data)
{
data.writeInt(shotData.size());
for(int i = 0; i < shotData.size(); i++)
{
ShotData current = shotData.get(i);
data.writeByte((byte)current.slot);
data.writeInt(current.shotFrom.hashCode());
data.writeInt(current.shotType.hashCode());
if(current instanceof SpawnEntityShotData)
{
SpawnEntityShotData currentCast = (SpawnEntityShotData)current;
data.writeByte(0);
data.writeInt(currentCast.shooterID);
currentCast.direction.writeToBuffer(data);
}
else if(current instanceof InstantShotData)
{
InstantShotData currentCast = (InstantShotData)current;
data.writeByte(1);
data.writeInt(currentCast.shooterID);
currentCast.origin.writeToBuffer(data);
FlansModRaytracer.WriteToBuffer(currentCast.hitData, data);
currentCast.hitPos.writeToBuffer(data);
data.writeFloat(currentCast.damage);
data.writeBoolean(currentCast.isExtraBullet);
data.writeBoolean(currentCast.silenced);
}
}
}
@Override
public void decodeInto(ChannelHandlerContext ctx, ByteBuf data)
{
shotData = new ArrayList<ShotData>();
int numEntries = data.readInt();
for(int i = 0; i < numEntries; i++)
{
// Lookup types by hash
byte slot = data.readByte();
InfoType shotFrom = InfoType.getType(data.readInt());
ShootableType shotType = ShootableType.getShootableType(data.readInt());
byte dataType = data.readByte();
switch(dataType)
{
case 0: // SpawnEntityShotData
{
int shooterID = data.readInt();
Vector3f direction = Vector3f.readFromBuffer(data);
shotData.add(new SpawnEntityShotData(slot, shotFrom, shotType, shooterID, direction));
break;
}
case 1: // InstantShotData
{
int shooterID = data.readInt();
Vector3f origin = Vector3f.readFromBuffer(data);
BulletHit hitData = FlansModRaytracer.ReadFromBuffer(data);
Vector3f hit = Vector3f.readFromBuffer(data);
float damage = data.readFloat();
boolean isExtraBullet = data.readBoolean();
boolean silenced = data.readBoolean();
shotData.add(new InstantShotData(slot, shotFrom, shotType, shooterID, origin, hitData, hit, damage, isExtraBullet, silenced));
break;
}
default:
break;
}
}
}
@Override
public void handleServerSide(EntityPlayerMP player)
{
PlayerData data = PlayerHandler.getPlayerData(player, Side.SERVER);
for(ShotData entry : shotData)
{
if(entry.slot == -1)
{
if(entry.shotFrom instanceof GunType)
{
((ItemGun)entry.shotFrom.item).ServerHandleShotData(null, entry.slot, player.worldObj, player, false, entry);
}
}
else
{
ItemStack gunStack = player.inventory.getStackInSlot(entry.slot);
if(gunStack != null && gunStack.getItem() instanceof ItemGun)
{
ItemGun gunItem = (ItemGun)gunStack.getItem();
boolean isOffHand = (data.offHandGunSlot + 1 == entry.slot);
gunItem.ServerHandleShotData(gunStack, entry.slot, player.worldObj, player, isOffHand, entry);
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public void handleClientSide(EntityPlayer clientPlayer)
{
for(ShotData entry : shotData)
{
if(entry instanceof InstantShotData)
{
InstantShotData instantData = ((InstantShotData)entry);
if(entry.shotFrom instanceof GunType)
{
ItemGun gunItem = (ItemGun)entry.shotFrom.getItem();
gunItem.DoInstantShot(clientPlayer.worldObj,
FlansModRaytracer.GetEntityByID(instantData.shooterID),
instantData.shotFrom, (BulletType)instantData.shotType,
instantData.origin, instantData.hitPos,
instantData.hitData, instantData.damage,
instantData.isExtraBullet,
instantData.silenced);
}
}
else
{
FlansMod.log("Only expect instant shot types on client side.");
}
}
}
}