From bc02d178cee1e76fc681229c5effea632ff0ced6 Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 3 Oct 2019 18:53:43 -0400 Subject: [PATCH] Support for zones --- core/assets/bundles/bundle.properties | 1 + core/src/io/anuke/mindustry/core/UI.java | 2 +- .../io/anuke/mindustry/mod/ContentParser.java | 11 ++++++--- core/src/io/anuke/mindustry/mod/Mods.java | 9 +++++++ core/src/io/anuke/mindustry/type/Zone.java | 10 +++++--- .../mindustry/ui/dialogs/ModsDialog.java | 24 +++++++++++++++++++ 6 files changed, 50 insertions(+), 7 deletions(-) diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6f93137fa9..33bbc8c1f9 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -78,6 +78,7 @@ mod.enable = Enable mod.requiresrestart = The game will now close to apply the mod changes. mod.reloadrequired = [scarlet]Reload Required mod.import = Import Mod +mod.import.github = Import Github Mod mod.remove.confirm = This mod will be deleted. mod.author = [LIGHT_GRAY]Author:[] {0} mod.missing = This save contains mods that you have recently updated or no longer have installed. Save corruption may occur. Are you sure you want to load it?\n[lightgray]Mods:\n{0} diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 99c654e579..5998f90cc7 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -284,7 +284,7 @@ public class UI implements ApplicationListener, Loadable{ new Dialog(titleText){{ cont.margin(30).add(dtext).padRight(6f); TextFieldFilter filter = inumeric ? TextFieldFilter.digitsOnly : (f, c) -> true; - TextField field = cont.addField(def, t -> {}).size(170f, 50f).get(); + TextField field = cont.addField(def, t -> {}).size(330f, 50f).get(); field.setFilter((f, c) -> field.getText().length() < textLength && filter.acceptChar(f, c)); buttons.defaults().size(120, 54).pad(4); buttons.addButton("$ok", () -> { diff --git a/core/src/io/anuke/mindustry/mod/ContentParser.java b/core/src/io/anuke/mindustry/mod/ContentParser.java index dc8c6b3f28..fda221c100 100644 --- a/core/src/io/anuke/mindustry/mod/ContentParser.java +++ b/core/src/io/anuke/mindustry/mod/ContentParser.java @@ -2,11 +2,13 @@ package io.anuke.mindustry.mod; import io.anuke.arc.*; import io.anuke.arc.audio.*; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.*; import io.anuke.arc.function.*; import io.anuke.arc.graphics.*; import io.anuke.arc.util.ArcAnnotate.*; import io.anuke.arc.util.*; +import io.anuke.arc.util.reflect.Field; import io.anuke.arc.util.reflect.*; import io.anuke.arc.util.serialization.*; import io.anuke.arc.util.serialization.Json.*; @@ -21,6 +23,8 @@ import io.anuke.mindustry.mod.Mods.*; import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.*; +import java.lang.reflect.*; + @SuppressWarnings("unchecked") public class ContentParser{ private static final boolean ignoreUnknownFields = true; @@ -29,6 +33,7 @@ public class ContentParser{ put(BulletType.class, (type, data) -> field(Bullets.class, data)); put(Effect.class, (type, data) -> field(Fx.class, data)); put(StatusEffect.class, (type, data) -> field(StatusEffects.class, data)); + put(Loadout.class, (type, data) -> field(Loadouts.class, data)); put(Color.class, (type, data) -> Color.valueOf(data.asString())); put(Music.class, (type, data) -> { if(fieldOpt(Musics.class, data) != null) return fieldOpt(Musics.class, data); @@ -173,7 +178,7 @@ public class ContentParser{ if(!arr.isEmpty()){ Class c = arr.first().getClass(); //get base content class, skipping intermediates - while(!(c.getSuperclass() == Content.class || c.getSuperclass() == UnlockableContent.class || c.getSuperclass() == UnlockableContent.class)){ + while(!(c.getSuperclass() == Content.class || c.getSuperclass() == UnlockableContent.class || Modifier.isAbstract(c.getSuperclass().getModifiers()))){ c = c.getSuperclass(); } @@ -260,13 +265,13 @@ public class ContentParser{ private void checkNulls(Object object, ObjectSet checked){ checked.add(object); - parser.getFields(object.getClass()).each((name, field) -> { + parser.getFields(object.getClass()).values().toArray().each(field -> { try{ if(field.field.getType().isPrimitive()) return; Object obj = field.field.get(object); if(field.field.isAnnotationPresent(NonNull.class) && field.field.get(object) == null){ - throw new RuntimeException("Field '" + name + "' in " + object.getClass().getSimpleName() + " is missing!"); + throw new RuntimeException("Field '" + field.field.getName() + "' in " + object.getClass().getSimpleName() + " is missing!"); } if(obj != null && !checked.contains(obj)){ diff --git a/core/src/io/anuke/mindustry/mod/Mods.java b/core/src/io/anuke/mindustry/mod/Mods.java index 50254ce995..bfe8df2ce1 100644 --- a/core/src/io/anuke/mindustry/mod/Mods.java +++ b/core/src/io/anuke/mindustry/mod/Mods.java @@ -331,6 +331,9 @@ public class Mods implements Loadable{ * Note that directories can be loaded as mods.*/ private LoadedMod loadMod(FileHandle sourceFile) throws Exception{ FileHandle zip = sourceFile.isDirectory() ? sourceFile : new ZipFileHandle(sourceFile); + if(zip.list().length == 1 && zip.list()[0].isDirectory()){ + zip = zip.list()[0]; + } FileHandle metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("plugin.json"); if(!metaf.exists()){ @@ -341,6 +344,12 @@ public class Mods implements Loadable{ ModMeta meta = json.fromJson(ModMeta.class, metaf.readString()); String camelized = meta.name.replace(" ", ""); String mainClass = meta.main == null ? camelized.toLowerCase() + "." + camelized + "Mod" : meta.main; + String baseName = meta.name.toLowerCase().replace(" ", "-"); + + if(loaded.contains(m -> m.name.equals(baseName)) || disabled.contains(m -> m.name.equals(baseName))){ + throw new IllegalArgumentException("A mod with the name '" + baseName + "' is already imported."); + } + Mod mainMod; FileHandle mainFile = zip; diff --git a/core/src/io/anuke/mindustry/type/Zone.java b/core/src/io/anuke/mindustry/type/Zone.java index 471a74c9d7..3a499996c4 100644 --- a/core/src/io/anuke/mindustry/type/Zone.java +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -47,7 +47,7 @@ public class Zone extends UnlockableContent{ @Override public void load(){ - preview = Core.atlas.find("zone-" + name); + preview = Core.atlas.find("zone-" + name, Core.atlas.find(name + "-zone")); } public Rules getRules(){ @@ -209,14 +209,18 @@ public class Zone extends UnlockableContent{ } public static class ZoneRequirement{ - public final Zone zone; - public final int wave; + public @NonNull Zone zone; + public @NonNull int wave; public ZoneRequirement(Zone zone, int wave){ this.zone = zone; this.wave = wave; } + protected ZoneRequirement(){ + + } + public static ZoneRequirement[] with(Object... objects){ ZoneRequirement[] out = new ZoneRequirement[objects.length / 2]; for(int i = 0; i < objects.length; i += 2){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ModsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ModsDialog.java index 9b3fbbd6f4..5a542f31ea 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ModsDialog.java @@ -3,6 +3,8 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.*; import io.anuke.arc.collection.*; import io.anuke.arc.util.*; +import io.anuke.arc.util.io.*; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.gen.*; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.mod.Mods.*; @@ -107,5 +109,27 @@ public class ModsDialog extends FloatingDialog{ } }); }).margin(12f).width(500f); + + //not well tested currently + if(Version.build == -1){ + cont.row(); + + cont.addImageTextButton("$mod.import.github", Icon.github, () -> { + ui.showTextInput("$mod.import.github", "", "Anuken/ExampleMod", text -> { + Core.net.httpGet("http://api.github.com/repos/" + text + "/zipball/master", loc -> { + Core.net.httpGet(loc.getHeader("Location"), result -> { + try{ + Streams.copyStream(result.getResultAsStream(), modDirectory.child(text.replace("/", "") + ".zip").write(false)); + ui.loadAnd(() -> { + mods.reloadContent(); + }); + }catch(Exception e){ + ui.showException(e); + } + }, ui::showException); + }, ui::showException); + }); + }).margin(12f).width(500f); + } } } \ No newline at end of file