diff --git a/core/assets/maps/canyon.msav b/core/assets/maps/canyon.msav index 06f5b6e064..4e5c688302 100644 Binary files a/core/assets/maps/canyon.msav and b/core/assets/maps/canyon.msav differ diff --git a/core/assets/music/editor.mp3 b/core/assets/music/editor.mp3 deleted file mode 100644 index ed3f0e5e6e..0000000000 Binary files a/core/assets/music/editor.mp3 and /dev/null differ diff --git a/core/assets/music/editor.ogg b/core/assets/music/editor.ogg new file mode 100644 index 0000000000..61348f1b75 Binary files /dev/null and b/core/assets/music/editor.ogg differ diff --git a/core/assets/music/game1.mp3 b/core/assets/music/game1.mp3 deleted file mode 100644 index bd8450231f..0000000000 Binary files a/core/assets/music/game1.mp3 and /dev/null differ diff --git a/core/assets/music/game1.ogg b/core/assets/music/game1.ogg new file mode 100644 index 0000000000..d69bb0e931 Binary files /dev/null and b/core/assets/music/game1.ogg differ diff --git a/core/assets/music/game2.mp3 b/core/assets/music/game2.mp3 deleted file mode 100644 index e8b78e4ff2..0000000000 Binary files a/core/assets/music/game2.mp3 and /dev/null differ diff --git a/core/assets/music/game2.ogg b/core/assets/music/game2.ogg new file mode 100644 index 0000000000..9cf7898026 Binary files /dev/null and b/core/assets/music/game2.ogg differ diff --git a/core/assets/music/game3.mp3 b/core/assets/music/game3.mp3 deleted file mode 100644 index 434c155689..0000000000 Binary files a/core/assets/music/game3.mp3 and /dev/null differ diff --git a/core/assets/music/game3.ogg b/core/assets/music/game3.ogg new file mode 100644 index 0000000000..657848a0da Binary files /dev/null and b/core/assets/music/game3.ogg differ diff --git a/core/assets/music/game4.mp3 b/core/assets/music/game4.mp3 deleted file mode 100644 index 87b291c803..0000000000 Binary files a/core/assets/music/game4.mp3 and /dev/null differ diff --git a/core/assets/music/game4.ogg b/core/assets/music/game4.ogg new file mode 100644 index 0000000000..5b9dbe5ee4 Binary files /dev/null and b/core/assets/music/game4.ogg differ diff --git a/core/assets/music/game5.mp3 b/core/assets/music/game5.mp3 deleted file mode 100644 index 3e421d83ae..0000000000 Binary files a/core/assets/music/game5.mp3 and /dev/null differ diff --git a/core/assets/music/game5.ogg b/core/assets/music/game5.ogg new file mode 100644 index 0000000000..d988882f7a Binary files /dev/null and b/core/assets/music/game5.ogg differ diff --git a/core/assets/music/game6.mp3 b/core/assets/music/game6.mp3 deleted file mode 100644 index 9eb948ab5e..0000000000 Binary files a/core/assets/music/game6.mp3 and /dev/null differ diff --git a/core/assets/music/game6.ogg b/core/assets/music/game6.ogg new file mode 100644 index 0000000000..d57cdae0c2 Binary files /dev/null and b/core/assets/music/game6.ogg differ diff --git a/core/assets/music/game7.ogg b/core/assets/music/game7.ogg new file mode 100644 index 0000000000..58d0eb7db9 Binary files /dev/null and b/core/assets/music/game7.ogg differ diff --git a/core/assets/music/launch.mp3 b/core/assets/music/launch.mp3 deleted file mode 100644 index 25fe82b69d..0000000000 Binary files a/core/assets/music/launch.mp3 and /dev/null differ diff --git a/core/assets/music/launch.ogg b/core/assets/music/launch.ogg new file mode 100644 index 0000000000..1da1a065c6 Binary files /dev/null and b/core/assets/music/launch.ogg differ diff --git a/core/assets/music/menu.mp3 b/core/assets/music/menu.mp3 deleted file mode 100644 index 3c9319daa2..0000000000 Binary files a/core/assets/music/menu.mp3 and /dev/null differ diff --git a/core/assets/music/menu.ogg b/core/assets/music/menu.ogg new file mode 100644 index 0000000000..90dfbb6378 Binary files /dev/null and b/core/assets/music/menu.ogg differ diff --git a/core/src/io/anuke/mindustry/game/Gamemode.java b/core/src/io/anuke/mindustry/game/Gamemode.java index 7f94b867ae..4c8e42e1f1 100644 --- a/core/src/io/anuke/mindustry/game/Gamemode.java +++ b/core/src/io/anuke/mindustry/game/Gamemode.java @@ -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())), diff --git a/core/src/io/anuke/mindustry/io/JsonIO.java b/core/src/io/anuke/mindustry/io/JsonIO.java index e5cd5509c6..500374994a 100644 --- a/core/src/io/anuke/mindustry/io/JsonIO.java +++ b/core/src/io/anuke/mindustry/io/JsonIO.java @@ -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(){ - @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(){ - @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(){ - @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(){ - @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(){ - @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(){ - @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 read(Class 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(){ + @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(){ + @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(){ + @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(){ + @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(){ + @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(){ + @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 fromJson(Class type, String json){ + return fromBaseJson(type, null, json); + } + + public T fromBaseJson(Class 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; + } + } } diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index 7bea6f1bb1..7e2e63071a 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -62,10 +62,24 @@ public class Map implements Comparable{ 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){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java index 80ccca0d46..26ed6bf1c9 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java @@ -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 diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 7fd9bbad75..6e49684e8f 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -239,7 +239,7 @@ public class ServerControl implements ApplicationListener{ lastMode = preset; try{ world.loadMap(result); - state.rules = preset.apply(result.rules()); + state.rules = result.applyRules(preset); logic.play(); info("Map loaded."); @@ -706,7 +706,7 @@ public class ServerControl implements ApplicationListener{ Call.onWorldDataBegin(); run.run(); logic.play(); - state.rules = lastMode.apply(world.getMap().rules()); + state.rules = world.getMap().applyRules(lastMode); for(Player p : players){ p.reset(); if(state.rules.pvp){