package net.tropicraft.entity.placeable;
import io.netty.buffer.ByteBuf;
import java.util.Collections;
import java.util.List;
import CoroUtil.packet.PacketHelper;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.ai.EntityAITasks;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import net.tropicraft.Tropicraft;
import net.tropicraft.registry.TCItemRegistry;
import net.tropicraft.util.EffectHelper;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class EntitySnareTrap extends Entity implements IEntityAdditionalSpawnData {
private static final int FULL_ID = 16;
private static final int USERNAME_ID = 17;
private static final int ENTITY_HEIGHT_ID = 18;
public static final int MIN_HEIGHT = 3;
public static final int MAX_HEIGHT = 6;
public static final int SCAN_INTERVAL = 5;
public EntityLivingBase caughtEntity;
/** Stored AI tasks field of caught entities. AI tasks are disabled (set to
* null) on catch to prevent mobs from attacking, and restored on release.
*/
private EntityAITasks caughtEntityAITasks;
/**
* Stored move speed field of caught entities. Move speed is set to 0 on
* catch, then restored on release.
*/
private float caughtEntityMoveSpeed;
public int trapPosX;
public int trapPosY;
public int trapPosZ;
public int trapHeight;
public ForgeDirection trapDirection;
private boolean prevFull;
/** Cooldown ticker to prevent us from scanning for entities every tick */
private int scanCoolDown;
public EntitySnareTrap(World par1World) {
super(par1World);
scanCoolDown = SCAN_INTERVAL;
ignoreFrustumCheck = true;
preventEntitySpawning = true;
}
public EntitySnareTrap(World world, int x, int y, int z, int height, ForgeDirection dir) {
this(world);
trapPosX = x;
trapPosY = y;
trapPosZ = z;
trapHeight = height;
trapDirection = dir;
setSize(0.6f, height-0.5f);
setLocationAndAngles(x+0.5, y, z+0.5, 0f, 0f);
}
// TODO NOTE: Replaced variables with these two methods to make it dynamic and not
// needed to be stored in NBT. If it stops working because of that...put it back!
/** The block ID of the block this trap is attached to at the top. */
public Block getHookBlock(World world) {
return world.getBlock(trapPosX - trapDirection.offsetX, trapPosY + trapHeight - 1,
trapPosZ - trapDirection.offsetZ);
}
/** The block ID of the block below this trap. */
public Block getBottomBlock(World world) {
return world.getBlock(trapPosX, trapPosY - 1, trapPosZ);
}
@Override
public boolean canBeCollidedWith() {
return true;
}
@Override
public boolean canBePushed() {
return false;
}
@Override
public void onUpdate() {
super.onUpdate();
if (worldObj.isRemote) {
// update our height
boolean newFull = getFull();
if (prevFull != newFull) {
prevFull = newFull;
if (newFull) {
setSize(0.6f, trapHeight-getEntityHeight()-0.5f);
} else {
setSize(0.6f, trapHeight-0.5f);
}
// to make the new entity height take effect
setLocationAndAngles(posX, posY, posZ, 0f, 0f);
}
// if the client player is trapped, prevent them from moving
EntityPlayer player = getClientPlayer();
if (getUsername().equals(player.getGameProfile().getName())) {
player.setLocationAndAngles(trapPosX+0.5, trapPosY, trapPosZ+0.5, player.rotationYaw, player.rotationPitch);
}
return;
}
if (caughtEntity == null) {
scanCoolDown--;
if (scanCoolDown == 0) {
scanCoolDown = SCAN_INTERVAL;
List ents = worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.expand(5.0, 5.0, 5.0));
for (Object obj: ents) {
Entity ent = (Entity)obj;
if (ent instanceof EntityLivingBase && ((EntityLivingBase)ent).isEntityAlive() && ent.posX >= trapPosX && ent.posX <= trapPosX+1 && ent.posZ >= trapPosZ && ent.posZ <= trapPosZ+1 && Math.abs(trapPosY-ent.posY) < 0.01) {
boolean alreadyTrapped = false;
for (Object trapObj: ents) {
if (!(trapObj instanceof EntitySnareTrap)) {
continue;
}
EntitySnareTrap trap = (EntitySnareTrap) trapObj;
if (trap.caughtEntity == ent) {
alreadyTrapped = true;
break;
}
}
if (!alreadyTrapped) {
catchEntity((EntityLivingBase)ent);
}
}
}
}
} else {
if (!caughtEntity.isEntityAlive()) {
releaseEntity();
} else {
caughtEntity.setLocationAndAngles(trapPosX+0.5, trapPosY, trapPosZ+0.5, caughtEntity.rotationYaw, caughtEntity.rotationPitch);
caughtEntity.motionX = 0.0;
caughtEntity.motionY = 0.0;
caughtEntity.motionZ = 0.0;
}
}
// possible bug with this check: dirt turning into grass below would
// drop the trap
if (worldObj.getBlock(trapPosX-trapDirection.offsetX, trapPosY+trapHeight-1, trapPosZ-trapDirection.offsetZ) != getHookBlock(worldObj) ||
worldObj.getBlock(trapPosX, trapPosY-1, trapPosZ) != getBottomBlock(worldObj)) {
if (caughtEntity != null) {
releaseEntity();
}
this.dropItem(TCItemRegistry.snareTrap, 1);
setDead();
}
}
@SideOnly(Side.CLIENT)
public EntityPlayer getClientPlayer() {
return Minecraft.getMinecraft().thePlayer;
}
public void catchEntity(EntityLivingBase ent) {
caughtEntity = ent;
setFull(true);
setEntityHeight(ent.height+ent.yOffset);
worldObj.playSoundAtEntity(this, "random.bow", 1.0F, 1.0F / (rand.nextFloat() * 0.4F + 1.2F));
setSize(0.6f, trapHeight-ent.height-ent.yOffset-0.5f);
setLocationAndAngles(trapPosX+0.5, trapPosY+ent.height+ent.yOffset, trapPosZ+0.5, 0f, 0f);
if (ent instanceof EntityPlayer) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setString("packetCommand", "effectAdd");
nbt.setInteger("effectID", 0);
nbt.setInteger("effectTime", -1);
Tropicraft.eventChannel.sendTo(PacketHelper.getNBTPacket(nbt, Tropicraft.eventChannelName), (EntityPlayerMP) ent);
/*EntityPlayer player = (EntityPlayer)ent;
setUsername(player.getGameProfile().getName());
PacketDispatcher.sendPacketToAllPlayers(TropicraftPacketHandler.getSnareTrapPacket(false, true, Collections.singleton(player.username)));
Tropicraft.proxy.getUpsideDownUsernames().add(player.getGameProfile().getName());*/
} else if (ent instanceof EntityLiving) {
EffectHelper.addEntry(ent, -1);
/*caughtEntityMoveSpeed = EntityDartHelper.getEntityMoveSpeed(ent);
caughtEntityAITasks = EntityDartHelper.getEntityAITasks((EntityLiving) ent);
EntityDartHelper.setEntityAITasks(ent, null);
EntityDartHelper.setEntityMoveSpeed(ent, 0);
EntityDartHelper.setIsEntityJumping(ent, false);
if (ent instanceof EntityCreature) {
EntityDartHelper.setEntityToAttack((EntityCreature) ent, null);
}
if (ent instanceof EntityCreeper) {
EntityDartHelper.setCreeperIgnitionTime((EntityCreeper) ent, 0);
}*/
}
}
public void releaseEntity() {
scanCoolDown = SCAN_INTERVAL;
setFull(false);
setUsername("");
setSize(0.6f, trapHeight-0.5f);
setLocationAndAngles(trapPosX+0.5, trapPosY, trapPosZ+0.5, 0f, 0f);
if (caughtEntity instanceof EntityPlayer) {
NBTTagCompound nbt = new NBTTagCompound();
nbt.setString("packetCommand", "effectRemove");
Tropicraft.eventChannel.sendTo(PacketHelper.getNBTPacket(nbt, Tropicraft.eventChannelName), (EntityPlayerMP) caughtEntity);
/*EntityPlayer player = (EntityPlayer)caughtEntity;
PacketDispatcher.sendPacketToAllPlayers(TropicraftPacketHandler.getSnareTrapPacket(false, false, Collections.singleton(player.username)));
Tropicraft.proxy.getUpsideDownUsernames().remove(player.getGameProfile().getName());*/
} else {
EffectHelper.removeEntry(caughtEntity);
/*EntityDartHelper.setEntityMoveSpeed(caughtEntity, caughtEntityMoveSpeed);
EntityDartHelper.setEntityAITasks(caughtEntity, caughtEntityAITasks);
caughtEntityAITasks = null;*/
}
caughtEntity = null;
}
@Override
public boolean attackEntityFrom(DamageSource source, float dmg) {
if (worldObj.isRemote) {
return true;
}
worldObj.playSoundAtEntity(this, "note.harp", 1.0F, 2f-rand.nextFloat()/2f);
if (caughtEntity != null && source.getEntity() == caughtEntity) {
if (rand.nextFloat() > 0.1f) {
return false;
}
}
if (caughtEntity != null) {
releaseEntity();
}
Entity sourceEnt = source.getEntity();
if (!(sourceEnt instanceof EntityPlayer && ((EntityPlayer)sourceEnt).capabilities.isCreativeMode)) {
this.dropItem(TCItemRegistry.snareTrap, 1);
}
setDead();
return true;
}
@Override
protected void entityInit() {
this.dataWatcher.addObject(FULL_ID, Byte.valueOf((byte)0));
this.dataWatcher.addObject(USERNAME_ID, "");
this.dataWatcher.addObject(ENTITY_HEIGHT_ID, Integer.valueOf(0));
}
public void setEntityHeight(float height) {
this.dataWatcher.updateObject(ENTITY_HEIGHT_ID, Integer.valueOf((int)(height*100)));
}
public float getEntityHeight() {
return this.dataWatcher.getWatchableObjectInt(ENTITY_HEIGHT_ID)/100f;
}
public void setUsername(String username) {
this.dataWatcher.updateObject(USERNAME_ID, username);
}
public String getUsername() {
return this.dataWatcher.getWatchableObjectString(USERNAME_ID);
}
public void setFull(boolean full) {
this.dataWatcher.updateObject(FULL_ID, Byte.valueOf((byte)(full?1:0)));
}
public boolean getFull() {
return this.dataWatcher.getWatchableObjectByte(FULL_ID) == 1;
}
@Override
protected void readEntityFromNBT(NBTTagCompound var1) {
trapHeight = var1.getInteger("Height");
trapDirection = ForgeDirection.getOrientation(var1.getByte("Direction"));
trapPosX = var1.getInteger("XPos");
trapPosY = var1.getInteger("YPos");
trapPosZ = var1.getInteger("ZPos");
}
@Override
protected void writeEntityToNBT(NBTTagCompound var1) {
var1.setInteger("Height", trapHeight);
var1.setByte("Direction", (byte)trapDirection.ordinal());
var1.setInteger("XPos", trapPosX);
var1.setInteger("YPos", trapPosY);
var1.setInteger("ZPos", trapPosZ);
}
@Override
public void writeSpawnData(ByteBuf data) {
data.writeInt(this.trapPosX);
data.writeInt(this.trapPosY);
data.writeInt(this.trapPosZ);
data.writeInt(this.trapHeight);
data.writeByte(this.trapDirection.ordinal());
}
@Override
public void readSpawnData(ByteBuf data) {
this.trapPosX = data.readInt();
this.trapPosY = data.readInt();
this.trapPosZ = data.readInt();
this.trapHeight = data.readInt();
this.trapDirection = ForgeDirection.getOrientation((int)data.readByte());
setSize(0.6f, this.trapHeight-0.5f);
setLocationAndAngles(this.trapPosX+0.5, this.trapPosY, trapPosZ+0.5, 0f, 0f);
}
}