MS-ES v1.1 (first extended instruction set, now with stacks and split)

This commit is contained in:
Boblet 2026-06-24 15:02:08 +02:00
parent 372c51e411
commit 5cee3ed8fa
11 changed files with 289 additions and 87 deletions

View File

@ -39,3 +39,4 @@
* Fixed some recipes not using ore dict when they should * Fixed some recipes not using ore dict when they should
* Fixed `anyBismoid` group not being a proper group, causing other mods' bismuth and arsenic to not be included * Fixed `anyBismoid` group not being a proper group, causing other mods' bismuth and arsenic to not be included
* Fixed RoR gauge not using SI suffixes on values below 0 * Fixed RoR gauge not using SI suffixes on values below 0
* Fixed AUTOCAL units not closing their GUI when the unit is destroyed

View File

@ -12,12 +12,7 @@ import com.hbm.blocks.machine.fusion.*;
import com.hbm.blocks.machine.pile.*; import com.hbm.blocks.machine.pile.*;
import com.hbm.blocks.machine.rbmk.*; import com.hbm.blocks.machine.rbmk.*;
import com.hbm.blocks.network.*; import com.hbm.blocks.network.*;
import com.hbm.blocks.network.pneumatic.PneumoStorageAccess; import com.hbm.blocks.network.pneumatic.*;
import com.hbm.blocks.network.pneumatic.PneumoStorageClutter;
import com.hbm.blocks.network.pneumatic.PneumoStorageImporter;
import com.hbm.blocks.network.pneumatic.PneumoStorageMono;
import com.hbm.blocks.network.pneumatic.PneumoTube;
import com.hbm.blocks.network.pneumatic.PneumoTubePaintableBlock;
import com.hbm.blocks.rail.*; import com.hbm.blocks.rail.*;
import com.hbm.blocks.test.*; import com.hbm.blocks.test.*;
import com.hbm.blocks.turret.*; import com.hbm.blocks.turret.*;
@ -810,6 +805,7 @@ public class ModBlocks {
public static Block pneumatic_storage_clutter; public static Block pneumatic_storage_clutter;
public static Block pneumatic_storage_mono; public static Block pneumatic_storage_mono;
public static Block pneumatic_storage_importer; public static Block pneumatic_storage_importer;
public static Block pneumatic_storage_exporter;
public static Block fan; public static Block fan;
public static Block piston_inserter; public static Block piston_inserter;
@ -1915,6 +1911,7 @@ public class ModBlocks {
pneumatic_storage_clutter = new PneumoStorageClutter().setBlockName("pneumatic_storage_clutter").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_clutter"); pneumatic_storage_clutter = new PneumoStorageClutter().setBlockName("pneumatic_storage_clutter").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_clutter");
pneumatic_storage_mono = new PneumoStorageMono().setBlockName("pneumatic_storage_mono").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_mono"); pneumatic_storage_mono = new PneumoStorageMono().setBlockName("pneumatic_storage_mono").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_mono");
pneumatic_storage_importer = new PneumoStorageImporter().setBlockName("pneumatic_storage_importer").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_importer"); pneumatic_storage_importer = new PneumoStorageImporter().setBlockName("pneumatic_storage_importer").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_importer");
pneumatic_storage_exporter = new PneumoStorageExporter().setBlockName("pneumatic_storage_exporter").setStepSound(ModSoundTypes.pipe).setHardness(5.0F).setResistance(10.0F).setCreativeTab(null).setBlockTextureName(RefStrings.MODID + ":pneumatic_storage_exporter");
chain = new BlockChain(Material.iron).setBlockName("dungeon_chain").setHardness(0.25F).setResistance(2.0F).setCreativeTab(MainRegistry.blockTab).setBlockTextureName(RefStrings.MODID + ":chain"); chain = new BlockChain(Material.iron).setBlockName("dungeon_chain").setHardness(0.25F).setResistance(2.0F).setCreativeTab(MainRegistry.blockTab).setBlockTextureName(RefStrings.MODID + ":chain");
@ -3183,6 +3180,7 @@ public class ModBlocks {
register(pneumatic_storage_clutter); register(pneumatic_storage_clutter);
register(pneumatic_storage_mono); register(pneumatic_storage_mono);
register(pneumatic_storage_importer); register(pneumatic_storage_importer);
register(pneumatic_storage_exporter);
register(fan); register(fan);
register(piston_inserter); register(piston_inserter);

View File

@ -22,7 +22,7 @@ public class RadioAUTOCAL extends BlockDummyable {
return null; return null;
} }
@Override public int[] getDimensions() { return new int[] {1, 0, 0, 0, 0 ,0}; } @Override public int[] getDimensions() { return new int[] {1, 0, 0, 0, 0, 0}; }
@Override public int getOffset() { return 0; } @Override public int getOffset() { return 0; }
@Override @Override

View File

@ -0,0 +1,19 @@
package com.hbm.blocks.network.pneumatic;
import com.hbm.blocks.machine.BlockMachineBase;
import net.minecraft.block.material.Material;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
public class PneumoStorageExporter extends BlockMachineBase {
public PneumoStorageExporter() {
super(Material.iron, 0);
}
@Override
public TileEntity createNewTileEntity(World world, int meta) {
return null;
}
}

View File

@ -1,33 +1,20 @@
package com.hbm.blocks.network.pneumatic; package com.hbm.blocks.network.pneumatic;
import com.hbm.main.MainRegistry; import com.hbm.blocks.machine.BlockMachineBase;
import com.hbm.tileentity.network.pneumatic.TileEntityPneumoStorageImporter; import com.hbm.tileentity.network.pneumatic.TileEntityPneumoStorageImporter;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World; import net.minecraft.world.World;
public class PneumoStorageImporter extends BlockContainer { public class PneumoStorageImporter extends BlockMachineBase {
public PneumoStorageImporter() { public PneumoStorageImporter() {
super(Material.iron); super(Material.iron, 0);
} }
@Override @Override
public TileEntity createNewTileEntity(World world, int meta) { public TileEntity createNewTileEntity(World world, int meta) {
return new TileEntityPneumoStorageImporter(); return new TileEntityPneumoStorageImporter();
} }
@Override
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) {
if(world.isRemote) return true;
if(!player.isSneaking()) {
FMLNetworkHandler.openGui(player, MainRegistry.instance, 0, world, x, y, z);
return true;
}
return false;
}
} }

View File

@ -6,7 +6,11 @@ import com.hbm.tileentity.network.pneumatic.TileEntityPneumoStorageMono;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler; import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import net.minecraft.block.BlockContainer; import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -30,4 +34,46 @@ public class PneumoStorageMono extends BlockContainer {
} }
return false; return false;
} }
@Override
public boolean removedByPlayer(World world, EntityPlayer player, int x, int y, int z, boolean willHarvest) {
if(!player.capabilities.isCreativeMode && !world.isRemote && willHarvest) {
TileEntityPneumoStorageMono inv = (TileEntityPneumoStorageMono) world.getTileEntity(x, y, z);
ItemStack drop = new ItemStack(this);
NBTTagCompound nbt = new NBTTagCompound();
if(inv != null) {
for(int i = 0; i < 3; i++) {
ItemStack stack = inv.getStackInSlot(i);
if(stack == null) continue;
NBTTagCompound slot = new NBTTagCompound();
stack.writeToNBT(slot);
nbt.setTag("slot" + i, slot);
nbt.setInteger("amount" + i, inv.amounts[i]);
}
}
if(!nbt.hasNoTags()) drop.stackTagCompound = nbt;
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, drop));
}
return world.setBlockToAir(x, y, z);
}
@Override
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack stack) {
TileEntityPneumoStorageMono inv = (TileEntityPneumoStorageMono) world.getTileEntity(x, y, z);
if(inv != null && stack.hasTagCompound()) {
for(int i = 0; i < 3; i++) {
inv.setInventorySlotContents(i, ItemStack.loadItemStackFromNBT(stack.stackTagCompound.getCompoundTag("slot" + i)));
inv.amounts[i] = stack.stackTagCompound.getInteger("amount" + i);
}
}
super.onBlockPlacedBy(world, x, y, z, player, stack);
}
} }

View File

@ -64,6 +64,12 @@ public class GUIScreenRadioAUTOCAL extends GuiScreen {
@Override @Override
public void drawScreen(int mouseX, int mouseY, float f) { public void drawScreen(int mouseX, int mouseY, float f) {
if(this.autocal == null || this.autocal.isInvalid()) {
Minecraft.getMinecraft().thePlayer.closeScreen();
return;
}
this.drawDefaultBackground(); this.drawDefaultBackground();
this.drawGuiContainerBackgroundLayer(f, mouseX, mouseY); this.drawGuiContainerBackgroundLayer(f, mouseX, mouseY);
GL11.glDisable(GL11.GL_LIGHTING); GL11.glDisable(GL11.GL_LIGHTING);

View File

@ -15,12 +15,59 @@ public interface IParse {
public NBTTagCompound variables = new NBTTagCompound(); public NBTTagCompound variables = new NBTTagCompound();
public HashMap<String, Integer> jmp = new HashMap(); public HashMap<String, Integer> jmp = new HashMap();
public String buffer = ""; public static final int MAX_BUFFER_LENGTH = 256;
public static final int MAX_STACK_SIZE = 256;
private String buffer = "";
private String[] stack = new String[MAX_STACK_SIZE];
private int stackSize = 0;
public String splitString = ";";
public int clockSpeed = 1; public int clockSpeed = 1;
public int current = 0; public int current = 0;
public ParseContext(World world) { public ParseContext(World world) {
this.world = world; this.world = world;
for(int i = 0; i < MAX_STACK_SIZE; i++) stack[i] = "";
}
public String readBuffer() {
return this.buffer;
}
/** Sets the buffer and imposes length restrictions. Returns true if successful, and false if truncation has taken place. */
public boolean writeBuffer(String buffer) {
if(buffer.length() > MAX_BUFFER_LENGTH) {
this.buffer = buffer.substring(0, MAX_BUFFER_LENGTH);
return false;
}
this.buffer = buffer;
return true;
}
public boolean push(String line) {
if(stackSize >= MAX_STACK_SIZE) return false;
if(line.length() > MAX_BUFFER_LENGTH) line = line.substring(0, MAX_BUFFER_LENGTH);
stack[stackSize] = line;
stackSize++;
return true;
}
public String pop() {
if(stackSize <= 0) return null;
if(stackSize > MAX_STACK_SIZE) stackSize = MAX_STACK_SIZE;
String ret = stack[stackSize - 1];
stack[stackSize - 1] = "";
stackSize--;
return ret;
}
public String peek() {
if(stackSize <= 0) return null;
if(stackSize > MAX_STACK_SIZE) stackSize = MAX_STACK_SIZE;
return stack[stackSize - 1];
} }
public void turnOff() { public void turnOff() {
@ -29,6 +76,30 @@ public interface IParse {
this.buffer = ""; this.buffer = "";
if(!this.variables.hasNoTags()) this.variables = new NBTTagCompound(); if(!this.variables.hasNoTags()) this.variables = new NBTTagCompound();
} }
// NBT R/W is now in control of the CTX, meaning additions to the AUTOCAL runtime should be a lot easier
public void readFromNBT(NBTTagCompound nbt, String[] script, IParse parser) {
current = nbt.getInteger("current");
clockSpeed = nbt.getInteger("clockSpeed");
buffer = nbt.getString("buffer");
splitString = nbt.getString("splitString");
variables = nbt.getCompoundTag("variables");
stackSize = nbt.getInteger("stackSize");
for(int i = 0; i < MAX_STACK_SIZE; i++) stack[i] = nbt.getString("st" + i);
for(int i = 0; i < script.length; i++) parser.generateJumpPoints(this, script[i], i);
}
public void writeToNBT(NBTTagCompound nbt) {
nbt.setInteger("current", current);
nbt.setInteger("clockSpeed", clockSpeed);
nbt.setString("buffer", buffer);
nbt.setString("splitString", splitString);
nbt.setTag("variables", variables);
nbt.setInteger("stackSize", stackSize);
for(int i = 0; i < MAX_STACK_SIZE; i++) nbt.setString("st" + i, stack[i]);
}
} }
public static enum EnumStatementReturn { public static enum EnumStatementReturn {
@ -45,6 +116,8 @@ public interface IParse {
/** Skips the instruction, doesn't use up a clock cycle */ /** Skips the instruction, doesn't use up a clock cycle */
SKIP, SKIP,
/** General undefined behavior */ /** General undefined behavior */
UNDEFINED UNDEFINED,
/** Stack ran full */
STACK_EXCEEDED
} }
} }

View File

@ -48,7 +48,7 @@ public class ParseMSES1 implements IParse {
// sets the script index to the jump point, if the buffer is the string 'true' // sets the script index to the jump point, if the buffer is the string 'true'
if(lower.startsWith("jmpif ")) { if(lower.startsWith("jmpif ")) {
if(line.length() <= 6) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 6) return EnumStatementReturn.PARAMETER_ERROR;
if(!ctx.buffer.equals("true")) return EnumStatementReturn.OK; if(!ctx.readBuffer().equals("true")) return EnumStatementReturn.OK;
String jmpKey = substitute(ctx, line.substring(6), false); String jmpKey = substitute(ctx, line.substring(6), false);
if(ctx.jmp.containsKey(jmpKey)) { if(ctx.jmp.containsKey(jmpKey)) {
ctx.current = ctx.jmp.get(jmpKey); ctx.current = ctx.jmp.get(jmpKey);
@ -60,7 +60,7 @@ public class ParseMSES1 implements IParse {
// sets the script index to the jump point, if the buffer is the NOT 'true' // sets the script index to the jump point, if the buffer is the NOT 'true'
if(lower.startsWith("jmpnot ")) { if(lower.startsWith("jmpnot ")) {
if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR;
if(ctx.buffer.equals("true")) return EnumStatementReturn.OK; if(ctx.readBuffer().equals("true")) return EnumStatementReturn.OK;
String jmpKey = substitute(ctx, line.substring(7), false); String jmpKey = substitute(ctx, line.substring(7), false);
if(ctx.jmp.containsKey(jmpKey)) { if(ctx.jmp.containsKey(jmpKey)) {
ctx.current = ctx.jmp.get(jmpKey); ctx.current = ctx.jmp.get(jmpKey);
@ -82,21 +82,21 @@ public class ParseMSES1 implements IParse {
// loads the requested variable into the buffer // loads the requested variable into the buffer
if(lower.startsWith("load ")) { if(lower.startsWith("load ")) {
if(line.length() <= 5) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 5) return EnumStatementReturn.PARAMETER_ERROR;
ctx.buffer = ctx.variables.getString(line.substring(5)); ctx.writeBuffer(ctx.variables.getString(line.substring(5)));
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// saves the buffer with the specified name // saves the buffer with the specified name
if(lower.startsWith("save ")) { if(lower.startsWith("save ")) {
if(line.length() <= 5 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 5 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
ctx.variables.setString(line.substring(5), ctx.buffer); ctx.variables.setString(line.substring(5), ctx.readBuffer());
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// stores the specified value in the buffer // stores the specified value in the buffer
if(lower.startsWith("buffer ")) { if(lower.startsWith("buffer ")) {
if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR;
ctx.buffer = line.substring(7); ctx.writeBuffer(line.substring(7));
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
@ -106,7 +106,7 @@ public class ParseMSES1 implements IParse {
String statement = substitute(ctx, line.substring(5), true); String statement = substitute(ctx, line.substring(5), true);
try { try {
double result = Calculator.evaluateExpression(statement); double result = Calculator.evaluateExpression(statement);
ctx.buffer = "" + result; ctx.writeBuffer("" + result);
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
@ -117,115 +117,115 @@ public class ParseMSES1 implements IParse {
String statement = substitute(ctx, line.substring(6), true); String statement = substitute(ctx, line.substring(6), true);
try { try {
double result = Calculator.evaluateExpression(statement); double result = Calculator.evaluateExpression(statement);
ctx.buffer = "" + (int) Math.round(result); ctx.writeBuffer("" + (int) Math.round(result));
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// runs the calculation from the buffer, allows string substitution, saves result to buffer // runs the calculation from the buffer, allows string substitution, saves result to buffer
if(lower.equals("evalr")) { if(lower.equals("evalr")) {
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
String statement = substitute(ctx, ctx.buffer, true); String statement = substitute(ctx, ctx.readBuffer(), true);
try { try {
double result = Calculator.evaluateExpression(statement); double result = Calculator.evaluateExpression(statement);
ctx.buffer = "" + (int) Math.round(result); ctx.writeBuffer("" + (int) Math.round(result));
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// rounds the buffer down to the nearest integer // rounds the buffer down to the nearest integer
if(lower.equals("rounddown") || lower.equals("floor")) { if(lower.equals("rounddown") || lower.equals("floor")) {
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double d = Double.parseDouble(ctx.buffer); double d = Double.parseDouble(ctx.readBuffer());
ctx.buffer = "" + (int) Math.floor(d); ctx.writeBuffer("" + (int) Math.floor(d));
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// rounds the buffer up to the nearest integer // rounds the buffer up to the nearest integer
if(lower.equals("roundup") || lower.equals("ceil")) { if(lower.equals("roundup") || lower.equals("ceil")) {
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double d = Double.parseDouble(ctx.buffer); double d = Double.parseDouble(ctx.readBuffer());
ctx.buffer = "" + (int) Math.ceil(d); ctx.writeBuffer("" + (int) Math.ceil(d));
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// rounds the buffer to the nearest integer (.5 cutoff rule) // rounds the buffer to the nearest integer (.5 cutoff rule)
if(lower.equals("round") || lower.equals("nearest")) { if(lower.equals("round") || lower.equals("nearest")) {
if(ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double d = Double.parseDouble(ctx.buffer); double d = Double.parseDouble(ctx.readBuffer());
ctx.buffer = "" + (int) Math.round(d); ctx.writeBuffer("" + (int) Math.round(d));
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// concatenate, same as buffer but evaluates $var$ substitutions // concatenate, same as buffer but evaluates $var$ substitutions
if(lower.startsWith("concat ")) { if(lower.startsWith("concat ")) {
if(line.length() <= 7 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 7 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
String concat = substitute(ctx, line.substring(7), false); String concat = substitute(ctx, line.substring(7), false);
ctx.buffer = concat; ctx.writeBuffer(concat);
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// compares the buffer with a value, allows substitutions // compares the buffer with a value, allows substitutions
if(lower.startsWith("eq ")) { if(lower.startsWith("eq ")) {
if(line.length() <= 3 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 3 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
ctx.buffer = ctx.buffer.equals(substitute(ctx, line.substring(3), false)) ? "true" : "false"; ctx.writeBuffer(ctx.readBuffer().equals(substitute(ctx, line.substring(3), false)) ? "true" : "false");
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// greater than buffer // greater than buffer
if(lower.startsWith("gtb ")) { if(lower.startsWith("gtb ")) {
if(line.length() <= 4 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 4 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double buffer = Double.parseDouble(ctx.buffer); double buffer = Double.parseDouble(ctx.readBuffer());
double val = Double.parseDouble(substitute(ctx, line.substring(4), false)); double val = Double.parseDouble(substitute(ctx, line.substring(4), false));
ctx.buffer = val > buffer ? "true" : "false"; ctx.writeBuffer(val > buffer ? "true" : "false");
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// lower than buffer // lower than buffer
if(lower.startsWith("ltb ")) { if(lower.startsWith("ltb ")) {
if(line.length() <= 4 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 4 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double buffer = Double.parseDouble(ctx.buffer); double buffer = Double.parseDouble(ctx.readBuffer());
double val = Double.parseDouble(substitute(ctx, line.substring(4), false)); double val = Double.parseDouble(substitute(ctx, line.substring(4), false));
ctx.buffer = val < buffer ? "true" : "false"; ctx.writeBuffer(val < buffer ? "true" : "false");
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// greater than or equal buffer // greater than or equal buffer
if(lower.startsWith("geb ")) { if(lower.startsWith("geb ")) {
if(line.length() <= 4 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 4 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double buffer = Double.parseDouble(ctx.buffer); double buffer = Double.parseDouble(ctx.readBuffer());
double val = Double.parseDouble(substitute(ctx, line.substring(4), false)); double val = Double.parseDouble(substitute(ctx, line.substring(4), false));
ctx.buffer = val >= buffer ? "true" : "false"; ctx.writeBuffer(val >= buffer ? "true" : "false");
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// lower than or equal buffer // lower than or equal buffer
if(lower.startsWith("leb ")) { if(lower.startsWith("leb ")) {
if(line.length() <= 4 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 4 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
try { try {
double buffer = Double.parseDouble(ctx.buffer); double buffer = Double.parseDouble(ctx.readBuffer());
double val = Double.parseDouble(substitute(ctx, line.substring(4), false)); double val = Double.parseDouble(substitute(ctx, line.substring(4), false));
ctx.buffer = val <= buffer ? "true" : "false"; ctx.writeBuffer(val <= buffer ? "true" : "false");
} catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; } } catch(Exception ex) { return EnumStatementReturn.PARAMETER_ERROR; }
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
// sends an RoR signal using the buffer's contents as the message over the supplied channel // sends an RoR signal using the buffer's contents as the message over the supplied channel
if(lower.startsWith("send ")) { if(lower.startsWith("send ")) {
if(line.length() <= 5 || ctx.buffer.isEmpty()) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 5 || ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
RTTYSystem.broadcast(ctx.world, substitute(ctx, line.substring(5), false), ctx.buffer); RTTYSystem.broadcast(ctx.world, substitute(ctx, line.substring(5), false), ctx.readBuffer());
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
@ -233,7 +233,7 @@ public class ParseMSES1 implements IParse {
if(lower.startsWith("listen ")) { if(lower.startsWith("listen ")) {
if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR; if(line.length() <= 7) return EnumStatementReturn.PARAMETER_ERROR;
RTTYChannel chan = RTTYSystem.listen(ctx.world, substitute(ctx, line.substring(7), false)); RTTYChannel chan = RTTYSystem.listen(ctx.world, substitute(ctx, line.substring(7), false));
if(chan != null) ctx.buffer = chan.signal + ""; if(chan != null) ctx.writeBuffer(chan.signal + "");
return EnumStatementReturn.OK; return EnumStatementReturn.OK;
} }
@ -254,7 +254,7 @@ public class ParseMSES1 implements IParse {
readingVar = true; readingVar = true;
} else { } else {
if("buffer".equals(var)) { if("buffer".equals(var)) {
joined.append(ctx.buffer); joined.append(ctx.readBuffer());
} else { } else {
String variable = ctx.variables.getString(var.toString()); String variable = ctx.variables.getString(var.toString());
if(forceNumber && variable.isEmpty()) variable = "0"; if(forceNumber && variable.isEmpty()) variable = "0";

View File

@ -0,0 +1,82 @@
package com.hbm.module;
import java.util.Locale;
import java.util.regex.Pattern;
/**
* MSES1-FEIS: Machine Script, Equestrian Standard - First Extended Instruction Set (v1.1)
*
* Additions compared to v1 Standard:
* * Support for splitter chars, splitting and split count
* * Support for the stack, a secondary buffer that can push, pop and peek
*
* @author hbm
*/
public class ParseMSES1Ext1 extends ParseMSES1 {
@Override
public EnumStatementReturn eval(ParseContext ctx, String line) {
String lower = line.toLowerCase(Locale.US);
// sets the splitter char
if(lower.startsWith("splitter ")) {
if(line.length() <= 9) return EnumStatementReturn.PARAMETER_ERROR;
String splitter = substitute(ctx, line.substring(9), false);
ctx.splitString = splitter;
return EnumStatementReturn.OK;
}
// grabs a fragment based on index
if(lower.startsWith("split ")) {
if(line.length() <= 6) return EnumStatementReturn.PARAMETER_ERROR;
try {
int index = Integer.parseInt(line.substring(6));
if(index < 1) return EnumStatementReturn.PARAMETER_ERROR;
String[] frags = ctx.readBuffer().split(Pattern.quote(ctx.splitString));
if(index > frags.length) return EnumStatementReturn.PARAMETER_ERROR;
ctx.writeBuffer(frags[index - 1]);
return EnumStatementReturn.OK;
} catch(Throwable ex) { return EnumStatementReturn.PARAMETER_ERROR; }
}
// counts the amount of fragments in this string
if(lower.equals("splitcount")) {
if(ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
String[] frags = ctx.readBuffer().split(Pattern.quote(ctx.splitString));
ctx.writeBuffer(frags.length + "");
return EnumStatementReturn.OK;
}
// pushes the buffer to stack
if(lower.equals("push")) {
if(ctx.readBuffer().isEmpty()) return EnumStatementReturn.PARAMETER_ERROR;
boolean succ = ctx.push(ctx.readBuffer());
return succ ? EnumStatementReturn.OK : EnumStatementReturn.STACK_EXCEEDED;
}
// pushes the supplied value (or variable) to stack
if(lower.startsWith("push ")) {
if(line.length() <= 5) return EnumStatementReturn.PARAMETER_ERROR;
boolean succ = ctx.push(substitute(ctx, line.substring(5), false));
return succ ? EnumStatementReturn.OK : EnumStatementReturn.STACK_EXCEEDED;
}
// removes the most recent element from stack and writes it to the buffer
if(lower.equals("pop")) {
String val = ctx.pop();
if(val == null) return EnumStatementReturn.UNDEFINED;
ctx.writeBuffer(val);
return EnumStatementReturn.OK;
}
// writes the most recent element to the buffer
if(lower.equals("peek")) {
String val = ctx.peek();
if(val == null) return EnumStatementReturn.UNDEFINED;
ctx.writeBuffer(val);
return EnumStatementReturn.OK;
}
return super.eval(ctx, line);
}
}

View File

@ -5,7 +5,7 @@ import com.hbm.inventory.gui.GUIScreenRadioAUTOCAL;
import com.hbm.module.IParse; import com.hbm.module.IParse;
import com.hbm.module.IParse.EnumStatementReturn; import com.hbm.module.IParse.EnumStatementReturn;
import com.hbm.module.IParse.ParseContext; import com.hbm.module.IParse.ParseContext;
import com.hbm.module.ParseMSES1; import com.hbm.module.ParseMSES1Ext1;
import com.hbm.tileentity.IGUIProvider; import com.hbm.tileentity.IGUIProvider;
import com.hbm.tileentity.TileEntityTickingBase; import com.hbm.tileentity.TileEntityTickingBase;
import com.hbm.util.BufferUtil; import com.hbm.util.BufferUtil;
@ -27,10 +27,8 @@ public class TileEntityRadioAUTOCAL extends TileEntityTickingBase implements ICo
public boolean ignoreError = false; public boolean ignoreError = false;
public boolean autoReboot = false; public boolean autoReboot = false;
public static final int MAX_BUFFER_LENGTH = 256;
public String[] script = new String[0]; public String[] script = new String[0];
public IParse msesv1 = new ParseMSES1(); public IParse msesv1ext = new ParseMSES1Ext1();
public ParseContext ctx; public ParseContext ctx;
public String[] history = new String[] {"", "", "", "", "", ""}; public String[] history = new String[] {"", "", "", "", "", ""};
@ -69,16 +67,16 @@ public class TileEntityRadioAUTOCAL extends TileEntityTickingBase implements ICo
int index = this.ctx.current; int index = this.ctx.current;
this.ctx.current ++; this.ctx.current ++;
String line = this.script[index]; String line = this.script[index];
EnumStatementReturn ret = msesv1.eval(ctx, line); EnumStatementReturn ret = msesv1ext.eval(ctx, line);
if(ctx.buffer.length() > MAX_BUFFER_LENGTH) ctx.buffer = ctx.buffer.substring(0, MAX_BUFFER_LENGTH);
if(ret != EnumStatementReturn.SKIP) pushMsg(index + ": " + line); if(ret != EnumStatementReturn.SKIP) pushMsg(index + ": " + line);
this.history[0] = "Buffer: " + ctx.buffer; this.history[0] = "Buffer: " + ctx.readBuffer();
if(ret == EnumStatementReturn.END_TICK) break; if(ret == EnumStatementReturn.END_TICK) break;
if(ret == EnumStatementReturn.SHUTDOWN) this.stop("Program requested shutdown"); if(ret == EnumStatementReturn.SHUTDOWN) this.stop("Program requested shutdown");
if(!this.ignoreError) { if(!this.ignoreError) {
if(ret == EnumStatementReturn.UNRECOGNIZED_COMMAND) this.stop("Unrecognized command"); if(ret == EnumStatementReturn.UNRECOGNIZED_COMMAND) this.stop("Unrecognized command");
if(ret == EnumStatementReturn.PARAMETER_ERROR) this.stop("Parameter error"); if(ret == EnumStatementReturn.PARAMETER_ERROR) this.stop("Parameter error");
if(ret == EnumStatementReturn.UNDEFINED) this.stop("Undefined behavior"); if(ret == EnumStatementReturn.UNDEFINED) this.stop("Undefined behavior");
if(ret == EnumStatementReturn.STACK_EXCEEDED) this.stop("Stack exceeded capacity");
} }
if(ret == EnumStatementReturn.SKIP) i--; if(ret == EnumStatementReturn.SKIP) i--;
} catch(Exception ex) { } catch(Exception ex) {
@ -132,19 +130,14 @@ public class TileEntityRadioAUTOCAL extends TileEntityTickingBase implements ICo
this.ignoreError = nbt.getBoolean("ignoreError"); this.ignoreError = nbt.getBoolean("ignoreError");
this.autoReboot = nbt.getBoolean("autoReboot"); 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); NBTTagList lineList = nbt.getTagList("script", 8);
this.script = new String[lineList.tagList.size()]; this.script = new String[lineList.tagList.size()];
for(int i = 0; i < script.length; i++) { for(int i = 0; i < script.length; i++) {
this.script[i] = lineList.getStringTagAt(i); this.script[i] = lineList.getStringTagAt(i);
this.msesv1.generateJumpPoints(ctx, script[i], i);
} }
this.ctx.variables = nbt.getCompoundTag("variables"); this.ctx = new ParseContext(null);
this.ctx.readFromNBT(nbt, script, msesv1ext);
} }
@Override @Override
@ -155,16 +148,13 @@ public class TileEntityRadioAUTOCAL extends TileEntityTickingBase implements ICo
nbt.setBoolean("ignoreError", ignoreError); nbt.setBoolean("ignoreError", ignoreError);
nbt.setBoolean("autoReboot", autoReboot); nbt.setBoolean("autoReboot", autoReboot);
nbt.setInteger("current", ctx.current);
nbt.setInteger("clockSpeed", ctx.clockSpeed);
nbt.setString("buffer", ctx.buffer);
NBTTagList lineList = new NBTTagList(); NBTTagList lineList = new NBTTagList();
for(String line : this.script) { for(String line : this.script) {
lineList.appendTag(new NBTTagString(line)); lineList.appendTag(new NBTTagString(line));
} }
nbt.setTag("script", lineList); nbt.setTag("script", lineList);
nbt.setTag("variables", this.ctx.variables);
this.ctx.writeToNBT(nbt);
} }
@Override public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; } @Override public Container provideContainer(int ID, EntityPlayer player, World world, int x, int y, int z) { return null; }
@ -189,7 +179,7 @@ public class TileEntityRadioAUTOCAL extends TileEntityTickingBase implements ICo
this.script = data.getString("payload").split("\n"); this.script = data.getString("payload").split("\n");
for(int i = 0; i < script.length; i++) { for(int i = 0; i < script.length; i++) {
script[i] = script[i].trim(); script[i] = script[i].trim();
this.msesv1.generateJumpPoints(ctx, script[i], i); this.msesv1ext.generateJumpPoints(ctx, script[i], i);
} }
if(this.isOn) stop("Script has changed"); if(this.isOn) stop("Script has changed");
} }