Logic wait & content look up instructions
This commit is contained in:
@@ -1591,6 +1591,8 @@ lst.sensor = Get data from a building or unit.
|
|||||||
lst.set = Set a variable.
|
lst.set = Set a variable.
|
||||||
lst.operation = Perform an operation on 1-2 variables.
|
lst.operation = Perform an operation on 1-2 variables.
|
||||||
lst.end = Jump to the top of the instruction stack.
|
lst.end = Jump to the top of the instruction stack.
|
||||||
|
lst.wait = Wait a certain number of seconds.
|
||||||
|
lst.lookup = Look up a item/liquid/unit/block type by ID.\nTotal counts of each type can be accessed with:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[]
|
||||||
lst.jump = Conditionally jump to another statement.
|
lst.jump = Conditionally jump to another statement.
|
||||||
lst.unitbind = Bind to the next unit of a type, and store it in [accent]@unit[].
|
lst.unitbind = Bind to the next unit of a type, and store it in [accent]@unit[].
|
||||||
lst.unitcontrol = Control the currently bound unit.
|
lst.unitcontrol = Control the currently bound unit.
|
||||||
|
|||||||
BIN
core/assets/logicids.dat
Normal file
BIN
core/assets/logicids.dat
Normal file
Binary file not shown.
@@ -126,6 +126,10 @@ public abstract class UnlockableContent extends MappableContent{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean logicVisible(){
|
||||||
|
return !isHidden();
|
||||||
|
}
|
||||||
|
|
||||||
/** Makes this piece of content unlocked; if it already unlocked, nothing happens. */
|
/** Makes this piece of content unlocked; if it already unlocked, nothing happens. */
|
||||||
public void unlock(){
|
public void unlock(){
|
||||||
if(!unlocked && !alwaysUnlocked){
|
if(!unlocked && !alwaysUnlocked){
|
||||||
|
|||||||
@@ -1,20 +1,28 @@
|
|||||||
package mindustry.logic;
|
package mindustry.logic;
|
||||||
|
|
||||||
|
import arc.*;
|
||||||
|
import arc.files.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
import mindustry.ctype.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.logic.LExecutor.*;
|
import mindustry.logic.LExecutor.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
/** Stores global constants for logic processors. */
|
/** Stores global constants for logic processors. */
|
||||||
public class GlobalConstants{
|
public class GlobalConstants{
|
||||||
public static final int ctrlProcessor = 1, ctrlPlayer = 2, ctrlFormation = 3;
|
public static final int ctrlProcessor = 1, ctrlPlayer = 2, ctrlFormation = 3;
|
||||||
|
public static final ContentType[] lookableContent = {ContentType.block, ContentType.unit, ContentType.item, ContentType.liquid};
|
||||||
|
|
||||||
private ObjectIntMap<String> namesToIds = new ObjectIntMap<>();
|
private ObjectIntMap<String> namesToIds = new ObjectIntMap<>();
|
||||||
private Seq<Var> vars = new Seq<>(Var.class);
|
private Seq<Var> vars = new Seq<>(Var.class);
|
||||||
|
private UnlockableContent[][] logicIdToContent;
|
||||||
|
private int[][] contentIdToLogicId;
|
||||||
|
|
||||||
public void init(){
|
public void init(){
|
||||||
put("the end", null);
|
put("the end", null);
|
||||||
@@ -61,6 +69,49 @@ public class GlobalConstants{
|
|||||||
for(UnitCommand cmd : UnitCommand.all){
|
for(UnitCommand cmd : UnitCommand.all){
|
||||||
put("@command" + Strings.capitalize(cmd.name()), cmd);
|
put("@command" + Strings.capitalize(cmd.name()), cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logicIdToContent = new UnlockableContent[ContentType.all.length][];
|
||||||
|
contentIdToLogicId = new int[ContentType.all.length][];
|
||||||
|
|
||||||
|
Fi ids = Core.files.internal("logicids.dat");
|
||||||
|
if(ids.exists()){
|
||||||
|
//read logic ID mapping data (generated in ImagePacker)
|
||||||
|
try(DataInputStream in = new DataInputStream(ids.readByteStream())){
|
||||||
|
for(ContentType ctype : lookableContent){
|
||||||
|
short amount = in.readShort();
|
||||||
|
logicIdToContent[ctype.ordinal()] = new UnlockableContent[amount];
|
||||||
|
contentIdToLogicId[ctype.ordinal()] = new int[Vars.content.getBy(ctype).size];
|
||||||
|
|
||||||
|
//store count constants
|
||||||
|
put("@" + ctype.name() + "Count", amount);
|
||||||
|
|
||||||
|
for(int i = 0; i < amount; i++){
|
||||||
|
String name = in.readUTF();
|
||||||
|
UnlockableContent fetched = Vars.content.getByName(ctype, name);
|
||||||
|
|
||||||
|
if(fetched != null){
|
||||||
|
logicIdToContent[ctype.ordinal()][i] = fetched;
|
||||||
|
contentIdToLogicId[ctype.ordinal()][fetched.id] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch(IOException e){
|
||||||
|
//don't crash?
|
||||||
|
Log.err("Error reading logic ID mapping", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return a piece of content based on its logic ID. This is not equivalent to content ID. */
|
||||||
|
public @Nullable Content lookupContent(ContentType type, int id){
|
||||||
|
var arr = logicIdToContent[type.ordinal()];
|
||||||
|
return arr != null && id >= 0 && id < arr.length ? arr[id] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the integer logic ID of content, or -1 if invalid. */
|
||||||
|
public int lookupLogicId(UnlockableContent content){
|
||||||
|
var arr = contentIdToLogicId[content.getContentType().ordinal()];
|
||||||
|
return arr != null && content.id >= 0 && content.id < arr.length ? arr[content.id] : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return a constant ID > 0 if there is a constant with this name, otherwise -1. */
|
/** @return a constant ID > 0 if there is a constant with this name, otherwise -1. */
|
||||||
|
|||||||
@@ -1023,6 +1023,26 @@ public class LExecutor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class LookupI implements LInstruction{
|
||||||
|
public int dest;
|
||||||
|
public int from;
|
||||||
|
public ContentType type;
|
||||||
|
|
||||||
|
public LookupI(int dest, int from, ContentType type){
|
||||||
|
this.dest = dest;
|
||||||
|
this.from = from;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LookupI(){
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(LExecutor exec){
|
||||||
|
exec.setobj(dest, constants.lookupContent(type, exec.numi(from)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import arc.scene.ui.*;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.ctype.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.logic.LCanvas.*;
|
import mindustry.logic.LCanvas.*;
|
||||||
@@ -662,8 +663,7 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO untested
|
@RegisterStatement("wait")
|
||||||
//@RegisterStatement("wait")
|
|
||||||
public static class WaitStatement extends LStatement{
|
public static class WaitStatement extends LStatement{
|
||||||
public String value = "0.5";
|
public String value = "0.5";
|
||||||
|
|
||||||
@@ -684,6 +684,42 @@ public class LStatements{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RegisterStatement("lookup")
|
||||||
|
public static class LookupStatement extends LStatement{
|
||||||
|
public ContentType type = ContentType.item;
|
||||||
|
public String result = "result", id = "0";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(Table table){
|
||||||
|
fields(table, result, str -> result = str);
|
||||||
|
|
||||||
|
table.add(" = lookup ");
|
||||||
|
|
||||||
|
row(table);
|
||||||
|
|
||||||
|
table.button(b -> {
|
||||||
|
b.label(() -> type.name());
|
||||||
|
b.clicked(() -> showSelect(b, GlobalConstants.lookableContent, type, o -> {
|
||||||
|
type = o;
|
||||||
|
}));
|
||||||
|
}, Styles.logict, () -> {}).size(64f, 40f).pad(4f).color(table.color);
|
||||||
|
|
||||||
|
table.add(" # ");
|
||||||
|
|
||||||
|
fields(table, id, str -> id = str);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color color(){
|
||||||
|
return Pal.logicOperations;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LInstruction build(LAssembler builder){
|
||||||
|
return new LookupI(builder.var(result), builder.var(id), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@RegisterStatement("end")
|
@RegisterStatement("end")
|
||||||
public static class EndStatement extends LStatement{
|
public static class EndStatement extends LStatement{
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -774,6 +774,11 @@ public class Block extends UnlockableContent{
|
|||||||
return ContentType.block;
|
return ContentType.block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean logicVisible(){
|
||||||
|
return buildVisibility != BuildVisibility.hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/** Called after all blocks are created. */
|
/** Called after all blocks are created. */
|
||||||
@Override
|
@Override
|
||||||
@CallSuper
|
@CallSuper
|
||||||
|
|||||||
@@ -10,4 +10,4 @@ kapt.include.compile.classpath=false
|
|||||||
kotlin.stdlib.default.dependency=false
|
kotlin.stdlib.default.dependency=false
|
||||||
#needed for android compilation
|
#needed for android compilation
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
archash=52f21644b8f70c3a926d3d8d8130f0d71e0e4e79
|
archash=d9fd4b9092c136de8a9b35ca0e393b1a306d0628
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import mindustry.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.logic.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -86,7 +87,8 @@ public class ImagePacker{
|
|||||||
Time.mark();
|
Time.mark();
|
||||||
Generators.run();
|
Generators.run();
|
||||||
Log.info("&ly[Generator]&lc Total time to generate: &lg@&lcms", Time.elapsed());
|
Log.info("&ly[Generator]&lc Total time to generate: &lg@&lcms", Time.elapsed());
|
||||||
//Log.info("&ly[Generator]&lc Total images created: &lg@", Image.total());
|
|
||||||
|
//write icons to icons.properties
|
||||||
|
|
||||||
//format:
|
//format:
|
||||||
//character-ID=contentname:texture-name
|
//character-ID=contentname:texture-name
|
||||||
@@ -118,6 +120,74 @@ public class ImagePacker{
|
|||||||
}
|
}
|
||||||
|
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
||||||
|
//now, write the IDs to logicids.dat
|
||||||
|
|
||||||
|
//don't write to the file unless I'm packing, because logic IDs rarely change and I don't want merge conflicts from PRs
|
||||||
|
if(!OS.username.equals("anuke")) return;
|
||||||
|
|
||||||
|
//format: ([content type (byte)] [content count (short)] (repeat [name (string)])) until EOF
|
||||||
|
Fi logicidfile = Fi.get("../../../assets/logicids.dat");
|
||||||
|
|
||||||
|
Seq<UnlockableContent> lookupCont = new Seq<>();
|
||||||
|
|
||||||
|
for(ContentType t : GlobalConstants.lookableContent){
|
||||||
|
lookupCont.addAll(Vars.content.<UnlockableContent>getBy(t).select(UnlockableContent::logicVisible));
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectIntMap<UnlockableContent>[] registered = new ObjectIntMap[ContentType.all.length];
|
||||||
|
IntMap<UnlockableContent>[] idToContent = new IntMap[ContentType.all.length];
|
||||||
|
|
||||||
|
for(int i = 0; i < ContentType.all.length; i++){
|
||||||
|
registered[i] = new ObjectIntMap<>();
|
||||||
|
idToContent[i] = new IntMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(logicidfile.exists()){
|
||||||
|
try(DataInputStream in = new DataInputStream(logicidfile.readByteStream())){
|
||||||
|
for(ContentType ctype : GlobalConstants.lookableContent){
|
||||||
|
short amount = in.readShort();
|
||||||
|
for(int i = 0; i < amount; i++){
|
||||||
|
String name = in.readUTF();
|
||||||
|
UnlockableContent fetched = Vars.content.getByName(ctype, name);
|
||||||
|
if(fetched != null){
|
||||||
|
registered[ctype.ordinal()].put(fetched, i);
|
||||||
|
idToContent[ctype.ordinal()].put(i, fetched);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//map stuff that hasn't been mapped yet
|
||||||
|
for(UnlockableContent c : lookupCont){
|
||||||
|
int ctype = c.getContentType().ordinal();
|
||||||
|
if(!registered[ctype].containsKey(c)){
|
||||||
|
int nextId = 0;
|
||||||
|
//find next ID - this is O(N) but content counts are so low that I don't really care
|
||||||
|
//checking the last ID doesn't work because there might be "holes"
|
||||||
|
for(UnlockableContent other : lookupCont){
|
||||||
|
if(!idToContent[ctype].containsKey(other.id + 1)){
|
||||||
|
nextId = other.id + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
idToContent[ctype].put(nextId, c);
|
||||||
|
registered[ctype].put(c, nextId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//write the resulting IDs
|
||||||
|
try(DataOutputStream out = new DataOutputStream(logicidfile.write(false, 2048))){
|
||||||
|
for(ContentType t : GlobalConstants.lookableContent){
|
||||||
|
Seq<UnlockableContent> all = idToContent[t.ordinal()].values().toArray().sort(u -> registered[t.ordinal()].get(u));
|
||||||
|
out.writeShort(all.size);
|
||||||
|
for(UnlockableContent u : all){
|
||||||
|
out.writeUTF(u.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static String texname(UnlockableContent c){
|
static String texname(UnlockableContent c){
|
||||||
|
|||||||
Reference in New Issue
Block a user