Logic progress
This commit is contained in:
@@ -45,6 +45,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
idleSound = Sounds.conveyor;
|
||||
idleSoundVolume = 0.004f;
|
||||
unloadable = false;
|
||||
noUpdateDisabled = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,7 +115,7 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
int frame = clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * timeScale())) % 4) : 0;
|
||||
int frame = enabled && clogHeat <= 0.5f ? (int)(((Time.time() * speed * 8f * timeScale())) % 4) : 0;
|
||||
|
||||
//draw extra conveyors facing this one for non-square tiling purposes
|
||||
Draw.z(Layer.blockUnder);
|
||||
@@ -208,10 +209,11 @@ public class Conveyor extends Block implements Autotiler{
|
||||
}
|
||||
|
||||
float nextMax = aligned ? 1f - Math.max(itemSpace - nextc.minitem, 0) : 1f;
|
||||
float moved = speed * edelta();
|
||||
|
||||
for(int i = len - 1; i >= 0; i--){
|
||||
float nextpos = (i == len - 1 ? 100f : ys[i + 1]) - itemSpace;
|
||||
float maxmove = Mathf.clamp(nextpos - ys[i], 0, speed * delta());
|
||||
float maxmove = Mathf.clamp(nextpos - ys[i], 0, moved);
|
||||
|
||||
ys[i] += maxmove;
|
||||
|
||||
|
||||
@@ -0,0 +1,293 @@
|
||||
package mindustry.world.blocks.logic;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.logic.LAssembler.*;
|
||||
import mindustry.logic.LExecutor.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class LogicBlock extends Block{
|
||||
private static final IntSeq removal = new IntSeq();
|
||||
|
||||
public int maxInstructionScale = 8;
|
||||
public int instructionsPerTick = 1;
|
||||
public float range = 8 * 10;
|
||||
public int memory = 16;
|
||||
|
||||
public LogicBlock(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
configurable = true;
|
||||
|
||||
config(String.class, (LogicEntity entity, String code) -> entity.updateCode(code));
|
||||
|
||||
config(Integer.class, (LogicEntity entity, Integer pos) -> {
|
||||
if(entity.connections.contains(pos)){
|
||||
entity.connections.removeValue(pos);
|
||||
}else{
|
||||
entity.connections.add(pos);
|
||||
}
|
||||
|
||||
entity.updateCode(entity.code);
|
||||
});
|
||||
}
|
||||
|
||||
public class LogicEntity extends Building{
|
||||
/** logic "source code" as list of asm statements */
|
||||
public String code = "";
|
||||
public LExecutor executor = new LExecutor();
|
||||
public float accumulator = 0;
|
||||
public IntSeq connections = new IntSeq();
|
||||
public boolean loaded = false;
|
||||
|
||||
public LogicEntity(){
|
||||
executor.memory = new double[memory];
|
||||
}
|
||||
|
||||
public void updateCode(String str){
|
||||
updateCode(str, null);
|
||||
}
|
||||
|
||||
public void updateCode(String str, Cons<LAssembler> assemble){
|
||||
if(str != null){
|
||||
code = str;
|
||||
|
||||
try{
|
||||
//create assembler to store extra variables
|
||||
LAssembler asm = LAssembler.assemble(str);
|
||||
|
||||
//store connections
|
||||
for(int i = 0; i < connections.size; i++){
|
||||
asm.putConst("@" + i, world.build(connections.get(i)));
|
||||
}
|
||||
|
||||
//store any older variables
|
||||
for(Var var : executor.vars){
|
||||
if(!var.constant){
|
||||
BVar dest = asm.getVar(var.name);
|
||||
if(dest != null && !dest.constant){
|
||||
dest.value = var.isobj ? var.objval : var.numval;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//inject any extra variables
|
||||
if(assemble != null){
|
||||
assemble.get(asm);
|
||||
}
|
||||
|
||||
asm.putConst("@this", this);
|
||||
|
||||
executor.load(asm);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
|
||||
//handle malformed code and replace it with nothing
|
||||
executor.load("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(){
|
||||
super.onProximityUpdate();
|
||||
|
||||
if(!loaded){
|
||||
//properly fetches connections
|
||||
updateCode(code);
|
||||
loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
//remove invalid links
|
||||
//TODO remove variables
|
||||
removal.clear();
|
||||
|
||||
for(int i = 0; i < connections.size; i++){
|
||||
int val = connections.get(i);
|
||||
if(!validLink(val)){
|
||||
removal.add(val);
|
||||
}
|
||||
}
|
||||
|
||||
if(!removal.isEmpty()){
|
||||
updateCode(code);
|
||||
}
|
||||
|
||||
connections.removeAll(removal);
|
||||
|
||||
accumulator += edelta() * instructionsPerTick;
|
||||
|
||||
if(accumulator > maxInstructionScale * instructionsPerTick) accumulator = maxInstructionScale * instructionsPerTick;
|
||||
|
||||
for(int i = 0; i < (int)accumulator; i++){
|
||||
if(executor.initialized()){
|
||||
executor.runOnce();
|
||||
}
|
||||
|
||||
accumulator --;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String config(){
|
||||
return code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawConfigure(){
|
||||
super.drawConfigure();
|
||||
|
||||
Drawf.circles(x, y, range);
|
||||
|
||||
for(int i = 0; i < connections.size; i++){
|
||||
int pos = connections.get(i);
|
||||
|
||||
if(validLink(pos)){
|
||||
Building other = Vars.world.build(pos);
|
||||
Drawf.square(other.x, other.y, other.block.size * tilesize / 2f + 1f, Pal.place);
|
||||
}
|
||||
}
|
||||
|
||||
//draw top text on separate layer
|
||||
for(int i = 0; i < connections.size; i++){
|
||||
int pos = connections.get(i);
|
||||
|
||||
if(validLink(pos)){
|
||||
Building other = Vars.world.build(pos);
|
||||
other.block.drawPlaceText("@" + i, other.tileX(), other.tileY(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validLink(int pos){
|
||||
Building other = Vars.world.build(pos);
|
||||
return other != null && other.team == team && other.within(this, range + other.block.size*tilesize/2f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildConfiguration(Table table){
|
||||
Table cont = new Table();
|
||||
cont.defaults().size(40);
|
||||
|
||||
cont.button(Icon.pencil, Styles.clearTransi, () -> {
|
||||
Vars.ui.logic.show(code, this::configure);
|
||||
});
|
||||
|
||||
//cont.button(Icon.refreshSmall, Styles.clearTransi, () -> {
|
||||
|
||||
//});
|
||||
|
||||
table.add(cont);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onConfigureTileTapped(Building other){
|
||||
if(this == other){
|
||||
return true;
|
||||
}
|
||||
|
||||
if(validLink(other.pos())){
|
||||
configure(other.pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
return super.onConfigureTileTapped(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
|
||||
write.str(code);
|
||||
write.s(connections.size);
|
||||
for(int i = 0; i < connections.size; i++){
|
||||
write.i(connections.get(i));
|
||||
}
|
||||
|
||||
//write only the non-constant variables
|
||||
int count = Structs.count(executor.vars, v -> !v.constant);
|
||||
|
||||
write.i(count);
|
||||
for(int i = 0; i < executor.vars.length; i++){
|
||||
Var v = executor.vars[i];
|
||||
|
||||
if(v.constant) continue;
|
||||
|
||||
//write the name and the object value
|
||||
write.str(v.name);
|
||||
|
||||
Object value = v.isobj ? v.objval : v.numval;
|
||||
TypeIO.writeObject(write, value);
|
||||
}
|
||||
|
||||
write.i(executor.memory.length);
|
||||
for(int i = 0; i < executor.memory.length; i++){
|
||||
write.d(executor.memory[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
|
||||
code = read.str();
|
||||
connections.clear();
|
||||
short total = read.s();
|
||||
for(int i = 0; i < total; i++){
|
||||
connections.add(read.i());
|
||||
}
|
||||
|
||||
int varcount = read.i();
|
||||
|
||||
//variables need to be temporarily stored in an array until they can be used
|
||||
String[] names = new String[varcount];
|
||||
Object[] values = new Object[varcount];
|
||||
|
||||
for(int i = 0; i < varcount; i++){
|
||||
String name = read.str();
|
||||
Object value = TypeIO.readObject(read);
|
||||
|
||||
names[i] = name;
|
||||
values[i] = value;
|
||||
}
|
||||
|
||||
int memory = read.i();
|
||||
double[] memorybank = executor.memory.length != memory ? new double[memory] : executor.memory;
|
||||
for(int i = 0; i < memory; i++){
|
||||
memorybank[i] = read.d();
|
||||
}
|
||||
|
||||
updateCode(code, asm -> {
|
||||
|
||||
//load up the variables that were stored
|
||||
for(int i = 0; i < varcount; i++){
|
||||
BVar dest = asm.getVar(names[i]);
|
||||
if(dest != null && !dest.constant){
|
||||
dest.value = values[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
executor.memory = memorybank;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package mindustry.world.blocks.logic;
|
||||
|
||||
import arc.util.io.*;
|
||||
import mindustry.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class LogicProcessor extends Block{
|
||||
|
||||
public LogicProcessor(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
configurable = true;
|
||||
|
||||
config(String.class, (LogicEntity entity, String code) -> {
|
||||
if(code != null){
|
||||
entity.code = code;
|
||||
|
||||
try{
|
||||
entity.executor.load(entity, code);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
|
||||
//handle malformed code and replace it with nothing
|
||||
entity.executor.load(entity, "");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public class LogicEntity extends Building{
|
||||
/** logic "source code" as list of json statements */
|
||||
String code = "";
|
||||
LExecutor executor = new LExecutor();
|
||||
|
||||
@Override
|
||||
public void updateTile(){
|
||||
if(executor.initialized()){
|
||||
executor.runOnce();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean configTapped(){
|
||||
Vars.ui.logic.show(code, this::configure);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
|
||||
write.str(code);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
|
||||
code = read.str();
|
||||
try{
|
||||
executor.load(this, code);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
|
||||
//handle malformed code and ignore it
|
||||
executor = new LExecutor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,9 @@ public class MessageBlock extends Block{
|
||||
throw new ValidateException(player, "Player has gone above text limit.");
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder(text.length());
|
||||
tile.message.ensureCapacity(text.length());
|
||||
tile.message.setLength(0);
|
||||
|
||||
text = text.trim();
|
||||
int count = 0;
|
||||
for(int i = 0; i < text.length(); i++){
|
||||
@@ -42,21 +44,17 @@ public class MessageBlock extends Block{
|
||||
if(c == '\n' || c == '\r'){
|
||||
count ++;
|
||||
if(count <= maxNewlines){
|
||||
result.append('\n');
|
||||
tile.message.append('\n');
|
||||
}
|
||||
}else{
|
||||
result.append(c);
|
||||
tile.message.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
tile.message = result.toString();
|
||||
tile.lines = tile.message.split("\n");
|
||||
});
|
||||
}
|
||||
|
||||
public class MessageBlockEntity extends Building{
|
||||
public String message = "";
|
||||
public String[] lines = {""};
|
||||
public StringBuilder message = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public void drawSelect(){
|
||||
@@ -68,7 +66,7 @@ public class MessageBlock extends Block{
|
||||
font.getData().setScale(1 / 4f / Scl.scl(1f));
|
||||
font.setUseIntegerPositions(false);
|
||||
|
||||
String text = message == null || message.isEmpty() ? "[lightgray]" + Core.bundle.get("empty") : message;
|
||||
CharSequence text = message == null || message.length() == 0 ? "[lightgray]" + Core.bundle.get("empty") : message;
|
||||
|
||||
l.setText(font, text, Color.white, 90f, Align.left, true);
|
||||
float offset = 1f;
|
||||
@@ -90,7 +88,7 @@ public class MessageBlock extends Block{
|
||||
table.button(Icon.pencil, () -> {
|
||||
if(mobile){
|
||||
Core.input.getTextInput(new TextInput(){{
|
||||
text = message;
|
||||
text = message.toString();
|
||||
multiline = true;
|
||||
maxLength = maxTextLength;
|
||||
accepted = str -> configure(str);
|
||||
@@ -98,7 +96,7 @@ public class MessageBlock extends Block{
|
||||
}else{
|
||||
BaseDialog dialog = new BaseDialog("@editmessage");
|
||||
dialog.setFillParent(false);
|
||||
TextArea a = dialog.cont.add(new TextArea(message.replace("\n", "\r"))).size(380f, 160f).get();
|
||||
TextArea a = dialog.cont.add(new TextArea(message.toString().replace("\n", "\r"))).size(380f, 160f).get();
|
||||
a.setFilter((textField, c) -> {
|
||||
if(c == '\n' || c == '\r'){
|
||||
int count = 0;
|
||||
@@ -127,6 +125,12 @@ public class MessageBlock extends Block{
|
||||
}).size(40f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleString(Object value){
|
||||
message.setLength(0);
|
||||
message.append(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTableAlign(Table table){
|
||||
Vec2 pos = Core.input.mouseScreen(x, y + size * tilesize / 2f + 1);
|
||||
@@ -135,19 +139,19 @@ public class MessageBlock extends Block{
|
||||
|
||||
@Override
|
||||
public String config(){
|
||||
return message;
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Writes write){
|
||||
super.write(write);
|
||||
write.str(message);
|
||||
write.str(message.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Reads read, byte revision){
|
||||
super.read(read, revision);
|
||||
message = read.str();
|
||||
message = new StringBuilder(read.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user