package mcjty.rftools.blocks.spaceprojector;
import cpw.mods.fml.common.Optional;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import li.cil.oc.api.machine.Arguments;
import li.cil.oc.api.machine.Callback;
import li.cil.oc.api.machine.Context;
import li.cil.oc.api.network.SimpleComponent;
import mcjty.lib.container.InventoryHelper;
import mcjty.lib.entity.GenericEnergyReceiverTileEntity;
import mcjty.lib.network.Argument;
import mcjty.lib.varia.Coordinate;
import mcjty.rftools.blocks.RedstoneMode;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.world.World;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.util.Constants;
import java.util.Map;
@Optional.InterfaceList({
@Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers"),
@Optional.Interface(iface = "dan200.computercraft.api.peripheral.IPeripheral", modid = "ComputerCraft")})
public class SpaceProjectorTileEntity extends GenericEnergyReceiverTileEntity implements ISidedInventory, SimpleComponent, IPeripheral {
public static final String COMPONENT_NAME = "space_projector";
public static final String CMD_RSMODE = "rsMode";
public static final String CMD_PROJECT = "project";
private InventoryHelper inventoryHelper = new InventoryHelper(this, SpaceProjectorContainer.factory, 1);
private RedstoneMode redstoneMode = RedstoneMode.REDSTONE_IGNORED;
private int powered = 0;
private Coordinate minBox = null;
private Coordinate maxBox = null;
public SpaceProjectorTileEntity() {
super(SpaceProjectorConfiguration.SPACEPROJECTOR_MAXENERGY, SpaceProjectorConfiguration.SPACEPROJECTOR_RECEIVEPERTICK);
}
@Override
@Optional.Method(modid = "ComputerCraft")
public String getType() {
return COMPONENT_NAME;
}
@Override
@Optional.Method(modid = "ComputerCraft")
public String[] getMethodNames() {
return new String[] { "hasCard", "getRedstoneMode", "setRedstoneMode" };
}
@Override
@Optional.Method(modid = "ComputerCraft")
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException {
switch (method) {
case 0: return new Object[] { hasCard() != null };
case 1: return new Object[] { getRedstoneMode().getDescription() };
case 2: return setRedstoneMode((String) arguments[0]);
}
return new Object[0];
}
@Override
@Optional.Method(modid = "ComputerCraft")
public void attach(IComputerAccess computer) {
}
@Override
@Optional.Method(modid = "ComputerCraft")
public void detach(IComputerAccess computer) {
}
@Override
@Optional.Method(modid = "ComputerCraft")
public boolean equals(IPeripheral other) {
return false;
}
@Override
@Optional.Method(modid = "OpenComputers")
public String getComponentName() {
return COMPONENT_NAME;
}
@Callback(doc = "Return true if this projector has a space card in it", getter = true)
@Optional.Method(modid = "OpenComputers")
public Object[] hasCard(Context context, Arguments args) throws Exception {
return new Object[] { hasCard() != null };
}
@Callback(doc = "Get the current redstone mode. Values are 'Ignored', 'Off', or 'On'", getter = true)
@Optional.Method(modid = "OpenComputers")
public Object[] getRedstoneMode(Context context, Arguments args) throws Exception {
return new Object[] { getRedstoneMode().getDescription() };
}
@Callback(doc = "Set the current redstone mode. Values are 'Ignored', 'Off', or 'On'", setter = true)
@Optional.Method(modid = "OpenComputers")
public Object[] setRedstoneMode(Context context, Arguments args) throws Exception {
String mode = args.checkString(0);
return setRedstoneMode(mode);
}
private NBTTagCompound hasCard() {
ItemStack itemStack = inventoryHelper.getStackInSlot(0);
if (itemStack == null || itemStack.stackSize == 0) {
return null;
}
NBTTagCompound tagCompound = itemStack.getTagCompound();
return tagCompound;
}
@Override
public void setPowered(int powered) {
if (this.powered != powered) {
this.powered = powered;
markDirty();
}
}
public RedstoneMode getRedstoneMode() {
return redstoneMode;
}
private Object[] setRedstoneMode(String mode) {
RedstoneMode redstoneMode = RedstoneMode.getMode(mode);
if (redstoneMode == null) {
throw new IllegalArgumentException("Not a valid mode");
}
setRedstoneMode(redstoneMode);
return null;
}
public void setRedstoneMode(RedstoneMode redstoneMode) {
this.redstoneMode = redstoneMode;
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
markDirty();
}
public void unproject() {
if (minBox == null) {
return;
}
for (int x = minBox.getX() ; x <= maxBox.getX() ; x++) {
for (int y = minBox.getY() ; y <= maxBox.getY() ; y++) {
for (int z = minBox.getZ() ; z <= maxBox.getZ() ; z++) {
Block block = worldObj.getBlock(x, y, z);
if (block.equals(SpaceProjectorSetup.proxyBlock)) {
worldObj.setBlockToAir(x, y, z);
}
}
}
}
minBox = null;
maxBox = null;
markDirty();
}
private void project() {
if (minBox != null) {
unproject();
}
NBTTagCompound tc = hasCard();
if (tc == null) {
return;
}
int channel = tc.getInteger("channel");
if (channel == -1) {
return;
}
SpaceChamberRepository repository = SpaceChamberRepository.getChannels(worldObj);
SpaceChamberRepository.SpaceChamberChannel chamberChannel = repository.getChannel(channel);
if (chamberChannel == null) {
return;
}
Coordinate minCorner = chamberChannel.getMinCorner();
Coordinate maxCorner = chamberChannel.getMaxCorner();
if (minCorner == null || maxCorner == null) {
return;
}
int dimension = chamberChannel.getDimension();
World world = DimensionManager.getWorld(dimension);
int dx = xCoord + 1 - minCorner.getX();
int dy = yCoord + 1 - minCorner.getY();
int dz = zCoord + 1 - minCorner.getZ();
minBox = new Coordinate(minCorner.getX() + dx, minCorner.getY() + dy, minCorner.getZ() + dz);
maxBox = new Coordinate(maxCorner.getX() + dx, maxCorner.getY() + dy, maxCorner.getZ() + dz);
for (int x = minCorner.getX() ; x <= maxCorner.getX() ; x++) {
for (int y = minCorner.getY() ; y <= maxCorner.getY() ; y++) {
for (int z = minCorner.getZ() ; z <= maxCorner.getZ() ; z++) {
Block block = world.getBlock(x, y, z);
if (block != null && !block.isAir(world, x, y, z)) {
worldObj.setBlock(dx + x, dy + y, dz + z, SpaceProjectorSetup.proxyBlock, world.getBlockMetadata(x, y, z), 3);
ProxyBlockTileEntity proxyBlockTileEntity = (ProxyBlockTileEntity) worldObj.getTileEntity(dx + x, dy + y, dz + z);
proxyBlockTileEntity.setCamoBlock(Block.blockRegistry.getIDForObject(block));
proxyBlockTileEntity.setOrigCoordinate(new Coordinate(x, y, z), dimension);
}
}
}
}
markDirty();
}
@Override
protected void checkStateServer() {
if (minBox != null) {
NBTTagCompound tc = hasCard();
if (tc == null) {
unproject();
}
}
}
@Override
public int[] getAccessibleSlotsFromSide(int side) {
return SpaceProjectorContainer.factory.getAccessibleSlots();
}
@Override
public boolean canInsertItem(int index, ItemStack item, int side) {
return SpaceProjectorContainer.factory.isInputSlot(index);
}
@Override
public boolean canExtractItem(int index, ItemStack item, int side) {
return SpaceProjectorContainer.factory.isOutputSlot(index);
}
@Override
public int getSizeInventory() {
return inventoryHelper.getCount();
}
@Override
public ItemStack getStackInSlot(int index) {
return inventoryHelper.getStackInSlot(index);
}
@Override
public ItemStack decrStackSize(int index, int amount) {
return inventoryHelper.decrStackSize(index, amount);
}
@Override
public ItemStack getStackInSlotOnClosing(int index) {
return null;
}
@Override
public void setInventorySlotContents(int index, ItemStack stack) {
inventoryHelper.setInventorySlotContents(getInventoryStackLimit(), index, stack);
}
@Override
public String getInventoryName() {
return "Space Projector";
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public int getInventoryStackLimit() {
return 1;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return canPlayerAccess(player);
}
@Override
public void openInventory() {
}
@Override
public void closeInventory() {
}
@Override
public boolean isItemValidForSlot(int index, ItemStack stack) {
return true;
}
@Override
public void readFromNBT(NBTTagCompound tagCompound) {
super.readFromNBT(tagCompound);
powered = tagCompound.getByte("powered");
minBox = Coordinate.readFromNBT(tagCompound, "minBox");
maxBox = Coordinate.readFromNBT(tagCompound, "maxBox");
}
@Override
public void readRestorableFromNBT(NBTTagCompound tagCompound) {
super.readRestorableFromNBT(tagCompound);
readBufferFromNBT(tagCompound);
int m = tagCompound.getByte("rsMode");
redstoneMode = RedstoneMode.values()[m];
}
private void readBufferFromNBT(NBTTagCompound tagCompound) {
NBTTagList bufferTagList = tagCompound.getTagList("Items", Constants.NBT.TAG_COMPOUND);
for (int i = 0 ; i < bufferTagList.tagCount() ; i++) {
NBTTagCompound nbtTagCompound = bufferTagList.getCompoundTagAt(i);
inventoryHelper.setStackInSlot(i, ItemStack.loadItemStackFromNBT(nbtTagCompound));
}
}
@Override
public void writeToNBT(NBTTagCompound tagCompound) {
super.writeToNBT(tagCompound);
tagCompound.setByte("powered", (byte) powered);
Coordinate.writeToNBT(tagCompound, "minBox", minBox);
Coordinate.writeToNBT(tagCompound, "maxBox", maxBox);
}
@Override
public void writeRestorableToNBT(NBTTagCompound tagCompound) {
super.writeRestorableToNBT(tagCompound);
writeBufferToNBT(tagCompound);
tagCompound.setByte("rsMode", (byte) redstoneMode.ordinal());
}
private void writeBufferToNBT(NBTTagCompound tagCompound) {
NBTTagList bufferTagList = new NBTTagList();
for (int i = 0 ; i < inventoryHelper.getCount() ; i++) {
ItemStack stack = inventoryHelper.getStackInSlot(i);
NBTTagCompound nbtTagCompound = new NBTTagCompound();
if (stack != null) {
stack.writeToNBT(nbtTagCompound);
}
bufferTagList.appendTag(nbtTagCompound);
}
tagCompound.setTag("Items", bufferTagList);
}
@Override
public boolean execute(EntityPlayerMP playerMP, String command, Map<String, Argument> args) {
boolean rc = super.execute(playerMP, command, args);
if (rc) {
return true;
}
if (CMD_RSMODE.equals(command)) {
String m = args.get("rs").getString();
setRedstoneMode(RedstoneMode.getMode(m));
return true;
} else if (CMD_PROJECT.equals(command)) {
project();
return true;
}
return false;
}
}