Support for zones
This commit is contained in:
@@ -78,6 +78,7 @@ mod.enable = Enable
|
|||||||
mod.requiresrestart = The game will now close to apply the mod changes.
|
mod.requiresrestart = The game will now close to apply the mod changes.
|
||||||
mod.reloadrequired = [scarlet]Reload Required
|
mod.reloadrequired = [scarlet]Reload Required
|
||||||
mod.import = Import Mod
|
mod.import = Import Mod
|
||||||
|
mod.import.github = Import Github Mod
|
||||||
mod.remove.confirm = This mod will be deleted.
|
mod.remove.confirm = This mod will be deleted.
|
||||||
mod.author = [LIGHT_GRAY]Author:[] {0}
|
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}
|
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}
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ public class UI implements ApplicationListener, Loadable{
|
|||||||
new Dialog(titleText){{
|
new Dialog(titleText){{
|
||||||
cont.margin(30).add(dtext).padRight(6f);
|
cont.margin(30).add(dtext).padRight(6f);
|
||||||
TextFieldFilter filter = inumeric ? TextFieldFilter.digitsOnly : (f, c) -> true;
|
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));
|
field.setFilter((f, c) -> field.getText().length() < textLength && filter.acceptChar(f, c));
|
||||||
buttons.defaults().size(120, 54).pad(4);
|
buttons.defaults().size(120, 54).pad(4);
|
||||||
buttons.addButton("$ok", () -> {
|
buttons.addButton("$ok", () -> {
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package io.anuke.mindustry.mod;
|
|||||||
|
|
||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.audio.*;
|
import io.anuke.arc.audio.*;
|
||||||
|
import io.anuke.arc.collection.Array;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.function.*;
|
import io.anuke.arc.function.*;
|
||||||
import io.anuke.arc.graphics.*;
|
import io.anuke.arc.graphics.*;
|
||||||
import io.anuke.arc.util.ArcAnnotate.*;
|
import io.anuke.arc.util.ArcAnnotate.*;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
|
import io.anuke.arc.util.reflect.Field;
|
||||||
import io.anuke.arc.util.reflect.*;
|
import io.anuke.arc.util.reflect.*;
|
||||||
import io.anuke.arc.util.serialization.*;
|
import io.anuke.arc.util.serialization.*;
|
||||||
import io.anuke.arc.util.serialization.Json.*;
|
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.type.*;
|
||||||
import io.anuke.mindustry.world.*;
|
import io.anuke.mindustry.world.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class ContentParser{
|
public class ContentParser{
|
||||||
private static final boolean ignoreUnknownFields = true;
|
private static final boolean ignoreUnknownFields = true;
|
||||||
@@ -29,6 +33,7 @@ public class ContentParser{
|
|||||||
put(BulletType.class, (type, data) -> field(Bullets.class, data));
|
put(BulletType.class, (type, data) -> field(Bullets.class, data));
|
||||||
put(Effect.class, (type, data) -> field(Fx.class, data));
|
put(Effect.class, (type, data) -> field(Fx.class, data));
|
||||||
put(StatusEffect.class, (type, data) -> field(StatusEffects.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(Color.class, (type, data) -> Color.valueOf(data.asString()));
|
||||||
put(Music.class, (type, data) -> {
|
put(Music.class, (type, data) -> {
|
||||||
if(fieldOpt(Musics.class, data) != null) return fieldOpt(Musics.class, data);
|
if(fieldOpt(Musics.class, data) != null) return fieldOpt(Musics.class, data);
|
||||||
@@ -173,7 +178,7 @@ public class ContentParser{
|
|||||||
if(!arr.isEmpty()){
|
if(!arr.isEmpty()){
|
||||||
Class<?> c = arr.first().getClass();
|
Class<?> c = arr.first().getClass();
|
||||||
//get base content class, skipping intermediates
|
//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();
|
c = c.getSuperclass();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,13 +265,13 @@ public class ContentParser{
|
|||||||
private void checkNulls(Object object, ObjectSet<Object> checked){
|
private void checkNulls(Object object, ObjectSet<Object> checked){
|
||||||
checked.add(object);
|
checked.add(object);
|
||||||
|
|
||||||
parser.getFields(object.getClass()).each((name, field) -> {
|
parser.getFields(object.getClass()).values().toArray().each(field -> {
|
||||||
try{
|
try{
|
||||||
if(field.field.getType().isPrimitive()) return;
|
if(field.field.getType().isPrimitive()) return;
|
||||||
|
|
||||||
Object obj = field.field.get(object);
|
Object obj = field.field.get(object);
|
||||||
if(field.field.isAnnotationPresent(NonNull.class) && field.field.get(object) == null){
|
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)){
|
if(obj != null && !checked.contains(obj)){
|
||||||
|
|||||||
@@ -331,6 +331,9 @@ public class Mods implements Loadable{
|
|||||||
* Note that directories can be loaded as mods.*/
|
* Note that directories can be loaded as mods.*/
|
||||||
private LoadedMod loadMod(FileHandle sourceFile) throws Exception{
|
private LoadedMod loadMod(FileHandle sourceFile) throws Exception{
|
||||||
FileHandle zip = sourceFile.isDirectory() ? sourceFile : new ZipFileHandle(sourceFile);
|
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");
|
FileHandle metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("plugin.json");
|
||||||
if(!metaf.exists()){
|
if(!metaf.exists()){
|
||||||
@@ -341,6 +344,12 @@ public class Mods implements Loadable{
|
|||||||
ModMeta meta = json.fromJson(ModMeta.class, metaf.readString());
|
ModMeta meta = json.fromJson(ModMeta.class, metaf.readString());
|
||||||
String camelized = meta.name.replace(" ", "");
|
String camelized = meta.name.replace(" ", "");
|
||||||
String mainClass = meta.main == null ? camelized.toLowerCase() + "." + camelized + "Mod" : meta.main;
|
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;
|
Mod mainMod;
|
||||||
|
|
||||||
FileHandle mainFile = zip;
|
FileHandle mainFile = zip;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class Zone extends UnlockableContent{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void load(){
|
public void load(){
|
||||||
preview = Core.atlas.find("zone-" + name);
|
preview = Core.atlas.find("zone-" + name, Core.atlas.find(name + "-zone"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rules getRules(){
|
public Rules getRules(){
|
||||||
@@ -209,14 +209,18 @@ public class Zone extends UnlockableContent{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class ZoneRequirement{
|
public static class ZoneRequirement{
|
||||||
public final Zone zone;
|
public @NonNull Zone zone;
|
||||||
public final int wave;
|
public @NonNull int wave;
|
||||||
|
|
||||||
public ZoneRequirement(Zone zone, int wave){
|
public ZoneRequirement(Zone zone, int wave){
|
||||||
this.zone = zone;
|
this.zone = zone;
|
||||||
this.wave = wave;
|
this.wave = wave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected ZoneRequirement(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static ZoneRequirement[] with(Object... objects){
|
public static ZoneRequirement[] with(Object... objects){
|
||||||
ZoneRequirement[] out = new ZoneRequirement[objects.length / 2];
|
ZoneRequirement[] out = new ZoneRequirement[objects.length / 2];
|
||||||
for(int i = 0; i < objects.length; i += 2){
|
for(int i = 0; i < objects.length; i += 2){
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package io.anuke.mindustry.ui.dialogs;
|
|||||||
import io.anuke.arc.*;
|
import io.anuke.arc.*;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.util.*;
|
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.gen.*;
|
||||||
import io.anuke.mindustry.graphics.*;
|
import io.anuke.mindustry.graphics.*;
|
||||||
import io.anuke.mindustry.mod.Mods.*;
|
import io.anuke.mindustry.mod.Mods.*;
|
||||||
@@ -107,5 +109,27 @@ public class ModsDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}).margin(12f).width(500f);
|
}).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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user