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;
}
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();
}
}
}
}
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);
}
}
}
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());
}
}
}
}
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();
}
Aggregations