use of logisticspipes.routing.IRouter in project LogisticsPipes by RS485.
the class RequestTreeNode method getProviders.
private static List<Pair<IProvide, List<IFilter>>> getProviders(IRouter destination, IResource item) {
// get all the routers
BitSet routersIndex = ServerRouter.getRoutersInterestedIn(item);
// get the routing table
List<ExitRoute> validSources = new ArrayList<>();
for (int i = routersIndex.nextSetBit(0); i >= 0; i = routersIndex.nextSetBit(i + 1)) {
IRouter r = SimpleServiceLocator.routerManager.getServerRouter(i);
if (r.isCacheInvalid()) {
// Skip Routers without a valid pipe
continue;
}
List<ExitRoute> e = destination.getDistanceTo(r);
if (e != null) {
validSources.addAll(e);
}
}
// closer providers are good
validSources.sort(new workWeightedSorter(1.0));
List<Pair<IProvide, List<IFilter>>> providers = new LinkedList<>();
validSources.stream().filter(r -> r.containsFlag(PipeRoutingConnectionType.canRequestFrom)).forEach(r -> {
CoreRoutedPipe pipe = r.destination.getPipe();
if (pipe instanceof IProvide) {
List<IFilter> list = new LinkedList<>(r.filters);
providers.add(new Pair<>((IProvide) pipe, list));
}
});
return providers;
}
use of logisticspipes.routing.IRouter in project LogisticsPipes by RS485.
the class RequestTreeNode method checkCrafting.
private boolean checkCrafting() {
// get all the routers
BitSet routersIndex = ServerRouter.getRoutersInterestedIn(getRequestType());
// get the routing table
List<ExitRoute> validSources = new ArrayList<>();
for (int i = routersIndex.nextSetBit(0); i >= 0; i = routersIndex.nextSetBit(i + 1)) {
IRouter r = SimpleServiceLocator.routerManager.getServerRouter(i);
if (r.isCacheInvalid()) {
// Skip Routers without a valid pipe
continue;
}
List<ExitRoute> e = getRequestType().getRouter().getDistanceTo(r);
if (e != null) {
validSources.addAll(e);
}
}
// distance doesn't matter, because ingredients have to be delivered to the crafter, and we can't tell how long that will take.
workWeightedSorter wSorter = new workWeightedSorter(0);
Collections.sort(validSources, wSorter);
List<Pair<ICraftingTemplate, List<IFilter>>> allCraftersForItem = RequestTreeNode.getCrafters(getRequestType(), validSources);
// if you have a crafter which can make the top treeNode.getStack().getItem()
Iterator<Pair<ICraftingTemplate, List<IFilter>>> iterAllCrafters = allCraftersForItem.iterator();
// a queue to store the crafters, sorted by todo; we will fill up from least-most in a balanced way.
PriorityQueue<CraftingSorterNode> craftersSamePriority = new PriorityQueue<>(5);
ArrayList<CraftingSorterNode> craftersToBalance = new ArrayList<>();
// TODO ^ Make this a generic list
boolean done = false;
Pair<ICraftingTemplate, List<IFilter>> lastCrafter = null;
int currentPriority = 0;
outer: while (!done) {
// / First: Create a list of all crafters with the same priority (craftersSamePriority).
if (iterAllCrafters.hasNext()) {
if (lastCrafter == null) {
lastCrafter = iterAllCrafters.next();
}
} else if (lastCrafter == null) {
done = true;
}
int itemsNeeded = getMissingAmount();
if (lastCrafter != null && (craftersSamePriority.isEmpty() || (currentPriority == lastCrafter.getValue1().getPriority()))) {
currentPriority = lastCrafter.getValue1().getPriority();
Pair<ICraftingTemplate, List<IFilter>> crafter = lastCrafter;
lastCrafter = null;
ICraftingTemplate template = crafter.getValue1();
if (isCrafterUsed(template)) {
continue;
}
if (!template.canCraft(getRequestType())) {
// we this is crafting something else
continue;
}
for (IFilter filter : crafter.getValue2()) {
// is this filtered for some reason.
if (filter.isBlocked() == filter.isFilteredItem(template.getResultItem()) || filter.blockCrafting()) {
continue outer;
}
}
CraftingSorterNode cn = new CraftingSorterNode(crafter, itemsNeeded, root, this);
// if(cn.getWorkSetsAvailableForCrafting()>0)
craftersSamePriority.add(cn);
continue;
}
if (craftersToBalance.isEmpty() && (craftersSamePriority == null || craftersSamePriority.isEmpty())) {
// nothing at this priority was available for crafting
continue;
}
if (craftersSamePriority.size() == 1) {
// then no need to balance.
craftersToBalance.add(craftersSamePriority.poll());
// automatically capped at the real amount of extra work.
craftersToBalance.get(0).addToWorkRequest(itemsNeeded);
} else {
// or the amount of work they have is equal to the next-least busy crafter. then pull the next crafter and repeat.
if (!craftersSamePriority.isEmpty()) {
craftersToBalance.add(craftersSamePriority.poll());
}
// while we crafters that can work and we have work to do.
while (!craftersToBalance.isEmpty() && itemsNeeded > 0) {
// typically pulls 1 at a time, but may pull multiple, if they have the exact same todo.
while (!craftersSamePriority.isEmpty() && craftersSamePriority.peek().currentToDo() <= craftersToBalance.get(0).currentToDo()) {
craftersToBalance.add(craftersSamePriority.poll());
}
// find the most we can add this iteration
int cap;
if (!craftersSamePriority.isEmpty()) {
cap = craftersSamePriority.peek().currentToDo();
} else {
cap = Integer.MAX_VALUE;
}
// split the work between N crafters, up to "cap" (at which point we would be dividing the work between N+1 crafters.
int floor = craftersToBalance.get(0).currentToDo();
cap = Math.min(cap, floor + (itemsNeeded + craftersToBalance.size() - 1) / craftersToBalance.size());
for (CraftingSorterNode crafter : craftersToBalance) {
int request = Math.min(itemsNeeded, cap - floor);
if (request > 0) {
int craftingDone = crafter.addToWorkRequest(request);
// ignored under-crafting
itemsNeeded -= craftingDone;
}
}
}
// all craftersToBalance exhausted, or work completed.
}
// end of else more than 1 crafter at this priority
// commit this work set.
Iterator<CraftingSorterNode> iter = craftersToBalance.iterator();
while (iter.hasNext()) {
CraftingSorterNode c = iter.next();
if (c.stacksOfWorkRequested > 0 && !c.addWorkPromisesToTree()) {
// then it ran out of resources
iter.remove();
}
}
itemsNeeded = getMissingAmount();
if (itemsNeeded <= 0) {
// we have everything we need for this crafting request
break;
}
// don't clear, because we might have under-requested, and need to consider these again
if (!craftersToBalance.isEmpty()) {
done = false;
// craftersSamePriority.clear(); // we've extracted all we can from these priority crafters, and we still have more to do, back to the top to get the next priority level.
}
}
// LogisticsPipes.log.info("done");
return isDone();
}
use of logisticspipes.routing.IRouter in project LogisticsPipes by RS485.
the class DebugController method handledPipe.
public void handledPipe(boolean flag) {
for (int i = 0; i < closedSet.size(); i++) {
EnumSet<PipeRoutingConnectionType> set = closedSet.get(i);
if (set != null) {
IRouter router = SimpleServiceLocator.routerManager.getRouter(i);
if (router != null) {
MainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugClosedSet.class).setPos(router.getLPPosition()).setSet(set), (EntityPlayer) sender);
}
}
}
for (int i = 0; i < filterList.size(); i++) {
EnumMap<PipeRoutingConnectionType, List<List<IFilter>>> filters = filterList.get(i);
if (filters != null) {
IRouter router = SimpleServiceLocator.routerManager.getRouter(i);
if (router != null) {
MainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugFilters.class).setPos(router.getLPPosition()).setFilters(filters), (EntityPlayer) sender);
}
}
}
LinkedList<ExitRoute> exitRoutes = new LinkedList<>(candidatesCost);
if (flag) {
exitRoutes.addFirst(nextNode);
}
MainProxy.sendPacketToPlayer(PacketHandler.getPacket(RoutingUpdateDebugCanidateList.class).setExitRoutes(exitRoutes), (EntityPlayer) sender);
if (prevNode == null || prevNode.debug.isTraced) {
// Display Information On Client Side
wait("Continue with next pipe?", false);
}
pipeHandled = true;
}
use of logisticspipes.routing.IRouter in project LogisticsPipes by RS485.
the class HudUpdateTick method tick.
public static void tick() {
if (HudUpdateTick.firstRouter == -1) {
return;
}
int slotSentCount = 0;
// cork the compressor
SimpleServiceLocator.serverBufferHandler.setPause(true);
while (HudUpdateTick.firstRouter != -1 && slotSentCount < HudUpdateTick.inventorySlotsToUpdatePerTick) {
HudUpdateTick.routersNeedingUpdate.clear(HudUpdateTick.firstRouter);
IRouter currentRouter = SimpleServiceLocator.routerManager.getServerRouter(HudUpdateTick.firstRouter);
if (currentRouter != null) {
CoreRoutedPipe pipe = currentRouter.getCachedPipe();
if (pipe != null) {
slotSentCount += pipe.sendQueueChanged(true);
}
}
HudUpdateTick.firstRouter = HudUpdateTick.routersNeedingUpdate.nextSetBit(HudUpdateTick.firstRouter);
}
// and let it compress and send
SimpleServiceLocator.serverBufferHandler.setPause(false);
}
use of logisticspipes.routing.IRouter in project LogisticsPipes by RS485.
the class ModuleProvider method sendStack.
// returns -1 on permanently failed, don't try another stack this tick
// returns 0 on "unable to do this delivery"
public int sendStack(ItemIdentifierStack stack, int maxCount, int destination, IAdditionalTargetInformation info) {
final IPipeServiceProvider service = _service;
if (service == null)
return -1;
ItemIdentifier item = stack.getItem();
Iterator<Pair<IInventoryUtil, EnumFacing>> iterator = service.getAvailableAdjacent().inventories().stream().flatMap(neighbor -> {
final IInventoryUtil invUtil = getInventoryUtilWithMode(neighbor);
if (invUtil == null)
return Stream.empty();
return Stream.of(new Pair<>(invUtil, neighbor.getDirection()));
}).iterator();
while (iterator.hasNext()) {
final Pair<IInventoryUtil, EnumFacing> current = iterator.next();
int available = current.getValue1().itemCount(item);
if (available == 0) {
continue;
}
int wanted = Math.min(available, stack.getStackSize());
wanted = Math.min(wanted, maxCount);
wanted = Math.min(wanted, item.getMaxStackSize());
IRouter dRtr = SimpleServiceLocator.routerManager.getServerRouter(destination);
if (dRtr == null) {
service.getItemOrderManager().sendFailed();
return 0;
}
SinkReply reply = LogisticsManager.canSink(stack.makeNormalStack(), dRtr, null, true, stack.getItem(), null, true, false);
boolean defersend = false;
if (reply != null) {
// some pipes are not aware of the space in the adjacent inventory, so they return null
if (reply.maxNumberOfItems < wanted) {
wanted = reply.maxNumberOfItems;
if (wanted <= 0) {
service.getItemOrderManager().deferSend();
return 0;
}
defersend = true;
}
}
if (!service.canUseEnergy(wanted * neededEnergy())) {
return -1;
}
ItemStack removed = current.getValue1().getMultipleItems(item, wanted);
if (removed.isEmpty()) {
continue;
}
int sent = removed.getCount();
service.useEnergy(sent * neededEnergy());
final IRoutedItem routedItem = service.sendStack(removed, destination, itemSendMode(), info, current.getValue2());
service.getItemOrderManager().sendSuccessfull(sent, defersend, routedItem);
return sent;
}
service.getItemOrderManager().sendFailed();
return 0;
}
Aggregations