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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/game1.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/game2.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/game3.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/game4.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/game5.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/game6.ogg Normal file

Binary file not shown.

BIN
core/assets/music/game7.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
core/assets/music/menu.ogg Normal file

Binary file not shown.

View File

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

View File

@@ -11,101 +11,7 @@ import io.anuke.mindustry.world.*;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public class JsonIO{ public class JsonIO{
private static Json json = new Json(){{ private static CustomJson json = new CustomJson();
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"));
}
});
}};
public static String write(Object object){ public static String write(Object object){
return json.toJson(object); return json.toJson(object);
@@ -119,7 +25,129 @@ public class JsonIO{
return json.fromJson(type, string); 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){ public static String print(String in){
return json.prettyPrint(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(); 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.*/ /** This creates a new instance of Rules.*/
public Rules rules(){ public Rules rules(){
return rules(new Rules());
}
public Rules rules(Rules base){
try{ 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(); if(result.spawns.isEmpty()) result.spawns = Vars.defaultWaves.get();
return result; return result;
}catch(Exception e){ }catch(Exception e){

View File

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

View File

@@ -239,7 +239,7 @@ public class ServerControl implements ApplicationListener{
lastMode = preset; lastMode = preset;
try{ try{
world.loadMap(result); world.loadMap(result);
state.rules = preset.apply(result.rules()); state.rules = result.applyRules(preset);
logic.play(); logic.play();
info("Map loaded."); info("Map loaded.");
@@ -706,7 +706,7 @@ public class ServerControl implements ApplicationListener{
Call.onWorldDataBegin(); Call.onWorldDataBegin();
run.run(); run.run();
logic.play(); logic.play();
state.rules = lastMode.apply(world.getMap().rules()); state.rules = world.getMap().applyRules(lastMode);
for(Player p : players){ for(Player p : players){
p.reset(); p.reset();
if(state.rules.pvp){ if(state.rules.pvp){