Fixed maps not being able to override gamemode-specific settings

This commit is contained in:
Anuken
2019-08-10 11:43:28 -04:00
parent 16f6b51857
commit 4ef60af4a8
25 changed files with 153 additions and 110 deletions

View File

@@ -22,7 +22,6 @@ public enum Gamemode{
attack(rules -> {
rules.enemyCheat = true;
rules.unitDrops = true;
rules.waves = false;
rules.attackMode = true;
rules.waves = true;
}, map -> map.teams.contains(waveTeam.ordinal())),

View File

@@ -11,101 +11,7 @@ import io.anuke.mindustry.world.*;
@SuppressWarnings("unchecked")
public class JsonIO{
private static Json json = new Json(){{
setIgnoreUnknownFields(true);
setElementType(Rules.class, "spawns", SpawnGroup.class);
setElementType(Rules.class, "loadout", ItemStack.class);
setSerializer(Zone.class, new Serializer<Zone>(){
@Override
public void write(Json json, Zone object, Class knownType){
json.writeValue(object.name);
}
@Override
public Zone read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.zone, jsonData.asString());
}
});
setSerializer(Item.class, new Serializer<Item>(){
@Override
public void write(Json json, Item object, Class knownType){
json.writeValue(object.name);
}
@Override
public Item read(Json json, JsonValue jsonData, Class type){
if(jsonData.asString() == null) return Items.copper;
Item i = Vars.content.getByName(ContentType.item, jsonData.asString());
return i == null ? Items.copper : i;
}
});
//TODO extremely hacky and disgusting
for(Block block : Vars.content.blocks()){
Class type = block.getClass();
if(type.isAnonymousClass()) type = type.getSuperclass();
setSerializer(type, new Serializer<Block>(){
@Override
public void write(Json json, Block object, Class knownType){
json.writeValue(object.name);
}
@Override
public Block read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.block, jsonData.asString());
}
});
}
setSerializer(Block.class, new Serializer<Block>(){
@Override
public void write(Json json, Block object, Class knownType){
json.writeValue(object.name);
}
@Override
public Block read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.block, jsonData.asString());
}
});
setSerializer(TeamData.class, new Serializer<TeamData>(){
@Override
public void write(Json json, TeamData object, Class knownType){
json.writeObjectStart();
json.writeValue("brokenBlocks", object.brokenBlocks.toArray());
json.writeValue("team", object.team.ordinal());
json.writeObjectEnd();
}
@Override
public TeamData read(Json json, JsonValue jsonData, Class type){
long[] blocks = jsonData.get("brokenBlocks").asLongArray();
Team team = Team.all[jsonData.getInt("team", 0)];
TeamData out = new TeamData(team, EnumSet.of(new Team[]{}));
out.brokenBlocks = new LongQueue(blocks);
return out;
}
});
setSerializer(ItemStack.class, new Serializer<ItemStack>(){
@Override
public void write(Json json, ItemStack object, Class knownType){
json.writeObjectStart();
json.writeValue("item", object.item);
json.writeValue("amount", object.amount);
json.writeObjectEnd();
}
@Override
public ItemStack read(Json json, JsonValue jsonData, Class type){
return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount"));
}
});
}};
private static CustomJson json = new CustomJson();
public static String write(Object object){
return json.toJson(object);
@@ -119,7 +25,129 @@ public class JsonIO{
return json.fromJson(type, string);
}
public static <T> T read(Class<T> type, T base, String string){
return json.fromBaseJson(type, base, string);
}
public static String print(String in){
return json.prettyPrint(in);
}
static class CustomJson extends Json{
private Object baseObject;
{
setIgnoreUnknownFields(true);
setElementType(Rules.class, "spawns", SpawnGroup.class);
setElementType(Rules.class, "loadout", ItemStack.class);
setSerializer(Zone.class, new Serializer<Zone>(){
@Override
public void write(Json json, Zone object, Class knownType){
json.writeValue(object.name);
}
@Override
public Zone read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.zone, jsonData.asString());
}
});
setSerializer(Item.class, new Serializer<Item>(){
@Override
public void write(Json json, Item object, Class knownType){
json.writeValue(object.name);
}
@Override
public Item read(Json json, JsonValue jsonData, Class type){
if(jsonData.asString() == null) return Items.copper;
Item i = Vars.content.getByName(ContentType.item, jsonData.asString());
return i == null ? Items.copper : i;
}
});
//TODO extremely hacky and disgusting
for(Block block : Vars.content.blocks()){
Class type = block.getClass();
if(type.isAnonymousClass()) type = type.getSuperclass();
setSerializer(type, new Serializer<Block>(){
@Override
public void write(Json json, Block object, Class knownType){
json.writeValue(object.name);
}
@Override
public Block read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.block, jsonData.asString());
}
});
}
setSerializer(Block.class, new Serializer<Block>(){
@Override
public void write(Json json, Block object, Class knownType){
json.writeValue(object.name);
}
@Override
public Block read(Json json, JsonValue jsonData, Class type){
return Vars.content.getByName(ContentType.block, jsonData.asString());
}
});
setSerializer(TeamData.class, new Serializer<TeamData>(){
@Override
public void write(Json json, TeamData object, Class knownType){
json.writeObjectStart();
json.writeValue("brokenBlocks", object.brokenBlocks.toArray());
json.writeValue("team", object.team.ordinal());
json.writeObjectEnd();
}
@Override
public TeamData read(Json json, JsonValue jsonData, Class type){
long[] blocks = jsonData.get("brokenBlocks").asLongArray();
Team team = Team.all[jsonData.getInt("team", 0)];
TeamData out = new TeamData(team, EnumSet.of(new Team[]{}));
out.brokenBlocks = new LongQueue(blocks);
return out;
}
});
setSerializer(ItemStack.class, new Serializer<ItemStack>(){
@Override
public void write(Json json, ItemStack object, Class knownType){
json.writeObjectStart();
json.writeValue("item", object.item);
json.writeValue("amount", object.amount);
json.writeObjectEnd();
}
@Override
public ItemStack read(Json json, JsonValue jsonData, Class type){
return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount"));
}
});
}
@Override
public <T> T fromJson(Class<T> type, String json){
return fromBaseJson(type, null, json);
}
public <T> T fromBaseJson(Class<T> type, T base, String json){
this.baseObject = base;
return readValue(type, null, new JsonReader().parse(json));
}
@Override
protected Object newInstance(Class type){
if(baseObject == null || baseObject.getClass() != type){
return super.newInstance(type);
}
return baseObject;
}
}
}

View File

@@ -62,10 +62,24 @@ public class Map implements Comparable<Map>{
Vars.data.modified();
}
/** Returns the result of applying this map's rules to the specified gamemode.*/
public Rules applyRules(Gamemode mode){
//mode specific defaults have been applied
Rules out = new Rules();
mode.apply(out);
//now apply map-specific overrides
return rules(out);
}
/** This creates a new instance of Rules.*/
public Rules rules(){
return rules(new Rules());
}
public Rules rules(Rules base){
try{
Rules result = JsonIO.read(Rules.class, tags.get("rules", "{}"));
Rules result = JsonIO.read(Rules.class, base, tags.get("rules", "{}"));
if(result.spawns.isEmpty()) result.spawns = Vars.defaultWaves.get();
return result;
}catch(Exception e){

View File

@@ -1,19 +1,20 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.arc.Core;
import io.anuke.arc.scene.ui.ScrollPane;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.maps.*;
import io.anuke.mindustry.ui.*;
import static io.anuke.mindustry.Vars.*;
public class MapPlayDialog extends FloatingDialog{
CustomRulesDialog dialog = new CustomRulesDialog();
Rules rules;
Gamemode selectedGamemode = Gamemode.survival;
@NonNull Gamemode selectedGamemode = Gamemode.survival;
Map lastMap;
public MapPlayDialog(){
@@ -37,10 +38,12 @@ public class MapPlayDialog extends FloatingDialog{
//reset to any valid mode after switching to attack (one must exist)
if(!selectedGamemode.valid(map)){
selectedGamemode = Structs.find(Gamemode.all, m -> m.valid(map));
if(selectedGamemode == null){
selectedGamemode = Gamemode.survival;
}
}
rules = map.rules();
rules = selectedGamemode.apply(map.rules());
rules = map.applyRules(selectedGamemode);
Table selmode = new Table();
selmode.add("$level.mode").colspan(4);
@@ -54,8 +57,7 @@ public class MapPlayDialog extends FloatingDialog{
modes.addButton(mode.toString(), "toggle", () -> {
selectedGamemode = mode;
rules = mode.apply(map.rules());
Log.info("toggle rules " + rules);
rules = map.applyRules(mode);
}).update(b -> b.setChecked(selectedGamemode == mode)).size(140f, 54f).disabled(!mode.valid(map));
if(i++ % 2 == 1) modes.row();
}
@@ -64,7 +66,7 @@ public class MapPlayDialog extends FloatingDialog{
cont.add(selmode);
cont.row();
cont.addImageTextButton("$customize", "icon-tools-small", iconsizesmall, () -> dialog.show(rules, () -> rules = (selectedGamemode == null ? map.rules() : selectedGamemode.apply(map.rules())))).width(230);
cont.addImageTextButton("$customize", "icon-tools-small", iconsizesmall, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
cont.row();
cont.add(new BorderImage(map.texture, 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
//only maps with survival are valid for high scores