Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@printbuffer #10499

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/assets/bundles/bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2506,6 +2506,7 @@ lglobal.@thisx = X coordinate of block executing the code
lglobal.@thisy = Y coordinate of block executing the code
lglobal.@links = Total number of blocks linked to this processors
lglobal.@ipt = Execution speed of the processor in instructions per tick (60 ticks = 1 second)
lglobal.@printbuffer = Print buffer of the processor

lglobal.@unitCount = Total number of types of unit content in the game; used with the lookup instruction
lglobal.@blockCount = Total number of types of block content in the game; used with the lookup instruction
Expand Down
4 changes: 4 additions & 0 deletions core/src/mindustry/io/TypeIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ public static void writeObject(Writes write, Object object){
}else if(object instanceof UnitCommand command){
write.b(23);
write.s(command.id);
}else if(object instanceof StringBuilder b){
write.b(24);
write.str(b.toString());
}else{
throw new IllegalArgumentException("Unknown object type: " + object.getClass());
}
Expand Down Expand Up @@ -205,6 +208,7 @@ public static Object readObjectBoxed(Reads read, boolean box){
yield objs;
}
case 23 -> content.unitCommand(read.us());
case 24 -> new StringBuilder(read.str());
default -> throw new IllegalArgumentException("Unknown object type: " + type);
};
}
Expand Down
5 changes: 3 additions & 2 deletions core/src/mindustry/logic/ConditionOp.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package mindustry.logic;

import arc.util.*;
import mindustry.logic.*;

public enum ConditionOp{
equal("==", (a, b) -> Math.abs(a - b) < 0.000001, Structs::eq),
notEqual("not", (a, b) -> Math.abs(a - b) >= 0.000001, (a, b) -> !Structs.eq(a, b)),
equal("==", (a, b) -> Math.abs(a - b) < 0.000001, LExecutor.OpI::equal),
notEqual("not", (a, b) -> Math.abs(a - b) >= 0.000001, (a, b) -> !LExecutor.OpI.equal(a, b)),
lessThan("<", (a, b) -> a < b),
lessThanEq("<=", (a, b) -> a <= b),
greaterThan(">", (a, b) -> a > b),
Expand Down
1 change: 1 addition & 0 deletions core/src/mindustry/logic/GlobalVars.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public void init(){
putEntryOnly("@thisy");
putEntryOnly("@links");
putEntryOnly("@ipt");
putEntryOnly("@printbuffer");

putEntryOnly("sectionGeneral");

Expand Down
58 changes: 51 additions & 7 deletions core/src/mindustry/logic/LExecutor.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public class LExecutor{
/** Non-constant variables used for network sync */
public LVar[] vars = {};

public LVar counter, unit, thisv, ipt;
public LVar counter, unit, thisv, ipt, printbuffer;

public int[] binds;
public boolean yield;
Expand All @@ -62,7 +62,7 @@ public class LExecutor{
//yes, this is a minor memory leak, but it's probably not significant enough to matter
protected static IntFloatMap unitTimeouts = new IntFloatMap();
//lookup variable by name, lazy init.
protected @Nullable ObjectIntMap<String> nameMap;
protected @Nullable ObjectIntMap<CharSequence> nameMap;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HashMap should use immutable class(String) as key.


static{
Events.on(ResetEvent.class, e -> unitTimeouts.clear());
Expand Down Expand Up @@ -105,12 +105,13 @@ public void load(LAssembler builder){
unit = builder.getVar("@unit");
thisv = builder.getVar("@this");
ipt = builder.putConst("@ipt", build != null ? build.ipt : 0);
printbuffer = builder.putConst("@printbuffer", textBuffer);
}

//region utility


public @Nullable LVar optionalVar(String name){
public @Nullable LVar optionalVar(CharSequence name){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you test this? Query with StringBuilder but String in Map.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gonna test it in a few hours

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i found a solution but cant fix it yet (nother 2 hours or so)

if(nameMap == null){
nameMap = new ObjectIntMap<>();
for(int i = 0; i < vars.length; i++){
Expand Down Expand Up @@ -571,7 +572,7 @@ public void run(LExecutor exec){

if(from instanceof MemoryBuild mem && (exec.privileged || (from.team == exec.team && !mem.block.privileged))){
output.setnum(address < 0 || address >= mem.memory.length ? 0 : mem.memory[address]);
}else if(from instanceof LogicBuild logic && (exec.privileged || (from.team == exec.team && !from.block.privileged)) && position.isobj && position.objval instanceof String name){
}else if(from instanceof LogicBuild logic && (exec.privileged || (from.team == exec.team && !from.block.privileged)) && position.isobj && position.objval instanceof CharSequence name){
LVar fromVar = logic.executor.optionalVar(name);
if(fromVar != null && !output.constant){
output.objval = fromVar.objval;
Expand Down Expand Up @@ -601,7 +602,7 @@ public void run(LExecutor exec){

if(from instanceof MemoryBuild mem && (exec.privileged || (from.team == exec.team && !mem.block.privileged)) && address >= 0 && address < mem.memory.length){
mem.memory[address] = value.num();
}else if(from instanceof LogicBuild logic && (exec.privileged || (from.team == exec.team && !from.block.privileged)) && position.isobj && position.objval instanceof String name){
}else if(from instanceof LogicBuild logic && (exec.privileged || (from.team == exec.team && !from.block.privileged)) && position.isobj && position.objval instanceof CharSequence name){
LVar toVar = logic.executor.optionalVar(name);
if(toVar != null && !toVar.constant){
toVar.objval = value.objval;
Expand Down Expand Up @@ -634,6 +635,11 @@ public void run(LExecutor exec){
return;
}

if(sense == LAccess.type && target instanceof CharSequence){
to.setobj(LogicDialog.typeName(from));
return;
}

//note that remote units/buildings can be sensed as well
if(target instanceof Senseable se){
if(sense instanceof Content co){
Expand Down Expand Up @@ -803,7 +809,10 @@ public OpI(LogicOp op, LVar a, LVar b, LVar dest){
@Override
public void run(LExecutor exec){
if(op == LogicOp.strictEqual){
dest.setnum(a.isobj == b.isobj && ((a.isobj && Structs.eq(a.objval, b.objval)) || (!a.isobj && a.numval == b.numval)) ? 1 : 0);
dest.setnum(a.isobj == b.isobj && (
(a.isobj && a.objval.getClass().equals(b.objval.getClass()) && a.objval instanceof CharSequence sa && b.objval instanceof CharSequence sb && strEquals(sa, sb)) ||
(a.isobj && Structs.eq(a.objval, b.objval)) ||
(!a.isobj && a.numval == b.numval)) ? 1 : 0);
}else if(op.unary){
dest.setnum(op.function1.get(a.num()));
}else{
Expand All @@ -817,6 +826,25 @@ public void run(LExecutor exec){

}
}

public static boolean strEquals(CharSequence a, CharSequence b){
//This should be faster than the other approach
if(a instanceof String || b instanceof String){
String p = a instanceof String sa ? sa : (String)b;
CharSequence s = p == a ? b : a;
return(p.contentEquals(s));
}
if(a.length()!=b.length()) return(false);
for(int i = 0; i < a.length(); i++){
if(a.charAt(i) != b.charAt(i)) return(false);
}
return(true);
}

public static boolean equal(Object a, Object b){
if(a instanceof CharSequence sa && b instanceof CharSequence sb) return(strEquals(sa, sb));
return(Structs.eq(a, b));
}
}

public static class EndI implements LInstruction{
Expand Down Expand Up @@ -989,6 +1017,12 @@ public void run(LExecutor exec){

//this should avoid any garbage allocation
if(value.isobj){

if(value.objval instanceof StringBuilder builder){
exec.textBuffer.append(builder);
return;
}

String strValue = toString(value.objval);

exec.textBuffer.append(strValue);
Expand All @@ -1006,6 +1040,7 @@ public static String toString(Object obj){
return
obj == null ? "null" :
obj instanceof String s ? s :
obj instanceof StringBuilder ? "[dyn-string]" : //Maybe use .toString, but it would allocate memory...
obj instanceof MappableContent content ? content.name :
obj instanceof Content ? "[content]" :
obj instanceof Building build ? build.block.name :
Expand Down Expand Up @@ -1073,6 +1108,12 @@ public void run(LExecutor exec){

//this should avoid any garbage allocation
if(value.isobj){
//avoid it even more
if(value.objval instanceof StringBuilder b){
exec.textBuffer.replace(placeholderIndex, placeholderIndex+3, "");
exec.textBuffer.insert(placeholderIndex,b);
return;
}
String strValue = PrintI.toString(value.objval);

exec.textBuffer.replace(placeholderIndex, placeholderIndex + 3, strValue);
Expand Down Expand Up @@ -1134,7 +1175,10 @@ public void run(LExecutor exec){
boolean cmp;

if(op == ConditionOp.strictEqual){
cmp = va.isobj == vb.isobj && ((va.isobj && va.objval == vb.objval) || (!va.isobj && va.numval == vb.numval));
cmp = va.isobj == vb.isobj && (
(va.isobj && va.objval.getClass().equals(vb.objval.getClass()) && va.objval instanceof CharSequence sa && vb.objval instanceof CharSequence sb && OpI.strEquals(sa, sb)) ||
(va.isobj && Structs.eq(va.objval, vb.objval)) ||
(!va.isobj && va.numval == vb.numval));
}else if(op.objFunction != null && va.isobj && vb.isobj){
//use object function if both are objects
cmp = op.objFunction.get(value.obj(), compare.obj());
Expand Down
3 changes: 2 additions & 1 deletion core/src/mindustry/logic/LogicDialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public static Color typeColor(LVar s, Color color){
return color.set(
!s.isobj ? Pal.place :
s.objval == null ? Color.darkGray :
s.objval instanceof String ? Pal.ammo :
s.objval instanceof CharSequence ? Pal.ammo :
s.objval instanceof Content ? Pal.logicOperations :
s.objval instanceof Building ? Pal.logicBlocks :
s.objval instanceof Unit ? Pal.logicUnits :
Expand All @@ -91,6 +91,7 @@ public static String typeName(LVar s){
!s.isobj ? "number" :
s.objval == null ? "null" :
s.objval instanceof String ? "string" :
s.objval instanceof StringBuilder ? "dyn-string" :
s.objval instanceof Content ? "content" :
s.objval instanceof Building ? "building" :
s.objval instanceof Team ? "team" :
Expand Down
5 changes: 3 additions & 2 deletions core/src/mindustry/logic/LogicOp.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import arc.math.*;
import arc.util.*;
import arc.util.noise.*;
import mindustry.logic.*;

public enum LogicOp{
add("+", (a, b) -> a + b),
Expand All @@ -13,8 +14,8 @@ public enum LogicOp{
mod("%", (a, b) -> a % b),
pow("^", Math::pow),

equal("==", (a, b) -> Math.abs(a - b) < 0.000001 ? 1 : 0, (a, b) -> Structs.eq(a, b) ? 1 : 0),
notEqual("not", (a, b) -> Math.abs(a - b) < 0.000001 ? 0 : 1, (a, b) -> !Structs.eq(a, b) ? 1 : 0),
equal("==", (a, b) -> Math.abs(a - b) < 0.000001 ? 1 : 0, (a, b) -> LExecutor.OpI.equal(a, b) ? 1 : 0),
notEqual("not", (a, b) -> Math.abs(a - b) < 0.000001 ? 0 : 1, (a, b) -> !LExecutor.OpI.equal(a, b) ? 1 : 0),
land("and", (a, b) -> a != 0 && b != 0 ? 1 : 0),
lessThan("<", (a, b) -> a < b ? 1 : 0),
lessThanEq("<=", (a, b) -> a <= b ? 1 : 0),
Expand Down