Extra mod field parsing (untested)
This commit is contained in:
@@ -3,6 +3,7 @@ package mindustry.content;
|
|||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
|
import arc.struct.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.entities.bullet.*;
|
import mindustry.entities.bullet.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -1801,30 +1802,30 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
groundFactory = new UnitFactory("ground-factory"){{
|
groundFactory = new UnitFactory("ground-factory"){{
|
||||||
requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80));
|
requirements(Category.units, with(Items.copper, 50, Items.lead, 120, Items.silicon, 80));
|
||||||
plans = new UnitPlan[]{
|
plans = Seq.with(
|
||||||
new UnitPlan(UnitTypes.dagger, 60f * 15, with(Items.silicon, 10, Items.lead, 10)),
|
new UnitPlan(UnitTypes.dagger, 60f * 15, with(Items.silicon, 10, Items.lead, 10)),
|
||||||
new UnitPlan(UnitTypes.crawler, 60f * 12, with(Items.silicon, 10, Items.coal, 20)),
|
new UnitPlan(UnitTypes.crawler, 60f * 12, with(Items.silicon, 10, Items.coal, 20)),
|
||||||
new UnitPlan(UnitTypes.nova, 60f * 40, with(Items.silicon, 30, Items.lead, 20, Items.titanium, 20)),
|
new UnitPlan(UnitTypes.nova, 60f * 40, with(Items.silicon, 30, Items.lead, 20, Items.titanium, 20))
|
||||||
};
|
);
|
||||||
size = 3;
|
size = 3;
|
||||||
consumes.power(1.2f);
|
consumes.power(1.2f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
airFactory = new UnitFactory("air-factory"){{
|
airFactory = new UnitFactory("air-factory"){{
|
||||||
requirements(Category.units, with(Items.copper, 60, Items.lead, 70));
|
requirements(Category.units, with(Items.copper, 60, Items.lead, 70));
|
||||||
plans = new UnitPlan[]{
|
plans = Seq.with(
|
||||||
new UnitPlan(UnitTypes.flare, 60f * 15, with(Items.silicon, 15)),
|
new UnitPlan(UnitTypes.flare, 60f * 15, with(Items.silicon, 15)),
|
||||||
new UnitPlan(UnitTypes.mono, 60f * 35, with(Items.silicon, 30, Items.lead, 15)),
|
new UnitPlan(UnitTypes.mono, 60f * 35, with(Items.silicon, 30, Items.lead, 15))
|
||||||
};
|
);
|
||||||
size = 3;
|
size = 3;
|
||||||
consumes.power(1.2f);
|
consumes.power(1.2f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
navalFactory = new UnitFactory("naval-factory"){{
|
navalFactory = new UnitFactory("naval-factory"){{
|
||||||
requirements(Category.units, with(Items.copper, 150, Items.lead, 130, Items.metaglass, 120));
|
requirements(Category.units, with(Items.copper, 150, Items.lead, 130, Items.metaglass, 120));
|
||||||
plans = new UnitPlan[]{
|
plans = Seq.with(
|
||||||
new UnitPlan(UnitTypes.risso, 60f * 45f, with(Items.silicon, 20, Items.metaglass, 35)),
|
new UnitPlan(UnitTypes.risso, 60f * 45f, with(Items.silicon, 20, Items.metaglass, 35))
|
||||||
};
|
);
|
||||||
size = 3;
|
size = 3;
|
||||||
consumes.power(1.2f);
|
consumes.power(1.2f);
|
||||||
floating = true;
|
floating = true;
|
||||||
@@ -1839,14 +1840,14 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
constructTime = 60f * 10f;
|
constructTime = 60f * 10f;
|
||||||
|
|
||||||
upgrades = new UnitType[][]{
|
upgrades.addAll(
|
||||||
{UnitTypes.nova, UnitTypes.pulsar},
|
new UnitType[]{UnitTypes.nova, UnitTypes.pulsar},
|
||||||
{UnitTypes.dagger, UnitTypes.mace},
|
new UnitType[]{UnitTypes.dagger, UnitTypes.mace},
|
||||||
{UnitTypes.crawler, UnitTypes.atrax},
|
new UnitType[]{UnitTypes.crawler, UnitTypes.atrax},
|
||||||
{UnitTypes.flare, UnitTypes.horizon},
|
new UnitType[]{UnitTypes.flare, UnitTypes.horizon},
|
||||||
{UnitTypes.mono, UnitTypes.poly},
|
new UnitType[]{UnitTypes.mono, UnitTypes.poly},
|
||||||
{UnitTypes.risso, UnitTypes.minke},
|
new UnitType[]{UnitTypes.risso, UnitTypes.minke}
|
||||||
};
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
multiplicativeReconstructor = new Reconstructor("multiplicative-reconstructor"){{
|
multiplicativeReconstructor = new Reconstructor("multiplicative-reconstructor"){{
|
||||||
@@ -1858,14 +1859,14 @@ public class Blocks implements ContentList{
|
|||||||
|
|
||||||
constructTime = 60f * 30f;
|
constructTime = 60f * 30f;
|
||||||
|
|
||||||
upgrades = new UnitType[][]{
|
upgrades.addAll(
|
||||||
{UnitTypes.horizon, UnitTypes.zenith},
|
new UnitType[]{UnitTypes.horizon, UnitTypes.zenith},
|
||||||
{UnitTypes.mace, UnitTypes.fortress},
|
new UnitType[]{UnitTypes.mace, UnitTypes.fortress},
|
||||||
{UnitTypes.poly, UnitTypes.mega},
|
new UnitType[]{UnitTypes.poly, UnitTypes.mega},
|
||||||
{UnitTypes.minke, UnitTypes.bryde},
|
new UnitType[]{UnitTypes.minke, UnitTypes.bryde},
|
||||||
{UnitTypes.pulsar, UnitTypes.quasar},
|
new UnitType[]{UnitTypes.pulsar, UnitTypes.quasar},
|
||||||
{UnitTypes.atrax, UnitTypes.spiroct},
|
new UnitType[]{UnitTypes.atrax, UnitTypes.spiroct}
|
||||||
};
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{
|
exponentialReconstructor = new Reconstructor("exponential-reconstructor"){{
|
||||||
@@ -1879,14 +1880,14 @@ public class Blocks implements ContentList{
|
|||||||
constructTime = 60f * 60f * 1.5f;
|
constructTime = 60f * 60f * 1.5f;
|
||||||
liquidCapacity = 60f;
|
liquidCapacity = 60f;
|
||||||
|
|
||||||
upgrades = new UnitType[][]{
|
upgrades.addAll(
|
||||||
{UnitTypes.zenith, UnitTypes.antumbra},
|
new UnitType[]{UnitTypes.zenith, UnitTypes.antumbra},
|
||||||
{UnitTypes.spiroct, UnitTypes.arkyid},
|
new UnitType[]{UnitTypes.spiroct, UnitTypes.arkyid},
|
||||||
{UnitTypes.fortress, UnitTypes.scepter},
|
new UnitType[]{UnitTypes.fortress, UnitTypes.scepter},
|
||||||
{UnitTypes.bryde, UnitTypes.sei},
|
new UnitType[]{UnitTypes.bryde, UnitTypes.sei},
|
||||||
{UnitTypes.mega, UnitTypes.quad},
|
new UnitType[]{UnitTypes.mega, UnitTypes.quad},
|
||||||
{UnitTypes.quasar, UnitTypes.vela},
|
new UnitType[]{UnitTypes.quasar, UnitTypes.vela}
|
||||||
};
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{
|
tetrativeReconstructor = new Reconstructor("tetrative-reconstructor"){{
|
||||||
@@ -1900,14 +1901,14 @@ public class Blocks implements ContentList{
|
|||||||
constructTime = 60f * 60f * 4;
|
constructTime = 60f * 60f * 4;
|
||||||
liquidCapacity = 180f;
|
liquidCapacity = 180f;
|
||||||
|
|
||||||
upgrades = new UnitType[][]{
|
upgrades.addAll(
|
||||||
{UnitTypes.antumbra, UnitTypes.eclipse},
|
new UnitType[]{UnitTypes.antumbra, UnitTypes.eclipse},
|
||||||
{UnitTypes.arkyid, UnitTypes.toxopid},
|
new UnitType[]{UnitTypes.arkyid, UnitTypes.toxopid},
|
||||||
{UnitTypes.scepter, UnitTypes.reign},
|
new UnitType[]{UnitTypes.scepter, UnitTypes.reign},
|
||||||
{UnitTypes.sei, UnitTypes.omura},
|
new UnitType[] {UnitTypes.sei, UnitTypes.omura},
|
||||||
{UnitTypes.quad, UnitTypes.oct},
|
new UnitType[]{UnitTypes.quad, UnitTypes.oct},
|
||||||
{UnitTypes.vela, UnitTypes.corvus}
|
new UnitType[]{UnitTypes.vela, UnitTypes.corvus}
|
||||||
};
|
);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
repairPoint = new RepairPoint("repair-point"){{
|
repairPoint = new RepairPoint("repair-point"){{
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import static mindustry.type.ItemStack.*;
|
|||||||
|
|
||||||
public class TechTree implements ContentList{
|
public class TechTree implements ContentList{
|
||||||
static ObjectMap<UnlockableContent, TechNode> map = new ObjectMap<>();
|
static ObjectMap<UnlockableContent, TechNode> map = new ObjectMap<>();
|
||||||
|
static TechNode context = null;
|
||||||
|
|
||||||
public static Seq<TechNode> all;
|
public static Seq<TechNode> all;
|
||||||
public static TechNode root;
|
public static TechNode root;
|
||||||
@@ -543,36 +544,46 @@ public class TechTree implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void setup(){
|
public static void setup(){
|
||||||
TechNode.context = null;
|
context = null;
|
||||||
map = new ObjectMap<>();
|
map = new ObjectMap<>();
|
||||||
all = new Seq<>();
|
all = new Seq<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TechNode node(UnlockableContent content, Runnable children){
|
//all the "node" methods are hidden, because they are for internal context-dependent use only
|
||||||
|
//for custom research, just use the TechNode constructor
|
||||||
|
|
||||||
|
static TechNode node(UnlockableContent content, Runnable children){
|
||||||
return node(content, content.researchRequirements(), children);
|
return node(content, content.researchRequirements(), children);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TechNode node(UnlockableContent content, ItemStack[] requirements, Runnable children){
|
static TechNode node(UnlockableContent content, ItemStack[] requirements, Runnable children){
|
||||||
return new TechNode(content, requirements, children);
|
return node(content, requirements, null, children);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TechNode node(UnlockableContent content, Seq<Objective> objectives, Runnable children){
|
static TechNode node(UnlockableContent content, ItemStack[] requirements, Seq<Objective> objectives, Runnable children){
|
||||||
TechNode node = new TechNode(content, content.researchRequirements(), children);
|
TechNode node = new TechNode(context, content, requirements);
|
||||||
node.objectives = objectives;
|
if(objectives != null){
|
||||||
|
node.objectives = objectives;
|
||||||
|
}
|
||||||
|
|
||||||
|
TechNode prev = context;
|
||||||
|
context = node;
|
||||||
|
children.run();
|
||||||
|
context = prev;
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TechNode node(UnlockableContent block){
|
static TechNode node(UnlockableContent content, Seq<Objective> objectives, Runnable children){
|
||||||
|
return node(content, content.researchRequirements(), objectives, children);
|
||||||
|
}
|
||||||
|
|
||||||
|
static TechNode node(UnlockableContent block){
|
||||||
return node(block, () -> {});
|
return node(block, () -> {});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TechNode create(UnlockableContent parent, UnlockableContent block){
|
@Nullable
|
||||||
TechNode.context = all.find(t -> t.content == parent);
|
public static TechNode get(UnlockableContent content){
|
||||||
return node(block, () -> {});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @Nullable
|
|
||||||
TechNode get(UnlockableContent content){
|
|
||||||
return map.get(content);
|
return map.get(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,8 +592,6 @@ public class TechTree implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class TechNode{
|
public static class TechNode{
|
||||||
static TechNode context;
|
|
||||||
|
|
||||||
/** Depth in tech tree. */
|
/** Depth in tech tree. */
|
||||||
public int depth;
|
public int depth;
|
||||||
/** Requirement node. */
|
/** Requirement node. */
|
||||||
@@ -600,10 +609,10 @@ public class TechTree implements ContentList{
|
|||||||
/** Nodes that depend on this node. */
|
/** Nodes that depend on this node. */
|
||||||
public final Seq<TechNode> children = new Seq<>();
|
public final Seq<TechNode> children = new Seq<>();
|
||||||
|
|
||||||
TechNode(@Nullable TechNode ccontext, UnlockableContent content, ItemStack[] requirements, Runnable children){
|
public TechNode(@Nullable TechNode parent, UnlockableContent content, ItemStack[] requirements){
|
||||||
if(ccontext != null) ccontext.children.add(this);
|
if(parent != null) parent.children.add(this);
|
||||||
|
|
||||||
this.parent = ccontext;
|
this.parent = parent;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.requirements = requirements;
|
this.requirements = requirements;
|
||||||
this.depth = parent == null ? 0 : parent.depth + 1;
|
this.depth = parent == null ? 0 : parent.depth + 1;
|
||||||
@@ -619,14 +628,15 @@ public class TechTree implements ContentList{
|
|||||||
content.getDependencies(d -> objectives.add(new Research(d)));
|
content.getDependencies(d -> objectives.add(new Research(d)));
|
||||||
|
|
||||||
map.put(content, this);
|
map.put(content, this);
|
||||||
context = this;
|
|
||||||
children.run();
|
|
||||||
context = ccontext;
|
|
||||||
all.add(this);
|
all.add(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TechNode(UnlockableContent content, ItemStack[] requirements, Runnable children){
|
/** Removes this node from the tech tree. */
|
||||||
this(context, content, requirements, children);
|
public void remove(){
|
||||||
|
all.remove(this);
|
||||||
|
if(parent != null){
|
||||||
|
parent.children.remove(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Flushes research progress to settings. */
|
/** Flushes research progress to settings. */
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ abstract class BuilderComp implements Unitc{
|
|||||||
BuildPlan plan = buildPlan();
|
BuildPlan plan = buildPlan();
|
||||||
Tile tile = world.tile(plan.x, plan.y);
|
Tile tile = world.tile(plan.x, plan.y);
|
||||||
|
|
||||||
if(dst(tile) > buildingRange && !state.isEditor()){
|
if(!within(tile, buildingRange) && !state.isEditor()){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -182,20 +182,23 @@ public class LExecutor{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(LExecutor exec){
|
public void run(LExecutor exec){
|
||||||
Object typeObj = exec.obj(type);
|
|
||||||
UnitType type = typeObj instanceof UnitType t ? t : null;
|
|
||||||
|
|
||||||
Seq<Unit> seq = type == null ? exec.team.data().units : exec.team.data().unitCache(type);
|
//binding to `null` was previously possible, but was too powerful and exploitable
|
||||||
|
if(exec.obj(type) instanceof UnitType type){
|
||||||
|
Seq<Unit> seq = exec.team.data().unitCache(type);
|
||||||
|
|
||||||
if(seq != null && seq.any()){
|
if(seq != null && seq.any()){
|
||||||
index %= seq.size;
|
index %= seq.size;
|
||||||
if(index < seq.size){
|
if(index < seq.size){
|
||||||
//bind to the next unit
|
//bind to the next unit
|
||||||
exec.setconst(varUnit, seq.get(index));
|
exec.setconst(varUnit, seq.get(index));
|
||||||
|
}
|
||||||
|
index ++;
|
||||||
|
}else{
|
||||||
|
//no units of this type found
|
||||||
|
exec.setconst(varUnit, null);
|
||||||
}
|
}
|
||||||
index ++;
|
|
||||||
}else{
|
}else{
|
||||||
//no units of this type found
|
|
||||||
exec.setconst(varUnit, null);
|
exec.setconst(varUnit, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import mindustry.mod.Mods.*;
|
|||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
|
import mindustry.world.blocks.units.*;
|
||||||
|
import mindustry.world.blocks.units.UnitFactory.*;
|
||||||
import mindustry.world.consumers.*;
|
import mindustry.world.consumers.*;
|
||||||
import mindustry.world.draw.*;
|
import mindustry.world.draw.*;
|
||||||
import mindustry.world.meta.*;
|
import mindustry.world.meta.*;
|
||||||
@@ -170,11 +172,9 @@ public class ContentParser{
|
|||||||
readBundle(ContentType.block, name, value);
|
readBundle(ContentType.block, name, value);
|
||||||
|
|
||||||
Block block;
|
Block block;
|
||||||
boolean exists;
|
|
||||||
|
|
||||||
if(locate(ContentType.block, name) != null){
|
if(locate(ContentType.block, name) != null){
|
||||||
block = locate(ContentType.block, name);
|
block = locate(ContentType.block, name);
|
||||||
exists = true;
|
|
||||||
|
|
||||||
if(value.has("type")){
|
if(value.has("type")){
|
||||||
throw new IllegalArgumentException("When defining properties for an existing block, you must not re-declare its type. The original type will be used. Block: " + name);
|
throw new IllegalArgumentException("When defining properties for an existing block, you must not re-declare its type. The original type will be used. Block: " + name);
|
||||||
@@ -182,7 +182,6 @@ public class ContentParser{
|
|||||||
}else{
|
}else{
|
||||||
//TODO generate dynamically instead of doing.. this
|
//TODO generate dynamically instead of doing.. this
|
||||||
Class<? extends Block> type;
|
Class<? extends Block> type;
|
||||||
exists = false;
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
type = resolve(getType(value),
|
type = resolve(getType(value),
|
||||||
@@ -208,14 +207,6 @@ public class ContentParser{
|
|||||||
|
|
||||||
currentContent = block;
|
currentContent = block;
|
||||||
|
|
||||||
String[] research = {null};
|
|
||||||
|
|
||||||
//add research tech node
|
|
||||||
if(value.has("research")){
|
|
||||||
research[0] = value.get("research").asString();
|
|
||||||
value.remove("research");
|
|
||||||
}
|
|
||||||
|
|
||||||
read(() -> {
|
read(() -> {
|
||||||
if(value.has("consumes")){
|
if(value.has("consumes")){
|
||||||
for(JsonValue child : value.get("consumes")){
|
for(JsonValue child : value.get("consumes")){
|
||||||
@@ -246,33 +237,6 @@ public class ContentParser{
|
|||||||
throw new IllegalArgumentException("Blocks cannot be larger than " + ConstructBlock.maxSize);
|
throw new IllegalArgumentException("Blocks cannot be larger than " + ConstructBlock.maxSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add research tech node
|
|
||||||
if(research[0] != null){
|
|
||||||
//TODO only works with blocks
|
|
||||||
Block parent = find(ContentType.block, research[0]);
|
|
||||||
TechNode baseNode = exists && TechTree.all.contains(t -> t.content == block) ? TechTree.all.find(t -> t.content == block) : TechTree.create(parent, block);
|
|
||||||
LoadedMod cur = currentMod;
|
|
||||||
|
|
||||||
postreads.add(() -> {
|
|
||||||
currentContent = block;
|
|
||||||
currentMod = cur;
|
|
||||||
|
|
||||||
if(baseNode.parent != null){
|
|
||||||
baseNode.parent.children.remove(baseNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
TechNode parnode = TechTree.all.find(t -> t.content == parent);
|
|
||||||
if(parnode == null){
|
|
||||||
throw new IllegalArgumentException("Block '" + parent.name + "' isn't in the tech tree, but '" + block.name + "' requires it to be researched.");
|
|
||||||
}
|
|
||||||
if(!parnode.children.contains(baseNode)){
|
|
||||||
parnode.children.add(baseNode);
|
|
||||||
}
|
|
||||||
baseNode.parent = parnode;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//make block visible by default if there are requirements and no visibility set
|
//make block visible by default if there are requirements and no visibility set
|
||||||
if(value.has("requirements") && block.buildVisibility == BuildVisibility.hidden){
|
if(value.has("requirements") && block.buildVisibility == BuildVisibility.hidden){
|
||||||
block.buildVisibility = BuildVisibility.shown;
|
block.buildVisibility = BuildVisibility.shown;
|
||||||
@@ -293,7 +257,37 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
|
|
||||||
currentContent = unit;
|
currentContent = unit;
|
||||||
read(() -> readFields(unit, value, true));
|
//TODO test this!
|
||||||
|
read(() -> {
|
||||||
|
//add reconstructor type
|
||||||
|
if(value.hasChild("requirements")){
|
||||||
|
JsonValue rec = value.remove("requirements");
|
||||||
|
|
||||||
|
//intermediate class for parsing
|
||||||
|
class UnitReq{
|
||||||
|
public Block block;
|
||||||
|
public ItemStack[] requirements = {};
|
||||||
|
@Nullable
|
||||||
|
public UnitType previous;
|
||||||
|
public float time = 60f * 10f;
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitReq req = parser.readValue(UnitReq.class, rec);
|
||||||
|
|
||||||
|
if(req.block instanceof Reconstructor r){
|
||||||
|
if(req.previous != null){
|
||||||
|
r.upgrades.add(new UnitType[]{req.previous, unit});
|
||||||
|
}
|
||||||
|
}else if(req.block instanceof UnitFactory f){
|
||||||
|
f.plans.add(new UnitPlan(unit, req.time, req.requirements));
|
||||||
|
}else{
|
||||||
|
throw new IllegalArgumentException("Missing a valid 'block' in 'requirements'");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
readFields(unit, value, true);
|
||||||
|
});
|
||||||
|
|
||||||
return unit;
|
return unit;
|
||||||
},
|
},
|
||||||
@@ -559,6 +553,59 @@ public class ContentParser{
|
|||||||
|
|
||||||
private void readFields(Object object, JsonValue jsonMap, boolean stripType){
|
private void readFields(Object object, JsonValue jsonMap, boolean stripType){
|
||||||
if(stripType) jsonMap.remove("type");
|
if(stripType) jsonMap.remove("type");
|
||||||
|
|
||||||
|
if(object instanceof UnlockableContent unlock){
|
||||||
|
JsonValue research = jsonMap.getChild("research");
|
||||||
|
//add research tech node
|
||||||
|
if(research != null){
|
||||||
|
String researchName;
|
||||||
|
ItemStack[] customRequirements;
|
||||||
|
|
||||||
|
//research can be a single string or an object with parent and requirements
|
||||||
|
if(research.isString()){
|
||||||
|
researchName = research.asString();
|
||||||
|
customRequirements = null;
|
||||||
|
}else{
|
||||||
|
researchName = research.getString("parent");
|
||||||
|
customRequirements = research.hasChild("requirements") ? parser.readValue(ItemStack[].class, research.getChild("requirements")) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
//remove old node
|
||||||
|
TechNode lastNode = TechTree.all.find(t -> t.content == unlock);
|
||||||
|
if(lastNode != null){
|
||||||
|
lastNode.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
TechNode node = new TechNode(null, unlock, customRequirements == null ? unlock.researchRequirements() : customRequirements);
|
||||||
|
LoadedMod cur = currentMod;
|
||||||
|
|
||||||
|
postreads.add(() -> {
|
||||||
|
currentContent = unlock;
|
||||||
|
currentMod = cur;
|
||||||
|
|
||||||
|
//remove old node from parent
|
||||||
|
if(node.parent != null){
|
||||||
|
node.parent.children.remove(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//find parent node.
|
||||||
|
TechNode parent = TechTree.all.find(t -> t.content.name.equals(researchName) || t.content.name.equals(currentMod.name + "-" + researchName));
|
||||||
|
|
||||||
|
if(parent == null){
|
||||||
|
throw new IllegalArgumentException("Content '" + researchName + "' isn't in the tech tree, but '" + unlock.name + "' requires it to be researched.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//add this node to the parent
|
||||||
|
if(!parent.children.contains(node)){
|
||||||
|
parent.children.add(node);
|
||||||
|
}
|
||||||
|
//reparent the node
|
||||||
|
node.parent = parent;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
readFields(object, jsonMap);
|
readFields(object, jsonMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ import mindustry.core.*;
|
|||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.abilities.*;
|
import mindustry.entities.abilities.*;
|
||||||
import mindustry.entities.bullet.*;
|
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@@ -297,14 +296,14 @@ public class UnitType extends UnlockableContent{
|
|||||||
ItemStack[] stacks = null;
|
ItemStack[] stacks = null;
|
||||||
|
|
||||||
//calculate costs based on reconstructors or factories found
|
//calculate costs based on reconstructors or factories found
|
||||||
Block rec = content.blocks().find(b -> b instanceof Reconstructor && Structs.contains(((Reconstructor)b).upgrades, u -> u[1] == this));
|
Block rec = content.blocks().find(b -> b instanceof Reconstructor && ((Reconstructor)b).upgrades.contains(u -> u[1] == this));
|
||||||
|
|
||||||
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems){
|
if(rec != null && rec.consumes.has(ConsumeType.item) && rec.consumes.get(ConsumeType.item) instanceof ConsumeItems){
|
||||||
stacks = ((ConsumeItems)rec.consumes.get(ConsumeType.item)).items;
|
stacks = ((ConsumeItems)rec.consumes.get(ConsumeType.item)).items;
|
||||||
}else{
|
}else{
|
||||||
UnitFactory factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory && Structs.contains(((UnitFactory)u).plans, p -> p.unit == this));
|
UnitFactory factory = (UnitFactory)content.blocks().find(u -> u instanceof UnitFactory && ((UnitFactory)u).plans.contains(p -> p.unit == this));
|
||||||
if(factory != null){
|
if(factory != null){
|
||||||
stacks = Structs.find(factory.plans, p -> p.unit == this).requirements;
|
stacks = factory.plans.find(p -> p.unit == this).requirements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public class PlacementFragment extends Fragment{
|
|||||||
final int rowWidth = 4;
|
final int rowWidth = 4;
|
||||||
|
|
||||||
public Category currentCategory = Category.distribution;
|
public Category currentCategory = Category.distribution;
|
||||||
|
|
||||||
Seq<Block> returnArray = new Seq<>(), returnArray2 = new Seq<>();
|
Seq<Block> returnArray = new Seq<>(), returnArray2 = new Seq<>();
|
||||||
Seq<Category> returnCatArray = new Seq<>();
|
Seq<Category> returnCatArray = new Seq<>();
|
||||||
boolean[] categoryEmpty = new boolean[Category.all.length];
|
boolean[] categoryEmpty = new boolean[Category.all.length];
|
||||||
@@ -80,6 +81,10 @@ public class PlacementFragment extends Fragment{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Displayable hover(){
|
||||||
|
return hover;
|
||||||
|
}
|
||||||
|
|
||||||
void rebuild(){
|
void rebuild(){
|
||||||
currentCategory = Category.turret;
|
currentCategory = Category.turret;
|
||||||
Group group = toggler.parent;
|
Group group = toggler.parent;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package mindustry.world.blocks.logic;
|
package mindustry.world.blocks.logic;
|
||||||
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.struct.Bits;
|
import arc.struct.Bits;
|
||||||
@@ -8,6 +9,7 @@ import arc.struct.*;
|
|||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
|
import mindustry.ai.types.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
@@ -432,6 +434,19 @@ public class LogicBlock extends Block{
|
|||||||
}).size(40);
|
}).size(40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(){
|
||||||
|
super.draw();
|
||||||
|
|
||||||
|
if(ui.hudfrag.blockfrag.hover() instanceof Unit unit && unit.controller() instanceof LogicAI ai && ai.controller == this){
|
||||||
|
Draw.z(Layer.overlayUI);
|
||||||
|
Drawf.square(x, y, size * tilesize/2f + 2f);
|
||||||
|
if(!unit.within(this, unit.hitSize * 2f)){
|
||||||
|
Drawf.arrow(unit.x, unit.y, x, y, unit.hitSize *2f, 4f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onConfigureTileTapped(Building other){
|
public boolean onConfigureTileTapped(Building other){
|
||||||
if(this == other){
|
if(this == other){
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package mindustry.world.blocks.units;
|
|||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
@@ -21,7 +22,7 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
public class Reconstructor extends UnitBlock{
|
public class Reconstructor extends UnitBlock{
|
||||||
public float constructTime = 60 * 2;
|
public float constructTime = 60 * 2;
|
||||||
public UnitType[][] upgrades = {};
|
public Seq<UnitType[]> upgrades = new Seq<>();
|
||||||
public int[] capacities;
|
public int[] capacities;
|
||||||
|
|
||||||
public Reconstructor(String name){
|
public Reconstructor(String name){
|
||||||
@@ -181,7 +182,7 @@ public class Reconstructor extends UnitBlock{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public UnitType upgrade(UnitType type){
|
public UnitType upgrade(UnitType type){
|
||||||
UnitType[] r = Structs.find(upgrades, arr -> arr[0] == type);
|
UnitType[] r = upgrades.find(u -> u[0] == type);
|
||||||
return r == null ? null : r[1];
|
return r == null ? null : r[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import mindustry.world.meta.*;
|
|||||||
public class UnitFactory extends UnitBlock{
|
public class UnitFactory extends UnitBlock{
|
||||||
public int[] capacities;
|
public int[] capacities;
|
||||||
|
|
||||||
public UnitPlan[] plans = new UnitPlan[0];
|
public Seq<UnitPlan> plans = new Seq<>(4);
|
||||||
|
|
||||||
public UnitFactory(String name){
|
public UnitFactory(String name){
|
||||||
super(name);
|
super(name);
|
||||||
@@ -39,11 +39,11 @@ public class UnitFactory extends UnitBlock{
|
|||||||
rotate = true;
|
rotate = true;
|
||||||
|
|
||||||
config(Integer.class, (UnitFactoryBuild tile, Integer i) -> {
|
config(Integer.class, (UnitFactoryBuild tile, Integer i) -> {
|
||||||
tile.currentPlan = i < 0 || i >= plans.length ? -1 : i;
|
tile.currentPlan = i < 0 || i >= plans.size ? -1 : i;
|
||||||
tile.progress = 0;
|
tile.progress = 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
consumes.add(new ConsumeItemDynamic((UnitFactoryBuild e) -> e.currentPlan != -1 ? plans[e.currentPlan].requirements : ItemStack.empty));
|
consumes.add(new ConsumeItemDynamic((UnitFactoryBuild e) -> e.currentPlan != -1 ? plans.get(e.currentPlan).requirements : ItemStack.empty));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -119,7 +119,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
public int currentPlan = -1;
|
public int currentPlan = -1;
|
||||||
|
|
||||||
public float fraction(){
|
public float fraction(){
|
||||||
return currentPlan == -1 ? 0 : progress / plans[currentPlan].time;
|
return currentPlan == -1 ? 0 : progress / plans.get(currentPlan).time;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -127,7 +127,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow());
|
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow());
|
||||||
|
|
||||||
if(units.any()){
|
if(units.any()){
|
||||||
ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans[currentPlan].unit, unit -> configure(Structs.indexOf(plans, u -> u.unit == unit)));
|
ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)));
|
||||||
}else{
|
}else{
|
||||||
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
|
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
|
||||||
}
|
}
|
||||||
@@ -148,11 +148,11 @@ public class UnitFactory extends UnitBlock{
|
|||||||
table.table(t -> {
|
table.table(t -> {
|
||||||
t.left();
|
t.left();
|
||||||
t.image().update(i -> {
|
t.image().update(i -> {
|
||||||
i.setDrawable(currentPlan == -1 ? Icon.cancel : reg.set(plans[currentPlan].unit.icon(Cicon.medium)));
|
i.setDrawable(currentPlan == -1 ? Icon.cancel : reg.set(plans.get(currentPlan).unit.icon(Cicon.medium)));
|
||||||
i.setScaling(Scaling.fit);
|
i.setScaling(Scaling.fit);
|
||||||
i.setColor(currentPlan == -1 ? Color.lightGray : Color.white);
|
i.setColor(currentPlan == -1 ? Color.lightGray : Color.white);
|
||||||
}).size(32).padBottom(-4).padRight(2);
|
}).size(32).padBottom(-4).padRight(2);
|
||||||
t.label(() -> currentPlan == -1 ? "@none" : plans[currentPlan].unit.localizedName).color(Color.lightGray);
|
t.label(() -> currentPlan == -1 ? "@none" : plans.get(currentPlan).unit.localizedName).color(Color.lightGray);
|
||||||
}).left();
|
}).left();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
Draw.rect(outRegion, x, y, rotdeg());
|
Draw.rect(outRegion, x, y, rotdeg());
|
||||||
|
|
||||||
if(currentPlan != -1){
|
if(currentPlan != -1){
|
||||||
UnitPlan plan = plans[currentPlan];
|
UnitPlan plan = plans.get(currentPlan);
|
||||||
Draw.draw(Layer.blockOver, () -> Drawf.construct(this, plan.unit, rotdeg() - 90f, progress / plan.time, speedScl, time));
|
Draw.draw(Layer.blockOver, () -> Drawf.construct(this, plan.unit, rotdeg() - 90f, progress / plan.time, speedScl, time));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateTile(){
|
public void updateTile(){
|
||||||
if(currentPlan < 0 || currentPlan >= plans.length){
|
if(currentPlan < 0 || currentPlan >= plans.size){
|
||||||
currentPlan = -1;
|
currentPlan = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ public class UnitFactory extends UnitBlock{
|
|||||||
moveOutPayload();
|
moveOutPayload();
|
||||||
|
|
||||||
if(currentPlan != -1 && payload == null){
|
if(currentPlan != -1 && payload == null){
|
||||||
UnitPlan plan = plans[currentPlan];
|
UnitPlan plan = plans.get(currentPlan);
|
||||||
|
|
||||||
if(progress >= plan.time && consValid()){
|
if(progress >= plan.time && consValid()){
|
||||||
progress = 0f;
|
progress = 0f;
|
||||||
@@ -228,11 +228,11 @@ public class UnitFactory extends UnitBlock{
|
|||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Building source, Item item){
|
public boolean acceptItem(Building source, Item item){
|
||||||
return currentPlan != -1 && items.get(item) < getMaximumAccepted(item) &&
|
return currentPlan != -1 && items.get(item) < getMaximumAccepted(item) &&
|
||||||
Structs.contains(plans[currentPlan].requirements, stack -> stack.item == item);
|
Structs.contains(plans.get(currentPlan).requirements, stack -> stack.item == item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable UnitType unit(){
|
public @Nullable UnitType unit(){
|
||||||
return currentPlan == - 1 ? null : plans[currentPlan].unit;
|
return currentPlan == - 1 ? null : plans.get(currentPlan).unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Reference in New Issue
Block a user