package com.flansmod.common.guns.raytracing;
import java.util.ArrayList;
import com.flansmod.common.FlansMod;
import com.flansmod.common.PlayerData;
import com.flansmod.common.PlayerHandler;
import com.flansmod.common.RotatedAxes;
import com.flansmod.common.guns.AttachmentType;
import com.flansmod.common.guns.GunType;
import com.flansmod.common.guns.ItemGun;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.BulletHit;
import com.flansmod.common.guns.raytracing.FlansModRaytracer.PlayerBulletHit;
import com.flansmod.common.vector.Vector3f;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
/** This class takes a snapshot of the player's position rotation and held items at a certain point in time.
* It is used to handle bullet detection. The server will store a second or two of snapshots so that it
* can work out where the player thought they were shooting accounting for packet lag */
public class PlayerSnapshot
{
/** The player this snapshot is for */
public EntityPlayer player;
/** The player's position at the point the snapshot was taken */
public Vector3f pos;
/** The hitboxes for this player */
public ArrayList<PlayerHitbox> hitboxes;
/** The time at which this snapshot was taken */
public long time;
public PlayerSnapshot(EntityPlayer p)
{
player = p;
pos = new Vector3f(p.posX, p.posY, p.posZ);
//if(FlansMod.proxy.isThePlayer(p))
// pos = new Vector3f(p.posX, p.posY - 1.6F, p.posZ);
hitboxes = new ArrayList<PlayerHitbox>();
RotatedAxes bodyAxes = new RotatedAxes(p.renderYawOffset, 0F, 0F);
RotatedAxes headAxes = new RotatedAxes(p.rotationYawHead - p.renderYawOffset, 0F, -p.rotationPitch);
hitboxes.add(new PlayerHitbox(player, bodyAxes, new Vector3f(0F, 0F, 0F), new Vector3f(-0.25F, 0F, -0.15F), new Vector3f(0.5F, 1.4F, 0.3F), EnumHitboxType.BODY));
hitboxes.add(new PlayerHitbox(player, bodyAxes.findLocalAxesGlobally(headAxes), new Vector3f(0.0F, 1.4F, 0F), new Vector3f(-0.25F, 0F, -0.25F), new Vector3f(0.5F, 0.5F, 0.5F), EnumHitboxType.HEAD));
//Calculate rotation of arms using modified code from ModelBiped
float yHead = (p.rotationYawHead - p.renderYawOffset) / (180F / (float)Math.PI);
float xHead = p.rotationPitch / (180F / (float)Math.PI);
float zRight = 0.0F;
float zLeft = 0.0F;
float yRight = -0.1F + yHead - ((float)Math.PI / 2F);
float yLeft = 0.1F + yHead + 0.4F - ((float)Math.PI / 2F);
float xRight = -((float)Math.PI / 2F) + xHead;
float xLeft = -((float)Math.PI / 2F) + xHead;
zRight += MathHelper.cos(p.ticksExisted * 0.09F) * 0.05F + 0.05F;
zLeft -= MathHelper.cos(p.ticksExisted * 0.09F) * 0.05F + 0.05F;
xRight += MathHelper.sin(p.ticksExisted * 0.067F) * 0.05F;
xLeft -= MathHelper.sin(p.ticksExisted * 0.067F) * 0.05F;
RotatedAxes leftArmAxes = (new RotatedAxes()).rotateGlobalPitchInRads(xLeft).rotateGlobalYawInRads((float)Math.PI + yLeft).rotateGlobalRollInRads(-zLeft);
RotatedAxes rightArmAxes = (new RotatedAxes()).rotateGlobalPitchInRads(xRight).rotateGlobalYawInRads((float)Math.PI + yRight).rotateGlobalRollInRads(-zRight);
float originZRight = MathHelper.sin(-p.renderYawOffset * 3.14159265F / 180F) * 5.0F / 16F;
float originXRight = -MathHelper.cos(-p.renderYawOffset * 3.14159265F / 180F) * 5.0F / 16F;
float originZLeft = -MathHelper.sin(-p.renderYawOffset * 3.14159265F / 180F) * 5.0F / 16F;
float originXLeft = MathHelper.cos(-p.renderYawOffset * 3.14159265F / 180F) * 5.0F / 16F;
hitboxes.add(new PlayerHitbox(player, bodyAxes.findLocalAxesGlobally(leftArmAxes), new Vector3f(originXLeft, 1.3F, originZLeft), new Vector3f(-2F / 16F, -0.6F, -2F / 16F), new Vector3f(0.25F, 0.7F, 0.25F), EnumHitboxType.LEFTARM));
hitboxes.add(new PlayerHitbox(player, bodyAxes.findLocalAxesGlobally(rightArmAxes), new Vector3f(originXRight, 1.3F, originZRight), new Vector3f(-2F / 16F, -0.6F, -2F / 16F), new Vector3f(0.25F, 0.7F, 0.25F), EnumHitboxType.RIGHTARM));
//Add box for right hand shield
ItemStack playerRightHandStack = player.getCurrentEquippedItem();
if(playerRightHandStack != null && playerRightHandStack.getItem() instanceof ItemGun)
{
GunType gunType = ((ItemGun)playerRightHandStack.getItem()).GetType();
if(gunType.shield)
{
hitboxes.add(new PlayerHitbox(player, bodyAxes.findLocalAxesGlobally(rightArmAxes), new Vector3f(originXRight, 1.3F, originZRight), new Vector3f(gunType.shieldOrigin.y, -1.05F + gunType.shieldOrigin.x, -1F / 16F + gunType.shieldOrigin.z), new Vector3f(gunType.shieldDimensions.y, gunType.shieldDimensions.x, gunType.shieldDimensions.z), EnumHitboxType.RIGHTITEM));
}
//Add left hand shield box
PlayerData data = PlayerHandler.getPlayerData(player);
if(gunType.oneHanded && data.offHandGunSlot != 0)
{
ItemStack leftHandStack = null;
//Client side other players
if(player.worldObj.isRemote && !FlansMod.proxy.isThePlayer(player))
leftHandStack = data.offHandGunStack;
else leftHandStack = player.inventory.getStackInSlot(data.offHandGunSlot - 1);
if(leftHandStack != null && leftHandStack.getItem() instanceof ItemGun)
{
GunType leftGunType = ((ItemGun)leftHandStack.getItem()).GetType();
if(leftGunType.shield)
{
hitboxes.add(new PlayerHitbox(player, bodyAxes.findLocalAxesGlobally(leftArmAxes), new Vector3f(originXLeft, 1.3F, originZLeft), new Vector3f(leftGunType.shieldOrigin.y, -1.05F + leftGunType.shieldOrigin.x, -1F / 16F + leftGunType.shieldOrigin.z), new Vector3f(leftGunType.shieldDimensions.y, leftGunType.shieldDimensions.x, leftGunType.shieldDimensions.z), EnumHitboxType.LEFTITEM));
}
}
}
}
}
public ArrayList<BulletHit> raytrace(Vector3f origin, Vector3f motion)
{
//Get the bullet raytrace vector into local coordinates
Vector3f localOrigin = Vector3f.sub(origin, pos, null);
//Prepare a list for the hits
ArrayList<BulletHit> hits = new ArrayList<BulletHit>();
//Check each hitbox for a hit
for(PlayerHitbox hitbox : hitboxes)
{
PlayerBulletHit hit = hitbox.raytrace(localOrigin, motion);
if(hit != null && hit.intersectTime >= 0F && hit.intersectTime <= 1F)
{
hits.add(hit);
}
}
return hits;
}
@SideOnly(Side.CLIENT)
public void renderSnapshot()
{
for(PlayerHitbox hitbox : hitboxes)
{
hitbox.renderHitbox(player.worldObj, pos);
}
}
public PlayerHitbox GetHitbox(EnumHitboxType type)
{
for(PlayerHitbox hitbox : hitboxes)
{
if(hitbox.type == type)
{
return hitbox;
}
}
return null;
}
public Vector3f GetMuzzleLocation(GunType gunType, AttachmentType barrelAttachment, boolean isOffHand)
{
PlayerHitbox hitbox = GetHitbox(isOffHand ? EnumHitboxType.LEFTARM : EnumHitboxType.RIGHTARM);
Vector3f muzzlePos = new Vector3f(hitbox.o.x, hitbox.o.y + hitbox.d.y * 0.5f, hitbox.o.z + hitbox.d.z * 0.5f);
if(gunType != null && gunType.model != null)
{
Vector3f barrelAttach = new Vector3f(
gunType.model.barrelAttachPoint.z,
-gunType.model.barrelAttachPoint.x,
gunType.model.barrelAttachPoint.y);
Vector3f.add(muzzlePos, barrelAttach, muzzlePos);
}
muzzlePos = hitbox.axes.findLocalVectorGlobally(muzzlePos);
Vector3f.add(muzzlePos, hitbox.rP, muzzlePos);
return muzzlePos;
}
}