feat: implement LogiscticsPipes compat

This commit is contained in:
Timo Ley 2023-01-05 13:46:10 +01:00
parent fcad99813f
commit e05bf29fa8
9 changed files with 138 additions and 328 deletions

View File

@ -1,15 +1,3 @@
task myJavadocs(type: Javadoc) {
source = sourceSets.api.java
include "appeng/api/**"
classpath = configurations.compile
}
task javadocJar(type: Jar, dependsOn: myJavadocs) {
classifier = 'javadoc'
from 'build/docs/javadoc/'
}
task sourceJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.main.allSource
@ -44,6 +32,5 @@ task apiJar(type: Jar) {
artifacts {
archives devJar
archives apiJar
archives javadocJar
archives sourceJar
}

View File

@ -6,7 +6,6 @@ publishing {
artifact devJar
artifact sourceJar
artifact javadocJar
artifact apiJar
}
}

View File

@ -29,8 +29,10 @@ import appeng.tile.misc.TileInterface;
import appeng.util.Platform;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
@ -88,4 +90,13 @@ public class BlockInterface extends AEBaseTileBlock {
((TileInterface) rotatable).setSide(axis);
}
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
super.onNeighborBlockChange(world, x, y, z, block);
TileEntity te = world.getTileEntity(x, y, z);
if (te instanceof TileInterface) {
((TileInterface)te).refreshRequestPipe();
}
}
}

View File

@ -18,41 +18,17 @@
package appeng.integration.abstraction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Set;
import net.minecraft.item.ItemStack;
import appeng.api.config.Actionable;
import appeng.api.storage.data.IAEItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Contains pipe logic to interact between storage buses and pipes
*
* @author Second_Fry
* @version rv3 01.01.2017
* @since rv3 01.01.2017
*/
public interface ILogisticsPipes {
/**
* checks weather if the {@code te} is injectable and simulates to inject the item
*
* @param te instanceof ILPPipe
* @param is to be injected item
* @param dir direction of the pipe
* @return {@code true} if items were simulated successfully being added
*/
boolean canAddItemsToPipe(TileEntity te, ItemStack is, ForgeDirection dir);
/**
* checks weather if the {@code te} is injectable, simulates the inject and tries to
* inject the item
*
* @param te instanceof ILPPipe
* @param is to be injected item
* @param dir direction of the pipe
* @return {@code true} if items were added to the buildcraft pipe
*/
boolean addItemsToPipe(
@Nullable TileEntity te, @Nullable ItemStack is, @Nonnull ForgeDirection dir
);
boolean isRequestPipe(TileEntity te);
Set<IAEItemStack> getRequestableItems(TileEntity te);
IAEItemStack requestStack(TileEntity te, IAEItemStack request, Actionable actionable);
}

View File

@ -1,64 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.LPHelpers;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IExternalStorageHandler;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.StorageChannel;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
import appeng.integration.abstraction.ILogisticsPipes;
import appeng.me.storage.MEMonitorIInventory;
import appeng.util.inv.IMEAdaptor;
import logisticspipes.api.ILPPipeTile;
import logisticspipes.pipes.basic.CoreUnroutedPipe;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public class LPPipeHandler implements IExternalStorageHandler {
@Override
public boolean canHandle(
final TileEntity te,
final ForgeDirection d,
final StorageChannel channel,
final BaseActionSource mySrc
) {
if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.LogisticsPipes)) {
return channel == StorageChannel.ITEMS && te instanceof ILPPipeTile
&& ((CoreUnroutedPipe) ((ILPPipeTile) te).getLPPipe())
.canPipeConnect(te, d);
}
return false;
}
@Override
public IMEInventory getInventory(
final TileEntity te,
final ForgeDirection d,
final StorageChannel channel,
final BaseActionSource src
) {
if (channel == StorageChannel.ITEMS) {
return new MEMonitorIInventory(new IMEAdaptor(new LPPipeInventory(te, d), src)
);
}
return null;
}
}

View File

@ -1,183 +0,0 @@
/*
* This file is part of Applied Energistics 2.
* Copyright (c) 2013 - 2015, AlgorithmX2, All rights reserved.
*
* Applied Energistics 2 is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Applied Energistics 2 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Applied Energistics 2. If not, see <http://www.gnu.org/licenses/lgpl>.
*/
package appeng.integration.modules.LPHelpers;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import appeng.api.config.Actionable;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.storage.IMEInventory;
import appeng.api.storage.StorageChannel;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.storage.data.IItemList;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
import appeng.integration.abstraction.ILogisticsPipes;
import appeng.tile.grid.AENetworkInvTile;
import appeng.util.item.AEItemStack;
import logisticspipes.api.ILPPipe;
import logisticspipes.api.ILPPipeTile;
import logisticspipes.api.IRequestAPI;
import logisticspipes.pipes.basic.CoreRoutedPipe;
import logisticspipes.proxy.SimpleServiceLocator;
import logisticspipes.routing.ExitRoute;
import logisticspipes.utils.AdjacentTile;
import logisticspipes.utils.item.ItemIdentifier;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
public class LPPipeInventory implements IMEInventory<IAEItemStack> {
private final TileEntity te;
private final ForgeDirection direction;
public LPPipeInventory(final TileEntity te, final ForgeDirection direction) {
this.te = te;
this.direction = direction;
}
@Override
public IAEItemStack
injectItems(IAEItemStack input, Actionable type, BaseActionSource src) {
if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.LogisticsPipes)) {
ILogisticsPipes registry = (ILogisticsPipes
) IntegrationRegistry.INSTANCE.getInstance(IntegrationType.LogisticsPipes);
if (type == Actionable.SIMULATE) {
if (registry.canAddItemsToPipe(
this.te, input.getItemStack(), this.direction
)) {
return null;
}
return input;
}
if (registry.addItemsToPipe(this.te, input.getItemStack(), this.direction)) {
return null;
}
}
return input;
}
@Override
public IAEItemStack
extractItems(IAEItemStack request, Actionable type, BaseActionSource src) {
if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.LogisticsPipes)) {
ILPPipe pipe = ((ILPPipeTile) this.te).getLPPipe();
if (pipe instanceof IRequestAPI) {
IRequestAPI requestAPI = (IRequestAPI) pipe;
if (type == Actionable.SIMULATE) {
IRequestAPI.SimulationResult simulation
= requestAPI.simulateRequest(request.getItemStack());
if (simulation.used.size() == 0) {
return null;
}
return AEItemStack.create(simulation.used.get(0));
}
List<ItemStack> returned
= requestAPI.performRequest(request.getItemStack());
if (returned.size() == 0) {
return null;
}
return AEItemStack.create(returned.get(0));
}
}
return null;
}
@Override
public IItemList<IAEItemStack> getAvailableItems(IItemList<IAEItemStack> out) {
ILPPipe pipe = ((ILPPipeTile) this.te).getLPPipe();
if (pipe instanceof IRequestAPI) {
List<ItemStack> provided = this.getLPItems(pipe);
for (ItemStack is : provided) {
out.add(AEItemStack.create(is));
}
}
return out;
}
/**
* Get items from Logistics Pipes network _excluding_ AE2 network items. Brilliant!
* (basically rewrite of CoreRoutedPipe.getProvidedItems() (implementation of
* IRequestAPI.getProvidedItems())
*
* @param pipe IRequestAPI pipe
* @return list of items in shared networks
*/
public List<ItemStack> getLPItems(ILPPipe pipe) {
CoreRoutedPipe coreRoutedPipeCast = (CoreRoutedPipe) pipe;
if (coreRoutedPipeCast.stillNeedReplace()) {
return new ArrayList<ItemStack>();
} else {
List<ExitRoute> exitRoutes
= coreRoutedPipeCast.getRouter().getIRoutersByCost();
ArrayList<ExitRoute> exitRoutesProcessed = new ArrayList<ExitRoute>();
for (ExitRoute exitRoute : exitRoutes) {
if (!isExitToAE(exitRoute)) {
exitRoutesProcessed.add(exitRoute);
}
}
Map items = SimpleServiceLocator.logisticsManager.getAvailableItems(
exitRoutesProcessed
);
ArrayList list = new ArrayList(items.size());
for (Object o : items.entrySet()) {
Map.Entry item = (Map.Entry) o;
ItemStack is
= ((ItemIdentifier) item.getKey())
.unsafeMakeNormalStack(((Integer) item.getValue()).intValue());
list.add(is);
}
return list;
}
}
/**
* Checks ExitRoute for connected AENetworkInvTiles
*
* @param exitRoute Logistics Pipes exit route to check
* @return true if AENetworkInvTiles is connected, otherwise false
*/
private boolean isExitToAE(ExitRoute exitRoute) {
LinkedList<AdjacentTile> connectedEntities
= exitRoute.destination.getPipe().getConnectedEntities();
for (AdjacentTile connectedEntity : connectedEntities) {
if (connectedEntity.tile instanceof AENetworkInvTile) {
return true;
}
}
return false;
}
@Override
public StorageChannel getChannel() {
return StorageChannel.ITEMS;
}
}

View File

@ -18,18 +18,24 @@
package appeng.integration.modules;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.storage.data.IAEItemStack;
import appeng.helpers.Reflected;
import appeng.integration.IIntegrationModule;
import appeng.integration.IntegrationHelper;
import appeng.integration.abstraction.ILogisticsPipes;
import appeng.integration.modules.LPHelpers.LPPipeHandler;
import buildcraft.api.transport.IInjectable;
import appeng.util.item.AEItemStack;
import logisticspipes.api.ILPPipeTile;
import logisticspipes.api.IRequestAPI;
import logisticspipes.api.IRequestAPI.SimulationResult;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
/**
* @author Second_Fry
@ -63,43 +69,61 @@ public class LogisticsPipes implements ILogisticsPipes, IIntegrationModule {
@Override
public void postInit() {
AEApi.instance().registries().externalStorage().addExternalStorageInterface(
new LPPipeHandler()
);
}
@Override
public boolean canAddItemsToPipe(
final TileEntity te, final ItemStack is, final ForgeDirection direction
) {
if (is != null && te != null && te instanceof IInjectable) {
final IInjectable pt = (IInjectable) te;
if (pt.canInjectItems(direction)) {
final int amt = pt.injectItem(is, false, direction, null);
if (amt == is.stackSize) {
return true;
}
}
}
return false;
public boolean isRequestPipe(TileEntity te) {
return te instanceof ILPPipeTile && ((ILPPipeTile)te).getLPPipe() instanceof IRequestAPI;
}
@Override
public boolean addItemsToPipe(
final TileEntity te, final ItemStack is, @Nonnull final ForgeDirection direction
) {
if (is != null && te != null && te instanceof IInjectable) {
final IInjectable pt = (IInjectable) te;
if (pt.canInjectItems(direction)) {
final int amt = pt.injectItem(is, false, direction, null);
if (amt == is.stackSize) {
pt.injectItem(is, true, direction, null);
return true;
public Set<IAEItemStack> getRequestableItems(TileEntity te) {
if (isRequestPipe(te)) {
IRequestAPI api = (IRequestAPI) ((ILPPipeTile)te).getLPPipe();
Map<IAEItemStack, IAEItemStack> stacks = new HashMap<>();
for(ItemStack s : api.getProvidedItems()) {
IAEItemStack stack = AEItemStack.create(s);
if (stacks.containsKey(stack)) {
stacks.get(stack).incStackSize(stack.getStackSize());
} else {
stacks.put(stack, stack);
}
}
return stacks.keySet();
}
return new HashSet<>();
}
@Override
public IAEItemStack requestStack(TileEntity te, IAEItemStack request, Actionable actionable) {
if (isRequestPipe(te) && request.getStackSize() <= Integer.MAX_VALUE) {
IRequestAPI api = (IRequestAPI) ((ILPPipeTile)te).getLPPipe();
if (actionable == Actionable.SIMULATE) {
SimulationResult res = api.simulateRequest(request.getItemStack());
if (res.missing.isEmpty()) {
return null;
} else {
return AEItemStack.create(res.missing.get(0));
}
} else {
List<ItemStack> returned = api.performRequest(request.getItemStack());
if (returned.isEmpty()) {
return null;
} else {
int missing = returned.get(0).stackSize;
if (missing > 0) {
IAEItemStack newRequest = request.copy();
newRequest.decStackSize(missing);
// LP should still request the items, which are available
api.performRequest(newRequest.getItemStack());
IAEItemStack leftover = request.copy();
leftover.setStackSize(missing);
return leftover;
}
}
}
}
return false;
return request;
}
}

View File

@ -94,6 +94,7 @@ public class RequestGridCache implements IRequestGrid, IMEInventoryHandler<IAEIt
}
}
}
storageGrid.postAlterationOfStoredItems(StorageChannel.ITEMS, requestable.keySet(), new BaseActionSource());
}
@Override

View File

@ -35,6 +35,7 @@ import appeng.api.networking.energy.IEnergyGrid;
import appeng.api.networking.events.MENetworkChannelsChanged;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.events.MENetworkRequestableChange;
import appeng.api.networking.request.IRequestProvider;
import appeng.api.networking.security.BaseActionSource;
import appeng.api.networking.ticking.IGridTickable;
@ -50,7 +51,9 @@ import appeng.api.util.IConfigManager;
import appeng.helpers.DualityInterface;
import appeng.helpers.IInterfaceHost;
import appeng.helpers.IPriorityHost;
import appeng.integration.IntegrationRegistry;
import appeng.integration.IntegrationType;
import appeng.integration.abstraction.ILogisticsPipes;
import appeng.me.GridAccessException;
import appeng.tile.TileEvent;
import appeng.tile.events.TileEventType;
@ -77,6 +80,12 @@ public class TileInterface extends AENetworkInvTile
IInventoryDestination, IInterfaceHost, IPriorityHost, IRequestProvider, ILogisticsPowerProvider {
private final DualityInterface duality = new DualityInterface(this.getProxy(), this);
private ForgeDirection pointAt = ForgeDirection.UNKNOWN;
private ILogisticsPipes logisticsPipes = null;
private TileEntity requestPipe = null;
private int ticksSinceRefresh = 0;
private Set<IAEItemStack> requestable = new HashSet<>();
private Set<IAEItemStack> prevRequestable = new HashSet<>();
@MENetworkEventSubscribe
public void stateChange(final MENetworkChannelsChanged c) {
@ -139,6 +148,10 @@ public class TileInterface extends AENetworkInvTile
this.getProxy().setValidSides(EnumSet.complementOf(EnumSet.of(this.pointAt)));
super.onReady();
this.duality.initialize();
if (IntegrationRegistry.INSTANCE.isEnabled(IntegrationType.LogisticsPipes)) {
logisticsPipes = (ILogisticsPipes) IntegrationRegistry.INSTANCE.getInstance(IntegrationType.LogisticsPipes);
refreshRequestPipe();
}
}
@TileEvent(TileEventType.WORLD_NBT_WRITE)
@ -300,13 +313,59 @@ public class TileInterface extends AENetworkInvTile
this.duality.setPriority(newValue);
}
@TileEvent(TileEventType.TICK)
public void tickEvent() {
if (logisticsPipes == null) return;
if (ticksSinceRefresh >= 10) {
refreshRequestable();
ticksSinceRefresh = 0;
}
ticksSinceRefresh++;
}
public void refreshRequestPipe() {
if (logisticsPipes != null) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
TileEntity te = worldObj.getTileEntity(this.xCoord + dir.offsetX, this.yCoord + dir.offsetY, this.zCoord + dir.offsetZ);
if (logisticsPipes.isRequestPipe(te)) {
if (requestPipe != te) {
requestPipe = te;
this.refreshRequestable();
}
return;
}
}
}
requestPipe = null;
this.refreshRequestable();
}
public void refreshRequestable() {
requestable.clear();
if (logisticsPipes != null && requestPipe != null) {
requestable.addAll(logisticsPipes.getRequestableItems(requestPipe));
}
if (!requestable.equals(prevRequestable)) { // TODO: post event when amount changes
prevRequestable.clear();
prevRequestable.addAll(requestable);
try {
this.getProxy().getGrid().postEvent(new MENetworkRequestableChange());
} catch (GridAccessException e) {
// :P
}
}
}
@Override
public Set<IAEItemStack> getRequestableItems() {
return new HashSet<>();
return requestable;
}
@Override
public IAEItemStack requestStack(IAEItemStack stack, Actionable actionable) {
if (logisticsPipes != null && requestPipe != null) {
return logisticsPipes.requestStack(requestPipe, stack, actionable);
}
return stack;
}