package com.austinv11.peripheralsplusplus.tiles;
import com.austinv11.peripheralsplusplus.PeripheralsPlusPlus;
import com.austinv11.peripheralsplusplus.reference.Config;
import com.austinv11.peripheralsplusplus.utils.ReflectionHelper;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
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 dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Facing;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import java.util.HashMap;
import java.util.Stack;
public class TileEntityTeleporter extends MountedTileEntity {
public static String publicName = "teleporter";
private String name = "tileEntityTeleporter";
public Stack<LinkData> links = new Stack<LinkData>();
public String tag = null;
public TileEntityTeleporter() {
super();
}
public String getName() {
return name;
}
public int getMaxLinks() {
return 1;
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound) {
super.readFromNBT(nbttagcompound);
if (nbttagcompound.hasKey("tTag"))
tag = nbttagcompound.getString("tTag");
NBTTagList links = nbttagcompound.getTagList("links", Constants.NBT.TAG_COMPOUND);
for (int i = 0; i < links.tagCount(); i++) {
NBTTagCompound link = links.getCompoundTagAt(i);
if (link.hasKey("linkX") && link.hasKey("linkY") && link.hasKey("linkZ") && link.hasKey("linkDim")) {
this.links.add(new LinkData(link.getInteger("linkDim"), new ChunkCoordinates(link.getInteger("linkX"), link.getInteger("linkY"), link.getInteger("linkZ"))));
}
}
}
@Override
public void writeToNBT(NBTTagCompound nbttagcompound) {
super.writeToNBT(nbttagcompound);
if (tag != null)
nbttagcompound.setString("tTag", tag);
NBTTagList list = new NBTTagList();
for (int i = 0; i < links.size(); i++) {
LinkData link = links.get(i);
if (link != null) {
NBTTagCompound lcompound = new NBTTagCompound();
lcompound.setInteger("linkX", link.link.posX);
lcompound.setInteger("linkY", link.link.posY);
lcompound.setInteger("linkZ", link.link.posZ);
lcompound.setInteger("linkDim", link.linkDim);
list.appendTag(lcompound);
}
}
nbttagcompound.setTag("links", list);
}
@Override
public String getType() {
return publicName;
}
@Override
public String[] getMethodNames() {
return new String[] {"teleport", "tp", "getLinks", "setName"};
}
@Override
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException {
if (!Config.enableTurtleTeleporter)
throw new LuaException("Turtle teleporters have been disabled");
if (method == 0 || method == 1) {
if (arguments.length > 0 && !(arguments[0] instanceof Double))
throw new LuaException("Bad argument #1 (expected number)");
int index = arguments.length > 0 ? (int)Math.floor((Double)arguments[0]) - 1 : 0;
if (index < 0 || index >= getMaxLinks())
throw new LuaException("Bad link "+(index+1)+" (expected 1-"+getMaxLinks()+")");
if (index >= links.size())
throw new LuaException("No such link");
LinkData link = links.get(index);
if (link == null)
throw new LuaException("No such link");
TileEntity te = worldObj.getTileEntity(xCoord + Facing.offsetsXForSide[getBlockMetadata()], yCoord + Facing.offsetsYForSide[getBlockMetadata()], zCoord + Facing.offsetsZForSide[getBlockMetadata()]);
try {
if (ReflectionHelper.getTurtle(te) == null)
throw new LuaException("No turtle in front");
}catch (Exception e) {
throw new LuaException("No turtle in front");
}
World destWorld = MinecraftServer.getServer().worldServerForDimension(link.linkDim);
if (destWorld == null)
throw new LuaException("Destination world missing");
TileEntity dest = destWorld.getTileEntity(link.link.posX, link.link.posY, link.link.posZ);
if (!(dest instanceof TileEntityTeleporter))
throw new LuaException("Destination is not a teleporter");
TileEntityTeleporter teleporter = (TileEntityTeleporter)dest;
int linkToX = link.link.posX + Facing.offsetsXForSide[teleporter.getBlockMetadata()];
int linkToY = link.link.posY + Facing.offsetsYForSide[teleporter.getBlockMetadata()];
int linkToZ = link.link.posZ + Facing.offsetsZForSide[teleporter.getBlockMetadata()];
if ((destWorld.blockExists(linkToX,linkToY,linkToZ) && !destWorld.isAirBlock(linkToX,linkToY,linkToZ)) || linkToY < 0 || linkToY > 254) //TODO: improve Block.blocksList[id] == null || Block.blocksList[id].isAirBlock(world, x, y, z) || Block.blocksList[id] instanceof BlockFluid || Block.blocksList[id] instanceof BlockSnow || Block.blocksList[id] instanceof BlockTallGrass;
throw new LuaException("Destination obstructed");
int xdif = Math.abs(xCoord - link.link.posX);
int ydif = Math.abs(yCoord - link.link.posY);
int zdif = Math.abs(zCoord - link.link.posZ);
ITurtleAccess turtle = null;
try {
turtle = ReflectionHelper.getTurtle(te);
}catch (Exception ignored) {}
if (!turtle.consumeFuel(Math.abs((int)Math.ceil((xdif + ydif + zdif) * (Math.abs(worldObj.provider.dimensionId - destWorld.provider.dimensionId) + 1) * Config.teleporterPenalty))))
throw new LuaException("Not enough fuel");
boolean result = turtle.teleportTo(destWorld, linkToX, linkToY, linkToZ);
destWorld.markBlockForUpdate(linkToX,linkToY,linkToZ);
worldObj.markBlockForUpdate(xCoord + Facing.offsetsXForSide[getBlockMetadata()], yCoord + Facing.offsetsYForSide[getBlockMetadata()], zCoord + Facing.offsetsZForSide[getBlockMetadata()]);
destWorld.notifyBlockChange(linkToX,linkToY,linkToZ, te.blockType);
worldObj.notifyBlockChange(xCoord + Facing.offsetsXForSide[getBlockMetadata()], yCoord + Facing.offsetsYForSide[getBlockMetadata()], zCoord + Facing.offsetsZForSide[getBlockMetadata()], null);
if (result) {
//int flag = worldObj.provider.dimensionId != destWorld.provider.dimensionId ? 1 : 0;
//onTeleport((byte)flag);TODO
//teleporter.onTeleport((byte)flag);
}
return new Object[]{result};
}else if (method == 2) {
HashMap<Integer, Object> map1 = new HashMap<Integer,Object>();
for (int i = 0; i < links.size(); i++) {
HashMap<String,Object> map2 = new HashMap<String,Object>();
map2.put("dim", links.get(i).linkDim);
map2.put("x", links.get(i).link.posX);
map2.put("y", links.get(i).link.posY);
map2.put("z", links.get(i).link.posZ);
map2.put("name", name);
map1.put(i, map2.clone());
}
return new Object[]{map1};
}else if (method == 3) {
if (!(arguments.length >= 1) || !(arguments[0] instanceof String))
throw new LuaException("Bad argument #1 (expected string)");
this.name = (String) arguments[0];
return new Object[]{name};
}
return new Object[0];
}
public void onTeleport(byte flag) {//FIXME
if (!FMLCommonHandler.instance().getEffectiveSide().isServer()) {
int facing = getBlockMetadata();
for (int j = 0; j < 32; j++) {
worldObj.spawnParticle("portal", xCoord + 0.5D + 1.0D * Facing.offsetsXForSide[facing], yCoord + 1.0D * Facing.offsetsYForSide[facing] + worldObj.rand.nextDouble() * 2.0D, zCoord + 0.5D + 1.0D * Facing.offsetsZForSide[getBlockMetadata()], worldObj.rand.nextGaussian(), 0.0D, worldObj.rand.nextGaussian());
}
} else {
String sound = "mob.endermen.portal";
if (Loader.isModLoaded("Mystcraft")) sound = flag == 1 ? "myst.sound.link-portal" : "myst.sound.link-intra";
worldObj.playSoundEffect(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D, sound, 1.0F, 1.0F);
}
}
@Override
public boolean equals(IPeripheral other) {//FIXME idk what I'm doing
return (other == this);
}
public void blockActivated(EntityPlayer player) {
ItemStack held = player.getCurrentEquippedItem();
if (held != null && held.isItemEqual(new ItemStack(Items.repeater))) {
if (held.stackTagCompound != null) {
if (held.stackTagCompound.hasKey("p++LinkX") && held.stackTagCompound.hasKey("p++LinkY") && held.stackTagCompound.hasKey("p++LinkZ") && held.stackTagCompound.hasKey("p++LinkDim")) {
ChunkCoordinates link = new ChunkCoordinates(held.stackTagCompound.getInteger("p++LinkX"), held.stackTagCompound.getInteger("p++LinkY"), held.stackTagCompound.getInteger("p++LinkZ"));
int linkDim = held.stackTagCompound.getInteger("p++LinkDim");
World srcWorld = MinecraftServer.getServer().worldServerForDimension(linkDim);
if (srcWorld == null) {
player.addChatComponentMessage(new ChatComponentText("Link failed: World is missing"));
} else {
TileEntity te = srcWorld.getTileEntity(link.posX, link.posY, link.posZ);
if (!(te instanceof TileEntityTeleporter)) {
player.addChatComponentMessage(new ChatComponentText("Link failed: Teleporter no longer exists"));
} else {
TileEntityTeleporter src = (TileEntityTeleporter)te;
if (link.posX == xCoord && link.posY == yCoord && link.posZ == zCoord) {
player.addChatComponentMessage(new ChatComponentText("Link canceled"));
} else {
boolean unlinked = false;
for (int i = 0; i < src.links.size(); i++) {
LinkData rlink = src.links.get(i);
if (rlink.link.posX == xCoord && rlink.link.posY == yCoord && rlink.link.posZ == zCoord && rlink.linkDim == worldObj.provider.dimensionId) {
player.addChatComponentMessage(new ChatComponentText("Unlinked teleporter at " + rlink.linkDim + ":(" + rlink.link.posX + "," + rlink.link.posY + "," + rlink.link.posZ + ") (link " + (i + 1) + ") from this teleporter"));
src.links.remove(i);
unlinked = true;
break;
}
}
if (!unlinked) {
src.addLink(worldObj.provider.dimensionId, new ChunkCoordinates(xCoord, yCoord, zCoord));
player.addChatComponentMessage(new ChatComponentText("Linked teleporter at " + linkDim + ":(" + link.posX + "," + link.posY + "," + link.posZ + ") (link " + src.links.size() + ") to this teleporter"));
}
}
}
}
held.stackTagCompound.removeTag("p++LinkX");
held.stackTagCompound.removeTag("p++LinkY");
held.stackTagCompound.removeTag("p++LinkZ");
held.stackTagCompound.removeTag("p++LinkDim");
if (held.stackTagCompound.hasKey("display")) {
NBTTagCompound display = held.stackTagCompound.getCompoundTag("display");
display.removeTag("Lore");
if (display.hasNoTags()) {
held.stackTagCompound.removeTag("display");
} else {
held.stackTagCompound.setTag("display", display);
}
}
return;
}
}
if (held.stackTagCompound == null)
held.stackTagCompound = new NBTTagCompound();
held.stackTagCompound.setInteger("p++LinkX", xCoord);
held.stackTagCompound.setInteger("p++LinkY", yCoord);
held.stackTagCompound.setInteger("p++LinkZ", zCoord);
held.stackTagCompound.setInteger("p++LinkDim", worldObj.provider.dimensionId);
NBTTagCompound display = new NBTTagCompound();
NBTTagList lore = new NBTTagList();
lore.appendTag(new NBTTagString("Turtle Teleporter Link"));
lore.appendTag(new NBTTagString(worldObj.provider.dimensionId+":("+xCoord+","+yCoord+","+zCoord+")"));
display.setTag("Lore", lore);
held.stackTagCompound.setTag("display", display);
player.addChatComponentMessage(new ChatComponentText("Link started"));
}
}
public int addLink(int linkDim, ChunkCoordinates link) {
links.add(new LinkData(linkDim, link));
while (links.size() > getMaxLinks())
links.pop();
return links.size();
}
public static class LinkData {
public int linkDim;
public ChunkCoordinates link;
public LinkData(int linkDim, ChunkCoordinates link) {
this.linkDim = linkDim;
this.link = link;
}
}
}