i spent all afternoon in a hole

This commit is contained in:
Boblet 2026-05-21 16:56:03 +02:00
parent e42bb12984
commit 0074c20f91
14 changed files with 335 additions and 211 deletions

View File

@ -12,6 +12,10 @@
* When cutting down hemp, willows, and other NTM double plants, only the top part will be cut off, no matter where the thresher touches it
* Can also harvest items from sunflowers and tall grass without breaking the blocks
* Can also handle tall plants like cacti and sugar cane
* New big-ass tank
* Successor to the BAT9k
* Larger footprint, way more storage space
* Needs to be placed on a proper foundation or else it'll sink into the ground
## Changed
* RoR graphs can now have their min and max bounds set to a fixed number
@ -29,7 +33,7 @@
* Increased the yield of lye from wood ash
* All fluid tanks larger than barrels now have dynamic IO speed instead of providing their entire contents instantly
* Tank fill will slow down the fuller the tank becomes, tank drain also slow downs as it gets emptier
* This means that multiple tanks in IO mode in the same network will still ping pong, but instead of firing their entire contents over the network, they will even out
* This means that multiple tanks in IO mode in the same network will still ping pong, but only a small portion of fluid will be "lost" (i.e. invisible due to subtick transfer operations)
* The stinger is now classified as a special weapon
* The carbine can now take a scope
* The battery socket now renders supports when a block is placed on top of it, allowing somewhat aesthetic stacking of sockets

View File

@ -778,6 +778,7 @@ public class ModBlocks {
public static Block radio_torch_reader;
public static Block radio_torch_controller;
public static Block radio_telex;
public static Block radio_autocal;
public static Block oc_cable_paintable;
public static Block conveyor;
@ -1894,6 +1895,7 @@ public class ModBlocks {
radio_torch_reader = new RadioTorchReader().setBlockName("radio_torch_reader").setHardness(0.1F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rtty_reader");
radio_torch_controller = new RadioTorchController().setBlockName("radio_torch_controller").setHardness(0.1F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":rtty_controller");
radio_telex = new RadioTelex().setBlockName("radio_telex").setHardness(3F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":radio_telex");
radio_autocal = new RadioAUTOCAL().setBlockName("radio_autocal").setHardness(3F).setResistance(10.0F).setCreativeTab(MainRegistry.machineTab).setBlockTextureName(RefStrings.MODID + ":block_steel");
conveyor = new BlockConveyor().setBlockName("conveyor").setHardness(2.0F).setResistance(2.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":conveyor");
conveyor_express = new BlockConveyorExpress().setBlockName("conveyor_express").setHardness(2.0F).setResistance(2.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":conveyor_express");
@ -3175,6 +3177,7 @@ public class ModBlocks {
register(radio_torch_reader);
register(radio_torch_controller);
register(radio_telex);
register(radio_autocal);
register(crane_extractor);
register(crane_inserter);

View File

@ -27,6 +27,7 @@ import net.minecraftforge.common.util.ForgeDirection;
import java.util.ArrayList;
import java.util.List;
@Deprecated
public class MachineBigAssTank9000 extends BlockDummyable implements IPersistentInfoProvider {
public MachineBigAssTank9000(Material mat) {

View File

@ -0,0 +1,25 @@
package com.hbm.blocks.network;
import com.hbm.blocks.machine.BlockMachineBase;
import com.hbm.tileentity.network.TileEntityRadioAUTOCAL;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
public class RadioAUTOCAL extends BlockMachineBase {
public RadioAUTOCAL() {
super(Material.iron, 0);
this.rotatable = true;
}
@Override
public TileEntity createNewTileEntity(World world, int meta) {
return new TileEntityRadioAUTOCAL();
}
@Override public int getRenderType(){ return -1; }
@Override public boolean isOpaqueCube() { return false; }
@Override public boolean renderAsNormalBlock() { return false; }
}

View File

@ -129,7 +129,7 @@ public class GeneralConfig {
preferredOutputMod = CommonConfig.createConfigStringList(config,CATEGORY_GENERAL,"1.42_preferredOutputMod",
"The mod which is preferred as output when certain machines autogenerate recipes. Currently used for the shredder", new String[] {RefStrings.MODID});
enableLoadScreenReplacement = config.get(CATEGORY_GENERAL, "1.43_enableLoadScreenReplacement", true, "Tries to replace the vanilla load screen with the 'tip of the day' one, may clash with other mods trying to do the same.").getBoolean(true);
enableMachineGravity = config.get(CATEGORY_GENERAL, "1.44_enableMachineGravity", true, "Requires large large machines to have a proper foundation, or else they tilt and break. Independent from the 528 version of this config, which does the same, but only works with 528 enabled.").getBoolean(false);
enableMachineGravity = config.get(CATEGORY_GENERAL, "1.44_enableMachineGravity", false, "Requires large large machines to have a proper foundation, or else they tilt and break. Independent from the 528 version of this config, which does the same, but only works with 528 enabled.").getBoolean(false);
enableExpensiveMode = config.get(CATEGORY_GENERAL, "1.99_enableExpensiveMode", false, "It does what the name implies.").getBoolean(false);
final String CATEGORY_528 = CommonConfig.CATEGORY_528;

View File

@ -1,5 +1,6 @@
package com.hbm.inventory.gui;
import com.hbm.util.Calculator;
import com.hbm.util.Tuple;
import net.minecraft.client.gui.GuiScreen;
@ -12,8 +13,6 @@ import java.math.MathContext;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.Locale;
import java.util.Stack;
public class GUICalculator extends GuiScreen {
private int xSize = 220;
@ -58,7 +57,7 @@ public class GUICalculator extends GuiScreen {
selectedHist = -1;
} else {
try {
double result = evaluateExpression(input);
double result = Calculator.evaluateExpression(input);
history.addFirst(new Tuple.Pair<String,Double>(input, result));
if (history.size() > maxHistory) history.removeLast();
String plainStringRepresentation = (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString();
@ -85,7 +84,7 @@ public class GUICalculator extends GuiScreen {
}
try {
latestResult = Double.toString(evaluateExpression(input));
latestResult = Double.toString(Calculator.evaluateExpression(input));
} catch (Exception e) { latestResult = e.toString(); }
}
@ -116,203 +115,4 @@ public class GUICalculator extends GuiScreen {
i++;
}
}
/**
* Mathematically evaluates user-inputted strings<br>
* It is recommended to catch all exceptions when using this
*/
public static double evaluateExpression(String input) {
if (input.contains("^")) input = preEvaluatePower(input);
char[] tokens = input.toCharArray();
Stack<Double> values = new Stack<>();
Stack<String> operators = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
if (tokens[i] == ' ') continue;
if (tokens[i] >= '0' && tokens[i] <= '9' || tokens[i] == '.' || (tokens[i] == '-' && (i == 0 || "+-*/^(".contains(String.valueOf(tokens[i - 1]))))) {
StringBuilder buffer = new StringBuilder();
if (tokens[i] == '-') {
buffer.append('-'); // for negative numbers
i++;
}
while (i < tokens.length && (tokens[i] >= '0' && tokens[i] <= '9' || tokens[i] == '.')) buffer.append(tokens[i++]);
values.push(Double.parseDouble(buffer.toString()));
i--;
} else if (tokens[i] == '(') operators.push(Character.toString(tokens[i]));
else if (tokens[i] == ')') {
while (!operators.isEmpty() && operators.peek().charAt(0) != '(')
values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
operators.pop();
if (!operators.isEmpty() && operators.peek().length() > 1)
values.push(evaluateFunction(operators.pop(), values.pop()));
} else if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/' || tokens[i] == '^') {
while (!operators.isEmpty() && hasPrecedence(String.valueOf(tokens[i]), operators.peek()))
values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
operators.push(Character.toString(tokens[i]));
} else if (tokens[i] == '!') {
values.push((double) factorial((int) Math.round(values.pop())));
}else if (tokens[i] >= 'A' && tokens[i] <= 'Z' || tokens[i] >= 'a' && tokens[i] <= 'z') {
StringBuilder charBuffer = new StringBuilder();
while (i < tokens.length && (tokens[i] >= 'A' && tokens[i] <= 'Z' || tokens[i] >= 'a' && tokens[i] <= 'z'))
charBuffer.append(tokens[i++]);
String string = charBuffer.toString();
if (string.equalsIgnoreCase("pi")) values.push(Math.PI);
else if (string.equalsIgnoreCase("e")) values.push(Math.E);
else operators.push(string.toLowerCase(Locale.ROOT));
i--;
}
}
// if the expression is correctly formatted, no function is remaining
while (!operators.empty()) values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
return values.pop();
}
private static double evaluateOperator(char operator, double x, double y) {
switch (operator) {
case '+': return y + x;
case '-': return y - x;
case '*': return y * x;
case '/': return y / x;
case '^': return Math.pow(y, x); // should not happen here, but oh well
}
return 0;
}
private static double evaluateFunction(String function, double x) {
switch (function) {
case "sqrt": return Math.sqrt(x);
case "sin": return Math.sin(x);
case "cos": return Math.cos(x);
case "tan": return Math.tan(x);
case "asin": return Math.asin(x);
case "acos": return Math.acos(x);
case "atan": return Math.atan(x);
case "log": return Math.log10(x);
case "ln": return Math.log(x);
case "ceil": return Math.ceil(x);
case "floor": return Math.floor(x);
case "round": return Math.round(x);
}
return 0;
}
/** Returns whether {@code second} has precedence over {@code first} */
private static boolean hasPrecedence(String first, String second) {
if (second.length() > 1) return false;
char firstChar = first.charAt(0);
char secondChar = second.charAt(0);
if (secondChar == '(' || secondChar == ')') return false;
else return (firstChar != '*' && firstChar != '/' && firstChar != '^') || (secondChar != '+' && secondChar != '-');
}
/** Returns the input with all powers evaluated */
private static String preEvaluatePower(String input) {
do {
int powerOperatorIndex = input.lastIndexOf('^');
// find base
boolean previousTokenIsParentheses = input.charAt(powerOperatorIndex - 1) == ')';
int parenthesesDepth = previousTokenIsParentheses ? 1 : 0;
int baseExpressionStart = previousTokenIsParentheses ? powerOperatorIndex - 2 : powerOperatorIndex - 1;
baseLoop:
for (; baseExpressionStart >= 0; baseExpressionStart--) { // search backwards
switch (input.charAt(baseExpressionStart)) {
case ')':
if (previousTokenIsParentheses) parenthesesDepth++;
else break baseLoop;
break;
case '(':
if (previousTokenIsParentheses && parenthesesDepth > 0) parenthesesDepth--;
else break baseLoop;
break;
case '+': case '-': case '*': case '/': case '^':
if (parenthesesDepth == 0) break baseLoop;
}
}
baseExpressionStart++; // go one token forward again
if (parenthesesDepth > 0) throw new IllegalArgumentException("Incomplete parentheses");
// find exponent
boolean nextTokenIsParentheses = input.charAt(powerOperatorIndex + 1) == '(';
parenthesesDepth = nextTokenIsParentheses ? 1 : 0;
int exponentExpressionEnd = nextTokenIsParentheses ? powerOperatorIndex + 2 : powerOperatorIndex + 1;
exponentLoop:
for (; exponentExpressionEnd < input.length(); exponentExpressionEnd++) {
switch (input.charAt(exponentExpressionEnd)) {
case '(':
if (nextTokenIsParentheses) parenthesesDepth++;
else break exponentLoop;
break;
case ')':
if (nextTokenIsParentheses && parenthesesDepth > 0) parenthesesDepth--;
else break exponentLoop;
break;
case '+': case '-': case '*': case '/': case '^':
if (parenthesesDepth == 0) break exponentLoop;
}
}
if (parenthesesDepth > 0) throw new IllegalArgumentException("Incomplete parentheses");
double base = evaluateExpression(input.substring(baseExpressionStart, powerOperatorIndex));
double exponent = evaluateExpression(input.substring(powerOperatorIndex + 1, exponentExpressionEnd));
double result = Math.pow(base, exponent);
// use big decimal to avoid scientific notation messing with the calculation
input = input.substring(0, baseExpressionStart) + (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString() + input.substring(exponentExpressionEnd);
} while (input.contains("^"));
return input;
}
// TODO Maybe switch the whole calculator to using BigInteger/BigDecimal?
// SplitRecursive algorithm
private static int factorial(int in) {
if (in < 0) throw new IllegalArgumentException("Factorial needs n >= 0");
if (in < 2) return 1;
int p = 1, r = 1;
factorialCurrentN = 1;
int h = 0, shift = 0, high = 1;
int log2n = log2(in);
while (h != in) {
shift += h;
h = in >> log2n--;
int len = high;
high = (h - 1) | 1;
len = (high - len) / 2;
if (len > 0) {
p *= factorialProduct(len);
r *= p;
}
}
return r << shift;
}
private static int factorialCurrentN;
private static int factorialProduct(int in) {
int m = in / 2;
if (m == 0) return factorialCurrentN += 2;
if (in == 2) return (factorialCurrentN += 2) * (factorialCurrentN += 2);
return factorialProduct(in - m) * factorialProduct(m);
}
private static int log2(int in) {
int log = 0;
if((in & 0xffff0000) != 0) { in >>>= 16; log = 16; }
if(in >= 256) { in >>>= 8; log += 8; }
if(in >= 16) { in >>>= 4; log += 4; }
if(in >= 4) { in >>>= 2; log += 2; }
return log + (in >>> 1);
}
}

View File

@ -0,0 +1,34 @@
package com.hbm.module;
import java.util.HashMap;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;
public interface IParse {
public EnumStatementReturn eval(ParseContext ctx, String line);
public static class ParseContext {
public World world;
public NBTTagCompound variables;
public HashMap<String, Integer> jmp;
public Object buffer;
public int clockSpeed;
public ParseContext(World world, NBTTagCompound variables, HashMap<String, Integer> jmp) {
this.world = world;
this.variables = variables;
this.jmp = jmp;
}
}
public static enum EnumStatementReturn {
OK,
UNRECOGNIZED_COMMAND,
PARAMETER_ERROR,
END_TICK,
UNDEFINED
}
}

View File

@ -0,0 +1,9 @@
package com.hbm.module;
public class ParseMSES1 implements IParse {
@Override
public EnumStatementReturn eval(ParseContext ctx, String line) {
return EnumStatementReturn.OK;
}
}

View File

@ -1,17 +1,11 @@
package com.hbm.tileentity;
import net.minecraftforge.fluids.FluidTank;
public abstract class TileEntityTickingBase extends TileEntityLoadedBase {
public TileEntityTickingBase() { }
public abstract String getInventoryName();
public int getGaugeScaled(int i, FluidTank tank) {
return tank.getFluidAmount() * i / tank.getCapacity();
}
//abstracting this method forces child classes to implement it
//so i don't have to remember the fucking method name
//was it update? onUpdate? updateTile? did it have any args?

View File

@ -7,6 +7,7 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.util.AxisAlignedBB;
@Deprecated
public class TileEntityMachineBAT9000 extends TileEntityBarrel {
public TileEntityMachineBAT9000() {

View File

@ -0,0 +1,41 @@
package com.hbm.tileentity.network;
import java.util.HashMap;
import com.hbm.tileentity.TileEntityTickingBase;
import io.netty.buffer.ByteBuf;
import net.minecraft.nbt.NBTTagCompound;
public class TileEntityRadioAUTOCAL extends TileEntityTickingBase {
public boolean isOn = false;
public Object buffer;
public NBTTagCompound variables;
public String[] script;
public HashMap<String, Integer> jmp = new HashMap();
@Override
public String getInventoryName() {
return "container.autocal";
}
@Override
public void updateEntity() {
if(!worldObj.isRemote) {
}
}
@Override
public void serialize(ByteBuf buf) {
super.serialize(buf);
}
@Override
public void deserialize(ByteBuf buf) {
super.deserialize(buf);
}
}

View File

@ -0,0 +1,208 @@
package com.hbm.util;
import java.math.BigDecimal;
import java.math.MathContext;
import java.util.Locale;
import java.util.Stack;
public class Calculator {
/**
* Mathematically evaluates user-inputted strings<br>
* It is recommended to catch all exceptions when using this
*/
public static double evaluateExpression(String input) {
if (input.contains("^")) input = preEvaluatePower(input);
char[] tokens = input.toCharArray();
Stack<Double> values = new Stack<>();
Stack<String> operators = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
if (tokens[i] == ' ') continue;
if (tokens[i] >= '0' && tokens[i] <= '9' || tokens[i] == '.' || (tokens[i] == '-' && (i == 0 || "+-*/^(".contains(String.valueOf(tokens[i - 1]))))) {
StringBuilder buffer = new StringBuilder();
if (tokens[i] == '-') {
buffer.append('-'); // for negative numbers
i++;
}
while (i < tokens.length && (tokens[i] >= '0' && tokens[i] <= '9' || tokens[i] == '.')) buffer.append(tokens[i++]);
values.push(Double.parseDouble(buffer.toString()));
i--;
} else if (tokens[i] == '(') operators.push(Character.toString(tokens[i]));
else if (tokens[i] == ')') {
while (!operators.isEmpty() && operators.peek().charAt(0) != '(')
values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
operators.pop();
if (!operators.isEmpty() && operators.peek().length() > 1)
values.push(evaluateFunction(operators.pop(), values.pop()));
} else if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/' || tokens[i] == '^') {
while (!operators.isEmpty() && hasPrecedence(String.valueOf(tokens[i]), operators.peek()))
values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
operators.push(Character.toString(tokens[i]));
} else if (tokens[i] == '!') {
values.push((double) factorial((int) Math.round(values.pop())));
}else if (tokens[i] >= 'A' && tokens[i] <= 'Z' || tokens[i] >= 'a' && tokens[i] <= 'z') {
StringBuilder charBuffer = new StringBuilder();
while (i < tokens.length && (tokens[i] >= 'A' && tokens[i] <= 'Z' || tokens[i] >= 'a' && tokens[i] <= 'z'))
charBuffer.append(tokens[i++]);
String string = charBuffer.toString();
if (string.equalsIgnoreCase("pi")) values.push(Math.PI);
else if (string.equalsIgnoreCase("e")) values.push(Math.E);
else operators.push(string.toLowerCase(Locale.ROOT));
i--;
}
}
// if the expression is correctly formatted, no function is remaining
while (!operators.empty()) values.push(evaluateOperator(operators.pop().charAt(0), values.pop(), values.pop()));
return values.pop();
}
private static double evaluateOperator(char operator, double x, double y) {
switch (operator) {
case '+': return y + x;
case '-': return y - x;
case '*': return y * x;
case '/': return y / x;
case '^': return Math.pow(y, x); // should not happen here, but oh well
}
return 0;
}
private static double evaluateFunction(String function, double x) {
switch (function) {
case "sqrt": return Math.sqrt(x);
case "sin": return Math.sin(x);
case "cos": return Math.cos(x);
case "tan": return Math.tan(x);
case "asin": return Math.asin(x);
case "acos": return Math.acos(x);
case "atan": return Math.atan(x);
case "log": return Math.log10(x);
case "ln": return Math.log(x);
case "ceil": return Math.ceil(x);
case "floor": return Math.floor(x);
case "round": return Math.round(x);
}
return 0;
}
/** Returns whether {@code second} has precedence over {@code first} */
private static boolean hasPrecedence(String first, String second) {
if (second.length() > 1) return false;
char firstChar = first.charAt(0);
char secondChar = second.charAt(0);
if (secondChar == '(' || secondChar == ')') return false;
else return (firstChar != '*' && firstChar != '/' && firstChar != '^') || (secondChar != '+' && secondChar != '-');
}
/** Returns the input with all powers evaluated */
private static String preEvaluatePower(String input) {
do {
int powerOperatorIndex = input.lastIndexOf('^');
// find base
boolean previousTokenIsParentheses = input.charAt(powerOperatorIndex - 1) == ')';
int parenthesesDepth = previousTokenIsParentheses ? 1 : 0;
int baseExpressionStart = previousTokenIsParentheses ? powerOperatorIndex - 2 : powerOperatorIndex - 1;
baseLoop:
for (; baseExpressionStart >= 0; baseExpressionStart--) { // search backwards
switch (input.charAt(baseExpressionStart)) {
case ')':
if (previousTokenIsParentheses) parenthesesDepth++;
else break baseLoop;
break;
case '(':
if (previousTokenIsParentheses && parenthesesDepth > 0) parenthesesDepth--;
else break baseLoop;
break;
case '+': case '-': case '*': case '/': case '^':
if (parenthesesDepth == 0) break baseLoop;
}
}
baseExpressionStart++; // go one token forward again
if (parenthesesDepth > 0) throw new IllegalArgumentException("Incomplete parentheses");
// find exponent
boolean nextTokenIsParentheses = input.charAt(powerOperatorIndex + 1) == '(';
parenthesesDepth = nextTokenIsParentheses ? 1 : 0;
int exponentExpressionEnd = nextTokenIsParentheses ? powerOperatorIndex + 2 : powerOperatorIndex + 1;
exponentLoop:
for (; exponentExpressionEnd < input.length(); exponentExpressionEnd++) {
switch (input.charAt(exponentExpressionEnd)) {
case '(':
if (nextTokenIsParentheses) parenthesesDepth++;
else break exponentLoop;
break;
case ')':
if (nextTokenIsParentheses && parenthesesDepth > 0) parenthesesDepth--;
else break exponentLoop;
break;
case '+': case '-': case '*': case '/': case '^':
if (parenthesesDepth == 0) break exponentLoop;
}
}
if (parenthesesDepth > 0) throw new IllegalArgumentException("Incomplete parentheses");
double base = evaluateExpression(input.substring(baseExpressionStart, powerOperatorIndex));
double exponent = evaluateExpression(input.substring(powerOperatorIndex + 1, exponentExpressionEnd));
double result = Math.pow(base, exponent);
// use big decimal to avoid scientific notation messing with the calculation
input = input.substring(0, baseExpressionStart) + (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString() + input.substring(exponentExpressionEnd);
} while (input.contains("^"));
return input;
}
// TODO Maybe switch the whole calculator to using BigInteger/BigDecimal?
// SplitRecursive algorithm
private static int factorial(int in) {
if (in < 0) throw new IllegalArgumentException("Factorial needs n >= 0");
if (in < 2) return 1;
int p = 1, r = 1;
factorialCurrentN = 1;
int h = 0, shift = 0, high = 1;
int log2n = log2(in);
while (h != in) {
shift += h;
h = in >> log2n--;
int len = high;
high = (h - 1) | 1;
len = (high - len) / 2;
if (len > 0) {
p *= factorialProduct(len);
r *= p;
}
}
return r << shift;
}
private static int factorialCurrentN;
private static int factorialProduct(int in) {
int m = in / 2;
if (m == 0) return factorialCurrentN += 2;
if (in == 2) return (factorialCurrentN += 2) * (factorialCurrentN += 2);
return factorialProduct(in - m) * factorialProduct(m);
}
private static int log2(int in) {
int log = 0;
if((in & 0xffff0000) != 0) { in >>>= 16; log = 16; }
if(in >= 256) { in >>>= 8; log += 8; }
if(in >= 16) { in >>>= 4; log += 4; }
if(in >= 4) { in >>>= 2; log += 2; }
return log + (in >>> 1);
}
}

View File

@ -223,6 +223,7 @@ container.bat9000=Big-Ass Tank 9000
container.battery=Energiespeicher
container.batteryREDD=FEnSU
container.batterySocket=Batteriesockel
container.bigAssTank=Big-Ass Tank
container.bombMulti=Mehrzweckbombe
container.casingBag=Hülsentasche
container.catalyticReformer=Katalytischer Reformer
@ -4414,6 +4415,7 @@ tile.machine_battery_potato.name=Kartoffelbatterieblock (LEGACY)
tile.machine_battery_redd.name=FEnSU
tile.machine_battery_socket.name=Batteriesockel
tile.machine_battery_socket.desc=Erlaubt es, Batterien direkt mit$dem Stromnetz zu verbinden.$Verhält sich wie ein Kabel, alle$Verbindungen sind im selben Netzwek.
tile.machine_bigasstank.name=Big-Ass Tank
tile.machine_boiler.name=Boiler
tile.machine_boiler.desc=Großer Boiler zum Verdampfen von Wasser oder$Erhitzen von Öl. Benötigt externe Hitzequelle.$Wärmestransferrate: ΔT*0.1 TU/t
tile.machine_boiler_electric_off.name=Elektrischer Ölwärmer

View File

@ -624,6 +624,7 @@ container.bat9000=Big-Ass Tank 9000
container.battery=Energy Storage
container.batteryREDD=FEnSU
container.batterySocket=Battery Socket
container.bigAssTank=Big-Ass Tank
container.bombMulti=Multi Purpose Bomb
container.casingBag=Bullet Casing Bag
container.catalyticReformer=Catalytic Reformer
@ -5662,6 +5663,7 @@ tile.machine_battery_potato.name=Potato Battery Block (LEGACY)
tile.machine_battery_redd.name=FEnSU
tile.machine_battery_socket.name=Battery Socket
tile.machine_battery_socket.desc=Allows battery items to be connected$to the power grid directly.$Acts as a cable, all ports are connected$to the same network.
tile.machine_bigasstank.name=Big-Ass Tank
tile.machine_boiler.name=Boiler
tile.machine_boiler.desc=Large boiler that can boil water or heat up oil.$Requires external heat source.$Heat transfer rate: ΔT*0.1 TU/t
tile.machine_boiler_electric_off.name=Electric Oil Heater