package openblocks.common.tileentity;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.common.util.ForgeDirection;
import openmods.api.IActivateAwareTile;
import openmods.api.IAddAwareTile;
import openmods.api.INeighbourAwareTile;
import openmods.api.ISurfaceAttachment;
import openmods.sync.ISyncListener;
import openmods.sync.ISyncableObject;
import openmods.sync.SyncableBoolean;
import openmods.sync.SyncableFlags;
import openmods.sync.SyncableUUID;
import openmods.tileentity.SyncedTileEntity;
public class TileEntityBearTrap extends SyncedTileEntity implements IActivateAwareTile, ISurfaceAttachment, INeighbourAwareTile, IAddAwareTile {
public static final int OPENING_ANIMATION_TIME = 15;
public enum Flags {
isShut
}
private SyncableFlags flags;
// can't be added as new flag, since animation depends on it
private SyncableBoolean isLocked;
private SyncableUUID trappedEntity;
private int tickSinceOpened;
private Entity cachedEntity;
public TileEntityBearTrap() {
syncMap.addUpdateListener(new ISyncListener() {
@Override
public void onSync(Set<ISyncableObject> changes) {
if (changes.contains(flags) && !isShut()) tickSinceOpened = 0;
}
});
}
private Entity getEntity() {
UUID uuid = trappedEntity.getValue();
if (uuid == null) return null;
if (cachedEntity != null && uuid.equals(cachedEntity.getUniqueID())) return cachedEntity;
@SuppressWarnings("unchecked")
final List<Entity> entityList = worldObj.loadedEntityList;
for (Entity entity : entityList)
if (uuid.equals(entity.getUniqueID())) {
cachedEntity = entity;
return entity;
}
return null;
}
@Override
protected void createSyncedFields() {
flags = SyncableFlags.create(Flags.values().length);
trappedEntity = new SyncableUUID();
isLocked = new SyncableBoolean();
flags.on(Flags.isShut);
}
@Override
public void updateEntity() {
super.updateEntity();
tickSinceOpened++;
if (!worldObj.isRemote) {
immobilizeEntity();
sync();
}
}
private void immobilizeEntity() {
final Entity trappedEntity = getEntity();
if (trappedEntity == null || trappedEntity.isDead) {
open();
return;
}
trappedEntity.distanceWalkedOnStepModified = 0.0f;
trappedEntity.distanceWalkedModified = 0.0f;
trappedEntity.posX = 0.5 + xCoord;
trappedEntity.posZ = 0.5 + zCoord;
trappedEntity.posY = yCoord;
trappedEntity.prevPosX = 0.5 + xCoord;
trappedEntity.prevPosZ = 0.5 + zCoord;
trappedEntity.prevPosY = yCoord;
trappedEntity.lastTickPosX = 0.5 + xCoord;
trappedEntity.lastTickPosZ = 0.5 + zCoord;
trappedEntity.lastTickPosY = yCoord;
trappedEntity.motionX = 0;
trappedEntity.motionY = 0;
trappedEntity.motionZ = 0;
}
public void onEntityCollided(Entity entity) {
if (!worldObj.isRemote) {
if (entity instanceof EntityCreature && !isLocked.get() && tickSinceOpened > OPENING_ANIMATION_TIME) {
close(entity);
}
}
}
public boolean isShut() {
return flags.get(Flags.isShut);
}
public int getComparatorLevel() {
final Entity e = getEntity();
return e != null? e.myEntitySize.ordinal() + 1 : 0;
}
public int ticksSinceOpened() {
return tickSinceOpened;
}
@Override
public boolean onBlockActivated(EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
if (!worldObj.isRemote) open();
return true;
}
private void close(Entity trapped) {
if (!flags.get(Flags.isShut)) {
flags.on(Flags.isShut);
trappedEntity.setValue(trapped.getUniqueID());
worldObj.playSoundEffect(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, "openblocks:beartrap.close", 0.5F, 1.0F);
worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, getBlockType());
}
}
private void open() {
if (flags.get(Flags.isShut)) {
flags.off(Flags.isShut);
trappedEntity.clear();
worldObj.playSoundEffect(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5, "openblocks:beartrap.open", 0.5F, 1.0F);
worldObj.notifyBlocksOfNeighborChange(xCoord, yCoord, zCoord, getBlockType());
}
}
@Override
public ForgeDirection getSurfaceDirection() {
return ForgeDirection.DOWN;
}
@Override
public void onNeighbourChanged(Block block) {
updateRedstone();
}
@Override
public void onAdded() {
updateRedstone();
}
private void updateRedstone() {
if (!worldObj.isRemote) {
boolean isLocked = worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord);
this.isLocked.set(isLocked);
if (isLocked) open();
}
}
}