Search in sources :

Example 1 with TransporterStack

use of mekanism.common.content.transporter.TransporterStack in project Mekanism by mekanism.

the class RenderLogisticalTransporter method getReducedTransit.

/**
 * Shrink the in transit list as much as possible. Don't try to render things of the same type that are in the same spot with the same color, ignoring stack size
 */
private Collection<TransporterStack> getReducedTransit(Collection<TransporterStack> inTransit) {
    Collection<TransporterStack> reducedTransit = new ArrayList<>();
    Set<TransportInformation> information = new ObjectOpenHashSet<>();
    for (TransporterStack stack : inTransit) {
        if (stack != null && !stack.itemStack.isEmpty() && information.add(new TransportInformation(stack))) {
            // Ensure the stack is valid AND we did not already have information matching the stack
            // We use add to check if it already contained the value, so that we only have to query the set once
            reducedTransit.add(stack);
        }
    }
    return reducedTransit;
}
Also used : TransporterStack(mekanism.common.content.transporter.TransporterStack) ObjectOpenHashSet(it.unimi.dsi.fastutil.objects.ObjectOpenHashSet) ArrayList(java.util.ArrayList)

Example 2 with TransporterStack

use of mekanism.common.content.transporter.TransporterStack in project Mekanism by mekanism.

the class RenderLogisticalTransporter method render.

@Override
protected void render(TileEntityLogisticalTransporterBase tile, float partialTick, MatrixStack matrix, IRenderTypeBuffer renderer, int light, int overlayLight, IProfiler profiler) {
    LogisticalTransporterBase transporter = tile.getTransmitter();
    Collection<TransporterStack> inTransit = transporter.getTransit();
    BlockPos pos = tile.getBlockPos();
    if (!inTransit.isEmpty()) {
        matrix.pushPose();
        itemRenderer.init(tile.getLevel(), pos);
        float partial = partialTick * transporter.tier.getSpeed();
        Collection<TransporterStack> reducedTransit = getReducedTransit(inTransit);
        for (TransporterStack stack : reducedTransit) {
            float[] stackPos = TransporterUtils.getStackPosition(transporter, stack, partial);
            matrix.pushPose();
            matrix.translate(stackPos[0], stackPos[1], stackPos[2]);
            matrix.scale(0.75F, 0.75F, 0.75F);
            itemRenderer.renderAsStack(matrix, renderer, stack.itemStack);
            matrix.popPose();
            if (stack.color != null) {
                modelBox.render(matrix, renderer, MekanismRenderer.FULL_LIGHT, overlayLight, stackPos[0], stackPos[1], stackPos[2], stack.color);
            }
        }
        matrix.popPose();
    }
    if (transporter instanceof DiversionTransporter) {
        PlayerEntity player = Minecraft.getInstance().player;
        ItemStack itemStack = player.inventory.getSelected();
        if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemConfigurator) {
            BlockRayTraceResult rayTraceResult = MekanismUtils.rayTrace(player);
            if (!rayTraceResult.getType().equals(Type.MISS) && rayTraceResult.getBlockPos().equals(pos)) {
                Direction side = tile.getSideLookingAt(player, rayTraceResult.getDirection());
                matrix.pushPose();
                matrix.scale(0.5F, 0.5F, 0.5F);
                matrix.translate(0.5, 0.5, 0.5);
                MekanismRenderer.renderObject(getOverlayModel((DiversionTransporter) transporter, side), matrix, renderer.getBuffer(Atlases.translucentCullBlockSheet()), MekanismRenderer.getColorARGB(255, 255, 255, 0.8F), MekanismRenderer.FULL_LIGHT, overlayLight, FaceDisplay.FRONT);
                matrix.popPose();
            }
        }
    }
}
Also used : TransporterStack(mekanism.common.content.transporter.TransporterStack) ItemConfigurator(mekanism.common.item.ItemConfigurator) BlockPos(net.minecraft.util.math.BlockPos) BlockRayTraceResult(net.minecraft.util.math.BlockRayTraceResult) LogisticalTransporterBase(mekanism.common.content.network.transmitter.LogisticalTransporterBase) TileEntityLogisticalTransporterBase(mekanism.common.tile.transmitter.TileEntityLogisticalTransporterBase) DiversionTransporter(mekanism.common.content.network.transmitter.DiversionTransporter) ItemStack(net.minecraft.item.ItemStack) Direction(net.minecraft.util.Direction) PlayerEntity(net.minecraft.entity.player.PlayerEntity)

Example 3 with TransporterStack

use of mekanism.common.content.transporter.TransporterStack in project Mekanism by mekanism.

the class PacketTransporterUpdate method encode.

@Override
public void encode(PacketBuffer buffer) {
    buffer.writeBlockPos(pos);
    buffer.writeBoolean(isSync);
    buffer.writeBoolean(isDiversion);
    if (isSync) {
        // Sync
        buffer.writeVarInt(stackId);
        stack.write(transporter, buffer);
    } else {
        // Batch
        buffer.writeVarInt(updates.size());
        for (Int2ObjectMap.Entry<TransporterStack> entry : updates.int2ObjectEntrySet()) {
            buffer.writeVarInt(entry.getIntKey());
            entry.getValue().write(transporter, buffer);
        }
        buffer.writeVarInt(deletes.size());
        for (int toDelete : deletes) {
            buffer.writeVarInt(toDelete);
        }
    }
    if (isDiversion) {
        for (DiversionControl mode : modes) {
            buffer.writeEnum(mode);
        }
    }
}
Also used : TransporterStack(mekanism.common.content.transporter.TransporterStack) DiversionControl(mekanism.common.content.network.transmitter.DiversionTransporter.DiversionControl) Int2ObjectMap(it.unimi.dsi.fastutil.ints.Int2ObjectMap)

Example 4 with TransporterStack

use of mekanism.common.content.transporter.TransporterStack in project Mekanism by mekanism.

the class LogisticalTransporterBase method tick.

public void tick() {
    if (isRemote()) {
        for (TransporterStack stack : transit.values()) {
            stack.progress = Math.min(100, stack.progress + tier.getSpeed());
        }
    } else if (getTransmitterNetwork() != null) {
        // Pull items into the transporter
        if (delay > 0) {
            // If a delay has been imposed, wait a bit
            delay--;
        } else {
            // Reset delay to 3 ticks; if nothing is available to insert OR inserted, we'll try again in 3 ticks
            delay = 3;
            // Attempt to pull
            for (Direction side : getConnections(ConnectionType.PULL)) {
                TileEntity tile = WorldUtils.getTileEntity(getTileWorld(), getTilePos().relative(side));
                if (tile != null) {
                    TransitRequest request = TransitRequest.anyItem(tile, side.getOpposite(), tier.getPullAmount());
                    // There's a stack available to insert into the network...
                    if (!request.isEmpty()) {
                        TransitResponse response = insert(tile, request, getColor(), true, 0);
                        if (response.isEmpty()) {
                            // Insert failed; increment the backoff and calculate delay. Note that we cap retries
                            // at a max of 40 ticks (2 seconds), which would be 4 consecutive retries
                            delayCount++;
                            delay = Math.min(40, (int) Math.exp(delayCount));
                        } else {
                            // If the insert succeeded, remove the inserted count and try again for another 10 ticks
                            response.useAll();
                            delay = 10;
                        }
                    }
                }
            }
        }
        if (!transit.isEmpty()) {
            InventoryNetwork network = getTransmitterNetwork();
            // Update stack positions
            IntSet deletes = new IntOpenHashSet();
            // collection to occur actually causing the tick time to go up slightly.
            for (Int2ObjectMap.Entry<TransporterStack> entry : transit.int2ObjectEntrySet()) {
                int stackId = entry.getIntKey();
                TransporterStack stack = entry.getValue();
                if (!stack.initiatedPath) {
                    if (stack.itemStack.isEmpty() || !recalculate(stackId, stack, null)) {
                        deletes.add(stackId);
                        continue;
                    }
                }
                int prevProgress = stack.progress;
                stack.progress += tier.getSpeed();
                if (stack.progress >= 100) {
                    BlockPos prevSet = null;
                    if (stack.hasPath()) {
                        int currentIndex = stack.getPath().indexOf(getTilePos());
                        if (currentIndex == 0) {
                            // Necessary for transition reasons, not sure why
                            deletes.add(stackId);
                            continue;
                        }
                        BlockPos next = stack.getPath().get(currentIndex - 1);
                        if (next != null) {
                            if (!stack.isFinal(this)) {
                                LogisticalTransporterBase transmitter = network.getTransmitter(next);
                                if (stack.canInsertToTransporter(transmitter, stack.getSide(this), this)) {
                                    transmitter.entityEntering(stack, stack.progress % 100);
                                    deletes.add(stackId);
                                    continue;
                                }
                                prevSet = next;
                            } else if (stack.getPathType() != Path.NONE) {
                                TileEntity tile = WorldUtils.getTileEntity(getTileWorld(), next);
                                if (tile != null) {
                                    TransitResponse response = TransitRequest.simple(stack.itemStack).addToInventory(tile, stack.getSide(this), 0, stack.getPathType() == Path.HOME);
                                    if (!response.isEmpty()) {
                                        // We were able to add at least part of the stack to the inventory
                                        ItemStack rejected = response.getRejected();
                                        if (rejected.isEmpty()) {
                                            // Nothing was rejected (it was all accepted); remove the stack from the prediction
                                            // tracker and schedule this stack for deletion. Continue the loop thereafter
                                            TransporterManager.remove(getTileWorld(), stack);
                                            deletes.add(stackId);
                                            continue;
                                        }
                                        // Some portion of the stack got rejected; save the remainder and
                                        // let the recalculate below sort out what to do next
                                        stack.itemStack = rejected;
                                    }
                                    // else the entire stack got rejected (Note: we don't need to update the stack to point to itself)
                                    prevSet = next;
                                }
                            }
                        }
                    }
                    if (!recalculate(stackId, stack, prevSet)) {
                        deletes.add(stackId);
                    } else if (prevSet == null) {
                        stack.progress = 50;
                    } else {
                        stack.progress = 0;
                    }
                } else if (prevProgress < 50 && stack.progress >= 50) {
                    boolean tryRecalculate;
                    if (stack.isFinal(this)) {
                        Path pathType = stack.getPathType();
                        if (pathType == Path.DEST || pathType == Path.HOME) {
                            Direction side = stack.getSide(this);
                            ConnectionType connectionType = getConnectionType(side);
                            tryRecalculate = connectionType != ConnectionType.NORMAL && connectionType != ConnectionType.PUSH || !TransporterUtils.canInsert(WorldUtils.getTileEntity(getTileWorld(), stack.getDest()), stack.color, stack.itemStack, side, pathType == Path.HOME);
                        } else {
                            tryRecalculate = pathType == Path.NONE;
                        }
                    } else {
                        LogisticalTransporterBase nextTransmitter = network.getTransmitter(stack.getNext(this));
                        if (nextTransmitter == null && stack.getPathType() == Path.NONE && stack.getPath().size() == 2) {
                            // If there is no next transmitter, and it was an idle path, assume that we are idling
                            // in a single length transmitter, in which case we only recalculate it at 50 if it won't
                            // be able to go into that connection type
                            ConnectionType connectionType = getConnectionType(stack.getSide(this));
                            tryRecalculate = connectionType != ConnectionType.NORMAL && connectionType != ConnectionType.PUSH;
                        } else {
                            tryRecalculate = !stack.canInsertToTransporter(nextTransmitter, stack.getSide(this), this);
                        }
                    }
                    if (tryRecalculate && !recalculate(stackId, stack, null)) {
                        deletes.add(stackId);
                    }
                }
            }
            if (!deletes.isEmpty() || !needsSync.isEmpty()) {
                // Notify clients, so that we send the information before we start clearing our lists
                Mekanism.packetHandler.sendToAllTracking(new PacketTransporterUpdate(this, needsSync, deletes), getTransmitterTile());
                // Now remove any entries from transit that have been deleted
                deletes.forEach((IntConsumer) (this::deleteStack));
                // Clear the pending sync packets
                needsSync.clear();
                // Finally, mark chunk for save
                WorldUtils.saveChunk(getTransmitterTile());
            }
        }
    }
}
Also used : Path(mekanism.common.content.transporter.TransporterStack.Path) ConnectionType(mekanism.common.lib.transmitter.ConnectionType) IntSet(it.unimi.dsi.fastutil.ints.IntSet) Direction(net.minecraft.util.Direction) TransitRequest(mekanism.common.lib.inventory.TransitRequest) InventoryNetwork(mekanism.common.content.network.InventoryNetwork) IntConsumer(java.util.function.IntConsumer) TileEntity(net.minecraft.tileentity.TileEntity) IntOpenHashSet(it.unimi.dsi.fastutil.ints.IntOpenHashSet) TransporterStack(mekanism.common.content.transporter.TransporterStack) PacketTransporterUpdate(mekanism.common.network.to_client.PacketTransporterUpdate) TransitResponse(mekanism.common.lib.inventory.TransitRequest.TransitResponse) BlockPos(net.minecraft.util.math.BlockPos) ItemStack(net.minecraft.item.ItemStack)

Example 5 with TransporterStack

use of mekanism.common.content.transporter.TransporterStack in project Mekanism by mekanism.

the class LogisticalTransporterBase method insert.

private TransitResponse insert(TileEntity outputter, TransitRequest request, EnumColor color, boolean doEmit, Function<TransporterStack, TransitResponse> pathCalculator) {
    BlockPos outputterPos = outputter.getBlockPos();
    Direction from = WorldUtils.sideDifference(getTilePos(), outputterPos);
    if (from != null && canReceiveFrom(from.getOpposite())) {
        TransporterStack stack = insertStack(outputterPos, color);
        if (stack.canInsertToTransporterNN(this, from, outputter)) {
            return updateTransit(doEmit, stack, pathCalculator.apply(stack));
        }
    }
    return request.getEmptyResponse();
}
Also used : TransporterStack(mekanism.common.content.transporter.TransporterStack) BlockPos(net.minecraft.util.math.BlockPos) Direction(net.minecraft.util.Direction)

Aggregations

TransporterStack (mekanism.common.content.transporter.TransporterStack)9 CompoundNBT (net.minecraft.nbt.CompoundNBT)3 ListNBT (net.minecraft.nbt.ListNBT)3 Direction (net.minecraft.util.Direction)3 BlockPos (net.minecraft.util.math.BlockPos)3 Int2ObjectMap (it.unimi.dsi.fastutil.ints.Int2ObjectMap)2 ItemStack (net.minecraft.item.ItemStack)2 IntOpenHashSet (it.unimi.dsi.fastutil.ints.IntOpenHashSet)1 IntSet (it.unimi.dsi.fastutil.ints.IntSet)1 ObjectOpenHashSet (it.unimi.dsi.fastutil.objects.ObjectOpenHashSet)1 ArrayList (java.util.ArrayList)1 IntConsumer (java.util.function.IntConsumer)1 Nonnull (javax.annotation.Nonnull)1 InventoryNetwork (mekanism.common.content.network.InventoryNetwork)1 DiversionTransporter (mekanism.common.content.network.transmitter.DiversionTransporter)1 DiversionControl (mekanism.common.content.network.transmitter.DiversionTransporter.DiversionControl)1 LogisticalTransporterBase (mekanism.common.content.network.transmitter.LogisticalTransporterBase)1 Path (mekanism.common.content.transporter.TransporterStack.Path)1 ItemConfigurator (mekanism.common.item.ItemConfigurator)1 TransitRequest (mekanism.common.lib.inventory.TransitRequest)1