From 5654e3120dfa0398e1199a1748c38b6e6b63208e Mon Sep 17 00:00:00 2001 From: Anuken Date: Mon, 7 Dec 2020 12:51:31 -0500 Subject: [PATCH] Logic constant optimizations / Display admins on top --- core/src/mindustry/Vars.java | 5 +- core/src/mindustry/core/ContentLoader.java | 1 + core/src/mindustry/logic/GlobalConstants.java | 78 +++++++++++++++++++ core/src/mindustry/logic/LAssembler.java | 45 ++--------- core/src/mindustry/logic/LExecutor.java | 44 ++++++----- .../ui/fragments/PlayerListFragment.java | 12 ++- 6 files changed, 123 insertions(+), 62 deletions(-) create mode 100644 core/src/mindustry/logic/GlobalConstants.java diff --git a/core/src/mindustry/Vars.java b/core/src/mindustry/Vars.java index 937e47c79e..d8928a434e 100644 --- a/core/src/mindustry/Vars.java +++ b/core/src/mindustry/Vars.java @@ -17,6 +17,7 @@ import mindustry.game.*; import mindustry.gen.*; import mindustry.input.*; import mindustry.io.*; +import mindustry.logic.*; import mindustry.maps.Map; import mindustry.maps.*; import mindustry.mod.*; @@ -68,7 +69,7 @@ public class Vars implements Loadable{ /** list of built-in servers.*/ public static final Seq defaultServers = Seq.with(); /** maximum size of any block, do not change unless you know what you're doing */ - public static final int maxBlockSize = 14; + public static final int maxBlockSize = 16; /** maximum distance between mine and core that supports automatic transferring */ public static final float mineTransferRange = 220f; /** max chat message length */ @@ -195,6 +196,7 @@ public class Vars implements Loadable{ public static BeControl becontrol; public static AsyncCore asyncCore; public static BaseRegistry bases; + public static GlobalConstants constants; public static Universe universe; public static World world; @@ -268,6 +270,7 @@ public class Vars implements Loadable{ indexer = new BlockIndexer(); pathfinder = new Pathfinder(); bases = new BaseRegistry(); + constants = new GlobalConstants(); state = new GameState(); diff --git a/core/src/mindustry/core/ContentLoader.java b/core/src/mindustry/core/ContentLoader.java index b7c0fbd0e0..c3c0918d44 100644 --- a/core/src/mindustry/core/ContentLoader.java +++ b/core/src/mindustry/core/ContentLoader.java @@ -96,6 +96,7 @@ public class ContentLoader{ /** Calls Content#init() on everything. Use only after all modules have been created.*/ public void init(){ initialize(Content::init); + if(constants != null) constants.init(); } /** Calls Content#load() on everything. Use only after all modules have been created on the client.*/ diff --git a/core/src/mindustry/logic/GlobalConstants.java b/core/src/mindustry/logic/GlobalConstants.java new file mode 100644 index 0000000000..eea74416c0 --- /dev/null +++ b/core/src/mindustry/logic/GlobalConstants.java @@ -0,0 +1,78 @@ +package mindustry.logic; + +import arc.struct.*; +import mindustry.*; +import mindustry.content.*; +import mindustry.logic.LExecutor.*; +import mindustry.type.*; +import mindustry.world.*; + +/** Stores global constants for logic processors. */ +public class GlobalConstants{ + private ObjectIntMap namesToIds = new ObjectIntMap<>(); + private Seq vars = new Seq<>(Var.class); + + public void init(){ + put("the end", null); + //add default constants + put("false", 0); + put("true", 1); + put("null", null); + + //store base content + + for(Item item : Vars.content.items()){ + put("@" + item.name, item); + } + + for(Liquid liquid : Vars.content.liquids()){ + put("@" + liquid.name, liquid); + } + + for(Block block : Vars.content.blocks()){ + if(block.synthetic()){ + put("@" + block.name, block); + } + } + + //used as a special value for any environmental solid block + put("@solid", Blocks.stoneWall); + put("@air", Blocks.air); + + for(UnitType type : Vars.content.units()){ + put("@" + type.name, type); + } + + //store sensor constants + for(LAccess sensor : LAccess.all){ + put("@" + sensor.name(), sensor); + } + } + + /** @return a constant ID > 0 if there is a constant with this name, otherwise -1. */ + public int get(String name){ + return namesToIds.get(name, -1); + } + + /** @return a constant variable by ID. ID is not bound checked and must be positive. */ + public Var get(int id){ + return vars.items[id]; + } + + /** Adds a constant value by name. */ + public Var put(String name, Object value){ + Var var = new Var(name); + var.constant = true; + if(value instanceof Number num){ + var.numval = num.doubleValue(); + }else{ + var.isobj = true; + var.objval = value; + } + + int index = vars.size; + namesToIds.put(name, index); + vars.add(var); + return var; + } +} diff --git a/core/src/mindustry/logic/LAssembler.java b/core/src/mindustry/logic/LAssembler.java index 560ac986ec..fe1c7e1267 100644 --- a/core/src/mindustry/logic/LAssembler.java +++ b/core/src/mindustry/logic/LAssembler.java @@ -4,12 +4,9 @@ import arc.func.*; import arc.struct.*; import arc.util.*; import mindustry.*; -import mindustry.content.*; import mindustry.gen.*; import mindustry.logic.LExecutor.*; import mindustry.logic.LStatements.*; -import mindustry.type.*; -import mindustry.world.*; /** "Compiles" a sequence of statements into instructions. */ public class LAssembler{ @@ -31,42 +28,6 @@ public class LAssembler{ putConst("@unit", null); //reference to self putConst("@this", null); - - //add default constants - putConst("false", 0); - putConst("true", 1); - putConst("null", null); - - //store base content (TODO hacky?) - - for(Item item : Vars.content.items()){ - putConst("@" + item.name, item); - } - - for(Liquid liquid : Vars.content.liquids()){ - putConst("@" + liquid.name, liquid); - } - - for(Block block : Vars.content.blocks()){ - if(block.synthetic()){ - putConst("@" + block.name, block); - } - } - - //used as a special value for any environmental solid block - putConst("@solid", Blocks.stoneWall); - - putConst("@air", Blocks.air); - - for(UnitType type : Vars.content.units()){ - putConst("@" + type.name, type); - } - - //store sensor constants - - for(LAccess sensor : LAccess.all){ - putConst("@" + sensor.name(), sensor); - } } public static LAssembler assemble(String data, int maxInstructions){ @@ -185,6 +146,12 @@ public class LAssembler{ /** @return a variable ID by name. * This may be a constant variable referring to a number or object. */ public int var(String symbol){ + int constId = Vars.constants.get(symbol); + if(constId > 0){ + //global constants are *negated* and stored separately + return -constId; + } + symbol = symbol.trim(); //string case diff --git a/core/src/mindustry/logic/LExecutor.java b/core/src/mindustry/logic/LExecutor.java index e2498fd431..6f667e8b95 100644 --- a/core/src/mindustry/logic/LExecutor.java +++ b/core/src/mindustry/logic/LExecutor.java @@ -97,28 +97,33 @@ public class LExecutor{ //region utility + public Var var(int index){ + //global constants have variable IDs < 0, and they are fetched from the global constants object after being negated + return index < 0 ? constants.get(-index) : vars[index]; + } + public @Nullable Building building(int index){ - Object o = vars[index].objval; - return vars[index].isobj && o instanceof Building building ? building : null; + Object o = var(index).objval; + return var(index).isobj && o instanceof Building building ? building : null; } public @Nullable Object obj(int index){ - Object o = vars[index].objval; - return vars[index].isobj ? o : null; + Object o = var(index).objval; + return var(index).isobj ? o : null; } public boolean bool(int index){ - Var v = vars[index]; + Var v = var(index); return v.isobj ? v.objval != null : Math.abs(v.numval) >= 0.00001; } public double num(int index){ - Var v = vars[index]; + Var v = var(index); return v.isobj ? v.objval != null ? 1 : 0 : Double.isNaN(v.numval) || Double.isInfinite(v.numval) ? 0 : v.numval; } public float numf(int index){ - Var v = vars[index]; + Var v = var(index); return v.isobj ? v.objval != null ? 1 : 0 : Double.isNaN(v.numval) || Double.isInfinite(v.numval) ? 0 : (float)v.numval; } @@ -131,7 +136,7 @@ public class LExecutor{ } public void setnum(int index, double value){ - Var v = vars[index]; + Var v = var(index); if(v.constant) return; v.numval = Double.isNaN(value) || Double.isInfinite(value) ? 0 : value; v.objval = null; @@ -139,20 +144,21 @@ public class LExecutor{ } public void setobj(int index, Object value){ - Var v = vars[index]; + Var v = var(index); if(v.constant) return; v.objval = value; v.isobj = true; } public void setconst(int index, Object value){ - Var v = vars[index]; + Var v = var(index); v.objval = value; v.isobj = true; } //endregion + /** A logic variable. */ public static class Var{ public final String name; @@ -735,8 +741,8 @@ public class LExecutor{ @Override public void run(LExecutor exec){ - Var v = exec.vars[to]; - Var f = exec.vars[from]; + Var v = exec.var(to); + Var f = exec.var(from); //TODO error out when the from-value is a constant if(!v.constant){ @@ -769,8 +775,8 @@ public class LExecutor{ if(op.unary){ exec.setnum(dest, op.function1.get(exec.num(a))); }else{ - Var va = exec.vars[a]; - Var vb = exec.vars[b]; + Var va = exec.var(a); + Var vb = exec.var(b); if(op.objFunction2 != null && (va.isobj || vb.isobj)){ //use object function if provided, and one of the variables is an object @@ -788,7 +794,7 @@ public class LExecutor{ @Override public void run(LExecutor exec){ - exec.vars[varCounter].numval = exec.instructions.length; + exec.var(varCounter).numval = exec.instructions.length; } } @@ -876,7 +882,7 @@ public class LExecutor{ if(exec.textBuffer.length() >= maxTextBuffer) return; //this should avoid any garbage allocation - Var v = exec.vars[value]; + Var v = exec.var(value); if(v.isobj && value != 0){ String strValue = v.objval == null ? "null" : @@ -940,8 +946,8 @@ public class LExecutor{ @Override public void run(LExecutor exec){ if(address != -1){ - Var va = exec.vars[value]; - Var vb = exec.vars[compare]; + Var va = exec.var(value); + Var vb = exec.var(compare); boolean cmp; if(op.objFunction != null && (va.isobj || vb.isobj)){ @@ -952,7 +958,7 @@ public class LExecutor{ } if(cmp){ - exec.vars[varCounter].numval = address; + exec.var(varCounter).numval = address; } } } diff --git a/core/src/mindustry/ui/fragments/PlayerListFragment.java b/core/src/mindustry/ui/fragments/PlayerListFragment.java index c006dcf3ff..392c6671c5 100644 --- a/core/src/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/mindustry/ui/fragments/PlayerListFragment.java @@ -6,6 +6,7 @@ import arc.scene.*; import arc.scene.event.*; import arc.scene.ui.*; import arc.scene.ui.layout.*; +import arc.struct.*; import arc.util.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -21,6 +22,7 @@ public class PlayerListFragment extends Fragment{ private Interval timer = new Interval(); private TextField sField; private boolean found = false; + private Seq players = new Seq<>(); @Override public void build(Group parent){ @@ -78,8 +80,12 @@ public class PlayerListFragment extends Fragment{ float h = 74f; found = false; - Groups.player.sort(Structs.comparing(Player::team)); - Groups.player.each(user -> { + players.clear(); + Groups.player.copy(players); + + players.sort(Structs.comps(Structs.comparing(Player::team), Structs.comparingBool(p -> !p.admin))); + + for(var user : players){ found = true; NetConnection connection = user.con; @@ -159,7 +165,7 @@ public class PlayerListFragment extends Fragment{ content.row(); content.image().height(4f).color(state.rules.pvp ? user.team().color : Pal.gray).growX(); content.row(); - }); + } if(!found){ content.add(Core.bundle.format("players.notfound")).padBottom(6).width(350f).maxHeight(h + 14);