Block consumer patch support
This commit is contained in:
@@ -24,6 +24,7 @@ import static mindustry.Vars.*;
|
|||||||
/** Base interface for an unlockable content type. */
|
/** Base interface for an unlockable content type. */
|
||||||
public abstract class UnlockableContent extends MappableContent{
|
public abstract class UnlockableContent extends MappableContent{
|
||||||
/** Stat storage for this content. Initialized on demand. */
|
/** Stat storage for this content. Initialized on demand. */
|
||||||
|
@NoPatch
|
||||||
public Stats stats = new Stats();
|
public Stats stats = new Stats();
|
||||||
/** Localized, formal name. Never null. Set to internal name if not found in bundle. */
|
/** Localized, formal name. Never null. Set to internal name if not found in bundle. */
|
||||||
public String localizedName;
|
public String localizedName;
|
||||||
|
|||||||
@@ -442,6 +442,52 @@ public class ContentParser{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public void readBlockConsumers(Block block, JsonValue value){
|
||||||
|
for(JsonValue child : value){
|
||||||
|
switch(child.name){
|
||||||
|
case "remove" -> {
|
||||||
|
String[] values = child.isString() ? new String[]{child.asString()} : child.asStringArray();
|
||||||
|
for(String type : values){
|
||||||
|
Class<?> consumeType = resolve("Consume" + Strings.capitalize(type), Consume.class);
|
||||||
|
if(consumeType != Consume.class){
|
||||||
|
block.removeConsumers(b -> consumeType.isAssignableFrom(b.getClass()));
|
||||||
|
}else{
|
||||||
|
Log.warn("Unknown consumer type '@' (Class: @) in consume: remove.", type, "Consume" + Strings.capitalize(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "item" -> block.consumeItem(find(ContentType.item, child.asString()));
|
||||||
|
case "itemCharged" -> block.consume((Consume)parser.readValue(ConsumeItemCharged.class, child));
|
||||||
|
case "itemFlammable" -> block.consume((Consume)parser.readValue(ConsumeItemFlammable.class, child));
|
||||||
|
case "itemRadioactive" -> block.consume((Consume)parser.readValue(ConsumeItemRadioactive.class, child));
|
||||||
|
case "itemExplosive" -> block.consume((Consume)parser.readValue(ConsumeItemExplosive.class, child));
|
||||||
|
case "itemList" -> block.consume((Consume)parser.readValue(ConsumeItemList.class, child));
|
||||||
|
case "itemExplode" -> block.consume((Consume)parser.readValue(ConsumeItemExplode.class, child));
|
||||||
|
case "items" -> block.consume(
|
||||||
|
child.isArray() ? new ConsumeItems(parser.readValue(ItemStack[].class, child)) :
|
||||||
|
child.isString() ? new ConsumeItems(new ItemStack[]{parser.readValue(ItemStack.class, child)}) :
|
||||||
|
parser.readValue(ConsumeItems.class, child));
|
||||||
|
|
||||||
|
case "liquidFlammable" -> block.consume((Consume)parser.readValue(ConsumeLiquidFlammable.class, child));
|
||||||
|
case "liquid" -> block.consume((Consume)parser.readValue(ConsumeLiquid.class, child));
|
||||||
|
case "liquids" -> block.consume(
|
||||||
|
child.isArray() ? new ConsumeLiquids(parser.readValue(LiquidStack[].class, child)) :
|
||||||
|
parser.readValue(ConsumeLiquids.class, child));
|
||||||
|
case "coolant" -> block.consume((Consume)parser.readValue(ConsumeCoolant.class, child));
|
||||||
|
case "power" -> {
|
||||||
|
if(child.isNumber()){
|
||||||
|
block.consumePower(child.asFloat());
|
||||||
|
}else{
|
||||||
|
block.consume((Consume)parser.readValue(ConsumePower.class, child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "powerBuffered" -> block.consumePowerBuffered(child.asFloat());
|
||||||
|
default -> throw new IllegalArgumentException("Unknown consumption type: '" + child.name + "' for block '" + block.name + "'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value.remove("consumes");
|
||||||
|
}
|
||||||
|
|
||||||
private ObjectMap<ContentType, TypeParser<?>> parsers = ObjectMap.of(
|
private ObjectMap<ContentType, TypeParser<?>> parsers = ObjectMap.of(
|
||||||
ContentType.block, (TypeParser<Block>)(mod, name, value) -> {
|
ContentType.block, (TypeParser<Block>)(mod, name, value) -> {
|
||||||
readBundle(ContentType.block, name, value);
|
readBundle(ContentType.block, name, value);
|
||||||
@@ -463,46 +509,7 @@ public class ContentParser{
|
|||||||
|
|
||||||
read(() -> {
|
read(() -> {
|
||||||
if(value.has("consumes") && value.get("consumes").isObject()){
|
if(value.has("consumes") && value.get("consumes").isObject()){
|
||||||
for(JsonValue child : value.get("consumes")){
|
readBlockConsumers(block, value.get("consumes"));
|
||||||
switch(child.name){
|
|
||||||
case "remove" -> {
|
|
||||||
String[] values = child.isString() ? new String[]{child.asString()} : child.asStringArray();
|
|
||||||
for(String type : values){
|
|
||||||
Class<?> consumeType = resolve("Consume" + Strings.capitalize(type), Consume.class);
|
|
||||||
if(consumeType != Consume.class){
|
|
||||||
block.removeConsumers(b -> consumeType.isAssignableFrom(b.getClass()));
|
|
||||||
}else{
|
|
||||||
Log.warn("Unknown consumer type '@' (Class: @) in consume: remove.", type, "Consume" + Strings.capitalize(type));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "item" -> block.consumeItem(find(ContentType.item, child.asString()));
|
|
||||||
case "itemCharged" -> block.consume((Consume)parser.readValue(ConsumeItemCharged.class, child));
|
|
||||||
case "itemFlammable" -> block.consume((Consume)parser.readValue(ConsumeItemFlammable.class, child));
|
|
||||||
case "itemRadioactive" -> block.consume((Consume)parser.readValue(ConsumeItemRadioactive.class, child));
|
|
||||||
case "itemExplosive" -> block.consume((Consume)parser.readValue(ConsumeItemExplosive.class, child));
|
|
||||||
case "itemList" -> block.consume((Consume)parser.readValue(ConsumeItemList.class, child));
|
|
||||||
case "itemExplode" -> block.consume((Consume)parser.readValue(ConsumeItemExplode.class, child));
|
|
||||||
case "items" -> block.consume(child.isArray() ?
|
|
||||||
new ConsumeItems(parser.readValue(ItemStack[].class, child)) :
|
|
||||||
parser.readValue(ConsumeItems.class, child));
|
|
||||||
case "liquidFlammable" -> block.consume((Consume)parser.readValue(ConsumeLiquidFlammable.class, child));
|
|
||||||
case "liquid" -> block.consume((Consume)parser.readValue(ConsumeLiquid.class, child));
|
|
||||||
case "liquids" -> block.consume(child.isArray() ?
|
|
||||||
new ConsumeLiquids(parser.readValue(LiquidStack[].class, child)) :
|
|
||||||
parser.readValue(ConsumeLiquids.class, child));
|
|
||||||
case "coolant" -> block.consume((Consume)parser.readValue(ConsumeCoolant.class, child));
|
|
||||||
case "power" -> {
|
|
||||||
if(child.isNumber()){
|
|
||||||
block.consumePower(child.asFloat());
|
|
||||||
}else{
|
|
||||||
block.consume((Consume)parser.readValue(ConsumePower.class, child));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case "powerBuffered" -> block.consumePowerBuffered(child.asFloat());
|
|
||||||
default -> throw new IllegalArgumentException("Unknown consumption type: '" + child.name + "' for block '" + block.name + "'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value.remove("consumes");
|
value.remove("consumes");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,13 @@ import arc.util.serialization.Jval.*;
|
|||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.core.*;
|
import mindustry.core.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.consumers.*;
|
||||||
|
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
/** The current implementation is awful. Consider it a proof of concept. */
|
/** The current implementation is awful. Consider it a proof of concept. */
|
||||||
//TODO block consumer support
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ContentPatcher{
|
public class ContentPatcher{
|
||||||
private static final Object root = new Object();
|
private static final Object root = new Object();
|
||||||
@@ -113,7 +114,7 @@ public class ContentPatcher{
|
|||||||
for(int i = 0; i < path.length - 1; i++){
|
for(int i = 0; i < path.length - 1; i++){
|
||||||
Object[] result = resolve(object, path[i], metadata);
|
Object[] result = resolve(object, path[i], metadata);
|
||||||
if(result == null){
|
if(result == null){
|
||||||
//TODO report error
|
warn("Failed to resolve @.@", object, path[i]);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
object = result[0];
|
object = result[0];
|
||||||
@@ -231,6 +232,23 @@ public class ContentPatcher{
|
|||||||
}
|
}
|
||||||
Reflect.set(fobj, fdata.field, fv);
|
Reflect.set(fobj, fdata.field, fv);
|
||||||
}, value, true);
|
}, value, true);
|
||||||
|
}else if(value instanceof JsonValue jsv && object instanceof Block bl && jsv.isObject() && field.equals("consumes")){
|
||||||
|
modifiedField(bl, "consumeBuilder", Reflect.<Seq<Consume>>get(Block.class, bl, "consumeBuilder").copy());
|
||||||
|
boolean hadItems = bl.hasItems, hadLiquids = bl.hasLiquids, hadPower = bl.hasPower, acceptedItems = bl.acceptsItems;
|
||||||
|
reset(() -> {
|
||||||
|
bl.hasItems = hadItems;
|
||||||
|
bl.hasLiquids = hadLiquids;
|
||||||
|
bl.hasPower = hadPower;
|
||||||
|
bl.acceptsItems = acceptedItems;
|
||||||
|
});
|
||||||
|
after(bl::reinitializeConsumers);
|
||||||
|
|
||||||
|
try{
|
||||||
|
Vars.mods.getContentParser().readBlockConsumers(bl, jsv);
|
||||||
|
}catch(Throwable e){
|
||||||
|
Log.err(e);
|
||||||
|
warn("Failed to read consumers for '@': @", bl, Strings.getSimpleMessage(e));
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
warn("Unknown field: '@' for class '@'", field, actualType.getSimpleName());
|
warn("Unknown field: '@' for class '@'", field, actualType.getSimpleName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1348,6 +1348,21 @@ public class Block extends UnlockableContent implements Senseable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reinitializeConsumers(){
|
||||||
|
consumers = consumeBuilder.toArray(Consume.class);
|
||||||
|
consPower = (ConsumePower)Structs.find(consumers, c -> c instanceof ConsumePower);
|
||||||
|
optionalConsumers = consumeBuilder.select(consume -> consume.optional && !consume.ignore()).toArray(Consume.class);
|
||||||
|
nonOptionalConsumers = consumeBuilder.select(consume -> !consume.optional && !consume.ignore()).toArray(Consume.class);
|
||||||
|
updateConsumers = consumeBuilder.select(consume -> consume.update && !consume.ignore()).toArray(Consume.class);
|
||||||
|
hasConsumers = consumers.length > 0;
|
||||||
|
itemFilter = new boolean[content.items().size];
|
||||||
|
liquidFilter = new boolean[content.liquids().size];
|
||||||
|
|
||||||
|
for(Consume cons : consumers){
|
||||||
|
cons.apply(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
super.load();
|
super.load();
|
||||||
|
|||||||
Reference in New Issue
Block a user