diff --git a/annotations/src/main/resources/revisions/Bullet/0.json b/annotations/src/main/resources/revisions/Bullet/0.json index 4904375b03..f9e8a830d5 100644 --- a/annotations/src/main/resources/revisions/Bullet/0.json +++ b/annotations/src/main/resources/revisions/Bullet/0.json @@ -1 +1 @@ -{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/Bullet/1.json b/annotations/src/main/resources/revisions/Bullet/1.json deleted file mode 100644 index c2d8c52eb2..0000000000 --- a/annotations/src/main/resources/revisions/Bullet/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/Bullet/2.json b/annotations/src/main/resources/revisions/Bullet/2.json deleted file mode 100644 index 04b1c437de..0000000000 --- a/annotations/src/main/resources/revisions/Bullet/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/Bullet/3.json b/annotations/src/main/resources/revisions/Bullet/3.json deleted file mode 100644 index 30b9ec33cc..0000000000 --- a/annotations/src/main/resources/revisions/Bullet/3.json +++ /dev/null @@ -1 +0,0 @@ -{version:3,fields:[{name:collided,type:arc.struct.IntSeq,size:-1},{name:damage,type:float,size:4},{name:data,type:java.lang.Object,size:-1},{name:lifetime,type:float,size:4},{name:owner,type:mindustry.gen.Entityc,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:time,type:float,size:4},{name:type,type:mindustry.entities.bullet.BulletType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/EffectState/0.json b/annotations/src/main/resources/revisions/EffectState/0.json index 5ce16bf09c..88eb281607 100644 --- a/annotations/src/main/resources/revisions/EffectState/0.json +++ b/annotations/src/main/resources/revisions/EffectState/0.json @@ -1 +1 @@ -{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file +{fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/EffectState/1.json b/annotations/src/main/resources/revisions/EffectState/1.json deleted file mode 100644 index 0ccd683257..0000000000 --- a/annotations/src/main/resources/revisions/EffectState/1.json +++ /dev/null @@ -1 +0,0 @@ -{version:1,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/EffectState/2.json b/annotations/src/main/resources/revisions/EffectState/2.json deleted file mode 100644 index fb05e5f923..0000000000 --- a/annotations/src/main/resources/revisions/EffectState/2.json +++ /dev/null @@ -1 +0,0 @@ -{version:2,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/EffectState/3.json b/annotations/src/main/resources/revisions/EffectState/3.json deleted file mode 100644 index 41991e73c4..0000000000 --- a/annotations/src/main/resources/revisions/EffectState/3.json +++ /dev/null @@ -1 +0,0 @@ -{version:3,fields:[{name:color,type:arc.graphics.Color,size:-1},{name:data,type:java.lang.Object,size:-1},{name:effect,type:mindustry.entities.Effect,size:-1},{name:lifetime,type:float,size:4},{name:offsetX,type:float,size:4},{name:offsetY,type:float,size:4},{name:parent,type:mindustry.gen.Posc,size:-1},{name:rotation,type:float,size:4},{name:time,type:float,size:4},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/annotations/src/main/resources/revisions/MinerUnit/0.json b/annotations/src/main/resources/revisions/MinerUnit/0.json deleted file mode 100644 index 5df97253d8..0000000000 --- a/annotations/src/main/resources/revisions/MinerUnit/0.json +++ /dev/null @@ -1 +0,0 @@ -{fields:[{name:ammo,type:int,size:4},{name:armor,type:float,size:4},{name:controller,type:mindustry.entities.units.UnitController,size:-1},{name:elevation,type:float,size:4},{name:health,type:float,size:4},{name:isShooting,type:boolean,size:1},{name:mineTile,type:mindustry.world.Tile,size:-1},{name:mounts,type:"mindustry.entities.units.WeaponMount[]",size:-1},{name:rotation,type:float,size:4},{name:shield,type:float,size:4},{name:spawnedByCore,type:boolean,size:1},{name:stack,type:mindustry.type.ItemStack,size:-1},{name:statuses,type:arc.struct.Seq,size:-1},{name:team,type:mindustry.game.Team,size:-1},{name:type,type:mindustry.type.UnitType,size:-1},{name:x,type:float,size:4},{name:y,type:float,size:4}]} \ No newline at end of file diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index f692611442..45de1fb9cf 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -125,6 +125,7 @@ mod.reloadrequired = [scarlet]Restart Required mod.import = Import Mod mod.import.file = Import File mod.import.github = Import From GitHub +mod.jarwarn = [scarlet]JAR mods are inherently unsafe.[]\nMake sure you're importing this mod from a trustworthy source! mod.item.remove = This item is part of the[accent] '{0}'[] mod. To remove it, uninstall that mod. mod.remove.confirm = This mod will be deleted. mod.author = [lightgray]Author:[] {0} @@ -197,8 +198,8 @@ server.admins.none = No admins found! server.add = Add Server server.delete = Are you sure you want to delete this server? server.edit = Edit Server -server.outdated = [crimson]Outdated Server![] -server.outdated.client = [crimson]Outdated Client![] +server.outdated = [scarlet]Outdated Server![] +server.outdated.client = [scarlet]Outdated Client![] server.version = [gray]v{0} {1} server.custombuild = [accent]Custom Build confirmban = Are you sure you want to ban "{0}[white]"? @@ -220,7 +221,7 @@ connecting.data = [accent]Loading world data... server.port = Port: server.addressinuse = Address already in use! server.invalidport = Invalid port number! -server.error = [crimson]Error hosting server. +server.error = [scarlet]Error hosting server. save.new = New Save save.overwrite = Are you sure you want to overwrite\nthis save slot? overwrite = Overwrite @@ -230,8 +231,8 @@ save.delete.confirm = Are you sure you want to delete this save? save.delete = Delete save.export = Export Save save.import.invalid = [accent]This save is invalid! -save.import.fail = [crimson]Failed to import save: [accent]{0} -save.export.fail = [crimson]Failed to export save: [accent]{0} +save.import.fail = [scarlet]Failed to import save: [accent]{0} +save.export.fail = [scarlet]Failed to export save: [accent]{0} save.import = Import Save save.newslot = Save name: save.rename = Rename @@ -486,7 +487,7 @@ zone.objective.attack = Destroy Enemy Core add = Add... boss.health = Boss Health -connectfail = [crimson]Connection error:\n\n[accent]{0} +connectfail = [scarlet]Connection error:\n\n[accent]{0} error.unreachable = Server unreachable.\nIs the address spelled correctly? error.invalidaddress = Invalid address. error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! @@ -545,7 +546,7 @@ unplaceable.sectorcaptured = [scarlet]Requires captured sector yes = Yes no = No info.title = Info -error.title = [crimson]An error has occured +error.title = [scarlet]An error has occured error.crashtitle = An error has occured unit.nobuild = [scarlet]Unit can't build blocks.input = Input diff --git a/core/src/mindustry/core/Platform.java b/core/src/mindustry/core/Platform.java index 767bfa993d..83390c82a8 100644 --- a/core/src/mindustry/core/Platform.java +++ b/core/src/mindustry/core/Platform.java @@ -136,7 +136,7 @@ public interface Platform{ * @param extension File extension to filter */ default void showFileChooser(boolean open, String extension, Cons cons){ - new FileChooser(open ? "$open" : "$save", file -> file.extension().toLowerCase().equals(extension), open, file -> { + new FileChooser(open ? "$open" : "$save", file -> file.extEquals(extension), open, file -> { if(!open){ cons.get(file.parent().child(file.nameWithoutExtension() + "." + extension)); }else{ @@ -145,6 +145,19 @@ public interface Platform{ }).show(); } + /** + * Show a file chooser for multiple file types. Only supported on desktop. + * @param cons Selection listener + * @param extensions File extensions to filter + */ + default void showMultiFileChooser(Cons cons, String... extensions){ + if(mobile){ + showFileChooser(true, extensions[0], cons); + }else{ + new FileChooser("$open", file -> Structs.contains(extensions, file.extension().toLowerCase()), true, cons).show(); + } + } + /** Hide the app. Android only. */ default void hide(){ } diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index b068b1337b..7712fbabe9 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -141,6 +141,8 @@ public class Universe{ //TODO events Events.fire(new TurnEvent()); + + save(); } public float secondsMod(float mod, float scale){ diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 9ee9081754..e03a22b2a5 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -74,7 +74,6 @@ public abstract class SaveVersion extends SaveFileReader{ //prepare campaign data for writing if(state.isCampaign()){ state.secinfo.prepare(); - state.getSector().setLastSecond(universe.seconds()); } //flush tech node progress diff --git a/core/src/mindustry/mod/Mod.java b/core/src/mindustry/mod/Mod.java index 5b4c31b7a0..eea38820c6 100644 --- a/core/src/mindustry/mod/Mod.java +++ b/core/src/mindustry/mod/Mod.java @@ -15,6 +15,11 @@ public class Mod{ } + /** Called on clientside mods. Load content here. */ + public void loadContent(){ + + } + /** Register any commands to be used on the server side, e.g. from the console. */ public void registerServerCommands(CommandHandler handler){ diff --git a/core/src/mindustry/mod/Mods.java b/core/src/mindustry/mod/Mods.java index 7d00599884..e4758a20a3 100644 --- a/core/src/mindustry/mod/Mods.java +++ b/core/src/mindustry/mod/Mods.java @@ -460,6 +460,17 @@ public class Mods implements Loadable{ /** Creates all the content found in mod files. */ public void loadContent(){ + //load class mod content first + for(LoadedMod mod : orderedMods()){ + //hidden mods can't load content + if(mod.main != null && !mod.meta.hidden){ + content.setCurrentMod(mod); + mod.main.loadContent(); + } + } + + content.setCurrentMod(null); + class LoadRun implements Comparable{ final ContentType type; final Fi file; @@ -583,7 +594,7 @@ public class Mods implements Loadable{ Fi metaf = zip.child("mod.json").exists() ? zip.child("mod.json") : zip.child("mod.hjson").exists() ? zip.child("mod.hjson") : zip.child("plugin.json"); if(!metaf.exists()){ Log.warn("Mod @ doesn't have a 'mod.json'/'mod.hjson'/'plugin.json' file, skipping.", sourceFile); - throw new IllegalArgumentException("No mod.json found."); + throw new IllegalArgumentException("Invalid file: No mod.json found."); } ModMeta meta = json.fromJson(ModMeta.class, Jval.read(metaf.readString()).toString(Jformat.plain)); @@ -607,9 +618,9 @@ public class Mods implements Loadable{ //make sure the main class exists before loading it; if it doesn't just don't put it there if(mainFile.exists()){ - //other platforms don't have standard java class loaders - if(!headless && Version.build != -1){ - throw new IllegalArgumentException("Java class mods are currently unsupported outside of custom builds."); + //mobile versions don't support class mods + if(mobile){ + throw new IllegalArgumentException("Java class mods are not supported on mobile."); } URLClassLoader classLoader = new URLClassLoader(new URL[]{sourceFile.file().toURI().toURL()}, ClassLoader.getSystemClassLoader()); diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 0a5004b2f5..5d922979a6 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -6,7 +6,6 @@ import arc.struct.*; import arc.util.ArcAnnotate.*; import arc.util.*; import arc.util.io.*; -import arc.util.noise.*; import mindustry.*; import mindustry.ctype.*; import mindustry.game.Saves.*; @@ -29,7 +28,7 @@ public class Sector{ public @Nullable SectorPreset preset; /** Sector enemy hostility from 0 to 1 */ - public float hostility; + //public float hostility; //TODO implement a dynamic launch period public int launchPeriod = 10; @@ -57,7 +56,7 @@ public class Sector{ /** @return whether the enemy has a generated base here. */ public boolean hasEnemyBase(){ - return hostility >= 0.02f && (save == null || save.meta.rules.waves); + return is(SectorAttribute.base) && (save == null || save.meta.rules.waves); } public boolean isBeingPlayed(){ @@ -80,7 +79,7 @@ public class Sector{ public void generate(){ //TODO use simplex and a seed - hostility = Math.max(Noise.snoise3(tile.v.x, tile.v.y, tile.v.z, 0.5f, 0.4f), 0); + //hostility = Math.max(Noise.snoise3(tile.v.x, tile.v.y, tile.v.z, 0.5f, 0.4f), 0); } public boolean locked(){ @@ -156,7 +155,8 @@ public class Sector{ return (seconds / 60) + ":" + (sf < 10 ? "0" : "") + sf; } - /** @return the stored amount of time spent in this sector this turn in ticks. */ + /** @return the stored amount of time spent in this sector this turn in ticks. + * Do not use unless you know what you're doing. */ public float getStoredTimeSpent(){ return Core.settings.getFloat(key("time-spent")); } @@ -165,6 +165,8 @@ public class Sector{ put("seconds-passed", number); } + /** @return how much time has passed in this sector without the player resuming here. + * Used for resource production calculations. */ public long getSecondsPassed(){ return Core.settings.getLong(key("seconds-passed")); } @@ -284,6 +286,8 @@ public class Sector{ /** Has snow. */ snowy, /** Has sandstorms. */ - desert + desert, + /** Has an enemy base. */ + base } } diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index 0132f954e7..ddb72815b4 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -77,15 +77,24 @@ public class ModsDialog extends BaseDialog{ t.button("$mod.import.file", Icon.file, bstyle, () -> { dialog.hide(); - platform.showFileChooser(true, "zip", file -> { - try{ - mods.importMod(file); - setup(); - }catch(IOException e){ - ui.showException(e); - e.printStackTrace(); + platform.showMultiFileChooser(file -> { + Runnable go = () -> { + try{ + mods.importMod(file); + setup(); + }catch(IOException e){ + ui.showException(e); + e.printStackTrace(); + } + }; + + //show unsafe jar file warning + if(file.extEquals("jar")){ + ui.showConfirm("$warning", "$mod.jarwarn", go); + }else{ + go.run(); } - }); + }, "zip", "jar"); }).margin(12f); t.row(); diff --git a/gradle.properties b/gradle.properties index 34f08723e2..78b0b3e1c8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ org.gradle.daemon=true org.gradle.jvmargs=-Xms256m -Xmx1024m -archash=6ed1b560047eaaf9ae83176526de51e5a49cadc3 +archash=b877b22de07db3cd2843a59eb92f5dfe1c61ae78