mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
Merge branch 'HbmMods:master' into METADATA
This commit is contained in:
commit
52440fca2f
@ -6,6 +6,7 @@ import java.nio.file.StandardCopyOption
|
|||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
|
maven { url = 'https://maven.ntmr.dev/proxy/' }
|
||||||
maven { url = 'https://maven.minecraftforge.net/' }
|
maven { url = 'https://maven.minecraftforge.net/' }
|
||||||
maven { url = 'https://plugins.gradle.org/m2' }
|
maven { url = 'https://plugins.gradle.org/m2' }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -67,6 +68,10 @@ eclipse.classpath.file.whenMerged { cp ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
maven {
|
||||||
|
name = 'Blerg'
|
||||||
|
url = 'https://maven.ntmr.dev/proxy/'
|
||||||
|
}
|
||||||
maven {
|
maven {
|
||||||
name = 'ModMaven'
|
name = 'ModMaven'
|
||||||
url = 'https://modmaven.dev'
|
url = 'https://modmaven.dev'
|
||||||
|
|||||||
@ -25,4 +25,5 @@
|
|||||||
* Fixed crash caused by the balefire bomb
|
* Fixed crash caused by the balefire bomb
|
||||||
* Fixed JSON gun reload animations becoming faster and faster with the trenchmaster set
|
* Fixed JSON gun reload animations becoming faster and faster with the trenchmaster set
|
||||||
* Fixed heat transfer rate labels on the boilers and coker unit being off by a magnitude of 10
|
* Fixed heat transfer rate labels on the boilers and coker unit being off by a magnitude of 10
|
||||||
* Fixed crucible not having a heat transfer rate tooltip
|
* Fixed crucible not having a heat transfer rate tooltip
|
||||||
|
* Fixed certain heliostat mirror rotations not showing the mirror
|
||||||
@ -1,23 +1,29 @@
|
|||||||
package com.hbm.inventory.gui;
|
package com.hbm.inventory.gui;
|
||||||
|
|
||||||
import com.hbm.lib.RefStrings;
|
import com.hbm.util.Tuple;
|
||||||
|
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
import net.minecraft.client.gui.GuiTextField;
|
import net.minecraft.client.gui.GuiTextField;
|
||||||
import net.minecraft.util.ResourceLocation;
|
|
||||||
import org.lwjgl.input.Keyboard;
|
import org.lwjgl.input.Keyboard;
|
||||||
import org.lwjgl.opengl.GL11;
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.MathContext;
|
import java.math.MathContext;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
public class GUICalculator extends GuiScreen {
|
public class GUICalculator extends GuiScreen {
|
||||||
private static final ResourceLocation texture = new ResourceLocation(RefStrings.MODID, "textures/gui/calculator.png");
|
|
||||||
private int xSize = 220;
|
private int xSize = 220;
|
||||||
private int ySize = 50;
|
private int ySize = 50;
|
||||||
|
private int borderWidth = 2;
|
||||||
private GuiTextField inputField;
|
private GuiTextField inputField;
|
||||||
|
|
||||||
|
private int selectedHist = -1;
|
||||||
|
private static final int maxHistory = 6;
|
||||||
|
private static Deque<Tuple.Pair<String, Double>> history = new ArrayDeque<>();
|
||||||
private String latestResult = "?";
|
private String latestResult = "?";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -46,15 +52,31 @@ public class GUICalculator extends GuiScreen {
|
|||||||
String input = inputField.getText().replaceAll("[^\\d+\\-*/^!.()\\sA-Za-z]+", "");
|
String input = inputField.getText().replaceAll("[^\\d+\\-*/^!.()\\sA-Za-z]+", "");
|
||||||
|
|
||||||
if (p_73869_1_ == 13 || p_73869_1_ == 10) { // when pressing enter (CR or LF)
|
if (p_73869_1_ == 13 || p_73869_1_ == 10) { // when pressing enter (CR or LF)
|
||||||
try {
|
if (selectedHist != -1) {
|
||||||
double result = evaluateExpression(input);
|
input = new ArrayList<>(history).get(selectedHist).key;
|
||||||
String plainStringRepresentation = (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString();
|
inputField.setText(input);
|
||||||
GuiScreen.setClipboardString(plainStringRepresentation);
|
selectedHist = -1;
|
||||||
inputField.setText(plainStringRepresentation);
|
} else {
|
||||||
inputField.setCursorPositionEnd();
|
try {
|
||||||
inputField.setSelectionPos(0);
|
double result = evaluateExpression(input);
|
||||||
} catch (Exception ignored) {}
|
history.addFirst(new Tuple.Pair<String,Double>(input, result));
|
||||||
return;
|
if (history.size() > maxHistory) history.removeLast();
|
||||||
|
String plainStringRepresentation = (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString();
|
||||||
|
GuiScreen.setClipboardString(plainStringRepresentation);
|
||||||
|
inputField.setText(plainStringRepresentation);
|
||||||
|
inputField.setCursorPositionEnd();
|
||||||
|
inputField.setSelectionPos(0);
|
||||||
|
} catch (Exception ignored) {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_73869_2_ == 200) { // up arrow
|
||||||
|
selectedHist = Math.max(selectedHist - 1, -1);
|
||||||
|
} else if (p_73869_2_ == 208) { // down arrow
|
||||||
|
selectedHist = Math.min(selectedHist + 1, history.size() - 1);
|
||||||
|
} else {
|
||||||
|
selectedHist = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input.isEmpty()) {
|
if (input.isEmpty()) {
|
||||||
@ -72,14 +94,27 @@ public class GUICalculator extends GuiScreen {
|
|||||||
super.drawScreen(mouseX, mouseY, partialTicks);
|
super.drawScreen(mouseX, mouseY, partialTicks);
|
||||||
|
|
||||||
GL11.glColor4f(1F, 1F, 1F, 1F);
|
GL11.glColor4f(1F, 1F, 1F, 1F);
|
||||||
mc.getTextureManager().bindTexture(texture);
|
|
||||||
int x = (width - xSize) / 2;
|
int x = (width - xSize) / 2;
|
||||||
int y = (height - ySize) / 2;
|
int y = (height - ySize) / 2;
|
||||||
|
int histHeight = (fontRendererObj.FONT_HEIGHT + 2) * maxHistory;
|
||||||
|
int histStart = y + 30 + fontRendererObj.FONT_HEIGHT + 8;
|
||||||
|
|
||||||
drawTexturedModalRect(x, y, 0, 0, xSize, ySize);
|
drawRect(x, y, x+xSize, y+ySize+histHeight, 0xFF2d2d2d);
|
||||||
|
drawRect(x+borderWidth, y+borderWidth, x+xSize-borderWidth, y+ySize-borderWidth+histHeight, 0xFF3d3d3d);
|
||||||
|
drawRect(x, histStart - 5, x+xSize, histStart - 3, 0xFF2d2d2d);
|
||||||
|
|
||||||
inputField.drawTextBox();
|
inputField.drawTextBox();
|
||||||
fontRendererObj.drawString("=" + latestResult, x + 5, y + 30, -1);
|
fontRendererObj.drawString("=" + latestResult, x + 5, y + 30, -1);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Tuple.Pair<String, Double> prevInput : history) {
|
||||||
|
int hy = y + 50 + (fontRendererObj.FONT_HEIGHT+1)*i;
|
||||||
|
if (i == selectedHist) {
|
||||||
|
drawRect(x + 4, hy - 1, x + 4 + xSize - 9, hy + fontRendererObj.FONT_HEIGHT, 0xFF111111);
|
||||||
|
}
|
||||||
|
fontRendererObj.drawString(prevInput.key + " = " + prevInput.value, x + 5, hy, -1);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -66,17 +66,15 @@ public class RenderMirror implements ISimpleBlockRenderingHandler {
|
|||||||
GroupObject go = null;
|
GroupObject go = null;
|
||||||
|
|
||||||
for(GroupObject obj : ((WavefrontObject)ResourceManager.solar_mirror).groupObjects) {
|
for(GroupObject obj : ((WavefrontObject)ResourceManager.solar_mirror).groupObjects) {
|
||||||
if(obj.name.equals("Mirror"))
|
if(obj.name.equals("Mirror")) go = obj;
|
||||||
go = obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(go == null)
|
if(go == null) return;
|
||||||
return;
|
|
||||||
|
|
||||||
Tessellator tes = Tessellator.instance;
|
Tessellator tes = Tessellator.instance;
|
||||||
|
|
||||||
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
double dist = Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||||
double pitch = -Math.asin((dy + 0.5) / dist) + Math.PI / 2D;
|
double pitch = -Math.asin(dy / dist) + Math.PI / 2D;
|
||||||
double yaw = -Math.atan2(dz, dx) - Math.PI / 2D;
|
double yaw = -Math.atan2(dz, dx) - Math.PI / 2D;
|
||||||
|
|
||||||
for(Face f : go.faces) {
|
for(Face f : go.faces) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package com.hbm.uninos.networkproviders;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -34,11 +35,11 @@ public class PneumaticNetwork extends NodeNet {
|
|||||||
|
|
||||||
protected static final int timeout = 1_000;
|
protected static final int timeout = 1_000;
|
||||||
public static final int ITEMS_PER_TRANSFER = 64;
|
public static final int ITEMS_PER_TRANSFER = 64;
|
||||||
|
|
||||||
// while the system has parts that expects IInventires to be TileEntities to work properly (mostly range checks),
|
// while the system has parts that expects IInventires to be TileEntities to work properly (mostly range checks),
|
||||||
// it can actually handle non-TileEntities just fine.
|
// it can actually handle non-TileEntities just fine.
|
||||||
public HashMap<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>> receivers = new HashMap();
|
public HashMap<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>> receivers = new HashMap();
|
||||||
|
|
||||||
public void addReceiver(IInventory inventory, ForgeDirection pipeDir, TileEntityPneumoTube endpoint) {
|
public void addReceiver(IInventory inventory, ForgeDirection pipeDir, TileEntityPneumoTube endpoint) {
|
||||||
receivers.put(inventory, new Triplet(pipeDir, System.currentTimeMillis(), endpoint));
|
receivers.put(inventory, new Triplet(pipeDir, System.currentTimeMillis(), endpoint));
|
||||||
}
|
}
|
||||||
@ -51,7 +52,7 @@ public class PneumaticNetwork extends NodeNet {
|
|||||||
long timestamp = System.currentTimeMillis();
|
long timestamp = System.currentTimeMillis();
|
||||||
receivers.entrySet().removeIf(x -> { return (timestamp - x.getValue().getY() > timeout) || NodeNet.isBadLink(x.getKey()); });
|
receivers.entrySet().removeIf(x -> { return (timestamp - x.getValue().getY() > timeout) || NodeNet.isBadLink(x.getKey()); });
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean send(IInventory source, TileEntityPneumoTube tube, ForgeDirection accessDir, int sendOrder, int receiveOrder, int maxRange, int nextReceiver) {
|
public boolean send(IInventory source, TileEntityPneumoTube tube, ForgeDirection accessDir, int sendOrder, int receiveOrder, int maxRange, int nextReceiver) {
|
||||||
|
|
||||||
// turns out there may be a short time window where the cleanup hasn't happened yet, but chunkloading has already caused tiles to go invalid
|
// turns out there may be a short time window where the cleanup hasn't happened yet, but chunkloading has already caused tiles to go invalid
|
||||||
@ -67,114 +68,144 @@ public class PneumaticNetwork extends NodeNet {
|
|||||||
if(sendOrder == SEND_LAST) BobMathUtil.reverseIntArray(sourceSlotAccess);
|
if(sendOrder == SEND_LAST) BobMathUtil.reverseIntArray(sourceSlotAccess);
|
||||||
if(sendOrder == SEND_RANDOM) BobMathUtil.shuffleIntArray(sourceSlotAccess);
|
if(sendOrder == SEND_RANDOM) BobMathUtil.shuffleIntArray(sourceSlotAccess);
|
||||||
|
|
||||||
|
ISidedInventory sidedSource = source instanceof ISidedInventory ? (ISidedInventory) source : null;
|
||||||
|
boolean hasItem = false;
|
||||||
|
|
||||||
|
for(int i : sourceSlotAccess) {
|
||||||
|
ItemStack stack = source.getStackInSlot(i);
|
||||||
|
if(stack != null) {
|
||||||
|
if(sidedSource != null && !sidedSource.canExtractItem(i, stack, sourceSide)) continue;
|
||||||
|
boolean match = tube.matchesFilter(stack);
|
||||||
|
if((match && !tube.whitelist) || (!match && tube.whitelist)) continue;
|
||||||
|
hasItem = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return early if there arent any items in the source inventory, saves on some cpu usage for idle networks
|
||||||
|
if(!hasItem) return false;
|
||||||
|
|
||||||
// for round robin, receivers are ordered by proximity to the source
|
// for round robin, receivers are ordered by proximity to the source
|
||||||
ReceiverComparator comparator = new ReceiverComparator(tube);
|
ReceiverComparator comparator = new ReceiverComparator(tube);
|
||||||
List<Entry<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>>> receiverList = new ArrayList(receivers.size());
|
List<Entry<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>>> receiverList = new ArrayList(receivers.size());
|
||||||
receiverList.addAll(receivers.entrySet());
|
receiverList.addAll(receivers.entrySet());
|
||||||
receiverList.sort(comparator);
|
|
||||||
|
|
||||||
int index = nextReceiver % receivers.size();
|
|
||||||
Entry<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>> chosenReceiverEntry = null;
|
|
||||||
|
|
||||||
if(receiveOrder == RECEIVE_ROBIN) chosenReceiverEntry = receiverList.get(index);
|
if(receiveOrder == RECEIVE_ROBIN) receiverList.sort(comparator);
|
||||||
if(receiveOrder == RECEIVE_RANDOM) chosenReceiverEntry = receiverList.get(rand.nextInt(receiverList.size()));
|
if(receiveOrder == RECEIVE_RANDOM) Collections.shuffle(receiverList);
|
||||||
|
|
||||||
if(chosenReceiverEntry == null) return false;
|
|
||||||
|
|
||||||
IInventory dest = chosenReceiverEntry.getKey();
|
|
||||||
TileEntityPneumoTube endpointTile = chosenReceiverEntry.getValue().getZ();
|
|
||||||
ISidedInventory sidedDest = dest instanceof ISidedInventory ? (ISidedInventory) dest : null;
|
|
||||||
ISidedInventory sidedSource = source instanceof ISidedInventory ? (ISidedInventory) source : null;
|
|
||||||
|
|
||||||
TileEntity tile1 = source instanceof TileEntity ? (TileEntity) source : null;
|
TileEntity tile1 = source instanceof TileEntity ? (TileEntity) source : null;
|
||||||
TileEntity tile2 = dest instanceof TileEntity ? (TileEntity) dest : null;
|
|
||||||
|
|
||||||
// range check for our compression level, skip if either source or dest aren't tile entities
|
|
||||||
if(tile1 != null && tile2 != null) {
|
|
||||||
int sq = (tile1.xCoord - tile2.xCoord) * (tile1.xCoord - tile2.xCoord) + (tile1.yCoord - tile2.yCoord) * (tile1.yCoord - tile2.yCoord) + (tile1.zCoord - tile2.zCoord) * (tile1.zCoord - tile2.zCoord);
|
|
||||||
if(sq > maxRange * maxRange) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int destSide = chosenReceiverEntry.getValue().getX().getOpposite().ordinal();
|
|
||||||
int[] destSlotAccess = getSlotAccess(dest, destSide);
|
|
||||||
int itemsLeftToSend = ITEMS_PER_TRANSFER; // not actually individual items, but rather the total "mass", based on max stack size
|
|
||||||
int itemHardCap = dest instanceof TileEntityMachineAutocrafter ? 1 : ITEMS_PER_TRANSFER;
|
|
||||||
boolean didSomething = false;
|
|
||||||
|
|
||||||
for(int sourceIndex : sourceSlotAccess) {
|
|
||||||
ItemStack sourceStack = source.getStackInSlot(sourceIndex);
|
|
||||||
if(sourceStack == null) continue;
|
|
||||||
if(sidedSource != null && !sidedSource.canExtractItem(sourceIndex, sourceStack, sourceSide)) continue;
|
|
||||||
// filter of the source
|
|
||||||
boolean match = tube.matchesFilter(sourceStack);
|
|
||||||
if((match && !tube.whitelist) || (!match && tube.whitelist)) continue;
|
|
||||||
// filter of the receiver, only if the sender and receiver aren't the same block
|
|
||||||
if(endpointTile != null && endpointTile != tube) {
|
|
||||||
match = endpointTile.matchesFilter(sourceStack);
|
|
||||||
if((match && !endpointTile.whitelist) || (!match && endpointTile.whitelist)) continue;
|
|
||||||
}
|
|
||||||
// the "mass" of an item. something that only stacks to 4 has a "mass" of 16. max transfer mass is 64, i.e. one standard stack, or one single unstackable item
|
|
||||||
int proportionalValue = MathHelper.clamp_int(64 / sourceStack.getMaxStackSize(), 1, 64);
|
|
||||||
|
|
||||||
// try to fill partial stacks first
|
|
||||||
for(int destIndex : destSlotAccess) {
|
|
||||||
ItemStack destStack = dest.getStackInSlot(destIndex);
|
|
||||||
if(destStack == null) continue;
|
|
||||||
if(!ItemStackUtil.areStacksCompatible(sourceStack, destStack)) continue;
|
|
||||||
int toMove = BobMathUtil.min(sourceStack.stackSize, destStack.getMaxStackSize() - destStack.stackSize, dest.getInventoryStackLimit() - destStack.stackSize, itemsLeftToSend / proportionalValue, itemHardCap);
|
|
||||||
if(toMove <= 0) continue;
|
|
||||||
|
|
||||||
ItemStack checkStack = destStack.copy();
|
|
||||||
checkStack.stackSize += toMove;
|
|
||||||
if(!dest.isItemValidForSlot(destIndex, checkStack)) continue;
|
|
||||||
if(sidedDest != null && !sidedDest.canInsertItem(destIndex, checkStack, destSide)) continue;
|
|
||||||
|
|
||||||
sourceStack.stackSize -= toMove;
|
|
||||||
if(sourceStack.stackSize <= 0) source.setInventorySlotContents(sourceIndex, null);
|
|
||||||
destStack.stackSize += toMove;
|
|
||||||
itemsLeftToSend -= toMove * proportionalValue;
|
|
||||||
didSomething = true;
|
|
||||||
if(itemsLeftToSend <= 0) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if there's stuff left to send, occupy empty slots
|
|
||||||
if(itemsLeftToSend > 0 && sourceStack.stackSize > 0) for(int destIndex : destSlotAccess) {
|
|
||||||
if(dest.getStackInSlot(destIndex) != null) continue;
|
|
||||||
int toMove = BobMathUtil.min(sourceStack.stackSize, dest.getInventoryStackLimit(), itemsLeftToSend / proportionalValue, itemHardCap);
|
|
||||||
if(toMove <= 0) continue;
|
|
||||||
|
|
||||||
ItemStack checkStack = sourceStack.copy();
|
|
||||||
checkStack.stackSize = toMove;
|
|
||||||
if(!dest.isItemValidForSlot(destIndex, checkStack)) continue;
|
|
||||||
if(sidedDest != null && !sidedDest.canInsertItem(destIndex, checkStack, destSide)) continue;
|
|
||||||
|
|
||||||
ItemStack newStack = sourceStack.copy();
|
int attempts = 0;
|
||||||
newStack.stackSize = toMove;
|
int maxAttempts = receiverList.size();
|
||||||
sourceStack.stackSize -= toMove;
|
|
||||||
if(sourceStack.stackSize <= 0) source.setInventorySlotContents(sourceIndex, null);
|
// try all receivers for both modes, in an attempts based system.
|
||||||
dest.setInventorySlotContents(destIndex, newStack);
|
// instead of bailing out of trying after the first failure (which means you have to wait 0.25 seconds), we just try the next one.
|
||||||
itemsLeftToSend -= toMove * proportionalValue;
|
while(attempts < maxAttempts) {
|
||||||
didSomething = true;
|
int index = (receiveOrder == RECEIVE_ROBIN) ? (nextReceiver + attempts) % receiverList.size() : attempts;
|
||||||
|
|
||||||
|
Entry<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>> candidate = receiverList.get(index);
|
||||||
|
|
||||||
|
if(NodeNet.isBadLink(candidate.getKey())) {
|
||||||
|
receivers.remove(candidate.getKey());
|
||||||
|
attempts++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IInventory dest = candidate.getKey();
|
||||||
|
TileEntityPneumoTube endpointTile = candidate.getValue().getZ();
|
||||||
|
TileEntity tile2 = dest instanceof TileEntity ? (TileEntity) dest : null;
|
||||||
|
|
||||||
|
// range check for our compression level, skip if either source or dest aren't tile entities
|
||||||
|
if(tile1 != null && tile2 != null) {
|
||||||
|
int sq = (tile1.xCoord - tile2.xCoord) * (tile1.xCoord - tile2.xCoord) + (tile1.yCoord - tile2.yCoord) * (tile1.yCoord - tile2.yCoord) + (tile1.zCoord - tile2.zCoord) * (tile1.zCoord - tile2.zCoord);
|
||||||
|
if(sq > maxRange * maxRange) {
|
||||||
|
attempts++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ISidedInventory sidedDest = dest instanceof ISidedInventory ? (ISidedInventory) dest : null;
|
||||||
|
int destSide = candidate.getValue().getX().getOpposite().ordinal();
|
||||||
|
int[] destSlotAccess = getSlotAccess(dest, destSide);
|
||||||
|
int itemsLeftToSend = ITEMS_PER_TRANSFER; // not actually individual items, but rather the total "mass", based on max stack size
|
||||||
|
int itemHardCap = dest instanceof TileEntityMachineAutocrafter ? 1 : ITEMS_PER_TRANSFER;
|
||||||
|
boolean didSomething = false;
|
||||||
|
|
||||||
|
for(int sourceIndex : sourceSlotAccess) {
|
||||||
|
ItemStack sourceStack = source.getStackInSlot(sourceIndex);
|
||||||
|
if(sourceStack == null) continue;
|
||||||
|
if(sidedSource != null && !sidedSource.canExtractItem(sourceIndex, sourceStack, sourceSide)) continue;
|
||||||
|
// filter of the source
|
||||||
|
boolean match = tube.matchesFilter(sourceStack);
|
||||||
|
if((match && !tube.whitelist) || (!match && tube.whitelist)) continue;
|
||||||
|
// filter of the receiver, only if the sender and receiver aren't the same block
|
||||||
|
if(endpointTile != null && endpointTile != tube) {
|
||||||
|
match = endpointTile.matchesFilter(sourceStack);
|
||||||
|
if((match && !endpointTile.whitelist) || (!match && endpointTile.whitelist)) continue;
|
||||||
|
}
|
||||||
|
// the "mass" of an item. something that only stacks to 4 has a "mass" of 16. max transfer mass is 64, i.e. one standard stack, or one single unstackable item
|
||||||
|
int proportionalValue = MathHelper.clamp_int(64 / sourceStack.getMaxStackSize(), 1, 64);
|
||||||
|
|
||||||
|
// try to fill partial stacks first
|
||||||
|
for(int destIndex : destSlotAccess) {
|
||||||
|
ItemStack destStack = dest.getStackInSlot(destIndex);
|
||||||
|
if(destStack == null) continue;
|
||||||
|
if(!ItemStackUtil.areStacksCompatible(sourceStack, destStack)) continue;
|
||||||
|
int toMove = BobMathUtil.min(sourceStack.stackSize, destStack.getMaxStackSize() - destStack.stackSize, dest.getInventoryStackLimit() - destStack.stackSize, itemsLeftToSend / proportionalValue, itemHardCap);
|
||||||
|
if(toMove <= 0) continue;
|
||||||
|
|
||||||
|
ItemStack checkStack = destStack.copy();
|
||||||
|
checkStack.stackSize += toMove;
|
||||||
|
if(!dest.isItemValidForSlot(destIndex, checkStack)) continue;
|
||||||
|
if(sidedDest != null && !sidedDest.canInsertItem(destIndex, checkStack, destSide)) continue;
|
||||||
|
|
||||||
|
sourceStack.stackSize -= toMove;
|
||||||
|
if(sourceStack.stackSize <= 0) source.setInventorySlotContents(sourceIndex, null);
|
||||||
|
destStack.stackSize += toMove;
|
||||||
|
itemsLeftToSend -= toMove * proportionalValue;
|
||||||
|
didSomething = true;
|
||||||
|
if(itemsLeftToSend <= 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if there's stuff left to send, occupy empty slots
|
||||||
|
if(itemsLeftToSend > 0 && sourceStack.stackSize > 0) for(int destIndex : destSlotAccess) {
|
||||||
|
if(dest.getStackInSlot(destIndex) != null) continue;
|
||||||
|
int toMove = BobMathUtil.min(sourceStack.stackSize, dest.getInventoryStackLimit(), itemsLeftToSend / proportionalValue, itemHardCap);
|
||||||
|
if(toMove <= 0) continue;
|
||||||
|
|
||||||
|
ItemStack checkStack = sourceStack.copy();
|
||||||
|
checkStack.stackSize = toMove;
|
||||||
|
if(!dest.isItemValidForSlot(destIndex, checkStack)) continue;
|
||||||
|
if(sidedDest != null && !sidedDest.canInsertItem(destIndex, checkStack, destSide)) continue;
|
||||||
|
|
||||||
|
ItemStack newStack = sourceStack.copy();
|
||||||
|
newStack.stackSize = toMove;
|
||||||
|
sourceStack.stackSize -= toMove;
|
||||||
|
if(sourceStack.stackSize <= 0) source.setInventorySlotContents(sourceIndex, null);
|
||||||
|
dest.setInventorySlotContents(destIndex, newStack);
|
||||||
|
itemsLeftToSend -= toMove * proportionalValue;
|
||||||
|
didSomething = true;
|
||||||
|
if(itemsLeftToSend <= 0) break;
|
||||||
|
}
|
||||||
|
|
||||||
if(itemsLeftToSend <= 0) break;
|
if(itemsLeftToSend <= 0) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(itemsLeftToSend <= 0) break;
|
// make sure both parties are saved to disk and increment the counter for round robin
|
||||||
|
if(didSomething) {
|
||||||
|
source.markDirty();
|
||||||
|
dest.markDirty();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
attempts++;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
// make sure both parties are saved to disk and increment the counter for round robin
|
|
||||||
if(didSomething) {
|
|
||||||
source.markDirty();
|
|
||||||
dest.markDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return didSomething;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns an array of accessible slots from the given side of an IInventory. If it's an ISidedInventory, uses the sided restrictions instead. */
|
/** Returns an array of accessible slots from the given side of an IInventory. If it's an ISidedInventory, uses the sided restrictions instead. */
|
||||||
public static int[] getSlotAccess(IInventory inventory, int dir) {
|
public static int[] getSlotAccess(IInventory inventory, int dir) {
|
||||||
|
|
||||||
if(inventory instanceof ISidedInventory) {
|
if(inventory instanceof ISidedInventory) {
|
||||||
int[] slotAccess = ((ISidedInventory) inventory).getAccessibleSlotsFromSide(dir);
|
int[] slotAccess = ((ISidedInventory) inventory).getAccessibleSlotsFromSide(dir);
|
||||||
return Arrays.copyOf(slotAccess, slotAccess.length); //we mess with the order, so better not use the original array
|
return Arrays.copyOf(slotAccess, slotAccess.length); //we mess with the order, so better not use the original array
|
||||||
@ -184,12 +215,12 @@ public class PneumaticNetwork extends NodeNet {
|
|||||||
return slotAccess;
|
return slotAccess;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Compares IInventory by distance, going off the assumption that they are TileEntities. Uses positional data for tie-breaking if the distance is the same. */
|
/** Compares IInventory by distance, going off the assumption that they are TileEntities. Uses positional data for tie-breaking if the distance is the same. */
|
||||||
public static class ReceiverComparator implements Comparator<Entry<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>>> {
|
public static class ReceiverComparator implements Comparator<Entry<IInventory, Triplet<ForgeDirection, Long, TileEntityPneumoTube>>> {
|
||||||
|
|
||||||
private TileEntityPneumoTube origin;
|
private TileEntityPneumoTube origin;
|
||||||
|
|
||||||
public ReceiverComparator(TileEntityPneumoTube origin) {
|
public ReceiverComparator(TileEntityPneumoTube origin) {
|
||||||
this.origin = origin;
|
this.origin = origin;
|
||||||
}
|
}
|
||||||
@ -204,11 +235,11 @@ public class PneumaticNetwork extends NodeNet {
|
|||||||
if(tile1 == null && tile2 != null) return 1;
|
if(tile1 == null && tile2 != null) return 1;
|
||||||
if(tile1 != null && tile2 == null) return -1;
|
if(tile1 != null && tile2 == null) return -1;
|
||||||
if(tile1 == null && tile2 == null) return 0;
|
if(tile1 == null && tile2 == null) return 0;
|
||||||
|
|
||||||
// calculate distances from origin
|
// calculate distances from origin
|
||||||
int dist1 = (tile1.xCoord - origin.xCoord) * (tile1.xCoord - origin.xCoord) + (tile1.yCoord - origin.yCoord) * (tile1.yCoord - origin.yCoord) + (tile1.zCoord - origin.zCoord) * (tile1.zCoord - origin.zCoord);
|
int dist1 = (tile1.xCoord - origin.xCoord) * (tile1.xCoord - origin.xCoord) + (tile1.yCoord - origin.yCoord) * (tile1.yCoord - origin.yCoord) + (tile1.zCoord - origin.zCoord) * (tile1.zCoord - origin.zCoord);
|
||||||
int dist2 = (tile2.xCoord - origin.xCoord) * (tile2.xCoord - origin.xCoord) + (tile2.yCoord - origin.yCoord) * (tile2.yCoord - origin.yCoord) + (tile2.zCoord - origin.zCoord) * (tile2.zCoord - origin.zCoord);
|
int dist2 = (tile2.xCoord - origin.xCoord) * (tile2.xCoord - origin.xCoord) + (tile2.yCoord - origin.yCoord) * (tile2.yCoord - origin.yCoord) + (tile2.zCoord - origin.zCoord) * (tile2.zCoord - origin.zCoord);
|
||||||
|
|
||||||
// tier-breaker: use hash value instead
|
// tier-breaker: use hash value instead
|
||||||
if(dist1 == dist2) {
|
if(dist1 == dist2) {
|
||||||
return TileEntityPneumoTube.getIdentifier(tile1.xCoord, tile1.yCoord, tile1.zCoord) - TileEntityPneumoTube.getIdentifier(tile2.xCoord, tile2.yCoord, tile2.zCoord);
|
return TileEntityPneumoTube.getIdentifier(tile1.xCoord, tile1.yCoord, tile1.zCoord) - TileEntityPneumoTube.getIdentifier(tile2.xCoord, tile2.yCoord, tile2.zCoord);
|
||||||
|
|||||||
@ -2222,16 +2222,16 @@ item.ballistite.name=Баллистит
|
|||||||
item.bandaid.name=Пластырь Вельвет
|
item.bandaid.name=Пластырь Вельвет
|
||||||
item.bathwater.name=Токсичная мыльная вода
|
item.bathwater.name=Токсичная мыльная вода
|
||||||
item.bathwater_mk2.name=Токсичная мыльная вода (Лошадиный аромат)
|
item.bathwater_mk2.name=Токсичная мыльная вода (Лошадиный аромат)
|
||||||
item.battery_advanced.name=Продвинутый аккумулятор
|
item.battery_advanced.name=Продвинутый аккумулятор (LEGACY)
|
||||||
item.battery_advanced_cell.name=Усовершенствованная энергоячейка
|
item.battery_advanced_cell.name=Усовершенствованная энергоячейка (LEGACY)
|
||||||
item.battery_advanced_cell_12.name=Двенадцатикратный массив из усовершенствованных энергоячеек
|
item.battery_advanced_cell_12.name=Двенадцатикратный массив из усовершенствованных энергоячеек (LEGACY)
|
||||||
item.battery_advanced_cell_4.name=Счетверённая усовершенствованная энергоячейка
|
item.battery_advanced_cell_4.name=Счетверённая усовершенствованная энергоячейка (LEGACY)
|
||||||
item.battery_creative.name=Бесконечная батарейка
|
item.battery_creative.name=Бесконечная батарейка
|
||||||
item.battery_generic.name=Аккумулятор
|
item.battery_generic.name=Аккумулятор (LEGACY)
|
||||||
item.battery_lithium.name=Литий-ионный аккумулятор
|
item.battery_lithium.name=Литий-ионный аккумулятор (LEGACY)
|
||||||
item.battery_lithium_cell.name=Литий-ионная энергоячейка
|
item.battery_lithium_cell.name=Литий-ионная энергоячейка (LEGACY)
|
||||||
item.battery_lithium_cell_3.name=Строенная литий-ионная энергоячейка
|
item.battery_lithium_cell_3.name=Строенная литий-ионная энергоячейка (LEGACY)
|
||||||
item.battery_lithium_cell_6.name=Сшестерённая литий-ионная энергоячейка
|
item.battery_lithium_cell_6.name=Сшестерённая литий-ионная энергоячейка (LEGACY)
|
||||||
item.battery_pack.battery_lead.name=Свинцово-серная батарея
|
item.battery_pack.battery_lead.name=Свинцово-серная батарея
|
||||||
item.battery_pack.battery_lithium.name=Литий-ионная батарея
|
item.battery_pack.battery_lithium.name=Литий-ионная батарея
|
||||||
item.battery_pack.battery_quantum.name=Квантовая батарея
|
item.battery_pack.battery_quantum.name=Квантовая батарея
|
||||||
@ -2246,30 +2246,33 @@ item.battery_pack.capacitor_spark.name=Спарк-конденсатор
|
|||||||
item.battery_pack.capacitor_tantalum.name=Танталовый конденсатор
|
item.battery_pack.capacitor_tantalum.name=Танталовый конденсатор
|
||||||
item.battery_potato.name=Картофельная батарейка
|
item.battery_potato.name=Картофельная батарейка
|
||||||
item.battery_potatos.name=КартошкОС
|
item.battery_potatos.name=КартошкОС
|
||||||
item.battery_red_cell.name=Энергоячейка из красной пыли
|
item.battery_red_cell.name=Энергоячейка из красной пыли (LEGACY)
|
||||||
item.battery_red_cell_24.name=Двадцатичетырёхкратный массив из краснопыльных энергоячеек
|
item.battery_red_cell_24.name=Двадцатичетырёхкратный массив из краснопыльных энергоячеек (LEGACY)
|
||||||
item.battery_red_cell_6.name=Сшестёренная энергоячейка из красной пыли
|
item.battery_red_cell_6.name=Сшестёренная энергоячейка из красной пыли (LEGACY)
|
||||||
item.battery_sc_americium.name=Самозаряжающаяся батарея с америцием-241
|
item.battery_sc.am241.name=Самозаряжающаяся батарея Америций-241
|
||||||
item.battery_sc_gold.name=Самозаряжающаяся батарея с золотом-198
|
item.battery_sc.au198.name=Самозаряжающаяся батарея Золото-198
|
||||||
item.battery_sc_lead.name=Самозаряжающаяся батарея со свинцом-209
|
item.battery_sc.co60.name=Самозаряжающаяся батарея Кобальт-60
|
||||||
item.battery_sc_plutonium.name=Самозаряжающаяся батарея с плутонием-238
|
item.battery_sc.pb209.name=Самозаряжающаяся батарея Свинец-209
|
||||||
item.battery_sc_polonium.name=Самозаряжающаяся батарея с полонием-210
|
item.battery_sc.po210.name=Самозаряжающаяся батарея Полоний-210
|
||||||
item.battery_sc_technetium.name=Самозаряжающаяся батарея с технецием-98
|
item.battery_sc.pu238.name=Самозаряжающаяся батарея Плутоний-238
|
||||||
item.battery_sc_uranium.name=Самозаряжающаяся батарея с ураном-238
|
item.battery_sc.ra226.name=Самозаряжающаяся батарея Радий-226
|
||||||
item.battery_schrabidium.name=Шрабидиевая батарея
|
item.battery_sc.tc99.name=Самозаряжающаяся батарея Технеций-99
|
||||||
item.battery_schrabidium_cell.name=Шрабидиевая энергоячейка
|
item.battery_sc.empty.name=Самозаряжающаяся батарея пустая
|
||||||
item.battery_schrabidium_cell_2.name=Сдвоенная шрабидиевая энергоячейка
|
item.battery_sc.waste.name=Самозаряжающаяся батарея отработаного топлива
|
||||||
item.battery_schrabidium_cell_4.name=Счетверённая шрабидиевая энергоячейка
|
item.battery_schrabidium.name=Шрабидиевая батарея (LEGACY)
|
||||||
item.battery_spark.name=Спарк-батарея
|
item.battery_schrabidium_cell.name=Шрабидиевая энергоячейка (LEGACY)
|
||||||
item.battery_spark_cell_100.name=Спарк-Магический массив хранения энергии
|
item.battery_schrabidium_cell_2.name=Сдвоенная шрабидиевая энергоячейка (LEGACY)
|
||||||
item.battery_spark_cell_1000.name=Спарк-Магическая масс-энергетическая пустота
|
item.battery_schrabidium_cell_4.name=Счетверённая шрабидиевая энергоячейка (LEGACY)
|
||||||
item.battery_spark_cell_10000.name=Устойчивый пространственно-временной спарк-кристалл
|
item.battery_spark.name=Спарк-батарея (LEGACY)
|
||||||
item.battery_spark_cell_25.name=Спарк-магический аккумулятор
|
item.battery_spark_cell_100.name=Спарк-Магический массив хранения энергии (LEGACY)
|
||||||
item.battery_spark_cell_2500.name=Спарк-магическое море Дирака
|
item.battery_spark_cell_1000.name=Спарк-Магическая масс-энергетическая пустота (LEGACY)
|
||||||
item.battery_spark_cell_6.name=Спарк-энергоячейка
|
item.battery_spark_cell_10000.name=Устойчивый пространственно-временной спарк-кристалл (LEGACY)
|
||||||
item.battery_spark_cell_power.name=Абсурдный физический спарк-блок накопления энергии
|
item.battery_spark_cell_25.name=Спарк-магический аккумулятор (LEGACY)
|
||||||
item.battery_steam.name=Паровой бак для хранения энергии
|
item.battery_spark_cell_2500.name=Спарк-магическое море Дирака (LEGACY)
|
||||||
item.battery_steam_large.name=Большой паровой бак для хранения энергии
|
item.battery_spark_cell_6.name=Спарк-энергоячейка (LEGACY)
|
||||||
|
item.battery_spark_cell_power.name=Абсурдный физический спарк-блок накопления энергии (LEGACY)
|
||||||
|
item.battery_steam.name=Паровой бак для хранения энергии (LEGACY)
|
||||||
|
item.battery_steam_large.name=Большой паровой бак для хранения энергии (LEGACY)
|
||||||
item.battery_su.name=Одноразовая батарейка
|
item.battery_su.name=Одноразовая батарейка
|
||||||
item.battery_su_l.name=Большая одноразовая батарейка
|
item.battery_su_l.name=Большая одноразовая батарейка
|
||||||
item.battery_trixite.name=Безымянная спарк-батарея
|
item.battery_trixite.name=Безымянная спарк-батарея
|
||||||
@ -6017,7 +6020,7 @@ tile.machine_battery_redd.name=ЭМЭХ
|
|||||||
tile.machine_battery_socket.name=Аккумуляторный массив
|
tile.machine_battery_socket.name=Аккумуляторный массив
|
||||||
tile.machine_battery_socket.desc=Позволяет подключать аккумуляторы$напрямую к энергосети.$Выступает в качестве кабеля, все порты$подключены к одной сети.
|
tile.machine_battery_socket.desc=Позволяет подключать аккумуляторы$напрямую к энергосети.$Выступает в качестве кабеля, все порты$подключены к одной сети.
|
||||||
tile.machine_boiler.name=Бойлер
|
tile.machine_boiler.name=Бойлер
|
||||||
tile.machine_boiler.desc=Большой бойлер для кипячения воды или нагрева нефти.$Требует внешний источник тепла.$Скорость передачи тепла: ΔT*0.01 TU/t
|
tile.machine_boiler.desc=Большой бойлер для кипячения воды или нагрева нефти.$Требует внешний источник тепла.$Скорость передачи тепла: ΔT*0.1 TU/t
|
||||||
tile.machine_boiler_electric_off.name=Электрический нагреватель нефти
|
tile.machine_boiler_electric_off.name=Электрический нагреватель нефти
|
||||||
tile.machine_boiler_electric_on.name=Электрический нагреватель нефти
|
tile.machine_boiler_electric_on.name=Электрический нагреватель нефти
|
||||||
tile.machine_boiler_off.name=Нагревательнефти
|
tile.machine_boiler_off.name=Нагревательнефти
|
||||||
@ -6034,7 +6037,7 @@ tile.machine_chungus.desc=Эффективность: 85%%
|
|||||||
tile.machine_coal_off.name=Генератор внутреннего сгорания
|
tile.machine_coal_off.name=Генератор внутреннего сгорания
|
||||||
tile.machine_coal_on.name=Генератор внутреннего сгорания
|
tile.machine_coal_on.name=Генератор внутреннего сгорания
|
||||||
tile.machine_coker.name=Коксовая установка
|
tile.machine_coker.name=Коксовая установка
|
||||||
tile.machine_coker.desc=Коксует жидкость, создавая жидкую побочку.$Требует внешний источник тепла.$Скорость передачи тепла: ΔT*0.025 TU/t
|
tile.machine_coker.desc=Коксует жидкость, создавая жидкую побочку.$Требует внешний источник тепла.$Скорость передачи тепла: ΔT*0.25 TU/t
|
||||||
tile.machine_combine_factory.name=Печь для стали Альянса
|
tile.machine_combine_factory.name=Печь для стали Альянса
|
||||||
tile.machine_combustion_engine.name=Промышленный двигатель внутреннего сгорания
|
tile.machine_combustion_engine.name=Промышленный двигатель внутреннего сгорания
|
||||||
tile.machine_compressor.name=Компрессор
|
tile.machine_compressor.name=Компрессор
|
||||||
@ -6047,6 +6050,7 @@ tile.machine_converter_rf_he.name=Конвертер энергии RF в HE
|
|||||||
tile.machine_conveyor_press.name=Конвейерный пресс
|
tile.machine_conveyor_press.name=Конвейерный пресс
|
||||||
tile.machine_conveyor_press.desc=Лента двигается слева направо$ПКМ, чтобы установить штамп$ПКМ отвёрткой, чтобы снять штамп
|
tile.machine_conveyor_press.desc=Лента двигается слева направо$ПКМ, чтобы установить штамп$ПКМ отвёрткой, чтобы снять штамп
|
||||||
tile.machine_crucible.name=Плавильня
|
tile.machine_crucible.name=Плавильня
|
||||||
|
tile.machine_crucible.desc=Скорость передачи тепла: ΔT*0,25 TU/t
|
||||||
tile.machine_crystallizer.name=Рудный окислитель
|
tile.machine_crystallizer.name=Рудный окислитель
|
||||||
tile.machine_cyclotron.name=Циклотрон
|
tile.machine_cyclotron.name=Циклотрон
|
||||||
tile.machine_detector.name=Детектор мощности
|
tile.machine_detector.name=Детектор мощности
|
||||||
@ -6083,7 +6087,7 @@ tile.machine_hephaestus.name=Геотермальный теплообменик
|
|||||||
tile.machine_icf_press.name=Топливный пресс ICF
|
tile.machine_icf_press.name=Топливный пресс ICF
|
||||||
tile.machine_icf_press.desc=Наполняет топливные пеллеты ICF$Левый топливный слот принимается сверху/снизу, правый - по бокам$Мюоны и пеллеты могут подаваться с любой стороны
|
tile.machine_icf_press.desc=Наполняет топливные пеллеты ICF$Левый топливный слот принимается сверху/снизу, правый - по бокам$Мюоны и пеллеты могут подаваться с любой стороны
|
||||||
tile.machine_industrial_boiler.name=Промышленный бойлер
|
tile.machine_industrial_boiler.name=Промышленный бойлер
|
||||||
tile.machine_industrial_boiler.desc=Большой бойлер, в котором можно вскипятить воду или разогреть нефть.$Требует внешний источник тепла.$Скорость передачи тепла: ΔT*0.01 TU/t$Не может взорваться
|
tile.machine_industrial_boiler.desc=Большой бойлер, в котором можно вскипятить воду или разогреть нефть.$Требует внешний источник тепла.$Скорость передачи тепла: ΔT*0.1 TU/t$Не может взорваться
|
||||||
tile.machine_industrial_generator.name=Промышленный генератор
|
tile.machine_industrial_generator.name=Промышленный генератор
|
||||||
tile.machine_intake.name=Воздухозаборник
|
tile.machine_intake.name=Воздухозаборник
|
||||||
tile.machine_keyforge.name=Стол мастера по замкам
|
tile.machine_keyforge.name=Стол мастера по замкам
|
||||||
@ -6835,5 +6839,6 @@ desc.gui.upgrade.speed= * §4Скорость§r: Стакается до 3-х
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 566 B |
Loading…
x
Reference in New Issue
Block a user