/**
* Copyright (c) Krapht, 2011
*
* "LogisticsPipes" is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package logisticspipes.pipes.basic;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.PriorityBlockingQueue;
import logisticspipes.Configs;
import logisticspipes.LPConstants;
import logisticspipes.LogisticsPipes;
import logisticspipes.api.ILogisticsPowerProvider;
import logisticspipes.asm.ModDependentMethod;
import logisticspipes.blocks.LogisticsSecurityTileEntity;
import logisticspipes.interfaces.IClientState;
import logisticspipes.interfaces.IInventoryUtil;
import logisticspipes.interfaces.IPipeServiceProvider;
import logisticspipes.interfaces.IQueueCCEvent;
import logisticspipes.interfaces.ISecurityProvider;
import logisticspipes.interfaces.ISubSystemPowerProvider;
import logisticspipes.interfaces.IWatchingHandler;
import logisticspipes.interfaces.IWorldProvider;
import logisticspipes.interfaces.routing.IAdditionalTargetInformation;
import logisticspipes.interfaces.routing.IFilter;
import logisticspipes.interfaces.routing.IRequestItems;
import logisticspipes.interfaces.routing.IRequireReliableFluidTransport;
import logisticspipes.interfaces.routing.IRequireReliableTransport;
import logisticspipes.items.ItemPipeSignCreator;
import logisticspipes.logisticspipes.ExtractionMode;
import logisticspipes.logisticspipes.IAdjacentWorldAccess;
import logisticspipes.logisticspipes.IRoutedItem;
import logisticspipes.logisticspipes.IRoutedItem.TransportMode;
import logisticspipes.logisticspipes.ITrackStatistics;
import logisticspipes.logisticspipes.PipeTransportLayer;
import logisticspipes.logisticspipes.RouteLayer;
import logisticspipes.logisticspipes.TransportLayer;
import logisticspipes.modules.abstractmodules.LogisticsGuiModule;
import logisticspipes.modules.abstractmodules.LogisticsModule;
import logisticspipes.network.GuiIDs;
import logisticspipes.network.LPDataInputStream;
import logisticspipes.network.LPDataOutputStream;
import logisticspipes.network.NewGuiHandler;
import logisticspipes.network.PacketHandler;
import logisticspipes.network.abstractpackets.ModernPacket;
import logisticspipes.network.guis.pipe.PipeController;
import logisticspipes.network.packets.pipe.ParticleFX;
import logisticspipes.network.packets.pipe.PipeSignTypes;
import logisticspipes.network.packets.pipe.RequestRoutingLasersPacket;
import logisticspipes.network.packets.pipe.RequestSignPacket;
import logisticspipes.network.packets.pipe.StatUpdate;
import logisticspipes.pipefxhandlers.Particles;
import logisticspipes.pipefxhandlers.PipeFXRenderHandler;
import logisticspipes.pipes.basic.debug.DebugLogController;
import logisticspipes.pipes.basic.debug.StatusEntry;
import logisticspipes.pipes.signs.IPipeSign;
import logisticspipes.pipes.upgrades.UpgradeManager;
import logisticspipes.proxy.MainProxy;
import logisticspipes.proxy.SimpleServiceLocator;
import logisticspipes.proxy.cc.CCConstants;
import logisticspipes.proxy.computers.interfaces.CCCommand;
import logisticspipes.proxy.computers.interfaces.CCDirectCall;
import logisticspipes.proxy.computers.interfaces.CCSecurtiyCheck;
import logisticspipes.proxy.computers.interfaces.CCType;
import logisticspipes.renderer.IIconProvider;
import logisticspipes.renderer.LogisticsHUDRenderer;
import logisticspipes.routing.ExitRoute;
import logisticspipes.routing.IRouter;
import logisticspipes.routing.IRouterQueuedTask;
import logisticspipes.routing.ItemRoutingInformation;
import logisticspipes.routing.ServerRouter;
import logisticspipes.routing.order.LogisticsOrderManager;
import logisticspipes.security.PermissionException;
import logisticspipes.security.SecuritySettings;
import logisticspipes.textures.Textures;
import logisticspipes.textures.Textures.TextureType;
import logisticspipes.transport.LPTravelingItem.LPTravelingItemServer;
import logisticspipes.transport.PipeTransportLogistics;
import logisticspipes.utils.AdjacentTile;
import logisticspipes.utils.FluidIdentifier;
import logisticspipes.utils.InventoryHelper;
import logisticspipes.utils.OrientationsUtil;
import logisticspipes.utils.PlayerCollectionList;
import logisticspipes.utils.SidedInventoryMinecraftAdapter;
import logisticspipes.utils.SinkReply;
import logisticspipes.utils.WorldUtil;
import logisticspipes.utils.item.ItemIdentifier;
import logisticspipes.utils.item.ItemIdentifierStack;
import logisticspipes.utils.tuples.LPPosition;
import logisticspipes.utils.tuples.Pair;
import logisticspipes.utils.tuples.Triplet;
import net.minecraft.client.Minecraft;
import net.minecraft.crash.CrashReportCategory;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
@CCType(name = "LogisticsPipes:Normal")
public abstract class CoreRoutedPipe extends CoreUnroutedPipe implements IClientState, IRequestItems, IAdjacentWorldAccess, ITrackStatistics, IWorldProvider, IWatchingHandler, IPipeServiceProvider, IQueueCCEvent {
public enum ItemSendMode {
Normal,
Fast
}
protected boolean stillNeedReplace = true;
public DebugLogController debug = new DebugLogController(this);
protected IRouter router;
protected String routerId;
protected Object routerIdLock = new Object();
private static int pipecount = 0;
protected int _delayOffset = 0;
private boolean _textureBufferPowered;
protected boolean _initialInit = true;
private boolean enabled = true;
private boolean preventRemove = false;
private boolean destroyByPlayer = false;
private PowerSupplierHandler powerHandler = new PowerSupplierHandler(this);
public long delayTo = 0;
public int repeatFor = 0;
protected RouteLayer _routeLayer;
protected TransportLayer _transportLayer;
protected final PriorityBlockingQueue<ItemRoutingInformation> _inTransitToMe = new PriorityBlockingQueue<ItemRoutingInformation>(10, new ItemRoutingInformation.DelayComparator());
private UpgradeManager upgradeManager = new UpgradeManager(this);
protected LogisticsOrderManager _orderManager = null;
public int stat_session_sent;
public int stat_session_recieved;
public int stat_session_relayed;
public long stat_lifetime_sent;
public long stat_lifetime_recieved;
public long stat_lifetime_relayed;
public int server_routing_table_size = 0;
protected final LinkedList<Triplet<IRoutedItem, ForgeDirection, ItemSendMode>> _sendQueue = new LinkedList<Triplet<IRoutedItem, ForgeDirection, ItemSendMode>>();
protected final Map<ItemIdentifierStack, ItemRoutingInformation> queuedDataForUnroutedItems = new HashMap<ItemIdentifierStack, ItemRoutingInformation>();
public final PlayerCollectionList watchers = new PlayerCollectionList();
protected List<IInventory> _cachedAdjacentInventories;
protected ForgeDirection pointedDirection = ForgeDirection.UNKNOWN;
//public BaseRoutingLogic logic;
// from BaseRoutingLogic
protected int throttleTime = 20;
private int throttleTimeLeft = 20 + new Random().nextInt(Configs.LOGISTICS_DETECTION_FREQUENCY);
private int[] queuedParticles = new int[Particles.values().length];
private boolean hasQueuedParticles = false;
protected IPipeSign[] signItem = new IPipeSign[6];
private boolean isOpaqueClientSide = false;
public CoreRoutedPipe(Item item) {
this(new PipeTransportLogistics(), item);
}
public CoreRoutedPipe(PipeTransportLogistics transport, Item item) {
super(transport, item);
pipecount++;
//Roughly spread pipe updates throughout the frequency, no need to maintain balance
_delayOffset = pipecount % Configs.LOGISTICS_DETECTION_FREQUENCY;
}
public RouteLayer getRouteLayer(){
if (_routeLayer == null){
_routeLayer = new RouteLayer(getRouter(), getTransportLayer(), this);
}
return _routeLayer;
}
public TransportLayer getTransportLayer()
{
if (_transportLayer == null) {
_transportLayer = new PipeTransportLayer(this, this, getRouter());
}
return _transportLayer;
}
public UpgradeManager getUpgradeManager() {
return upgradeManager;
}
public void queueRoutedItem(IRoutedItem routedItem, ForgeDirection from) {
if(from == null) {
throw new NullPointerException();
}
_sendQueue.addLast(new Triplet<IRoutedItem, ForgeDirection, ItemSendMode>(routedItem, from, ItemSendMode.Normal));
sendQueueChanged(false);
}
public void queueRoutedItem(IRoutedItem routedItem, ForgeDirection from, ItemSendMode mode) {
if(from == null) {
throw new NullPointerException();
}
_sendQueue.addLast(new Triplet<IRoutedItem, ForgeDirection, ItemSendMode>(routedItem, from, mode));
sendQueueChanged(false);
}
/**
* @param force == true never delegates to a thread
* @return number of things sent.
*/
public int sendQueueChanged(boolean force) {return 0;}
private void sendRoutedItem(IRoutedItem routedItem, ForgeDirection from) {
if(from == null) {
throw new NullPointerException();
}
((PipeTransportLogistics)transport).injectItem(routedItem, from.getOpposite());
IRouter r = SimpleServiceLocator.routerManager.getRouterUnsafe(routedItem.getDestination(), false);
if(r != null) {
CoreRoutedPipe pipe = r.getCachedPipe();
if(pipe != null) // pipes can unload at inconvenient times ...
pipe.notifyOfSend(routedItem.getInfo());
else {
// TODO: handle sending items to known chunk-unloaded destination?
}
} // should not be able to send to a non-existing router
// router.startTrackingRoutedItem((RoutedEntityItem) routedItem.getTravelingItem());
spawnParticle(Particles.OrangeParticle, 2);
stat_lifetime_sent++;
stat_session_sent++;
updateStats();
}
private void notifyOfSend(ItemRoutingInformation routedItem) {
this._inTransitToMe.add(routedItem);
//LogisticsPipes.log.info("Sending: "+routedItem.getIDStack().getItem().getFriendlyName());
}
public void notifyOfReroute(ItemRoutingInformation routedItem) {
this._inTransitToMe.remove(routedItem);
}
//When Recreating the Item from the TE version we have the same hashCode but a different instance so we need to refresh this
public void refreshItem(ItemRoutingInformation routedItem) {
if(this._inTransitToMe.contains(routedItem)) {
this._inTransitToMe.remove(routedItem);
this._inTransitToMe.add(routedItem);
}
}
public abstract ItemSendMode getItemSendMode();
/**
* Designed to help protect against routing loops - if both pipes are on the same block, and of ISided overlapps, return true
* @param other
* @return boolean indicating if both pull from the same inventory.
*/
public boolean sharesInventoryWith(CoreRoutedPipe other){
List<IInventory> others = other.getConnectedRawInventories();
if(others==null || others.size()==0)
return false;
for(IInventory i : getConnectedRawInventories()) {
if(others.contains(i)) {
return true;
}
}
return false;
}
protected List<IInventory> getConnectedRawInventories() {
if(_cachedAdjacentInventories != null) {
return _cachedAdjacentInventories;
}
WorldUtil worldUtil = new WorldUtil(this.getWorld(), this.getX(), this.getY(), this.getZ());
LinkedList<IInventory> adjacent = new LinkedList<IInventory>();
for (AdjacentTile tile : worldUtil.getAdjacentTileEntities(true)){
if (!(tile.tile instanceof IInventory)) continue;
adjacent.add(InventoryHelper.getInventory((IInventory)tile.tile));
}
_cachedAdjacentInventories=adjacent;
return _cachedAdjacentInventories;
}
/***
* first tick just create a router and do nothing.
*/
public void firstInitialiseTick() {
getRouter();
if(MainProxy.isClient(getWorld())) {
MainProxy.sendPacketToServer(PacketHandler.getPacket(RequestSignPacket.class).setTilePos(container));
}
}
/***
* Only Called Server Side
* Only Called when the pipe is enabled
*/
public void enabledUpdateEntity() {
powerHandler.update();
for(int i=0;i<6;i++) {
if(signItem[i] != null) {
signItem[i].updateServerSide();
}
}
}
/***
* Called Server and Client Side
* Called every tick
*/
public void ignoreDisableUpdateEntity() {}
@Override
public final void updateEntity() {
debug.tick();
spawnParticleTick();
if(stillNeedReplace) {
stillNeedReplace = false;
getWorld().notifyBlockChange(getX(), getY(), getZ(), getWorld().getBlock(getX(), getY(), getZ()));
/* TravelingItems are just held by a pipe, they don't need to know their world
* for(Triplet<IRoutedItem, ForgeDirection, ItemSendMode> item : _sendQueue) {
//assign world to any entityitem we created in readfromnbt
item.getValue1().getTravelingItem().setWorld(getWorld());
}*/
//first tick just create a router and do nothing.
firstInitialiseTick();
return;
}
if(repeatFor > 0) {
if(delayTo < System.currentTimeMillis()) {
delayTo = System.currentTimeMillis() + 200;
repeatFor--;
getWorld().markBlockForUpdate(this.getX(), this.getY(), this.getZ());
}
}
// remove old items _inTransit -- these should have arrived, but have probably been lost instead. In either case, it will allow a re-send so that another attempt to re-fill the inventory can be made.
while(this._inTransitToMe.peek()!=null && this._inTransitToMe.peek().getTickToTimeOut() <= 0){
final ItemRoutingInformation p=_inTransitToMe.poll();
if (LPConstants.DEBUG) {
LogisticsPipes.log.info("Timed Out: "+p.getItem().getFriendlyName() + " (" + p.hashCode() + ")");
}
debug.log("Timed Out: "+p.getItem().getFriendlyName() + " (" + p.hashCode() + ")");
}
//update router before ticking logic/transport
getRouter().update(getWorld().getTotalWorldTime() % Configs.LOGISTICS_DETECTION_FREQUENCY == _delayOffset || _initialInit, this);
getUpgradeManager().securityTick();
super.updateEntity();
// from BaseRoutingLogic
if (--throttleTimeLeft <= 0) {
throttledUpdateEntity();
throttleTimeLeft = throttleTime;
}
ignoreDisableUpdateEntity();
_initialInit = false;
if (!_sendQueue.isEmpty()){
if(getItemSendMode() == ItemSendMode.Normal) {
Triplet<IRoutedItem, ForgeDirection, ItemSendMode> itemToSend = _sendQueue.getFirst();
sendRoutedItem(itemToSend.getValue1(), itemToSend.getValue2());
_sendQueue.removeFirst();
for(int i=0;i < 16 && !_sendQueue.isEmpty() && _sendQueue.getFirst().getValue3() == ItemSendMode.Fast;i++) {
if (!_sendQueue.isEmpty()){
itemToSend = _sendQueue.getFirst();
sendRoutedItem(itemToSend.getValue1(), itemToSend.getValue2());
_sendQueue.removeFirst();
}
}
sendQueueChanged(false);
} else if(getItemSendMode() == ItemSendMode.Fast) {
for(int i=0;i < 16;i++) {
if (!_sendQueue.isEmpty()){
Triplet<IRoutedItem, ForgeDirection, ItemSendMode> itemToSend = _sendQueue.getFirst();
sendRoutedItem(itemToSend.getValue1(), itemToSend.getValue2());
_sendQueue.removeFirst();
}
}
sendQueueChanged(false);
} else if(getItemSendMode() == null) {
throw new UnsupportedOperationException("getItemSendMode() can't return null. "+this.getClass().getName());
} else {
throw new UnsupportedOperationException("getItemSendMode() returned unhandled value. " + getItemSendMode().name() + " in "+this.getClass().getName());
}
}
if(MainProxy.isClient(getWorld())) return;
checkTexturePowered();
if (!isEnabled()) return;
enabledUpdateEntity();
if (getLogisticsModule() == null) return;
getLogisticsModule().tick();
}
protected void onAllowedRemoval() {}
// From BaseRoutingLogic
public void throttledUpdateEntity(){}
protected void delayThrottle() {
//delay 6(+1) ticks to prevent suppliers from ticking between a item arriving at them and the item hitting their adj. inv
if(throttleTimeLeft < 7)
throttleTimeLeft = 7;
}
public boolean isNthTick(int n) {
return ((getWorld().getTotalWorldTime() + _delayOffset) % n == 0);
}
private void doDebugStuff(EntityPlayer entityplayer) {
//entityplayer.worldObj.setWorldTime(4951);
IRouter r = getRouter();
if(!(r instanceof ServerRouter)) return;
System.out.println("***");
System.out.println("---------Interests---------------");
for(Entry<ItemIdentifier, Set<IRouter>> i: ServerRouter.getInterestedInSpecifics().entrySet()){
System.out.print(i.getKey().getFriendlyName()+":");
for(IRouter j:i.getValue())
System.out.print(j.getSimpleID()+",");
System.out.println();
}
System.out.print("ALL ITEMS:");
for(IRouter j:ServerRouter.getInterestedInGeneral())
System.out.print(j.getSimpleID()+",");
System.out.println();
ServerRouter sr = (ServerRouter) r;
System.out.println(r.toString());
System.out.println("---------CONNECTED TO---------------");
for (CoreRoutedPipe adj : sr._adjacent.keySet()) {
System.out.println(adj.getRouter().getSimpleID());
}
System.out.println();
System.out.println("========DISTANCE TABLE==============");
for(ExitRoute n : r.getIRoutersByCost()) {
System.out.println(n.destination.getSimpleID()+ " @ " + n.distanceToDestination + " -> "+ n.connectionDetails +"("+n.destination.getId() +")");
}
System.out.println();
System.out.println("*******EXIT ROUTE TABLE*************");
List<List<ExitRoute>> table = r.getRouteTable();
for (int i=0; i < table.size(); i++){
if(table.get(i) != null) {
if(table.get(i).size() > 0) {
System.out.println(i + " -> " + table.get(i).get(0).destination.getSimpleID());
for(ExitRoute route:table.get(i)) {
System.out.println("\t\t via " + route.exitOrientation + "(" + route.distanceToDestination + " distance)");
}
}
}
}
System.out.println();
System.out.println("++++++++++CONNECTIONS+++++++++++++++");
System.out.println(Arrays.toString(ForgeDirection.VALID_DIRECTIONS));
System.out.println(Arrays.toString(sr.sideDisconnected));
System.out.println(Arrays.toString(container.pipeConnectionsBuffer));
System.out.println();
System.out.println("~~~~~~~~~~~~~~~POWER~~~~~~~~~~~~~~~~");
System.out.println(r.getPowerProvider());
System.out.println();
System.out.println("~~~~~~~~~~~SUBSYSTEMPOWER~~~~~~~~~~~");
System.out.println(r.getSubSystemPowerProvider());
System.out.println();
System.out.println("################END#################");
refreshConnectionAndRender(true);
System.out.print("");
sr.CreateRouteTable(Integer.MAX_VALUE);
}
// end FromBaseRoutingLogic
@Override
public final void onBlockRemoval() {
try {
onAllowedRemoval();
super.onBlockRemoval();
//invalidate() removes the router
// if (logic instanceof BaseRoutingLogic){
// ((BaseRoutingLogic)logic).destroy();
// }
//Just in case
pipecount = Math.max(pipecount - 1, 0);
if (transport != null && transport instanceof PipeTransportLogistics){
transport.dropBuffer();
}
getUpgradeManager().dropUpgrades();
} catch(Exception e) {
e.printStackTrace();
}
}
@Override
public void invalidate() {
super.invalidate();
if(router != null) {
router.destroy();
router = null;
}
}
@Override
public void onChunkUnload() {
super.onChunkUnload();
if(router != null) {
router.clearPipeCache();
router.clearInterests();
}
}
public void checkTexturePowered() {
if(Configs.LOGISTICS_POWER_USAGE_DISABLED) return;
if(!isNthTick(10)) return;
if(stillNeedReplace || _initialInit || router == null) return;
boolean flag;
if((flag = canUseEnergy(1)) != _textureBufferPowered) {
_textureBufferPowered = flag;
refreshRender(false);
spawnParticle(Particles.RedParticle, 3);
}
}
public abstract TextureType getCenterTexture();
public TextureType getTextureType(ForgeDirection connection) {
if(stillNeedReplace || _initialInit)
return getCenterTexture();
if (connection == ForgeDirection.UNKNOWN){
return getCenterTexture();
} else if ((router != null) && getRouter().isRoutedExit(connection)) {
return getRoutedTexture(connection);
} else {
TextureType texture = getNonRoutedTexture(connection);
if(this.getUpgradeManager().hasRFPowerSupplierUpgrade() || this.getUpgradeManager().getIC2PowerLevel() > 0) {
if(texture.fileName.equals(Textures.LOGISTICSPIPE_NOTROUTED_TEXTURE.fileName)) {
texture = Textures.LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE;
} else if(texture.fileName.equals(Textures.LOGISTICSPIPE_LIQUID_TEXTURE.fileName)) {
texture = Textures.LOGISTICSPIPE_LIQUID_POWERED_TEXTURE;
} else if(texture.fileName.equals(Textures.LOGISTICSPIPE_POWERED_TEXTURE.fileName)) {
texture = Textures.LOGISTICSPIPE_POWERED_POWERED_TEXTURE;
} else if(texture.fileName.equals(Textures.LOGISTICSPIPE_CHASSI_NOTROUTED_TEXTURE.fileName)) {
texture = Textures.LOGISTICSPIPE_NOTROUTED_POWERED_TEXTURE;
} else if(texture.fileName.equals(Textures.LOGISTICSPIPE_CHASSI_DIRECTION_TEXTURE.fileName)) {
texture = Textures.LOGISTICSPIPE_DIRECTION_POWERED_TEXTURE;
} else {
System.out.println("Unknown texture to power, :" + texture.fileName);
System.out.println(this.getClass());
System.out.println(connection);
}
}
return texture;
}
}
public TextureType getRoutedTexture(ForgeDirection connection) {
if(getRouter().isSubPoweredExit(connection)) {
return Textures.LOGISTICSPIPE_SUBPOWER_TEXTURE;
} else {
return Textures.LOGISTICSPIPE_ROUTED_TEXTURE;
}
}
public TextureType getNonRoutedTexture(ForgeDirection connection) {
if(isPowerProvider(connection)) {
return Textures.LOGISTICSPIPE_POWERED_TEXTURE;
}
return Textures.LOGISTICSPIPE_NOTROUTED_TEXTURE;
}
public void spawnParticle(Particles particle, int amount) {
if(!Configs.ENABLE_PARTICLE_FX)
return;
queuedParticles[particle.ordinal()] += amount;
hasQueuedParticles = true;
}
private void spawnParticleTick() {
if(!hasQueuedParticles)
return;
if(MainProxy.isServer(getWorld())) {
ArrayList<ParticleCount> tosend = new ArrayList<ParticleCount>(queuedParticles.length);
for(int i = 0; i < queuedParticles.length; i++) {
if(queuedParticles[i] > 0) {
tosend.add(new ParticleCount(Particles.values()[i], queuedParticles[i]));
}
}
MainProxy.sendPacketToAllWatchingChunk(this.getX(), this.getZ(), MainProxy.getDimensionForWorld(this.getWorld()), PacketHandler.getPacket(ParticleFX.class).setParticles(tosend).setPosX(this.getX()).setPosY(this.getY()).setPosZ(this.getZ()));
} else {
if(Minecraft.isFancyGraphicsEnabled()) {
for(int i = 0; i < queuedParticles.length; i++) {
if(queuedParticles[i] > 0) {
PipeFXRenderHandler.spawnGenericParticle(Particles.values()[i], this.getX(), this.getY(), this.getZ(), queuedParticles[i]);
}
}
}
}
for(int i = 0; i < queuedParticles.length; i++) {
queuedParticles[i] = 0;
}
hasQueuedParticles = false;
}
protected boolean isPowerProvider(ForgeDirection ori) {
TileEntity tilePipe = this.container.getTile(ori);
if(tilePipe == null || !this.container.canPipeConnect(tilePipe, ori)) {
return false;
}
if(tilePipe instanceof ILogisticsPowerProvider || tilePipe instanceof ISubSystemPowerProvider) {
return true;
}
return false;
}
@Override
public void writeToNBT(NBTTagCompound nbttagcompound) {
super.writeToNBT(nbttagcompound);
synchronized (routerIdLock) {
if (routerId == null || routerId.isEmpty()){
if(router != null)
routerId = router.getId().toString();
else
routerId = UUID.randomUUID().toString();
}
}
nbttagcompound.setString("routerId", routerId);
nbttagcompound.setLong("stat_lifetime_sent", stat_lifetime_sent);
nbttagcompound.setLong("stat_lifetime_recieved", stat_lifetime_recieved);
nbttagcompound.setLong("stat_lifetime_relayed", stat_lifetime_relayed);
if (getLogisticsModule() != null){
getLogisticsModule().writeToNBT(nbttagcompound);
}
NBTTagCompound upgradeNBT = new NBTTagCompound();
upgradeManager.writeToNBT(upgradeNBT);
nbttagcompound.setTag("upgradeManager", upgradeNBT);
NBTTagCompound powerNBT = new NBTTagCompound();
powerHandler.writeToNBT(powerNBT);
if(!powerNBT.hasNoTags())
nbttagcompound.setTag("powerHandler", powerNBT);
NBTTagList sendqueue = new NBTTagList();
for(Triplet<IRoutedItem, ForgeDirection, ItemSendMode> p : _sendQueue) {
NBTTagCompound tagentry = new NBTTagCompound();
NBTTagCompound tagentityitem = new NBTTagCompound();
p.getValue1().writeToNBT(tagentityitem);
tagentry.setTag("entityitem", tagentityitem);
tagentry.setByte("from", (byte)(p.getValue2().ordinal()));
tagentry.setByte("mode", (byte)(p.getValue3().ordinal()));
sendqueue.appendTag(tagentry);
}
nbttagcompound.setTag("sendqueue", sendqueue);
for(int i=0;i<6;i++) {
if(signItem[i] != null) {
nbttagcompound.setBoolean("PipeSign_" + i, true);
int signType = -1;
List<Class<? extends IPipeSign>> typeClasses = ItemPipeSignCreator.signTypes;
for(int j=0;j<typeClasses.size();j++) {
if(typeClasses.get(j) == signItem[i].getClass()) {
signType = j;
break;
}
}
nbttagcompound.setInteger("PipeSign_" + i + "_type", signType);
NBTTagCompound tag = new NBTTagCompound();
signItem[i].writeToNBT(tag);
nbttagcompound.setTag("PipeSign_" + i + "_tags", tag);
} else {
nbttagcompound.setBoolean("PipeSign_" + i, false);
}
}
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound) {
super.readFromNBT(nbttagcompound);
synchronized (routerIdLock) {
routerId = nbttagcompound.getString("routerId");
}
stat_lifetime_sent = nbttagcompound.getLong("stat_lifetime_sent");
stat_lifetime_recieved = nbttagcompound.getLong("stat_lifetime_recieved");
stat_lifetime_relayed = nbttagcompound.getLong("stat_lifetime_relayed");
if (getLogisticsModule() != null){
getLogisticsModule().readFromNBT(nbttagcompound);
}
upgradeManager.readFromNBT(nbttagcompound.getCompoundTag("upgradeManager"));
powerHandler.readFromNBT(nbttagcompound.getCompoundTag("powerHandler"));
_sendQueue.clear();
NBTTagList sendqueue = nbttagcompound.getTagList("sendqueue", nbttagcompound.getId());
for(int i = 0; i < sendqueue.tagCount(); i++) {
NBTTagCompound tagentry = sendqueue.getCompoundTagAt(i);
NBTTagCompound tagentityitem = tagentry.getCompoundTag("entityitem");
LPTravelingItemServer item = new LPTravelingItemServer(tagentityitem);
ForgeDirection from = ForgeDirection.values()[tagentry.getByte("from")];
ItemSendMode mode = ItemSendMode.values()[tagentry.getByte("mode")];
_sendQueue.add(new Triplet<IRoutedItem, ForgeDirection, ItemSendMode>(item, from, mode));
}
for(int i=0;i<6;i++) {
if(nbttagcompound.getBoolean("PipeSign_" + i)) {
int type = nbttagcompound.getInteger("PipeSign_" + i + "_type");
Class<? extends IPipeSign> typeClass = ItemPipeSignCreator.signTypes.get(type);
try {
signItem[i] = typeClass.newInstance();
signItem[i].init(this, ForgeDirection.getOrientation(i));
signItem[i].readFromNBT(nbttagcompound.getCompoundTag("PipeSign_" + i + "_tags"));
} catch(InstantiationException e) {
throw new RuntimeException(e);
} catch(IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
@Override
public IRouter getRouter() {
if(stillNeedReplace) {
System.out.println("Hey, don't get routers for pipes that aren't ready");
new Throwable().printStackTrace();
}
if (router == null){
synchronized (routerIdLock) {
UUID routerIntId = null;
if(routerId!=null && !routerId.isEmpty())
routerIntId = UUID.fromString(routerId);
router = SimpleServiceLocator.routerManager.getOrCreateRouter(routerIntId, MainProxy.getDimensionForWorld(getWorld()), getX(), getY(), getZ(), false);
}
}
return router;
}
public boolean isEnabled(){
return enabled;
}
public void setEnabled(boolean enabled){
this.enabled = enabled;
}
@Override
public void onNeighborBlockChange(int blockId) {
super.onNeighborBlockChange(blockId);
clearCache();
if(!stillNeedReplace && MainProxy.isServer(getWorld())) {
onNeighborBlockChange_Logistics();
}
}
public void onNeighborBlockChange_Logistics(){}
@Override
public void onBlockPlaced() {
super.onBlockPlaced();
}
@CCCommand(description="Returns the Internal LogisticsModule for this pipe")
public abstract LogisticsModule getLogisticsModule();
@Override
public final boolean blockActivated(EntityPlayer entityplayer) {
SecuritySettings settings = null;
if(MainProxy.isServer(entityplayer.worldObj)) {
LogisticsSecurityTileEntity station = SimpleServiceLocator.securityStationManager.getStation(getUpgradeManager().getSecurityID());
if(station != null) {
settings = station.getSecuritySettingsForPlayer(entityplayer, true);
}
}
if (MainProxy.isPipeControllerEquipped(entityplayer)) {
if(MainProxy.isServer(entityplayer.worldObj)) {
if(settings == null || settings.openNetworkMonitor) {
NewGuiHandler.getGui(PipeController.class).setTilePos(container).open(entityplayer);
} else {
entityplayer.addChatComponentMessage(new ChatComponentTranslation("lp.chat.permissiondenied"));
}
}
return true;
}
if(handleClick(entityplayer, settings)) {
return true;
}
if (entityplayer.getCurrentEquippedItem() == null) {
if (!entityplayer.isSneaking()) return false;
if(MainProxy.isClient(entityplayer.worldObj)) {
if(!LogisticsHUDRenderer.instance().hasLasers()) {
MainProxy.sendPacketToServer(PacketHandler.getPacket(RequestRoutingLasersPacket.class).setPosX(getX()).setPosY(getY()).setPosZ(getZ()));
} else {
LogisticsHUDRenderer.instance().resetLasers();
}
}
if (LPConstants.DEBUG) {
doDebugStuff(entityplayer);
}
return true;
}
if (entityplayer.getCurrentEquippedItem().getItem() == LogisticsPipes.LogisticsRemoteOrderer) {
if(MainProxy.isServer(entityplayer.worldObj)) {
if(settings == null || settings.openRequest) {
entityplayer.openGui(LogisticsPipes.instance, GuiIDs.GUI_Normal_Orderer_ID, getWorld(), getX(), getY(), getZ());
} else {
entityplayer.addChatComponentMessage(new ChatComponentTranslation("lp.chat.permissiondenied"));
}
}
return true;
}
if (SimpleServiceLocator.toolWrenchHandler.isWrenchEquipped(entityplayer) && SimpleServiceLocator.toolWrenchHandler.canWrench(entityplayer, this.getX(), this.getY(), this.getZ())) {
if(MainProxy.isServer(entityplayer.worldObj)) {
if (settings == null || settings.openGui) {
if (getLogisticsModule() != null && getLogisticsModule() instanceof LogisticsGuiModule) {
((LogisticsGuiModule)getLogisticsModule()).getPipeGuiProviderForModule().setTilePos(this.container).open(entityplayer);
} else {
onWrenchClicked(entityplayer);
}
} else {
entityplayer.addChatComponentMessage(new ChatComponentTranslation("lp.chat.permissiondenied"));
}
}
SimpleServiceLocator.toolWrenchHandler.wrenchUsed(entityplayer, this.getX(), this.getY(), this.getZ());
return true;
}
if(!(entityplayer.isSneaking()) && getUpgradeManager().tryIserting(getWorld(), entityplayer)) {
return true;
}
return super.blockActivated(entityplayer);
}
protected boolean handleClick(EntityPlayer entityplayer, SecuritySettings settings) {
return false;
}
protected void clearCache() {
_cachedAdjacentInventories=null;
}
public void refreshRender(boolean spawnPart) {
this.container.scheduleRenderUpdate();
if (spawnPart) {
spawnParticle(Particles.GreenParticle, 3);
}
}
public void refreshConnectionAndRender(boolean spawnPart) {
clearCache();
this.container.scheduleNeighborChange();
if (spawnPart) {
spawnParticle(Particles.GreenParticle, 3);
}
}
/*** -- IAdjacentWorldAccess -- ***/
@Override
public LinkedList<AdjacentTile> getConnectedEntities() {
WorldUtil world = new WorldUtil(this.getWorld(), this.getX(), this.getY(), this.getZ());
LinkedList<AdjacentTile> adjacent = world.getAdjacentTileEntities(true);
Iterator<AdjacentTile> iterator = adjacent.iterator();
while (iterator.hasNext()){
AdjacentTile tile = iterator.next();
if (!MainProxy.checkPipesConnections(this.container, tile.tile, tile.orientation)){
iterator.remove();
}
}
return adjacent;
}
@Override
public int getRandomInt(int maxSize) {
return getWorld().rand.nextInt(maxSize);
}
/*** -- ITrackStatistics -- ***/
@Override
public void recievedItem(int count) {
stat_session_recieved += count;
stat_lifetime_recieved += count;
updateStats();
}
@Override
public void relayedItem(int count) {
stat_session_relayed += count;
stat_lifetime_relayed += count;
updateStats();
}
@Override
public World getWorld() {
return container.getWorld();
}
@Override
public void playerStartWatching(EntityPlayer player, int mode) {
if(mode == 0) {
watchers.add(player);
MainProxy.sendPacketToPlayer(PacketHandler.getPacket(StatUpdate.class).setPipe(this), player);
}
}
@Override
public void playerStopWatching(EntityPlayer player, int mode) {
if(mode == 0) {
watchers.remove(player);
}
}
public void updateStats() {
if(watchers.size() > 0) {
MainProxy.sendToPlayerList(PacketHandler.getPacket(StatUpdate.class).setPipe(this), watchers);
}
}
@Override
public void itemCouldNotBeSend(ItemIdentifierStack item, IAdditionalTargetInformation info) {
if(this instanceof IRequireReliableTransport) {
((IRequireReliableTransport)this).itemLost(item, info);
}
}
public boolean isLockedExit(ForgeDirection orientation) {
return false;
}
public boolean logisitcsIsPipeConnected(TileEntity tile, ForgeDirection dir) {
return false;
}
public boolean disconnectPipe(TileEntity tile, ForgeDirection dir) {
return false;
}
@Override
public final boolean canPipeConnect(TileEntity tile, ForgeDirection dir) {
return canPipeConnect(tile, dir, false);
}
public boolean globalIgnoreConnectionDisconnection = false;
public final boolean canPipeConnect(TileEntity tile, ForgeDirection dir, boolean ignoreSystemDisconnection) {
ForgeDirection side = OrientationsUtil.getOrientationOfTilewithTile(this.container, tile);
if(getUpgradeManager().isSideDisconnected(side)) {
return false;
}
if(container != null && side != ForgeDirection.UNKNOWN && container.tilePart.hasBlockingPluggable(side)) {
return false;
}
if(!stillNeedReplace) {
if(getRouter().isSideDisconneceted(side) && !ignoreSystemDisconnection && !globalIgnoreConnectionDisconnection) {
return false;
}
}
return (super.canPipeConnect(tile, dir) || logisitcsIsPipeConnected(tile, dir)) && !disconnectPipe(tile, dir);
}
public void connectionUpdate() {
if(container != null && !stillNeedReplace) {
container.scheduleNeighborChange();
getWorld().notifyBlockChange(getX(), getY(), getZ(), getWorld().getBlock(getX(), getY(), getZ()));
}
}
public UUID getSecurityID() {
return getUpgradeManager().getSecurityID();
}
public void insetSecurityID(UUID id) {
getUpgradeManager().insetSecurityID(id);
}
/* Power System */
public List<Pair<ILogisticsPowerProvider,List<IFilter>>> getRoutedPowerProviders() {
if(MainProxy.isClient(getWorld())) {
return null;
}
if(stillNeedReplace) {
return null;
}
return this.getRouter().getPowerProvider();
}
@Override
public boolean useEnergy(int amount) {
return useEnergy(amount, null, true);
}
public boolean useEnergy(int amount, boolean sparkles) {
return useEnergy(amount, null, sparkles);
}
@Override
public boolean canUseEnergy(int amount) {
return canUseEnergy(amount,null);
}
@Override
public boolean canUseEnergy(int amount, List<Object> providersToIgnore) {
if(MainProxy.isClient(getWorld())) return false;
if(Configs.LOGISTICS_POWER_USAGE_DISABLED) return true;
if(amount == 0) return true;
if(providersToIgnore !=null && providersToIgnore.contains(this))
return false;
List<Pair<ILogisticsPowerProvider,List<IFilter>>> list = getRoutedPowerProviders();
if(list == null) return false;
outer:
for(Pair<ILogisticsPowerProvider,List<IFilter>> provider: list) {
for(IFilter filter:provider.getValue2()) {
if(filter.blockPower()) continue outer;
}
if(provider.getValue1().canUseEnergy(amount, providersToIgnore)) {
return true;
}
}
return false;
}
@Override
public boolean useEnergy(int amount, List<Object> providersToIgnore) {
return useEnergy(amount, providersToIgnore, false);
}
private boolean useEnergy(int amount, List<Object> providersToIgnore, boolean sparkles) {
if(MainProxy.isClient(getWorld())) return false;
if(Configs.LOGISTICS_POWER_USAGE_DISABLED) return true;
if(amount == 0) return true;
if(providersToIgnore==null)
providersToIgnore = new ArrayList<Object>();
if(providersToIgnore.contains(this))
return false;
providersToIgnore.add(this);
List<Pair<ILogisticsPowerProvider,List<IFilter>>> list = getRoutedPowerProviders();
if(list == null) return false;
outer:
for(Pair<ILogisticsPowerProvider,List<IFilter>> provider: list) {
for(IFilter filter:provider.getValue2()) {
if(filter.blockPower()) continue outer;
}
if(provider.getValue1().canUseEnergy(amount, providersToIgnore)) {
if(provider.getValue1().useEnergy(amount, providersToIgnore)) {
if(sparkles) {
int particlecount = amount;
if (particlecount > 10) {
particlecount = 10;
}
spawnParticle(Particles.GoldParticle, particlecount);
}
return true;
}
}
}
return false;
}
public void queueEvent(String event, Object[] arguments) {
if(this.container instanceof LogisticsTileGenericPipe) {
((LogisticsTileGenericPipe)this.container).queueEvent(event, arguments);
}
}
public boolean stillNeedReplace() {
return stillNeedReplace;
}
public boolean initialInit() {
return _initialInit;
}
@Override
public int compareTo(IRequestItems other){
return this.getID()-other.getID();
}
@Override
public int getID(){
return this.getRouter().getSimpleID();
}
public Set<ItemIdentifier> getSpecificInterests() {
return null;
}
public boolean hasGenericInterests() {
return false;
}
public ISecurityProvider getSecurityProvider() {
return SimpleServiceLocator.securityStationManager.getStation(getUpgradeManager().getSecurityID());
}
public boolean canBeDestroyedByPlayer(EntityPlayer entityPlayer) {
LogisticsSecurityTileEntity station = SimpleServiceLocator.securityStationManager.getStation(getUpgradeManager().getSecurityID());
if(station != null) {
return station.getSecuritySettingsForPlayer(entityPlayer, true).removePipes;
}
return true;
}
@Override
public boolean canBeDestroyed() {
ISecurityProvider sec = getSecurityProvider();
if(sec != null) {
if(!sec.canAutomatedDestroy()) {
return false;
}
}
return true;
}
public void setDestroyByPlayer() {
destroyByPlayer = true;
}
@Override
public boolean destroyByPlayer() {
return destroyByPlayer;
}
@Override
public boolean preventRemove() {
return preventRemove;
}
@CCSecurtiyCheck
public void checkCCAccess() throws PermissionException {
ISecurityProvider sec = getSecurityProvider();
if(sec != null) {
int id = -1;
if(this.container instanceof LogisticsTileGenericPipe) {
id = ((LogisticsTileGenericPipe)this.container).getLastCCID();
}
if(!sec.getAllowCC(id)) {
throw new PermissionException();
}
}
}
public void queueUnroutedItemInformation(ItemIdentifierStack item, ItemRoutingInformation informaiton) {
if(item != null) {
queuedDataForUnroutedItems.put(item, informaiton);
}
}
public ItemRoutingInformation getQueuedForItemStack(ItemIdentifierStack itemIdentifierStack) {
for(ItemIdentifierStack item:queuedDataForUnroutedItems.keySet()) {
if(item.equals(itemIdentifierStack)) {
return queuedDataForUnroutedItems.remove(item);
}
}
return null;
}
/** used as a distance offset when deciding which pipe to use
* NOTE: called very regularly, returning a pre-calculated int is probably appropriate.
* @return
*/
public double getLoadFactor() {
return 0.0;
}
public void notifyOfItemArival(ItemRoutingInformation information) {
this._inTransitToMe.remove(information);
if (this instanceof IRequireReliableTransport) {
((IRequireReliableTransport)this).itemArrived(information.getItem(), information.targetInfo);
}
if (this instanceof IRequireReliableFluidTransport) {
ItemIdentifierStack stack = information.getItem();
if(stack.getItem().isFluidContainer()) {
FluidStack liquid = SimpleServiceLocator.logisticsFluidManager.getFluidFromContainer(stack);
((IRequireReliableFluidTransport)this).liquidArrived(FluidIdentifier.get(liquid), liquid.amount);
}
}
}
public int countOnRoute(ItemIdentifier it) {
int count = 0;
for(Iterator<ItemRoutingInformation> iter = _inTransitToMe.iterator();iter.hasNext();) {
ItemRoutingInformation next = iter.next();
if(next.getItem().getItem().equals(it))
count += next.getItem().getStackSize();
}
return count;
}
@Override
@SideOnly(Side.CLIENT)
public IIconProvider getIconProvider() {
return Textures.LPpipeIconProvider;
}
@Override
public final int getIconIndex(ForgeDirection connection) {
TextureType texture = getTextureType(connection);
if(_textureBufferPowered) {
return texture.powered;
} else if(Configs.LOGISTICS_POWER_USAGE_DISABLED) {
return texture.normal;
} else {
return texture.unpowered;
}
}
public void addCrashReport(CrashReportCategory crashReportCategory) {
addRouterCrashReport(crashReportCategory);
crashReportCategory.addCrashSection("stillNeedReplace", stillNeedReplace);
}
protected void addRouterCrashReport(CrashReportCategory crashReportCategory) {
crashReportCategory.addCrashSection("Router", this.getRouter().toString());
}
public boolean isFluidPipe() {
return false;
}
/* --- CCCommands --- */
@CCCommand(description="Returns the Router UUID as an integer; all pipes have a unique ID (runtime stable)")
public int getRouterId() {
return getRouter().getSimpleID();
}
@CCCommand(description="Returns the Router UUID; all pipes have a unique ID (lifetime stable)")
public String getRouterUUID() {
return getRouter().getId().toString();
}
@CCCommand(description="Returns the Router UUID for the givvin router Id")
public String getRouterUUID(Double id) {
IRouter router = SimpleServiceLocator.routerManager.getRouter((int)((double)id));
if(router == null) return null;
return router.getId().toString();
}
@CCCommand(description="Sets the TurtleConnect flag for this Turtle on this LogisticsPipe")
@CCDirectCall
public void setTurtleConnect(Boolean flag) {
if(this.container instanceof LogisticsTileGenericPipe) {
((LogisticsTileGenericPipe)this.container).setTurtleConnect(flag);
}
}
@CCCommand(description="Returns the TurtleConnect flag for this Turtle on this LogisticsPipe")
@CCDirectCall
public boolean getTurtleConnect() {
if(this.container instanceof LogisticsTileGenericPipe) {
return ((LogisticsTileGenericPipe)this.container).getTurtleConnect();
}
return false;
}
@CCCommand(description="Returns true if the computer is allowed to interact with the connected pipe.", needPermission=false)
public boolean canAccess() {
ISecurityProvider sec = getSecurityProvider();
if(sec != null) {
int id = -1;
if(this.container instanceof LogisticsTileGenericPipe) {
id = ((LogisticsTileGenericPipe)this.container).getLastCCID();
}
return sec.getAllowCC(id);
}
return true;
}
@CCCommand(description="Sends a message to the givven computerId over the LP network. Event: " + CCConstants.LP_CC_MESSAGE_EVENT)
@CCDirectCall
public void sendMessage(final Double computerId, final Object message) {
int sourceId = -1;
if(this.container instanceof LogisticsTileGenericPipe) {
sourceId = SimpleServiceLocator.ccProxy.getLastCCID((LogisticsTileGenericPipe)this.container);
}
final int fSourceId = sourceId;
BitSet set = new BitSet(ServerRouter.getBiggestSimpleID());
for(ExitRoute exit:this.getRouter().getIRoutersByCost()) {
if(exit.destination != null && !set.get(exit.destination.getSimpleID())) {
exit.destination.queueTask(10, new IRouterQueuedTask() {
@Override
public void call(CoreRoutedPipe pipe, IRouter router) {
pipe.handleMesssage((int) ((double) computerId), message, fSourceId);
}
});
set.set(exit.destination.getSimpleID());
}
}
}
@CCCommand(description="Sends a broadcast message to all Computer connected to this LP network. Event: " + CCConstants.LP_CC_BROADCAST_EVENT)
@CCDirectCall
public void sendBroadcast(final String message) {
int sourceId = -1;
if(this.container instanceof LogisticsTileGenericPipe) {
sourceId = SimpleServiceLocator.ccProxy.getLastCCID((LogisticsTileGenericPipe)this.container);
}
final int fSourceId = sourceId;
BitSet set = new BitSet(ServerRouter.getBiggestSimpleID());
for(ExitRoute exit:this.getRouter().getIRoutersByCost()) {
if(exit.destination != null && !set.get(exit.destination.getSimpleID())) {
exit.destination.queueTask(10, new IRouterQueuedTask() {
@Override
public void call(CoreRoutedPipe pipe, IRouter router) {
pipe.handleBroadcast(message, fSourceId);
}
});
set.set(exit.destination.getSimpleID());
}
}
}
@CCCommand(description="Returns the access to the pipe of the givven router UUID")
@ModDependentMethod(modId="ComputerCraft@1.6")
@CCDirectCall
public Object getPipeForUUID(String sUuid) throws PermissionException {
if(!getUpgradeManager().hasCCRemoteControlUpgrade()) throw new PermissionException();
UUID uuid = UUID.fromString(sUuid);
int id = SimpleServiceLocator.routerManager.getIDforUUID(uuid);
IRouter router = SimpleServiceLocator.routerManager.getRouter(id);
if(router == null) return null;
CoreRoutedPipe pipe = router.getPipe();
if(!(pipe.container instanceof LogisticsTileGenericPipe)) return null;
return pipe.container;
}
@CCCommand(description="Returns the global LP object which is used to access general LP methods.", needPermission=false)
@CCDirectCall
public Object getLP() throws PermissionException {
return LogisticsPipes.getComputerLP();
}
@CCCommand(description="Returns true if the pipe has an internal module")
public boolean hasLogisticsModule() {
return this.getLogisticsModule() != null;
}
private void handleMesssage(int computerId, Object message, int sourceId) {
if(this.container instanceof LogisticsTileGenericPipe) {
((LogisticsTileGenericPipe)this.container).handleMesssage(computerId, message, sourceId);
}
}
private void handleBroadcast(String message, int sourceId) {
this.queueEvent(CCConstants.LP_CC_BROADCAST_EVENT, new Object[]{sourceId, message});
}
public void onWrenchClicked(EntityPlayer entityplayer) {
//do nothing, every pipe with a GUI should either have a LogisticsGuiModule or override this method
}
final void destroy(){ // no overide, put code in OnBlockRemoval
}
public void handleRFPowerArival(float toSend) {
powerHandler.addRFPower(toSend);
}
public void handleIC2PowerArival(float toSend) {
powerHandler.addIC2Power(toSend);
}
@Override
public String toString() {
return super.toString() + " (" + this.getX() + ", " + this.getY() + ", " + this.getZ() + ")";
}
public LPPosition getLPPosition() {
return new LPPosition(this);
}
public WorldUtil getWorldUtil() {
return new WorldUtil(this.getWorld(), this.getX(), this.getY(), this.getZ());
}
/*** IInventoryProvider ***/
@Override
public IInventoryUtil getPointedInventory(boolean forExtraction) {
return getSneakyInventory(this.getPointedOrientation().getOpposite(), forExtraction);
}
@Override
public IInventoryUtil getPointedInventory(ExtractionMode mode, boolean forExtraction) {
IInventory inv = getRealInventory();
if(inv == null) return null;
if (inv instanceof net.minecraft.inventory.ISidedInventory) inv = new SidedInventoryMinecraftAdapter((net.minecraft.inventory.ISidedInventory) inv, this.getPointedOrientation().getOpposite(), forExtraction);
switch(mode){
case LeaveFirst:
return SimpleServiceLocator.inventoryUtilFactory.getHidingInventoryUtil(inv, this.getPointedOrientation().getOpposite(), false, false, 1, 0);
case LeaveLast:
return SimpleServiceLocator.inventoryUtilFactory.getHidingInventoryUtil(inv, this.getPointedOrientation().getOpposite(), false, false, 0, 1);
case LeaveFirstAndLast:
return SimpleServiceLocator.inventoryUtilFactory.getHidingInventoryUtil(inv, this.getPointedOrientation().getOpposite(), false, false, 1, 1);
case Leave1PerStack:
return SimpleServiceLocator.inventoryUtilFactory.getHidingInventoryUtil(inv, this.getPointedOrientation().getOpposite(), true, false, 0, 0);
case Leave1PerType:
return SimpleServiceLocator.inventoryUtilFactory.getHidingInventoryUtil(inv, this.getPointedOrientation().getOpposite(), false, true, 0, 0);
default:
break;
}
return SimpleServiceLocator.inventoryUtilFactory.getHidingInventoryUtil(inv, this.getPointedOrientation().getOpposite(), false, false, 0, 0);
}
@Override
public IInventoryUtil getSneakyInventory(boolean forExtraction) {
UpgradeManager manager = getUpgradeManager();
ForgeDirection insertion = this.getPointedOrientation().getOpposite();
if(manager.hasSneakyUpgrade()) {
insertion = manager.getSneakyOrientation();
}
return getSneakyInventory(insertion, forExtraction);
}
@Override
public IInventoryUtil getSneakyInventory(ForgeDirection _sneakyOrientation, boolean forExtraction) {
IInventory inv = getRealInventory();
if(inv == null) return null;
if (inv instanceof net.minecraft.inventory.ISidedInventory) inv = new SidedInventoryMinecraftAdapter((net.minecraft.inventory.ISidedInventory) inv, _sneakyOrientation, forExtraction);
return SimpleServiceLocator.inventoryUtilFactory.getInventoryUtil(inv, _sneakyOrientation);
}
@Override
public IInventoryUtil getUnsidedInventory() {
IInventory inv = getRealInventory();
if(inv == null) return null;
return SimpleServiceLocator.inventoryUtilFactory.getInventoryUtil(inv);
}
@Override
public IInventory getRealInventory() {
TileEntity tile = getPointedTileEntity();
if (tile == null ) return null;
if (!(tile instanceof IInventory)) return null;
return InventoryHelper.getInventory((IInventory) tile);
}
private TileEntity getPointedTileEntity() {
if(pointedDirection == ForgeDirection.UNKNOWN) return null;
return this.getContainer().getTile(pointedDirection);
}
@Override
public ForgeDirection inventoryOrientation() {
return getPointedOrientation();
}
/*** ISendRoutedItem ***/
public int getSourceint() {
return this.getRouter().getSimpleID();
};
@Override
public Triplet<Integer, SinkReply, List<IFilter>> hasDestination(ItemIdentifier stack, boolean allowDefault, List<Integer> routerIDsToExclude) {
return SimpleServiceLocator.logisticsManager.hasDestination(stack, allowDefault, getRouter().getSimpleID(), routerIDsToExclude);
}
@Override
public IRoutedItem sendStack(ItemStack stack, Pair<Integer, SinkReply> reply, ItemSendMode mode) {
IRoutedItem itemToSend = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);
itemToSend.setDestination(reply.getValue1());
if (reply.getValue2().isPassive){
if (reply.getValue2().isDefault){
itemToSend.setTransportMode(TransportMode.Default);
} else {
itemToSend.setTransportMode(TransportMode.Passive);
}
}
queueRoutedItem(itemToSend, getPointedOrientation(), mode);
return itemToSend;
}
@Override
public IRoutedItem sendStack(ItemStack stack, int destination, ItemSendMode mode, IAdditionalTargetInformation info) {
IRoutedItem itemToSend = SimpleServiceLocator.routedItemHelper.createNewTravelItem(stack);
itemToSend.setDestination(destination);
itemToSend.setTransportMode(TransportMode.Active);
itemToSend.setAdditionalTargetInformation(info);
queueRoutedItem(itemToSend, getPointedOrientation(), mode);
return itemToSend;
}
public ForgeDirection getPointedOrientation() {
return this.pointedDirection;
}
@Override
public LogisticsOrderManager getOrderManager() {
_orderManager=_orderManager!=null?_orderManager:new LogisticsOrderManager();
return this._orderManager;
}
public void addPipeSign(ForgeDirection dir, IPipeSign type, EntityPlayer player) {
if(dir.ordinal() < 6) {
if(signItem[dir.ordinal()] == null) {
signItem[dir.ordinal()] = type;
signItem[dir.ordinal()].init(this, dir);
}
if(container != null) {
sendSignData(player);
}
}
}
public void sendSignData(EntityPlayer player) {
List<Integer> types = new ArrayList<Integer>();
for(int i=0;i<6;i++) {
if(signItem[i] == null) {
types.add(-1);
} else {
List<Class<? extends IPipeSign>> typeClasses = ItemPipeSignCreator.signTypes;
for(int j=0;j<typeClasses.size();j++) {
if(typeClasses.get(j) == signItem[i].getClass()) {
types.add(j);
break;
}
}
}
}
ModernPacket packet = PacketHandler.getPacket(PipeSignTypes.class).setTypes(types).setTilePos(container);
MainProxy.sendPacketToAllWatchingChunk(getX(), getZ(), MainProxy.getDimensionForWorld(getWorld()), packet);
MainProxy.sendPacketToPlayer(packet, player);
for(int i=0;i<6;i++) {
if(signItem[i] != null) {
packet = signItem[i].getPacket();
if(packet != null) {
MainProxy.sendPacketToAllWatchingChunk(getX(), getZ(), MainProxy.getDimensionForWorld(getWorld()), packet);
MainProxy.sendPacketToPlayer(packet, player);
}
}
}
this.refreshRender(false);
}
public void removePipeSign(ForgeDirection dir, EntityPlayer player) {
if(dir.ordinal() < 6) {
signItem[dir.ordinal()] = null;
}
sendSignData(player);
}
public boolean hasPipeSign(ForgeDirection dir) {
if(dir.ordinal() < 6) {
return signItem[dir.ordinal()] != null;
}
return false;
}
public void activatePipeSign(ForgeDirection dir, EntityPlayer player) {
if(dir.ordinal() < 6) {
if(signItem[dir.ordinal()] != null) {
signItem[dir.ordinal()].activate(player);
}
}
}
public List<Pair<ForgeDirection, IPipeSign>> getPipeSigns() {
List<Pair<ForgeDirection, IPipeSign>> list = new ArrayList<Pair<ForgeDirection, IPipeSign>>();
for(int i=0;i<6;i++) {
if(signItem[i] != null) {
list.add(new Pair<ForgeDirection, IPipeSign>(ForgeDirection.getOrientation(i), signItem[i]));
}
}
return list;
}
public void handleSignPacket(List<Integer> types) {
if(!MainProxy.isClient(getWorld())) return;
for(int i=0;i<6;i++) {
int integer = types.get(i);
if(integer >= 0) {
Class<? extends IPipeSign> type = ItemPipeSignCreator.signTypes.get(integer);
if(signItem[i] == null || signItem[i].getClass() != type) {
try {
signItem[i] = type.newInstance();
signItem[i].init(this, ForgeDirection.getOrientation(i));
} catch(InstantiationException e) {
throw new RuntimeException(e);
} catch(IllegalAccessException e) {
throw new RuntimeException(e);
}
}
} else {
signItem[i] = null;
}
}
}
public IPipeSign getPipeSign(ForgeDirection dir) {
if(dir.ordinal() < 6) {
return signItem[dir.ordinal()];
}
return null;
}
public void triggerDebug() {
if(this.debug.debugThisPipe) {
System.out.print("");
}
}
@Override
public void writeData(LPDataOutputStream data) throws IOException {
data.writeBoolean(isOpaque());
}
@Override
public void readData(LPDataInputStream data) throws IOException {
isOpaqueClientSide = data.readBoolean();
}
public boolean isOpaque() {
if(MainProxy.isClient(getWorld())) {
return Configs.OPAQUE || isOpaqueClientSide;
} else {
return Configs.OPAQUE || this.getUpgradeManager().isOpaque();
}
}
public void addStatusInformation(List<StatusEntry> status) {
StatusEntry entry = new StatusEntry();
entry.name = "Send Queue";
entry.subEntry = new ArrayList<StatusEntry>();
for(Triplet<IRoutedItem, ForgeDirection, ItemSendMode> part:_sendQueue) {
StatusEntry subEntry = new StatusEntry();
subEntry.name = part.toString();
entry.subEntry.add(subEntry);
}
status.add(entry);
entry = new StatusEntry();
entry.name = "In Transit To Me";
entry.subEntry = new ArrayList<StatusEntry>();
for(ItemRoutingInformation part:_inTransitToMe) {
StatusEntry subEntry = new StatusEntry();
subEntry.name = part.toString();
entry.subEntry.add(subEntry);
}
status.add(entry);
}
@Override
public int getSourceID() {
return this.getRouterId();
}
@Override
public DebugLogController getDebug() {
return debug;
}
public void setPreventRemove(boolean flag) {
preventRemove = flag;
}
@Override
public boolean isRoutedPipe() {
return true;
}
}