/**
* Copyright (c) Lambda Innovation, 2013-2016
* This file is part of the AcademyCraft mod.
* https://github.com/LambdaInnovation/AcademyCraft
* Licensed under GPLv3, see project root for more information.
*/
package cn.academy.ability.block;
import cn.academy.ability.client.render.RenderDeveloperAdvanced;
import cn.academy.ability.client.render.RenderDeveloperNormal;
import cn.academy.ability.client.ui.DeveloperUI;
import cn.academy.ability.develop.DeveloperType;
import cn.academy.ability.develop.IDeveloper;
import cn.academy.core.block.TileReceiverBase;
import cn.lambdalib.annoreg.core.Registrant;
import cn.lambdalib.annoreg.mc.RegTileEntity;
import cn.lambdalib.multiblock.BlockMulti;
import cn.lambdalib.multiblock.IMultiTile;
import cn.lambdalib.multiblock.InfoBlockMulti;
import cn.lambdalib.s11n.network.TargetPoints;
import cn.lambdalib.s11n.network.NetworkMessage;
import cn.lambdalib.s11n.network.NetworkMessage.Listener;
import com.google.common.base.Preconditions;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
/**
* @author WeAthFolD
*
*/
@Registrant
@RegTileEntity
public abstract class TileDeveloper extends TileReceiverBase implements IMultiTile, IDeveloper {
private static final String
MSG_OPEN_GUI = "gui",
MSG_UNUSE = "unuse",
MSG_SYNC = "sync";
@Registrant
@RegTileEntity
@RegTileEntity.HasRender
public static class Normal extends TileDeveloper {
public Normal() {
super(DeveloperType.NORMAL);
}
@SideOnly(Side.CLIENT)
@RegTileEntity.Render
public static RenderDeveloperNormal renderer;
}
@Registrant
@RegTileEntity
@RegTileEntity.HasRender
public static class Advanced extends TileDeveloper {
public Advanced() {
super(DeveloperType.ADVANCED);
}
@SideOnly(Side.CLIENT)
@RegTileEntity.Render
public static RenderDeveloperAdvanced renderer;
}
@SideOnly(Side.CLIENT)
@RegTileEntity.Render
public static RenderDeveloperNormal renderer;
public final DeveloperType type;
private int syncCD;
private EntityPlayer user;
private TileDeveloper(DeveloperType _type) {
super("ability_developer", 2, _type.getEnergy(), _type.getBandwidth());
type = _type;
}
@Override
public void updateEntity() {
if(info != null) {
info.update();
if(info.getSubID() != 0)
return;
super.updateEntity();
if(++syncCD == 20) {
syncCD = 0;
send(MSG_SYNC, user);
}
}
}
public EntityPlayer getUser() {
return user;
}
/**
* SERVER only. Start let the player use the developer, if currently no user is using it.
*/
public boolean use(EntityPlayer player) {
Preconditions.checkState(!player.worldObj.isRemote);
if(info.getSubID() != 0) {
TileDeveloper te = getOrigin();
return te == null ? false : te.use(player);
}
if (user != null) {
unuse();
}
user = player;
send(MSG_OPEN_GUI, player);
return true;
}
private TileDeveloper getOrigin() {
BlockDeveloper dev = (BlockDeveloper) getBlockType();
TileEntity te = dev.getOriginTile(this);
return te instanceof TileDeveloper ? (TileDeveloper) te : null;
}
/**
* Is effective in BOTH CLIENT AND SERVER. Let the current player(if is equal to argument) go away from the developer.
*/
public void unuse(EntityPlayer p) {
if(info.getSubID() != 0) {
TileDeveloper te = getOrigin();
if(te != null) {
te.unuse(p);
}
} else {
if(getWorldObj().isRemote) {
send(MSG_UNUSE, p);
} else {
if(user != null && user.equals(p))
unuse();
}
}
}
private void unuse() {
user = null;
}
@Override
public boolean tryPullEnergy(double amount) {
if(energy < amount)
return false;
pullEnergy(amount);
return true;
}
@Override
public void onGuiClosed() {
send(MSG_UNUSE, user);
}
private void send(String channel, Object ...args) {
if (getWorldObj().isRemote) {
NetworkMessage.sendToServer(this, channel, args);
} else {
NetworkMessage.sendToAllAround(TargetPoints.convert(this, 10), this, channel, args);
}
}
public final DeveloperType getType() {
return type;
}
@SideOnly(Side.CLIENT)
@Listener(channel=MSG_OPEN_GUI, side=Side.CLIENT)
private void hOpenGui(EntityPlayer player) {
// Sync the player right away to prevent bad lookup
this.user = player;
if (Minecraft.getMinecraft().thePlayer.equals(player)) {
Minecraft.getMinecraft().displayGuiScreen(DeveloperUI.apply(this));
}
}
@Listener(channel=MSG_UNUSE, side=Side.SERVER)
private void hUnuse(EntityPlayer player) {
unuse(player);
}
@Listener(channel=MSG_SYNC, side=Side.CLIENT)
private void hSync(EntityPlayer player) {
this.user = player;
}
private InfoBlockMulti info = new InfoBlockMulti(this);
@Override
public InfoBlockMulti getBlockInfo() {
return info;
}
@Override
public void setBlockInfo(InfoBlockMulti i) {
info = i;
}
@Override
public void readFromNBT(NBTTagCompound nbt) {
super.readFromNBT(nbt);
info = new InfoBlockMulti(this, nbt);
}
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
info.save(nbt);
}
@SideOnly(Side.CLIENT)
@Override
public AxisAlignedBB getRenderBoundingBox() {
Block block = getBlockType();
if(block instanceof BlockMulti) {
return ((BlockMulti) block).getRenderBB(xCoord, yCoord, zCoord, info.getDir());
} else {
return super.getRenderBoundingBox();
}
}
}