Logic constant optimizations / Display admins on top

This commit is contained in:
Anuken
2020-12-07 12:51:31 -05:00
parent b4e7928622
commit 5654e3120d
6 changed files with 123 additions and 62 deletions

View File

@@ -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<ServerGroup> 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();

View File

@@ -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.*/

View File

@@ -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<String> namesToIds = new ObjectIntMap<>();
private Seq<Var> 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;
}
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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<Player> 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);