Block consumer patch support
This commit is contained in:
@@ -24,6 +24,7 @@ import static mindustry.Vars.*;
|
||||
/** Base interface for an unlockable content type. */
|
||||
public abstract class UnlockableContent extends MappableContent{
|
||||
/** Stat storage for this content. Initialized on demand. */
|
||||
@NoPatch
|
||||
public Stats stats = new Stats();
|
||||
/** Localized, formal name. Never null. Set to internal name if not found in bundle. */
|
||||
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(
|
||||
ContentType.block, (TypeParser<Block>)(mod, name, value) -> {
|
||||
readBundle(ContentType.block, name, value);
|
||||
@@ -463,46 +509,7 @@ public class ContentParser{
|
||||
|
||||
read(() -> {
|
||||
if(value.has("consumes") && value.get("consumes").isObject()){
|
||||
for(JsonValue child : 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 + "'.");
|
||||
}
|
||||
}
|
||||
readBlockConsumers(block, value.get("consumes"));
|
||||
value.remove("consumes");
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,13 @@ import arc.util.serialization.Jval.*;
|
||||
import mindustry.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
/** The current implementation is awful. Consider it a proof of concept. */
|
||||
//TODO block consumer support
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ContentPatcher{
|
||||
private static final Object root = new Object();
|
||||
@@ -113,7 +114,7 @@ public class ContentPatcher{
|
||||
for(int i = 0; i < path.length - 1; i++){
|
||||
Object[] result = resolve(object, path[i], metadata);
|
||||
if(result == null){
|
||||
//TODO report error
|
||||
warn("Failed to resolve @.@", object, path[i]);
|
||||
return;
|
||||
}
|
||||
object = result[0];
|
||||
@@ -231,6 +232,23 @@ public class ContentPatcher{
|
||||
}
|
||||
Reflect.set(fobj, fdata.field, fv);
|
||||
}, 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{
|
||||
warn("Unknown field: '@' for class '@'", field, actualType.getSimpleName());
|
||||
}
|
||||
@@ -241,7 +259,7 @@ public class ContentPatcher{
|
||||
Object prevValue = getter.get();
|
||||
|
||||
if(value instanceof JsonValue jsv){ //setting values from object
|
||||
if(prevValue == null || !jsv.isObject() || jsv.has("type")){
|
||||
if(prevValue == null || !jsv.isObject() || jsv.has("type")){
|
||||
if(UnlockableContent.class.isAssignableFrom(metadata.type) && (jsv.isObject())){
|
||||
warn("New content must not be instantiated: @", jsv);
|
||||
return;
|
||||
|
||||
@@ -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
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
Reference in New Issue
Block a user