mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-08-10 17:55:44 +00:00
Compare commits
4 Commits
e42bb12984
...
c99d1da3bf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c99d1da3bf | ||
|
|
7db05f01ec | ||
|
|
2556741a6f | ||
|
|
0074c20f91 |
@ -12,6 +12,13 @@
|
|||||||
* 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
|
* 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 harvest items from sunflowers and tall grass without breaking the blocks
|
||||||
* Can also handle tall plants like cacti and sugar cane
|
* 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
|
||||||
|
* AUTOCAL Automatic Calculator
|
||||||
|
* Highly advanced programmable RoR device
|
||||||
|
* Can send and receive signals and do calculations with the same system as NTM's calculator
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
* RoR graphs can now have their min and max bounds set to a fixed number
|
* RoR graphs can now have their min and max bounds set to a fixed number
|
||||||
@ -29,7 +36,7 @@
|
|||||||
* Increased the yield of lye from wood ash
|
* 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
|
* 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
|
* 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 stinger is now classified as a special weapon
|
||||||
* The carbine can now take a scope
|
* 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
|
* The battery socket now renders supports when a block is placed on top of it, allowing somewhat aesthetic stacking of sockets
|
||||||
|
|||||||
@ -778,6 +778,7 @@ public class ModBlocks {
|
|||||||
public static Block radio_torch_reader;
|
public static Block radio_torch_reader;
|
||||||
public static Block radio_torch_controller;
|
public static Block radio_torch_controller;
|
||||||
public static Block radio_telex;
|
public static Block radio_telex;
|
||||||
|
public static Block radio_autocal;
|
||||||
public static Block oc_cable_paintable;
|
public static Block oc_cable_paintable;
|
||||||
|
|
||||||
public static Block conveyor;
|
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_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_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_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 = 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");
|
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_reader);
|
||||||
register(radio_torch_controller);
|
register(radio_torch_controller);
|
||||||
register(radio_telex);
|
register(radio_telex);
|
||||||
|
register(radio_autocal);
|
||||||
|
|
||||||
register(crane_extractor);
|
register(crane_extractor);
|
||||||
register(crane_inserter);
|
register(crane_inserter);
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import net.minecraftforge.common.util.ForgeDirection;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class MachineBigAssTank9000 extends BlockDummyable implements IPersistentInfoProvider {
|
public class MachineBigAssTank9000 extends BlockDummyable implements IPersistentInfoProvider {
|
||||||
|
|
||||||
public MachineBigAssTank9000(Material mat) {
|
public MachineBigAssTank9000(Material mat) {
|
||||||
|
|||||||
38
src/main/java/com/hbm/blocks/network/RadioAUTOCAL.java
Normal file
38
src/main/java/com/hbm/blocks/network/RadioAUTOCAL.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package com.hbm.blocks.network;
|
||||||
|
|
||||||
|
import com.hbm.blocks.BlockDummyable;
|
||||||
|
import com.hbm.main.MainRegistry;
|
||||||
|
import com.hbm.tileentity.network.TileEntityRadioAUTOCAL;
|
||||||
|
|
||||||
|
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
|
||||||
|
import net.minecraft.block.material.Material;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class RadioAUTOCAL extends BlockDummyable {
|
||||||
|
|
||||||
|
public RadioAUTOCAL() {
|
||||||
|
super(Material.iron);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileEntity createNewTileEntity(World world, int meta) {
|
||||||
|
if(meta >= 12) return new TileEntityRadioAUTOCAL();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int[] getDimensions() { return new int[] {1, 0, 0, 0, 0 ,0}; }
|
||||||
|
@Override public int getOffset() { return 0; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
|
||||||
|
if(player.isSneaking()) return false;
|
||||||
|
if(world.isRemote) {
|
||||||
|
int[] pos = this.findCore(world, x, y, z);
|
||||||
|
if(pos == null) return false;
|
||||||
|
FMLNetworkHandler.openGui(player, MainRegistry.instance, 0, world, pos[0], pos[1], pos[2]);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -129,7 +129,7 @@ public class GeneralConfig {
|
|||||||
preferredOutputMod = CommonConfig.createConfigStringList(config,CATEGORY_GENERAL,"1.42_preferredOutputMod",
|
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});
|
"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);
|
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);
|
enableExpensiveMode = config.get(CATEGORY_GENERAL, "1.99_enableExpensiveMode", false, "It does what the name implies.").getBoolean(false);
|
||||||
|
|
||||||
final String CATEGORY_528 = CommonConfig.CATEGORY_528;
|
final String CATEGORY_528 = CommonConfig.CATEGORY_528;
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.hbm.inventory.gui;
|
package com.hbm.inventory.gui;
|
||||||
|
|
||||||
|
import com.hbm.util.Calculator;
|
||||||
import com.hbm.util.Tuple;
|
import com.hbm.util.Tuple;
|
||||||
|
|
||||||
import net.minecraft.client.gui.GuiScreen;
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
@ -12,8 +13,6 @@ import java.math.MathContext;
|
|||||||
import java.util.ArrayDeque;
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
public class GUICalculator extends GuiScreen {
|
public class GUICalculator extends GuiScreen {
|
||||||
private int xSize = 220;
|
private int xSize = 220;
|
||||||
@ -58,7 +57,7 @@ public class GUICalculator extends GuiScreen {
|
|||||||
selectedHist = -1;
|
selectedHist = -1;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
double result = evaluateExpression(input);
|
double result = Calculator.evaluateExpression(input);
|
||||||
history.addFirst(new Tuple.Pair<String,Double>(input, result));
|
history.addFirst(new Tuple.Pair<String,Double>(input, result));
|
||||||
if (history.size() > maxHistory) history.removeLast();
|
if (history.size() > maxHistory) history.removeLast();
|
||||||
String plainStringRepresentation = (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString();
|
String plainStringRepresentation = (new BigDecimal(result, MathContext.DECIMAL64)).toPlainString();
|
||||||
@ -85,7 +84,7 @@ public class GUICalculator extends GuiScreen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
latestResult = Double.toString(evaluateExpression(input));
|
latestResult = Double.toString(Calculator.evaluateExpression(input));
|
||||||
} catch (Exception e) { latestResult = e.toString(); }
|
} catch (Exception e) { latestResult = e.toString(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,203 +115,4 @@ public class GUICalculator extends GuiScreen {
|
|||||||
i++;
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
159
src/main/java/com/hbm/inventory/gui/GUIScreenRadioAUTOCAL.java
Normal file
159
src/main/java/com/hbm/inventory/gui/GUIScreenRadioAUTOCAL.java
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
package com.hbm.inventory.gui;
|
||||||
|
|
||||||
|
import java.awt.Desktop;
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import com.hbm.lib.RefStrings;
|
||||||
|
import com.hbm.main.MainRegistry;
|
||||||
|
import com.hbm.packet.PacketDispatcher;
|
||||||
|
import com.hbm.packet.toserver.NBTControlPacket;
|
||||||
|
import com.hbm.tileentity.network.TileEntityRadioAUTOCAL;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.audio.PositionedSoundRecord;
|
||||||
|
import net.minecraft.client.gui.GuiScreen;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.util.EnumChatFormatting;
|
||||||
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
|
public class GUIScreenRadioAUTOCAL extends GuiScreen {
|
||||||
|
|
||||||
|
protected static final ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/machine/gui_rtty_autocal.png");
|
||||||
|
protected TileEntityRadioAUTOCAL autocal;
|
||||||
|
|
||||||
|
protected int xSize = 150;
|
||||||
|
protected int ySize = 90;
|
||||||
|
protected int guiLeft;
|
||||||
|
protected int guiTop;
|
||||||
|
|
||||||
|
public GUIScreenRadioAUTOCAL(TileEntityRadioAUTOCAL autocal) {
|
||||||
|
this.autocal = autocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initGui() {
|
||||||
|
super.initGui();
|
||||||
|
this.guiLeft = (this.width - this.xSize) / 2;
|
||||||
|
this.guiTop = (this.height - this.ySize) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawScreen(int mouseX, int mouseY, float f) {
|
||||||
|
this.drawDefaultBackground();
|
||||||
|
this.drawGuiContainerBackgroundLayer(f, mouseX, mouseY);
|
||||||
|
GL11.glDisable(GL11.GL_LIGHTING);
|
||||||
|
this.drawGuiContainerForegroundLayer(mouseX, mouseY);
|
||||||
|
GL11.glEnable(GL11.GL_LIGHTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void mouseClicked(int x, int y, int i) {
|
||||||
|
super.mouseClicked(x, y, i);
|
||||||
|
|
||||||
|
NBTTagCompound data = null;
|
||||||
|
|
||||||
|
if(checkClick(x, y, 8, 36, 18, 18)) { data = new NBTTagCompound(); data.setBoolean("on", true); }
|
||||||
|
if(checkClick(x, y, 28, 36, 18, 18)) { data = new NBTTagCompound(); data.setBoolean("ignore", true); }
|
||||||
|
if(checkClick(x, y, 48, 36, 18, 18)) { data = new NBTTagCompound(); data.setBoolean("auto", true); }
|
||||||
|
|
||||||
|
// open folder and generate new script file
|
||||||
|
if(checkClick(x, y, 104, 36, 18, 18)) {
|
||||||
|
try {
|
||||||
|
File uploadFolder = new File(MainRegistry.configDir.getParentFile(), "hbmComputerUpload");
|
||||||
|
File script = new File(uploadFolder, "script.txt");
|
||||||
|
if(!uploadFolder.exists()) uploadFolder.mkdir();
|
||||||
|
if(!script.exists()) script.createNewFile();
|
||||||
|
script.setExecutable(false);
|
||||||
|
Class oclass = Class.forName("java.awt.Desktop");
|
||||||
|
Object object = oclass.getMethod("getDesktop", new Class[0]).invoke((Object) null, new Object[0]);
|
||||||
|
oclass.getMethod("browse", new Class[] { URI.class }).invoke(object, new Object[] { script.toURI() });
|
||||||
|
//oclass.getMethod("edit", File.class).invoke(object, new Object[] { script });
|
||||||
|
} catch(Throwable ex) { MainRegistry.logger.error("Couldn't open link", ex); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if(checkClick(x, y, 84, 36, 18, 18)) {
|
||||||
|
try {
|
||||||
|
File uploadFolder = new File(MainRegistry.configDir.getParentFile(), "hbmComputerUpload");
|
||||||
|
File script = new File(uploadFolder, "script.txt");
|
||||||
|
if(!uploadFolder.exists()) uploadFolder.mkdir();
|
||||||
|
if(!script.exists()) {
|
||||||
|
script.createNewFile();
|
||||||
|
script.setExecutable(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/*FileReader reader = new FileReader(script);
|
||||||
|
BufferedReader buffer = new BufferedReader(reader);
|
||||||
|
String[] lines = buffer.lines().toArray(String[]::new);
|
||||||
|
buffer.close();
|
||||||
|
// this is going to blow the fuck up once we hit the max packet size, but let's ignore that for now
|
||||||
|
data = new NBTTagCompound();
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for(int l = 0; l < lines.length; l++) {
|
||||||
|
builder.append(lines[i]);
|
||||||
|
if(l < lines.length - 1) builder.append("\n"); // yeah why the fuck not
|
||||||
|
}
|
||||||
|
data.setString("payload", builder.toString());*/
|
||||||
|
byte[] bytes = Files.readAllBytes(Paths.get(script.toURI()));
|
||||||
|
data = new NBTTagCompound();
|
||||||
|
data.setString("payload", new String(bytes, StandardCharsets.UTF_8));
|
||||||
|
|
||||||
|
} catch(Throwable ex) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
// this thing can both upload and download files so let's be careful about this
|
||||||
|
// the upload is simple, it's just text that is handled by the AUTOCAL, so doing anything malicious isn't more likely than with any other package
|
||||||
|
// download is iffy, because we take text from the server, fully user-definable, and save it to disk. it's stored as a txt so accudentally running it
|
||||||
|
// or getting it to run itself, should it be a malicious script, is unlikely. still, we want to minimized the chances as much as we can
|
||||||
|
// option 1: set file attribute to disallow running (i.e. disable executable perm)
|
||||||
|
// option 2: add fluff that would break scripts, however they might work. we can't change the actual lines because we want the script to be edited,
|
||||||
|
// but we can add some extra crap that would either halt common scripting langs entirely or at least disrupt them into not functioning
|
||||||
|
// option 3: enforce validation so only MS-ES1 script can be received by the client. this means that info such as comments or incorrectly written commands
|
||||||
|
// are lost, however this is the safest way because it becomes impossible to send malicious code, but it also interferes with regular user operation more
|
||||||
|
|
||||||
|
if(data != null) {
|
||||||
|
mc.getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F));
|
||||||
|
PacketDispatcher.wrapper.sendToServer(new NBTControlPacket(data, autocal.xCoord, autocal.yCoord, autocal.zCoord));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean checkClick(int x, int y, int left, int top, int sizeX, int sizeY) {
|
||||||
|
return guiLeft + left <= x && guiLeft + left + sizeX > x && guiTop + top < y && guiTop + top + sizeY >= y;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawGuiContainerForegroundLayer(int x, int y) {
|
||||||
|
|
||||||
|
if(checkClick(x, y, 8, 36, 18, 18)) this.func_146283_a(Arrays.asList(new String[] {EnumChatFormatting.RED + "ON/OFF"}), x, y);
|
||||||
|
if(checkClick(x, y, 28, 36, 18, 18)) this.func_146283_a(Arrays.asList(new String[] {EnumChatFormatting.RED + "Ignore Errors", "Skips instructions that error,", "leaving the computer turned on.", "May cause unintended behavior", "and inconsistencies."}), x, y);
|
||||||
|
if(checkClick(x, y, 48, 36, 18, 18)) this.func_146283_a(Arrays.asList(new String[] {EnumChatFormatting.RED + "Automatic Reboot", "Restarts the computer automatically when", "the program stops due to an error", "or after finishing."}), x, y);
|
||||||
|
|
||||||
|
if(checkClick(x, y, 84, 36, 18, 18)) this.func_146283_a(Arrays.asList(new String[] {EnumChatFormatting.BLUE + "Upload Program"}), x, y);
|
||||||
|
if(checkClick(x, y, 104, 36, 18, 18)) this.func_146283_a(Arrays.asList(new String[] {EnumChatFormatting.BLUE + "Open Program File"}), x, y);
|
||||||
|
if(checkClick(x, y, 124, 36, 18, 18)) this.func_146283_a(Arrays.asList(new String[] {EnumChatFormatting.BLUE + "Download Program", EnumChatFormatting.RED + "Currently unsupported!"}), x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawGuiContainerBackgroundLayer(float f, int mouseX, int mouseY) {
|
||||||
|
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
Minecraft.getMinecraft().getTextureManager().bindTexture(texture);
|
||||||
|
drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
|
||||||
|
|
||||||
|
if(autocal.isOn) drawTexturedModalRect(guiLeft + 8, guiTop + 36, 150, 0, 18, 18);
|
||||||
|
if(!autocal.ignoreError) drawTexturedModalRect(guiLeft + 28, guiTop + 36, 150, 18, 18, 18);
|
||||||
|
if(!autocal.autoReboot) drawTexturedModalRect(guiLeft + 48, guiTop + 36, 150, 36, 18, 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void keyTyped(char c, int b) {
|
||||||
|
if(b == 1 || b == Minecraft.getMinecraft().gameSettings.keyBindInventory.getKeyCode()) {
|
||||||
|
Minecraft.getMinecraft().thePlayer.closeScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean doesGuiPauseGame() { return false; }
|
||||||
|
}
|
||||||
@ -22,7 +22,7 @@ import net.minecraft.util.EnumChatFormatting;
|
|||||||
import net.minecraft.util.MathHelper;
|
import net.minecraft.util.MathHelper;
|
||||||
import net.minecraft.util.ResourceLocation;
|
import net.minecraft.util.ResourceLocation;
|
||||||
|
|
||||||
public class GuiScreenRadioTelex extends GuiScreen {
|
public class GUIScreenRadioTelex extends GuiScreen {
|
||||||
|
|
||||||
protected static final ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/machine/gui_telex.png");
|
protected static final ResourceLocation texture = new ResourceLocation(RefStrings.MODID + ":textures/gui/machine/gui_telex.png");
|
||||||
protected TileEntityRadioTelex telex;
|
protected TileEntityRadioTelex telex;
|
||||||
@ -37,7 +37,7 @@ public class GuiScreenRadioTelex extends GuiScreen {
|
|||||||
protected String[] txBuffer;
|
protected String[] txBuffer;
|
||||||
protected int cursorPos = 0;
|
protected int cursorPos = 0;
|
||||||
|
|
||||||
public GuiScreenRadioTelex(TileEntityRadioTelex tile) {
|
public GUIScreenRadioTelex(TileEntityRadioTelex tile) {
|
||||||
this.telex = tile;
|
this.telex = tile;
|
||||||
this.txBuffer = new String[tile.txBuffer.length];
|
this.txBuffer = new String[tile.txBuffer.length];
|
||||||
|
|
||||||
@ -358,6 +358,7 @@ public class ClientProxy extends ServerProxy {
|
|||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityPistonInserter.class, new RenderPistonInserter());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityPistonInserter.class, new RenderPistonInserter());
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityConveyorPress.class, new RenderConveyorPress());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityConveyorPress.class, new RenderConveyorPress());
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRadioTelex.class, new RenderTelex());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRadioTelex.class, new RenderTelex());
|
||||||
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityRadioAUTOCAL.class, new RenderAUTOCAL());
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachinePumpSteam.class, new RenderPump());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachinePumpSteam.class, new RenderPump());
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachinePumpElectric.class, new RenderPump());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachinePumpElectric.class, new RenderPump());
|
||||||
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineArcWelder.class, new RenderArcWelder());
|
ClientRegistry.bindTileEntitySpecialRenderer(TileEntityMachineArcWelder.class, new RenderArcWelder());
|
||||||
|
|||||||
@ -421,6 +421,7 @@ public class ResourceManager {
|
|||||||
|
|
||||||
//TELEX
|
//TELEX
|
||||||
public static final IModelCustom telex = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/machines/telex.obj"));
|
public static final IModelCustom telex = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/machines/telex.obj"));
|
||||||
|
public static final IModelCustom autocal = AdvancedModelLoader.loadModel(new ResourceLocation(RefStrings.MODID, "models/machines/autocal.obj"));
|
||||||
|
|
||||||
////Textures TEs
|
////Textures TEs
|
||||||
|
|
||||||
@ -877,6 +878,7 @@ public class ResourceManager {
|
|||||||
|
|
||||||
//TELEX
|
//TELEX
|
||||||
public static final ResourceLocation telex_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/telex.png");
|
public static final ResourceLocation telex_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/telex.png");
|
||||||
|
public static final ResourceLocation autocal_tex = new ResourceLocation(RefStrings.MODID, "textures/models/machines/autocal.png");
|
||||||
|
|
||||||
////Obj Items
|
////Obj Items
|
||||||
|
|
||||||
|
|||||||
50
src/main/java/com/hbm/module/IParse.java
Normal file
50
src/main/java/com/hbm/module/IParse.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
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 void generateJumpPoints(ParseContext ctx, String line, int index);
|
||||||
|
|
||||||
|
public static class ParseContext {
|
||||||
|
public World world;
|
||||||
|
public NBTTagCompound variables = new NBTTagCompound();
|
||||||
|
public HashMap<String, Integer> jmp = new HashMap();
|
||||||
|
|
||||||
|
public String buffer = "";
|
||||||
|
public int clockSpeed = 1;
|
||||||
|
public int current = 0;
|
||||||
|
|
||||||
|
public ParseContext(World world) {
|
||||||
|
this.world = world;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void turnOff() {
|
||||||
|
this.clockSpeed = 1;
|
||||||
|
this.current = 0;
|
||||||
|
this.buffer = "";
|
||||||
|
if(!this.variables.hasNoTags()) this.variables = new NBTTagCompound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum EnumStatementReturn {
|
||||||
|
/** The command executed correctly (more or less) */
|
||||||
|
OK,
|
||||||
|
/** The command hasn't been recognized */
|
||||||
|
UNRECOGNIZED_COMMAND,
|
||||||
|
/** The expected parameters aren't present, or the parameters couldn't be parsed (i.e. using an undefined jump point) */
|
||||||
|
PARAMETER_ERROR,
|
||||||
|
/** Requests the AUTOCAL unit to end the tick, regardless of how many clock cycles are left */
|
||||||
|
END_TICK,
|
||||||
|
/** Requests an AUTOCAL shutdown */
|
||||||
|
SHUTDOWN,
|
||||||
|
/** Skips the instruction, doesn't use up a clock cycle */
|
||||||
|
SKIP,
|
||||||
|
/** General undefined behavior */
|
||||||
|
UNDEFINED
|
||||||
|
}
|
||||||
|
}
|
||||||
271
src/main/java/com/hbm/module/ParseMSES1.java
Normal file
271
src/main/java/com/hbm/module/ParseMSES1.java
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
package com.hbm.module;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import com.hbm.tileentity.network.RTTYSystem;
|
||||||
|
import com.hbm.tileentity.network.RTTYSystem.RTTYChannel;
|
||||||
|
import com.hbm.tileentity.network.TileEntityRadioAUTOCAL;
|
||||||
|
import com.hbm.util.Calculator;
|
||||||
|
|
||||||
|
public class ParseMSES1 implements IParse {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EnumStatementReturn eval(ParseContext ctx, String line) {
|
||||||
|
String lower = line.toLowerCase(Locale.US);
|
||||||
|
|
||||||
|
// jump point destination, skip
|
||||||
|
if(lower.startsWith("dest ") || lower.startsWith("# ")) {
|
||||||
|
return EnumStatementReturn.SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// no operation, still eats up a clock cycle
|
||||||
|
if(lower.equals("nop")) {
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the desired clock speed, then skips the operation
|
||||||
|
if(lower.startsWith("clockspeed ")) {
|
||||||
|
if(line.length() <= 11) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
int speed = Integer.parseInt(line.substring(11));
|
||||||
|
if(speed < 1 || speed > TileEntityRadioAUTOCAL.MAX_CLOCK_SPEED) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
ctx.clockSpeed = speed;
|
||||||
|
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.SKIP;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the script index to the jump point
|
||||||
|
if(lower.startsWith("jmp ")) {
|
||||||
|
if(line.length() <= 4) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
String jmpKey = line.substring(4);
|
||||||
|
if(ctx.jmp.containsKey(jmpKey)) {
|
||||||
|
ctx.current = ctx.jmp.get(jmpKey);
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the script index to the jump point, if the buffer is the string 'true'
|
||||||
|
if(lower.startsWith("jmpif ")) {
|
||||||
|
if(line.length() <= 6) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
if(!ctx.buffer.equals("true")) return EnumStatementReturn.OK;
|
||||||
|
String jmpKey = line.substring(6);
|
||||||
|
if(ctx.jmp.containsKey(jmpKey)) {
|
||||||
|
ctx.current = ctx.jmp.get(jmpKey);
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the script index to the jump point, if the buffer is the NOT 'true'
|
||||||
|
if(lower.startsWith("jmpnot ")) {
|
||||||
|
if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
if(ctx.buffer.equals("true")) return EnumStatementReturn.OK;
|
||||||
|
String jmpKey = line.substring(7);
|
||||||
|
if(ctx.jmp.containsKey(jmpKey)) {
|
||||||
|
ctx.current = ctx.jmp.get(jmpKey);
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ends the tick regardless of remaining clock cycles
|
||||||
|
if(lower.equals("endtick")) {
|
||||||
|
return EnumStatementReturn.END_TICK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// requests unit to shut down
|
||||||
|
if(lower.equals("shutdown")) {
|
||||||
|
return EnumStatementReturn.SHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
// loads the requested variable into the buffer
|
||||||
|
if(lower.startsWith("load ")) {
|
||||||
|
if(line.length() <= 5) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
ctx.buffer = ctx.variables.getString(line.substring(5));
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// saves the buffer with the specified name
|
||||||
|
if(lower.startsWith("save ")) {
|
||||||
|
if(line.length() <= 5 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
ctx.variables.setString(line.substring(5), ctx.buffer);
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stores the specified value in the buffer
|
||||||
|
if(lower.startsWith("buffer ")) {
|
||||||
|
if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
ctx.buffer = line.substring(7);
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// runs the calculation, allows string substitution, saves result to buffer
|
||||||
|
if(lower.startsWith("eval ")) {
|
||||||
|
if(line.length() <= 5) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
String statement = substitute(ctx, line.substring(5));
|
||||||
|
try {
|
||||||
|
double result = Calculator.evaluateExpression(statement);
|
||||||
|
ctx.buffer = "" + result;
|
||||||
|
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// runs the calculation, allows string substitution, rounds, saves result to buffer,
|
||||||
|
if(lower.startsWith("evalr ")) {
|
||||||
|
if(line.length() <= 6) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
String statement = substitute(ctx, line.substring(6));
|
||||||
|
try {
|
||||||
|
double result = Calculator.evaluateExpression(statement);
|
||||||
|
ctx.buffer = "" + (int) Math.round(result);
|
||||||
|
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// runs the calculation from the buffer, allows string substitution, saves result to buffer
|
||||||
|
if(lower.equals("evalr")) {
|
||||||
|
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
String statement = substitute(ctx, ctx.buffer);
|
||||||
|
try {
|
||||||
|
double result = Calculator.evaluateExpression(statement);
|
||||||
|
ctx.buffer = "" + (int) Math.round(result);
|
||||||
|
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rounds the buffer down to the nearest integer
|
||||||
|
if(lower.equals("rounddown") || lower.equals("floor")) {
|
||||||
|
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double d = Double.parseDouble(ctx.buffer);
|
||||||
|
ctx.buffer = "" + (int) Math.floor(d);
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rounds the buffer up to the nearest integer
|
||||||
|
if(lower.equals("roundup") || lower.equals("ceil")) {
|
||||||
|
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double d = Double.parseDouble(ctx.buffer);
|
||||||
|
ctx.buffer = "" + (int) Math.ceil(d);
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rounds the buffer to the nearest integer (.5 cutoff rule)
|
||||||
|
if(lower.equals("round") || lower.equals("nearest")) {
|
||||||
|
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double d = Double.parseDouble(ctx.buffer);
|
||||||
|
ctx.buffer = "" + (int) Math.round(d);
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// concatenate, same as buffer but evaluates $var$ substitutions
|
||||||
|
if(lower.startsWith("concat ")) {
|
||||||
|
if(line.length() <= 7 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
String concat = substitute(ctx, line.substring(5));
|
||||||
|
ctx.buffer = concat;
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// compares the buffer with a value, allows substitutions
|
||||||
|
if(lower.startsWith("eq ")) {
|
||||||
|
if(line.length() <= 3 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
ctx.buffer = ctx.buffer.equals(substitute(ctx, line.substring(3))) ? "true" : "false";
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// greater than buffer
|
||||||
|
if(lower.startsWith("gtb ")) {
|
||||||
|
if(line.length() <= 3 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double buffer = Double.parseDouble(ctx.buffer);
|
||||||
|
double val = Double.parseDouble(line.substring(3));
|
||||||
|
ctx.buffer = val > buffer ? "true" : "false";
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lower than buffer
|
||||||
|
if(lower.startsWith("ltb ")) {
|
||||||
|
if(line.length() <= 3 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double buffer = Double.parseDouble(ctx.buffer);
|
||||||
|
double val = Double.parseDouble(line.substring(3));
|
||||||
|
ctx.buffer = val < buffer ? "true" : "false";
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// greater than or equal buffer
|
||||||
|
if(lower.startsWith("geb ")) {
|
||||||
|
if(line.length() <= 3 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double buffer = Double.parseDouble(ctx.buffer);
|
||||||
|
double val = Double.parseDouble(line.substring(3));
|
||||||
|
ctx.buffer = val >= buffer ? "true" : "false";
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// lower than or equal buffer
|
||||||
|
if(lower.startsWith("leb ")) {
|
||||||
|
if(line.length() <= 3 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
try {
|
||||||
|
double buffer = Double.parseDouble(ctx.buffer);
|
||||||
|
double val = Double.parseDouble(line.substring(3));
|
||||||
|
ctx.buffer = val <= buffer ? "true" : "false";
|
||||||
|
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sends an RoR signal using the buffer's contents as the message over the supplied channel
|
||||||
|
if(lower.startsWith("send ")) {
|
||||||
|
if(line.length() <= 5 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
|
||||||
|
RTTYSystem.broadcast(ctx.world, line.substring(5), ctx.buffer);
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// listnes to an RoR signal using the buffer as the channel, then saves the signal to the buffer
|
||||||
|
if(lower.equals("listen")) {
|
||||||
|
// this picks up expired signals too, so polling has to be implemented by the user
|
||||||
|
RTTYChannel chan = RTTYSystem.listen(ctx.world, ctx.buffer);
|
||||||
|
if(chan != null) ctx.buffer = chan.signal + "";
|
||||||
|
return EnumStatementReturn.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EnumStatementReturn.UNRECOGNIZED_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String substitute(ParseContext ctx, String statement) {
|
||||||
|
if(!statement.contains("$")) return statement;
|
||||||
|
|
||||||
|
String[] frags = statement.split("\\$");
|
||||||
|
if(frags.length % 2 == 0 || frags.length < 3) return statement;
|
||||||
|
|
||||||
|
// since var names are enclosed with $ signs, we assume that every evenly numbered fragment is a var name
|
||||||
|
// example: 5 + $val1$ * $val2$ / (-$val3$)
|
||||||
|
// equals "5 + ", "val1", "* ", "val2", "/ (-", "val3", ")"
|
||||||
|
// 1 2 3 4 5 6 7
|
||||||
|
for(int i = 1; i < frags.length; i += 2) {
|
||||||
|
// special case, if we try to substitute $buffer$ then read the literal buffer
|
||||||
|
if(frags[i].equals("buffer")) {
|
||||||
|
frags[i] = ctx.buffer;
|
||||||
|
} else {
|
||||||
|
frags[i] = ctx.variables.getString(frags[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.join("", frags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generateJumpPoints(ParseContext ctx, String line, int index) {
|
||||||
|
if(line.startsWith("dest ") && line.length() > 5) {
|
||||||
|
ctx.jmp.put(line.substring(5), index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/main/java/com/hbm/render/tileentity/RenderAUTOCAL.java
Normal file
55
src/main/java/com/hbm/render/tileentity/RenderAUTOCAL.java
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
package com.hbm.render.tileentity;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL11;
|
||||||
|
|
||||||
|
import com.hbm.blocks.BlockDummyable;
|
||||||
|
import com.hbm.blocks.ModBlocks;
|
||||||
|
import com.hbm.main.ResourceManager;
|
||||||
|
import com.hbm.render.item.ItemRenderBase;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
import net.minecraftforge.client.IItemRenderer;
|
||||||
|
|
||||||
|
public class RenderAUTOCAL extends TileEntitySpecialRenderer implements IItemRendererProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderTileEntityAt(TileEntity tile, double x, double y, double z, float interp) {
|
||||||
|
GL11.glPushMatrix();
|
||||||
|
GL11.glTranslated(x + 0.5, y, z + 0.5);
|
||||||
|
GL11.glEnable(GL11.GL_LIGHTING);
|
||||||
|
GL11.glDisable(GL11.GL_CULL_FACE);
|
||||||
|
|
||||||
|
switch(tile.getBlockMetadata() - BlockDummyable.offset) {
|
||||||
|
case 2: GL11.glRotatef(90, 0F, 1F, 0F); break;
|
||||||
|
case 4: GL11.glRotatef(180, 0F, 1F, 0F); break;
|
||||||
|
case 3: GL11.glRotatef(270, 0F, 1F, 0F); break;
|
||||||
|
case 5: GL11.glRotatef(0, 0F, 1F, 0F); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bindTexture(ResourceManager.autocal_tex);
|
||||||
|
ResourceManager.autocal.renderAll();
|
||||||
|
|
||||||
|
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||||
|
GL11.glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Item getItemForRenderer() {
|
||||||
|
return Item.getItemFromBlock(ModBlocks.radio_autocal);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IItemRenderer getRenderer() {
|
||||||
|
return new ItemRenderBase( ) {
|
||||||
|
public void renderInventory() {
|
||||||
|
GL11.glTranslated(0, -4, 0);
|
||||||
|
GL11.glScaled(6.25, 6.25, 6.25);
|
||||||
|
}
|
||||||
|
public void renderCommon() {
|
||||||
|
bindTexture(ResourceManager.autocal_tex);
|
||||||
|
ResourceManager.autocal.renderAll();
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,17 +1,11 @@
|
|||||||
package com.hbm.tileentity;
|
package com.hbm.tileentity;
|
||||||
|
|
||||||
import net.minecraftforge.fluids.FluidTank;
|
|
||||||
|
|
||||||
public abstract class TileEntityTickingBase extends TileEntityLoadedBase {
|
public abstract class TileEntityTickingBase extends TileEntityLoadedBase {
|
||||||
|
|
||||||
public TileEntityTickingBase() { }
|
public TileEntityTickingBase() { }
|
||||||
|
|
||||||
public abstract String getInventoryName();
|
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
|
//abstracting this method forces child classes to implement it
|
||||||
//so i don't have to remember the fucking method name
|
//so i don't have to remember the fucking method name
|
||||||
//was it update? onUpdate? updateTile? did it have any args?
|
//was it update? onUpdate? updateTile? did it have any args?
|
||||||
|
|||||||
@ -480,6 +480,7 @@ public class TileMappings {
|
|||||||
put(TileEntityRadioTorchReader.class, "tileentity_rtty_reader");
|
put(TileEntityRadioTorchReader.class, "tileentity_rtty_reader");
|
||||||
put(TileEntityRadioTorchController.class, "tileentity_rtty_controller");
|
put(TileEntityRadioTorchController.class, "tileentity_rtty_controller");
|
||||||
put(TileEntityRadioTelex.class, "tileentity_rtty_telex");
|
put(TileEntityRadioTelex.class, "tileentity_rtty_telex");
|
||||||
|
put(TileEntityRadioAUTOCAL.class, "tileentity_rtty_autocal");
|
||||||
|
|
||||||
put(TileEntityDroneWaypoint.class, "tileentity_drone_waypoint");
|
put(TileEntityDroneWaypoint.class, "tileentity_drone_waypoint");
|
||||||
put(TileEntityDroneCrate.class, "tileentity_drone_crate");
|
put(TileEntityDroneCrate.class, "tileentity_drone_crate");
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import cpw.mods.fml.relauncher.Side;
|
|||||||
import cpw.mods.fml.relauncher.SideOnly;
|
import cpw.mods.fml.relauncher.SideOnly;
|
||||||
import net.minecraft.util.AxisAlignedBB;
|
import net.minecraft.util.AxisAlignedBB;
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public class TileEntityMachineBAT9000 extends TileEntityBarrel {
|
public class TileEntityMachineBAT9000 extends TileEntityBarrel {
|
||||||
|
|
||||||
public TileEntityMachineBAT9000() {
|
public TileEntityMachineBAT9000() {
|
||||||
|
|||||||
@ -0,0 +1,177 @@
|
|||||||
|
package com.hbm.tileentity.network;
|
||||||
|
|
||||||
|
import com.hbm.interfaces.IControlReceiver;
|
||||||
|
import com.hbm.inventory.gui.GUIScreenRadioAUTOCAL;
|
||||||
|
import com.hbm.module.IParse;
|
||||||
|
import com.hbm.module.IParse.EnumStatementReturn;
|
||||||
|
import com.hbm.module.IParse.ParseContext;
|
||||||
|
import com.hbm.module.ParseMSES1;
|
||||||
|
import com.hbm.tileentity.IGUIProvider;
|
||||||
|
import com.hbm.tileentity.TileEntityTickingBase;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
|
import net.minecraft.inventory.Container;
|
||||||
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
|
import net.minecraft.nbt.NBTTagList;
|
||||||
|
import net.minecraft.nbt.NBTTagString;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class TileEntityRadioAUTOCAL extends TileEntityTickingBase implements IControlReceiver, IGUIProvider {
|
||||||
|
|
||||||
|
public boolean isOn = false;
|
||||||
|
public boolean ignoreError = false;
|
||||||
|
public boolean autoReboot = false;
|
||||||
|
|
||||||
|
public static final int MAX_CLOCK_SPEED = 5;
|
||||||
|
|
||||||
|
public String[] script = new String[0];
|
||||||
|
public IParse msesv1 = new ParseMSES1();
|
||||||
|
public ParseContext ctx;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInventoryName() {
|
||||||
|
return "container.autocal";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateEntity() {
|
||||||
|
|
||||||
|
if(!worldObj.isRemote) {
|
||||||
|
|
||||||
|
if(this.worldObj.getTotalWorldTime() % 60 == 0) this.markChanged(); // ensure we're always saved to disk
|
||||||
|
|
||||||
|
if(this.ctx == null) {
|
||||||
|
this.ctx = new ParseContext(worldObj);
|
||||||
|
}
|
||||||
|
if(this.ctx.world != this.worldObj) this.ctx.world = this.worldObj;
|
||||||
|
|
||||||
|
if(!this.isOn && this.autoReboot) {
|
||||||
|
this.isOn = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this.isOn) {
|
||||||
|
|
||||||
|
int emergencyBrake = 100;
|
||||||
|
for(int i = 0; i < this.ctx.clockSpeed && emergencyBrake > 0; i++) {
|
||||||
|
emergencyBrake--;
|
||||||
|
|
||||||
|
if(this.ctx.current == this.script.length) { this.stop("Program has terminated"); break; }
|
||||||
|
if(this.ctx.current < 0 || this.ctx.current >= this.script.length) { this.stop("Program index is out of bounds"); break; }
|
||||||
|
|
||||||
|
try {
|
||||||
|
int index = this.ctx.current;
|
||||||
|
this.ctx.current ++;
|
||||||
|
EnumStatementReturn ret = msesv1.eval(ctx, this.script[index]);
|
||||||
|
if(ret == EnumStatementReturn.END_TICK) break;
|
||||||
|
if(ret == EnumStatementReturn.SHUTDOWN) this.stop("Program requested shutdown");
|
||||||
|
if(!this.ignoreError) {
|
||||||
|
if(ret == EnumStatementReturn.UNRECOGNIZED_COMMAND) this.stop("Unrecognized command");
|
||||||
|
if(ret == EnumStatementReturn.PARAMETER_ERROR) this.stop("Parameter error");
|
||||||
|
if(ret == EnumStatementReturn.UNDEFINED) this.stop("Undefined behavior");
|
||||||
|
}
|
||||||
|
if(ret == EnumStatementReturn.SKIP) i--;
|
||||||
|
} catch(Exception ex) {
|
||||||
|
this.stop("Evaluation unsuccessful");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.networkPackNT(15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop(String reason) {
|
||||||
|
this.isOn = false;
|
||||||
|
this.ctx.turnOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(ByteBuf buf) {
|
||||||
|
super.serialize(buf);
|
||||||
|
buf.writeBoolean(isOn);
|
||||||
|
buf.writeBoolean(ignoreError);
|
||||||
|
buf.writeBoolean(autoReboot);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deserialize(ByteBuf buf) {
|
||||||
|
super.deserialize(buf);
|
||||||
|
this.isOn = buf.readBoolean();
|
||||||
|
this.ignoreError = buf.readBoolean();
|
||||||
|
this.autoReboot = buf.readBoolean();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFromNBT(NBTTagCompound nbt) {
|
||||||
|
super.readFromNBT(nbt);
|
||||||
|
|
||||||
|
this.isOn = nbt.getBoolean("isOn");
|
||||||
|
this.ignoreError = nbt.getBoolean("ignoreError");
|
||||||
|
this.autoReboot = nbt.getBoolean("autoReboot");
|
||||||
|
|
||||||
|
this.ctx = new ParseContext(null);
|
||||||
|
this.ctx.current = nbt.getInteger("current");
|
||||||
|
this.ctx.clockSpeed = nbt.getInteger("clockSpeed");
|
||||||
|
this.ctx.buffer = nbt.getString("buffer");
|
||||||
|
|
||||||
|
NBTTagList lineList = nbt.getTagList("script", 8);
|
||||||
|
this.script = new String[lineList.tagList.size()];
|
||||||
|
for(int i = 0; i < script.length; i++) {
|
||||||
|
this.script[i] = lineList.getStringTagAt(i);
|
||||||
|
this.msesv1.generateJumpPoints(ctx, script[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ctx.variables = nbt.getCompoundTag("variables");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToNBT(NBTTagCompound nbt) {
|
||||||
|
super.writeToNBT(nbt);
|
||||||
|
|
||||||
|
nbt.setBoolean("isOn", isOn);
|
||||||
|
nbt.setBoolean("ignoreError", ignoreError);
|
||||||
|
nbt.setBoolean("autoReboot", autoReboot);
|
||||||
|
|
||||||
|
nbt.setInteger("current", ctx.current);
|
||||||
|
nbt.setInteger("clockSpeed", ctx.clockSpeed);
|
||||||
|
nbt.setString("buffer", ctx.buffer);
|
||||||
|
|
||||||
|
NBTTagList lineList = new NBTTagList();
|
||||||
|
for(String line : this.script) {
|
||||||
|
lineList.appendTag(new NBTTagString(line));
|
||||||
|
}
|
||||||
|
nbt.setTag("script", lineList);
|
||||||
|
nbt.setTag("variables", this.ctx.variables);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; }
|
||||||
|
@Override public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) { return new GUIScreenRadioAUTOCAL(this); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(EntityPlayer player) {
|
||||||
|
return player.getDistanceSq(xCoord + 0.5, yCoord + 1, zCoord + 0.5) <= 15 * 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void receiveControl(NBTTagCompound data) {
|
||||||
|
if(data.hasKey("on")) {
|
||||||
|
if(this.isOn) stop("User requested shutdown");
|
||||||
|
else this.isOn = true;
|
||||||
|
}
|
||||||
|
if(data.hasKey("ignore")) this.ignoreError = !this.ignoreError;
|
||||||
|
if(data.hasKey("auto")) this.autoReboot = !this.autoReboot;
|
||||||
|
|
||||||
|
if(data.hasKey("payload")) {
|
||||||
|
this.ctx.jmp.clear();
|
||||||
|
this.script = data.getString("payload").split("\n");
|
||||||
|
for(int i = 0; i < script.length; i++) {
|
||||||
|
script[i] = script[i].trim();
|
||||||
|
this.msesv1.generateJumpPoints(ctx, script[i], i);
|
||||||
|
}
|
||||||
|
if(this.isOn) stop("Script has changed");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.markChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import com.hbm.handler.CompatHandler;
|
import com.hbm.handler.CompatHandler;
|
||||||
import com.hbm.interfaces.IControlReceiver;
|
import com.hbm.interfaces.IControlReceiver;
|
||||||
import com.hbm.inventory.gui.GuiScreenRadioTelex;
|
import com.hbm.inventory.gui.GUIScreenRadioTelex;
|
||||||
import com.hbm.tileentity.IGUIProvider;
|
import com.hbm.tileentity.IGUIProvider;
|
||||||
import com.hbm.tileentity.TileEntityLoadedBase;
|
import com.hbm.tileentity.TileEntityLoadedBase;
|
||||||
import com.hbm.tileentity.network.RTTYSystem.RTTYChannel;
|
import com.hbm.tileentity.network.RTTYSystem.RTTYChannel;
|
||||||
@ -234,7 +234,7 @@ public class TileEntityRadioTelex extends TileEntityLoadedBase implements IContr
|
|||||||
@Override
|
@Override
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) {
|
public Object provideGUI(int ID, EntityPlayer player, World world, int x, int y, int z) {
|
||||||
return new GuiScreenRadioTelex(this);
|
return new GUIScreenRadioTelex(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
AxisAlignedBB bb = null;
|
AxisAlignedBB bb = null;
|
||||||
|
|||||||
208
src/main/java/com/hbm/util/Calculator.java
Normal file
208
src/main/java/com/hbm/util/Calculator.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -223,6 +223,7 @@ container.bat9000=Big-Ass Tank 9000
|
|||||||
container.battery=Energiespeicher
|
container.battery=Energiespeicher
|
||||||
container.batteryREDD=FEnSU
|
container.batteryREDD=FEnSU
|
||||||
container.batterySocket=Batteriesockel
|
container.batterySocket=Batteriesockel
|
||||||
|
container.bigAssTank=Big-Ass Tank
|
||||||
container.bombMulti=Mehrzweckbombe
|
container.bombMulti=Mehrzweckbombe
|
||||||
container.casingBag=Hülsentasche
|
container.casingBag=Hülsentasche
|
||||||
container.catalyticReformer=Katalytischer Reformer
|
container.catalyticReformer=Katalytischer Reformer
|
||||||
@ -4414,6 +4415,7 @@ tile.machine_battery_potato.name=Kartoffelbatterieblock (LEGACY)
|
|||||||
tile.machine_battery_redd.name=FEnSU
|
tile.machine_battery_redd.name=FEnSU
|
||||||
tile.machine_battery_socket.name=Batteriesockel
|
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_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.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.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
|
tile.machine_boiler_electric_off.name=Elektrischer Ölwärmer
|
||||||
@ -4760,6 +4762,7 @@ tile.pwr_port.desc=Erlaubt IO für Items und Flüssigkeiten$Platzierung: Hülle
|
|||||||
tile.pwr_reflector.name=PWR Neutronenreflektor
|
tile.pwr_reflector.name=PWR Neutronenreflektor
|
||||||
tile.pwr_reflector.desc=Reflektier Neutronen auf Brennstäbe zurück$Platzierung: Hülle, für höhere Reaktivität$Gültiger Block für Hülle
|
tile.pwr_reflector.desc=Reflektier Neutronen auf Brennstäbe zurück$Platzierung: Hülle, für höhere Reaktivität$Gültiger Block für Hülle
|
||||||
tile.radar_screen.name=Radarbildschirm
|
tile.radar_screen.name=Radarbildschirm
|
||||||
|
tile.radio_autocal.name=AUTOCAL-Rechenautomat
|
||||||
tile.radio_telex.name=Telex-Maschine
|
tile.radio_telex.name=Telex-Maschine
|
||||||
tile.radio_torch_controller.name=Redstone-over-Radio Controller
|
tile.radio_torch_controller.name=Redstone-over-Radio Controller
|
||||||
tile.radio_torch_controller.desc=Empfängt Steuersignale und gibt$sie an die verbundene Maschine weiter
|
tile.radio_torch_controller.desc=Empfängt Steuersignale und gibt$sie an die verbundene Maschine weiter
|
||||||
|
|||||||
@ -624,6 +624,7 @@ container.bat9000=Big-Ass Tank 9000
|
|||||||
container.battery=Energy Storage
|
container.battery=Energy Storage
|
||||||
container.batteryREDD=FEnSU
|
container.batteryREDD=FEnSU
|
||||||
container.batterySocket=Battery Socket
|
container.batterySocket=Battery Socket
|
||||||
|
container.bigAssTank=Big-Ass Tank
|
||||||
container.bombMulti=Multi Purpose Bomb
|
container.bombMulti=Multi Purpose Bomb
|
||||||
container.casingBag=Bullet Casing Bag
|
container.casingBag=Bullet Casing Bag
|
||||||
container.catalyticReformer=Catalytic Reformer
|
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_redd.name=FEnSU
|
||||||
tile.machine_battery_socket.name=Battery Socket
|
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_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.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.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
|
tile.machine_boiler_electric_off.name=Electric Oil Heater
|
||||||
@ -6026,6 +6028,7 @@ tile.pwr_reflector.name=PWR Neutron Reflector
|
|||||||
tile.pwr_reflector.desc=Reflects neutrons back to fuel rods$Placement: Grid, for increased reactivity$Valid casing material
|
tile.pwr_reflector.desc=Reflects neutrons back to fuel rods$Placement: Grid, for increased reactivity$Valid casing material
|
||||||
tile.rad_lava_block.name=Volcanic Lava
|
tile.rad_lava_block.name=Volcanic Lava
|
||||||
tile.radar_screen.name=Radar Screen
|
tile.radar_screen.name=Radar Screen
|
||||||
|
tile.radio_autocal.name=AUTOCAL Automatic Calculator
|
||||||
tile.radio_telex.name=Telex Machine
|
tile.radio_telex.name=Telex Machine
|
||||||
tile.radio_torch_controller.name=Redstone-over-Radio Controller
|
tile.radio_torch_controller.name=Redstone-over-Radio Controller
|
||||||
tile.radio_torch_controller.desc=Can receive command signals and relays$them to the connected machine
|
tile.radio_torch_controller.desc=Can receive command signals and relays$them to the connected machine
|
||||||
|
|||||||
134
src/main/resources/assets/hbm/models/machines/autocal.obj
Normal file
134
src/main/resources/assets/hbm/models/machines/autocal.obj
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
# Blender v2.79 (sub 0) OBJ File: 'autocal.blend'
|
||||||
|
# www.blender.org
|
||||||
|
o Plane
|
||||||
|
v 0.500000 0.125000 0.375000
|
||||||
|
v 0.500000 0.125000 -0.375000
|
||||||
|
v 0.500000 1.500000 0.375000
|
||||||
|
v 0.500000 1.500000 -0.375000
|
||||||
|
v -0.500000 0.125000 0.375000
|
||||||
|
v 0.500000 0.000000 0.500000
|
||||||
|
v 0.500000 0.000000 -0.500000
|
||||||
|
v -0.500000 0.125000 -0.375000
|
||||||
|
v -0.500000 1.500000 0.375000
|
||||||
|
v 0.500000 2.000000 0.500000
|
||||||
|
v 0.500000 2.000000 -0.500000
|
||||||
|
v -0.500000 1.500000 -0.375000
|
||||||
|
v -0.500000 0.000000 -0.500000
|
||||||
|
v -0.500000 0.000000 0.500000
|
||||||
|
v -0.500000 2.000000 -0.500000
|
||||||
|
v -0.500000 2.000000 0.500000
|
||||||
|
v 0.437500 0.125000 0.375000
|
||||||
|
v 0.437500 0.125000 -0.375000
|
||||||
|
v 0.437500 1.500000 0.375000
|
||||||
|
v 0.437500 1.500000 -0.375000
|
||||||
|
v -0.437500 0.125000 -0.375000
|
||||||
|
v -0.437500 0.125000 0.375000
|
||||||
|
v -0.437500 1.500000 -0.375000
|
||||||
|
v -0.437500 1.500000 0.375000
|
||||||
|
v 0.501000 1.671875 0.375000
|
||||||
|
v 0.501000 1.578125 0.375000
|
||||||
|
v 0.501000 1.671875 -0.375000
|
||||||
|
v 0.501000 1.578125 -0.375000
|
||||||
|
vt 0.428571 0.000000
|
||||||
|
vt 0.285714 0.250000
|
||||||
|
vt 0.285714 0.000000
|
||||||
|
vt 0.285714 0.750000
|
||||||
|
vt 0.428571 1.000000
|
||||||
|
vt 0.285714 1.000000
|
||||||
|
vt 0.580357 0.640625
|
||||||
|
vt 0.687500 0.625000
|
||||||
|
vt 0.687500 0.640625
|
||||||
|
vt 0.821429 0.625000
|
||||||
|
vt 0.812500 0.281250
|
||||||
|
vt 0.821429 0.281250
|
||||||
|
vt 0.687500 0.265625
|
||||||
|
vt 0.580357 0.281250
|
||||||
|
vt 0.580357 0.265625
|
||||||
|
vt 0.303571 0.281250
|
||||||
|
vt 0.428571 0.250000
|
||||||
|
vt 0.410714 0.281250
|
||||||
|
vt 0.410714 0.625000
|
||||||
|
vt 0.303571 0.625000
|
||||||
|
vt 0.428571 0.750000
|
||||||
|
vt 0.571429 0.250000
|
||||||
|
vt 0.571429 0.750000
|
||||||
|
vt 0.142857 0.750000
|
||||||
|
vt 0.017857 0.281250
|
||||||
|
vt 0.142857 0.250000
|
||||||
|
vt 0.125000 0.281250
|
||||||
|
vt 0.125000 0.625000
|
||||||
|
vt 0.000000 0.750000
|
||||||
|
vt 0.017857 0.625000
|
||||||
|
vt 0.000000 0.250000
|
||||||
|
vt 0.705357 0.625000
|
||||||
|
vt 0.705357 0.281250
|
||||||
|
vt 0.687500 0.281250
|
||||||
|
vt 0.580357 0.625000
|
||||||
|
vt 0.696429 0.281250
|
||||||
|
vt 0.696429 0.625000
|
||||||
|
vt 0.571429 0.281250
|
||||||
|
vt 0.571429 0.625000
|
||||||
|
vt 0.696429 0.625000
|
||||||
|
vt 0.696429 0.281250
|
||||||
|
vt 0.812500 0.265625
|
||||||
|
vt 0.705357 0.265625
|
||||||
|
vt 0.705357 0.640625
|
||||||
|
vt 0.812500 0.625000
|
||||||
|
vt 0.812500 0.640625
|
||||||
|
vt 0.428571 0.750000
|
||||||
|
vt 1.000000 0.875000
|
||||||
|
vt 0.428571 0.875000
|
||||||
|
vt 1.000000 0.750000
|
||||||
|
vn 0.0000 -1.0000 0.0000
|
||||||
|
vn 0.0000 1.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 1.0000
|
||||||
|
vn 1.0000 0.0000 0.0000
|
||||||
|
vn 0.0000 0.0000 -1.0000
|
||||||
|
vn -1.0000 0.0000 0.0000
|
||||||
|
s off
|
||||||
|
f 13/1/1 6/2/1 14/3/1
|
||||||
|
f 10/4/2 15/5/2 16/6/2
|
||||||
|
f 12/7/1 24/8/1 9/9/1
|
||||||
|
f 4/10/3 18/11/3 2/12/3
|
||||||
|
f 5/13/2 21/14/2 8/15/2
|
||||||
|
f 1/16/4 7/17/4 2/18/4
|
||||||
|
f 4/19/4 10/4/4 3/20/4
|
||||||
|
f 4/19/4 7/17/4 11/21/4
|
||||||
|
f 3/20/4 6/2/4 1/16/4
|
||||||
|
f 11/21/5 13/22/5 15/23/5
|
||||||
|
f 16/24/3 6/2/3 10/4/3
|
||||||
|
f 8/25/6 14/26/6 5/27/6
|
||||||
|
f 9/28/6 15/29/6 12/30/6
|
||||||
|
f 12/30/6 13/31/6 8/25/6
|
||||||
|
f 9/28/6 14/26/6 16/24/6
|
||||||
|
f 18/11/4 19/32/4 17/33/4
|
||||||
|
f 22/34/6 23/35/6 21/14/6
|
||||||
|
f 1/36/5 19/32/5 3/37/5
|
||||||
|
f 8/38/3 23/35/3 12/39/3
|
||||||
|
f 9/40/5 22/34/5 5/41/5
|
||||||
|
f 2/42/2 17/33/2 1/43/2
|
||||||
|
f 3/44/1 20/45/1 4/46/1
|
||||||
|
f 26/47/4 27/48/4 25/49/4
|
||||||
|
f 13/1/1 7/17/1 6/2/1
|
||||||
|
f 10/4/2 11/21/2 15/5/2
|
||||||
|
f 12/7/1 23/35/1 24/8/1
|
||||||
|
f 4/10/3 20/45/3 18/11/3
|
||||||
|
f 5/13/2 22/34/2 21/14/2
|
||||||
|
f 1/16/4 6/2/4 7/17/4
|
||||||
|
f 4/19/4 11/21/4 10/4/4
|
||||||
|
f 4/19/4 2/18/4 7/17/4
|
||||||
|
f 3/20/4 10/4/4 6/2/4
|
||||||
|
f 11/21/5 7/17/5 13/22/5
|
||||||
|
f 16/24/3 14/26/3 6/2/3
|
||||||
|
f 8/25/6 13/31/6 14/26/6
|
||||||
|
f 9/28/6 16/24/6 15/29/6
|
||||||
|
f 12/30/6 15/29/6 13/31/6
|
||||||
|
f 9/28/6 5/27/6 14/26/6
|
||||||
|
f 18/11/4 20/45/4 19/32/4
|
||||||
|
f 22/34/6 24/8/6 23/35/6
|
||||||
|
f 1/36/5 17/33/5 19/32/5
|
||||||
|
f 8/38/3 21/14/3 23/35/3
|
||||||
|
f 9/40/5 24/8/5 22/34/5
|
||||||
|
f 2/42/2 18/11/2 17/33/2
|
||||||
|
f 3/44/1 19/32/1 20/45/1
|
||||||
|
f 26/47/4 28/50/4 27/48/4
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Loading…
x
Reference in New Issue
Block a user