diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index 66eb7e4636..f3fb569aff 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -222,6 +222,8 @@ public class EntityProcess extends BaseProcessor{ Array syncedFields = new Array<>(); Array allFields = new Array<>(); + boolean isSync = components.contains(s -> s.name().contains("Sync")); + //add all components for(Stype comp : components){ @@ -257,7 +259,7 @@ public class EntityProcess extends BaseProcessor{ allFields.add(f); //add extra sync fields - if(f.has(SyncField.class)){ + if(f.has(SyncField.class) && isSync){ if(!f.tname().toString().equals("float")) err("All SyncFields must be of type float", f); syncedFields.add(f); diff --git a/annotations/src/main/resources/classids.properties b/annotations/src/main/resources/classids.properties index 92e667b660..7ce51d941c 100644 --- a/annotations/src/main/resources/classids.properties +++ b/annotations/src/main/resources/classids.properties @@ -12,7 +12,7 @@ mindustry.entities.comp.PlayerComp=8 mindustry.entities.comp.PuddleComp=9 mindustry.entities.comp.TileComp=10 mindustry.type.Weather.WeatherComp=11 -mindustry.world.blocks.storage.LaunchPad.LaunchPayloadComp=12 +mindustry.world.blocks.campaign.LaunchPad.LaunchPayloadComp=12 oculon=13 phantom=14 tau=19 diff --git a/core/assets-raw/sprites/units/reaper.png b/core/assets-raw/sprites/units/reaper.png index ab6175801b..a85075830f 100644 Binary files a/core/assets-raw/sprites/units/reaper.png and b/core/assets-raw/sprites/units/reaper.png differ diff --git a/core/assets/scripts/global.js b/core/assets/scripts/global.js index 813f18a16c..b8acc336b9 100755 --- a/core/assets/scripts/global.js +++ b/core/assets/scripts/global.js @@ -24,70 +24,72 @@ const extend = function(classType, params){ const newEffect = (lifetime, renderer) => new Effects.Effect(lifetime, new Effects.EffectRenderer({render: renderer})) Call = Packages.mindustry.gen.Call -importPackage(Packages.mindustry.game) -importPackage(Packages.arc.func) -importPackage(Packages.mindustry.entities) +importPackage(Packages.mindustry.graphics.g3d) +importPackage(Packages.mindustry.ctype) importPackage(Packages.mindustry.gen) -importPackage(Packages.mindustry.core) -importPackage(Packages.mindustry.world.blocks.storage) -importPackage(Packages.mindustry.ui.dialogs) -importPackage(Packages.arc.scene.ui) -importPackage(Packages.mindustry.world.blocks.defense.turrets) -importPackage(Packages.mindustry.world.blocks.distribution) -importPackage(Packages.mindustry.ui) -importPackage(Packages.mindustry.content) -importPackage(Packages.mindustry.world.blocks.liquid) -importPackage(Packages.arc.struct) -importPackage(Packages.arc.scene.ui.layout) -importPackage(Packages.mindustry.world.modules) -importPackage(Packages.arc.util) -importPackage(Packages.arc.graphics) -importPackage(Packages.mindustry.entities.def) -importPackage(Packages.mindustry.maps.generators) importPackage(Packages.arc.scene.actions) -importPackage(Packages.mindustry.graphics) -importPackage(Packages.mindustry.entities.bullet) -importPackage(Packages.mindustry.world.blocks.legacy) -importPackage(Packages.mindustry.world.blocks.experimental) importPackage(Packages.mindustry.editor) +importPackage(Packages.mindustry.type) +importPackage(Packages.arc.scene.ui) +importPackage(Packages.arc.math.geom) +importPackage(Packages.mindustry.game) +importPackage(Packages.mindustry.maps.filters) +importPackage(Packages.arc.struct) +importPackage(Packages.arc.scene.style) +importPackage(Packages.mindustry.ui.dialogs) +importPackage(Packages.mindustry.entities.comp) +importPackage(Packages.mindustry.world.blocks.defense.turrets) +importPackage(Packages.mindustry.async) +importPackage(Packages.mindustry.world.blocks.distribution) +importPackage(Packages.mindustry.world.blocks.environment) +importPackage(Packages.mindustry.world.blocks.campaign) +importPackage(Packages.mindustry.world.blocks.liquid) +importPackage(Packages.mindustry.ui) +importPackage(Packages.mindustry.world.blocks.production) +importPackage(Packages.mindustry.ai) +importPackage(Packages.mindustry.world.blocks.defense) +importPackage(Packages.mindustry.world.meta) +importPackage(Packages.mindustry.world.blocks.legacy) +importPackage(Packages.mindustry.world.blocks.units) +importPackage(Packages.arc.graphics) +importPackage(Packages.arc.func) +importPackage(Packages.mindustry.content) importPackage(Packages.mindustry.world.blocks.power) -importPackage(Packages.mindustry.ui.layout) +importPackage(Packages.mindustry.world.blocks) +importPackage(Packages.arc.scene.event) +importPackage(Packages.mindustry.logic) +importPackage(Packages.arc.math) +importPackage(Packages.mindustry.world) +importPackage(Packages.mindustry.maps) +importPackage(Packages.mindustry.maps.generators) +importPackage(Packages.mindustry.world.meta.values) +importPackage(Packages.mindustry.entities) +importPackage(Packages.arc.util) +importPackage(Packages.mindustry.graphics) +importPackage(Packages.mindustry.world.modules) importPackage(Packages.mindustry.world.blocks.sandbox) importPackage(Packages.mindustry.input) -importPackage(Packages.mindustry.world.consumers) -importPackage(Packages.mindustry.ui.fragments) -importPackage(Packages.mindustry.ai.formations) -importPackage(Packages.mindustry.type) -importPackage(Packages.mindustry.world.blocks.production) -importPackage(Packages.arc.scene.event) -importPackage(Packages.arc.math) -importPackage(Packages.arc.scene.utils) -importPackage(Packages.mindustry.world.blocks.defense) -importPackage(Packages.mindustry.graphics.g3d) -importPackage(Packages.mindustry.world.meta) -importPackage(Packages.mindustry.world.blocks.payloads) -importPackage(Packages.mindustry.world) -importPackage(Packages.mindustry.async) -importPackage(Packages.arc.scene.style) -importPackage(Packages.mindustry.world.blocks) -importPackage(Packages.arc.math.geom) -importPackage(Packages.mindustry.ai) -importPackage(Packages.mindustry.maps.filters) -importPackage(Packages.arc.graphics.g2d) -importPackage(Packages.mindustry.ai.formations.patterns) -importPackage(Packages.mindustry.world.blocks.environment) -importPackage(Packages.mindustry) importPackage(Packages.mindustry.entities.units) -importPackage(Packages.mindustry.ctype) +importPackage(Packages.arc.scene.ui.layout) importPackage(Packages.mindustry.ai.types) -importPackage(Packages.mindustry.maps) -importPackage(Packages.mindustry.world.meta.values) -importPackage(Packages.mindustry.world.producers) -importPackage(Packages.mindustry.world.blocks.units) +importPackage(Packages.mindustry.ai.formations.patterns) +importPackage(Packages.arc.scene.utils) +importPackage(Packages.mindustry.ai.formations) +importPackage(Packages.mindustry.ui.fragments) +importPackage(Packages.mindustry.world.blocks.experimental) +importPackage(Packages.mindustry.world.blocks.storage) +importPackage(Packages.mindustry.audio) +importPackage(Packages.mindustry.ui.layout) +importPackage(Packages.mindustry.entities.bullet) +importPackage(Packages.mindustry.world.consumers) +importPackage(Packages.mindustry.core) importPackage(Packages.arc.scene) -importPackage(Packages.mindustry.maps.planet) +importPackage(Packages.mindustry) importPackage(Packages.arc) -importPackage(Packages.mindustry.world.blocks.logic) +importPackage(Packages.mindustry.world.blocks.payloads) +importPackage(Packages.mindustry.world.producers) +importPackage(Packages.arc.graphics.g2d) +importPackage(Packages.mindustry.maps.planet) const PlayerIpUnbanEvent = Packages.mindustry.game.EventType.PlayerIpUnbanEvent const PlayerIpBanEvent = Packages.mindustry.game.EventType.PlayerIpBanEvent const PlayerUnbanEvent = Packages.mindustry.game.EventType.PlayerUnbanEvent @@ -95,8 +97,7 @@ const PlayerBanEvent = Packages.mindustry.game.EventType.PlayerBanEvent const PlayerLeave = Packages.mindustry.game.EventType.PlayerLeave const PlayerConnect = Packages.mindustry.game.EventType.PlayerConnect const PlayerJoin = Packages.mindustry.game.EventType.PlayerJoin -const MechChangeEvent = Packages.mindustry.game.EventType.MechChangeEvent -const ResizeEvent = Packages.mindustry.game.EventType.ResizeEvent +const UnitChangeEvent = Packages.mindustry.game.EventType.UnitChangeEvent const UnitCreateEvent = Packages.mindustry.game.EventType.UnitCreateEvent const UnitDestroyEvent = Packages.mindustry.game.EventType.UnitDestroyEvent const BlockDestroyEvent = Packages.mindustry.game.EventType.BlockDestroyEvent @@ -107,12 +108,19 @@ const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent -const WorldLoadEvent = Packages.mindustry.game.EventType.WorldLoadEvent const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent const TapConfigEvent = Packages.mindustry.game.EventType.TapConfigEvent const TapEvent = Packages.mindustry.game.EventType.TapEvent const DepositEvent = Packages.mindustry.game.EventType.DepositEvent const WithdrawEvent = Packages.mindustry.game.EventType.WithdrawEvent +const SectorCaptureEvent = Packages.mindustry.game.EventType.SectorCaptureEvent +const ZoneConfigureCompleteEvent = Packages.mindustry.game.EventType.ZoneConfigureCompleteEvent +const ZoneRequireCompleteEvent = Packages.mindustry.game.EventType.ZoneRequireCompleteEvent +const PlayerChatEvent = Packages.mindustry.game.EventType.PlayerChatEvent +const CommandIssueEvent = Packages.mindustry.game.EventType.CommandIssueEvent +const LaunchItemEvent = Packages.mindustry.game.EventType.LaunchItemEvent +const WorldLoadEvent = Packages.mindustry.game.EventType.WorldLoadEvent +const ClientLoadEvent = Packages.mindustry.game.EventType.ClientLoadEvent const BlockInfoEvent = Packages.mindustry.game.EventType.BlockInfoEvent const CoreItemDeliverEvent = Packages.mindustry.game.EventType.CoreItemDeliverEvent const TurretAmmoDeliverEvent = Packages.mindustry.game.EventType.TurretAmmoDeliverEvent @@ -123,17 +131,13 @@ const PlayEvent = Packages.mindustry.game.EventType.PlayEvent const DisposeEvent = Packages.mindustry.game.EventType.DisposeEvent const ContentReloadEvent = Packages.mindustry.game.EventType.ContentReloadEvent const ServerLoadEvent = Packages.mindustry.game.EventType.ServerLoadEvent -const ClientLoadEvent = Packages.mindustry.game.EventType.ClientLoadEvent const ClientCreateEvent = Packages.mindustry.game.EventType.ClientCreateEvent const SaveLoadEvent = Packages.mindustry.game.EventType.SaveLoadEvent -const ZoneConfigureCompleteEvent = Packages.mindustry.game.EventType.ZoneConfigureCompleteEvent -const ZoneRequireCompleteEvent = Packages.mindustry.game.EventType.ZoneRequireCompleteEvent -const PlayerChatEvent = Packages.mindustry.game.EventType.PlayerChatEvent -const CommandIssueEvent = Packages.mindustry.game.EventType.CommandIssueEvent const MapPublishEvent = Packages.mindustry.game.EventType.MapPublishEvent const MapMakeEvent = Packages.mindustry.game.EventType.MapMakeEvent -const LaunchItemEvent = Packages.mindustry.game.EventType.LaunchItemEvent +const ResizeEvent = Packages.mindustry.game.EventType.ResizeEvent const LaunchEvent = Packages.mindustry.game.EventType.LaunchEvent const LoseEvent = Packages.mindustry.game.EventType.LoseEvent const WinEvent = Packages.mindustry.game.EventType.WinEvent +const TurnEvent = Packages.mindustry.game.EventType.TurnEvent const Trigger = Packages.mindustry.game.EventType.Trigger diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index 820e3b6c77..7142c4f48d 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -14,6 +14,7 @@ import mindustry.graphics.*; import mindustry.type.*; import mindustry.world.*; import mindustry.world.blocks.*; +import mindustry.world.blocks.campaign.LaunchPad; import mindustry.world.blocks.defense.*; import mindustry.world.blocks.defense.turrets.*; import mindustry.world.blocks.distribution.*; @@ -1315,7 +1316,7 @@ public class Blocks implements ContentList{ speed = 7f; }}; - launchPad = new LaunchPad("launch-pad"){{ + launchPad = new mindustry.world.blocks.campaign.LaunchPad("launch-pad"){{ requirements(Category.effect, BuildVisibility.campaignOnly, ItemStack.with(Items.copper, 350, Items.silicon, 140, Items.lead, 200, Items.titanium, 150)); size = 3; itemCapacity = 100; diff --git a/core/src/mindustry/core/GameState.java b/core/src/mindustry/core/GameState.java index db2e4686e2..51ab59a460 100644 --- a/core/src/mindustry/core/GameState.java +++ b/core/src/mindustry/core/GameState.java @@ -23,6 +23,8 @@ public class GameState{ public Rules rules = new Rules(); /** Statistics for this save/game. Displayed after game over. */ public Stats stats = new Stats(); + /** Sector information. Only valid in the campaign. */ + public SectorInfo secinfo = new SectorInfo(); /** Team data. Gets reset every new game. */ public Teams teams = new Teams(); /** Number of enemies in the game; only used clientside in servers. */ diff --git a/core/src/mindustry/core/Logic.java b/core/src/mindustry/core/Logic.java index 502d3f2571..0f01ee8948 100644 --- a/core/src/mindustry/core/Logic.java +++ b/core/src/mindustry/core/Logic.java @@ -90,7 +90,7 @@ public class Logic implements ApplicationListener{ } }); - Events.on(LaunchItemEvent.class, e -> state.stats.handleItemExport(e.stack)); + Events.on(LaunchItemEvent.class, e -> state.secinfo.handleItemExport(e.stack)); //when loading a 'damaged' sector, propagate the damage Events.on(WorldLoadEvent.class, e -> { @@ -100,13 +100,14 @@ public class Logic implements ApplicationListener{ } }); - //TODO this should be in the same place as launch handling code + //TODO dying takes up a turn (?) + /* Events.on(GameOverEvent.class, e -> { //simulate a turn on a normal non-launch gameover if(state.isCampaign() && !state.launched){ universe.runTurn(); } - }); + });*/ //disable new waves after the boss spawns Events.on(WaveEvent.class, e -> { @@ -269,11 +270,9 @@ public class Logic implements ApplicationListener{ //save over the data w/o the cores sector.save.save(); - //TODO mark sector as not containing any cores //run a turn, since launching takes up a turn universe.runTurn(); - //TODO needs extra damage to prevent player from landing immediately afterwards sector.setTurnsPassed(sector.getTurnsPassed() + 3); Events.fire(new LaunchEvent()); @@ -300,7 +299,7 @@ public class Logic implements ApplicationListener{ } if(!state.isPaused()){ - state.stats.update(); + state.secinfo.update(); if(state.isCampaign()){ universe.update(); diff --git a/core/src/mindustry/entities/comp/TileComp.java b/core/src/mindustry/entities/comp/TileComp.java index 4de8c7519c..cc02265511 100644 --- a/core/src/mindustry/entities/comp/TileComp.java +++ b/core/src/mindustry/entities/comp/TileComp.java @@ -188,6 +188,12 @@ abstract class TileComp implements Posc, Teamc, Healthc, Tilec, Timerc, QuadTree } } + /** Called clientside when the client taps a block to config. + * @return whether the configuration UI should be shown. */ + public boolean configTapped(){ + return true; + } + public void applyBoost(float intensity, float duration){ timeScale = Math.max(timeScale, intensity); timeScaleDuration = Math.max(timeScaleDuration, duration); diff --git a/core/src/mindustry/game/Saves.java b/core/src/mindustry/game/Saves.java index 30fb17af67..8c521c534f 100644 --- a/core/src/mindustry/game/Saves.java +++ b/core/src/mindustry/game/Saves.java @@ -242,10 +242,6 @@ public class Saves{ return isSector(); } - public ObjectFloatMap getProductionRates(){ - return meta.exportRates; - } - public String getPlayTime(){ return Strings.formatMillis(current == this ? totalPlaytime : meta.timePlayed); } diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java new file mode 100644 index 0000000000..7361acdad7 --- /dev/null +++ b/core/src/mindustry/game/SectorInfo.java @@ -0,0 +1,124 @@ +package mindustry.game; + +import arc.math.*; +import arc.struct.*; +import arc.util.*; +import mindustry.content.*; +import mindustry.type.*; +import mindustry.world.*; +import mindustry.world.blocks.storage.CoreBlock.*; +import mindustry.world.modules.*; + +import static mindustry.Vars.*; + +public class SectorInfo{ + /** export window size in seconds */ + private static final int exportWindow = 60; + /** refresh period of export in ticks */ + private static final float refreshPeriod = 60; + /** Export statistics. */ + public ObjectMap export = new ObjectMap<>(); + /** Items stored in all cores. */ + public ObjectIntMap coreItems = new ObjectIntMap<>(); + /** The best available core type. */ + public Block bestCoreType = Blocks.air; + /** Max storage capacity. */ + public int storageCapacity = 0; + /** Whether a core is available here. */ + public boolean hasCore = true; + + /** Counter refresh state. */ + private transient Interval time = new Interval(); + /** Core item storage to prevent spoofing. */ + private transient int[] lastCoreItems; + + /** Updates export statistics. */ + public void handleItemExport(ItemStack stack){ + handleItemExport(stack.item, stack.amount); + } + + /** Updates export statistics. */ + public void handleItemExport(Item item, int amount){ + export.get(item, ExportStat::new).counter += amount; + } + + /** Subtracts from export statistics. */ + public void handleItemImport(Item item, int amount){ + export.get(item, ExportStat::new).counter -= amount; + } + + public float getExport(Item item){ + return export.get(item, ExportStat::new).mean; + } + + /** Prepare data for writing to a save. */ + public void prepare(){ + //update core items + coreItems.clear(); + + CoreEntity entity = state.rules.defaultTeam.core(); + + if(entity != null){ + ItemModule items = entity.items; + for(int i = 0; i < items.length(); i++){ + coreItems.put(content.item(i), items.get(i)); + } + } + + hasCore = entity != null; + bestCoreType = !hasCore ? Blocks.air : state.rules.defaultTeam.cores().max(e -> e.block.size).block; + storageCapacity = entity != null ? entity.storageCapacity : 0; + } + + /** Update averages of various stats. */ + public void update(){ + //create last stored core items + if(lastCoreItems == null){ + lastCoreItems = new int[content.items().size]; + updateCoreDeltas(); + } + + //refresh throughput + if(time.get(refreshPeriod)){ + CoreEntity ent = state.rules.defaultTeam.core(); + + export.each((item, stat) -> { + //initialize stat after loading + if(!stat.loaded){ + stat.means.fill(stat.mean); + stat.loaded = true; + } + + //how the resources changed - only interested in negative deltas, since that's what happens during spoofing + int coreDelta = Math.min(ent == null ? 0 : ent.items.get(item) - lastCoreItems[item.id], 0); + + //add counter, subtract how many items were taken from the core during this time + stat.means.add(Math.max(stat.counter + coreDelta, 0)); + stat.counter = 0; + stat.mean = stat.means.rawMean(); + }); + + updateCoreDeltas(); + } + } + + private void updateCoreDeltas(){ + CoreEntity ent = state.rules.defaultTeam.core(); + for(int i = 0; i < lastCoreItems.length; i++){ + lastCoreItems[i] = ent == null ? 0 : ent.items.get(i); + } + } + + public ObjectFloatMap exportRates(){ + ObjectFloatMap map = new ObjectFloatMap<>(); + export.each((item, value) -> map.put(item, value.mean)); + return map; + } + + public static class ExportStat{ + public transient float counter; + public transient WindowedMean means = new WindowedMean(exportWindow); + public transient boolean loaded; + public float mean; + } +} diff --git a/core/src/mindustry/game/Stats.java b/core/src/mindustry/game/Stats.java index bc2147c7e8..01744a7537 100644 --- a/core/src/mindustry/game/Stats.java +++ b/core/src/mindustry/game/Stats.java @@ -2,21 +2,11 @@ package mindustry.game; import arc.math.*; import arc.struct.*; -import arc.util.*; import mindustry.type.*; -import mindustry.world.blocks.storage.CoreBlock.*; -import mindustry.world.modules.*; - -import static mindustry.Vars.*; //TODO more stats: //- units constructed public class Stats{ - /** export window size in seconds */ - private static final int exportWindow = 60; - /** refresh period of export in ticks */ - private static final float refreshPeriod = 60; - /** Total items delivered to global resoure counter. Campaign only. */ public ObjectIntMap itemsDelivered = new ObjectIntMap<>(); /** Enemy (red team) units destroyed. */ @@ -31,89 +21,6 @@ public class Stats{ public int buildingsDeconstructed; /** Friendly buildings destroyed. */ public int buildingsDestroyed; - /** Export statistics. */ - public ObjectMap export = new ObjectMap<>(); - /** Items stored in all cores. Used for the campaign. */ - public ObjectIntMap coreItems = new ObjectIntMap<>(); - - /** Counter refresh state. */ - private transient Interval time = new Interval(); - /** Core item storage to prevent spoofing. */ - private transient int[] lastCoreItems; - - /** Updates export statistics. */ - public void handleItemExport(ItemStack stack){ - handleItemExport(stack.item, stack.amount); - } - - /** Updates export statistics. */ - public void handleItemExport(Item item, int amount){ - export.get(item, ExportStat::new).counter += amount; - } - - /** Subtracts from export statistics. */ - public void handleItemImport(Item item, int amount){ - export.get(item, ExportStat::new).counter -= amount; - } - - public float getExport(Item item){ - return export.get(item, ExportStat::new).mean; - } - - public void update(){ - //update core items - CoreEntity entity = state.rules.defaultTeam.core(); - if(entity != null){ - ItemModule items = entity.items; - for(int i = 0; i < items.length(); i++){ - coreItems.put(content.item(i), items.get(i)); - } - }else{ - coreItems.clear(); - } - - //create last stored core items - if(lastCoreItems == null){ - lastCoreItems = new int[content.items().size]; - updateCoreDeltas(); - } - - //refresh throughput - if(time.get(refreshPeriod)){ - CoreEntity ent = state.rules.defaultTeam.core(); - - export.each((item, stat) -> { - //initialize stat after loading - if(!stat.loaded){ - stat.means.fill(stat.mean); - stat.loaded = true; - } - - //how the resources changed - only interested in negative deltas, since that's what happens during spoofing - int coreDelta = Math.min(ent == null ? 0 : ent.items.get(item) - lastCoreItems[item.id], 0); - - //add counter, subtract how many items were taken from the core during this time - stat.means.add(Math.max(stat.counter + coreDelta, 0)); - stat.counter = 0; - stat.mean = stat.means.rawMean(); - }); - - updateCoreDeltas(); - } - } - - private void updateCoreDeltas(){ - CoreEntity ent = state.rules.defaultTeam.core(); - for(int i = 0; i < lastCoreItems.length; i++){ - lastCoreItems[i] = ent == null ? 0 : ent.items.get(i); - } - } - - public ObjectFloatMap exportRates(){ - ObjectFloatMap map = new ObjectFloatMap<>(); - export.each((item, value) -> map.put(item, value.mean)); - return map; - } public RankResult calculateRank(Sector zone, boolean launched){ float score = 0; @@ -161,15 +68,7 @@ public class Stats{ } } - public enum Rank{ F, D, C, B, A, S, SS } - - public static class ExportStat{ - public transient float counter; - public transient WindowedMean means = new WindowedMean(exportWindow); - public transient boolean loaded; - public float mean; - } } diff --git a/core/src/mindustry/io/SaveMeta.java b/core/src/mindustry/io/SaveMeta.java index a28b1ac6ce..0a3730d8e1 100644 --- a/core/src/mindustry/io/SaveMeta.java +++ b/core/src/mindustry/io/SaveMeta.java @@ -3,7 +3,6 @@ package mindustry.io; import arc.struct.*; import mindustry.game.*; import mindustry.maps.*; -import mindustry.type.*; import static mindustry.Vars.maps; @@ -15,13 +14,12 @@ public class SaveMeta{ public Map map; public int wave; public Rules rules; + public SectorInfo secinfo; public StringMap tags; public String[] mods; - /** These are in items/second. */ - public ObjectFloatMap exportRates; public boolean hasProduction; - public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, ObjectFloatMap exportRates, StringMap tags){ + public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, SectorInfo secinfo, StringMap tags){ this.version = version; this.build = build; this.timestamp = timestamp; @@ -31,8 +29,8 @@ public class SaveMeta{ this.rules = rules; this.tags = tags; this.mods = JsonIO.read(String[].class, tags.get("mods", "[]")); - this.exportRates = exportRates; + this.secinfo = secinfo; - exportRates.each(e -> hasProduction |= e.value > 0.001f); + secinfo.exportRates().each(e -> hasProduction |= e.value > 0.001f); } } diff --git a/core/src/mindustry/io/SaveVersion.java b/core/src/mindustry/io/SaveVersion.java index 0635b12ab6..05c5425df1 100644 --- a/core/src/mindustry/io/SaveVersion.java +++ b/core/src/mindustry/io/SaveVersion.java @@ -39,7 +39,7 @@ public abstract class SaveVersion extends SaveFileReader{ map.get("mapname"), map.getInt("wave"), JsonIO.read(Rules.class, map.get("rules", "{}")), - JsonIO.read(Stats.class, map.get("stats", "{}")).exportRates(), + JsonIO.read(SectorInfo.class, map.get("secinfo", "{}")), map ); } @@ -70,6 +70,11 @@ public abstract class SaveVersion extends SaveFileReader{ } public void writeMeta(DataOutput stream, StringMap tags) throws IOException{ + //prepare campaign data for writing + if(state.isCampaign()){ + state.secinfo.prepare(); + } + writeStringMap(stream, StringMap.of( "saved", Time.millis(), "playtime", headless ? 0 : control.saves.getTotalPlaytime(), @@ -78,6 +83,7 @@ public abstract class SaveVersion extends SaveFileReader{ "wave", state.wave, "wavetime", state.wavetime, "stats", JsonIO.write(state.stats), + "secinfo", state.isCampaign() ? JsonIO.write(state.secinfo) : "{}", "rules", JsonIO.write(state.rules), "mods", JsonIO.write(mods.getModStrings().toArray(String.class)), "width", world.width(), @@ -94,6 +100,7 @@ public abstract class SaveVersion extends SaveFileReader{ state.wave = map.getInt("wave"); state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing); state.stats = JsonIO.read(Stats.class, map.get("stats", "{}")); + state.secinfo = JsonIO.read(SectorInfo.class, map.get("secinfo", "{}")); state.rules = JsonIO.read(Rules.class, map.get("rules", "{}")); if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get(); lastReadBuild = map.getInt("build", -1); diff --git a/core/src/mindustry/mod/Scripts.java b/core/src/mindustry/mod/Scripts.java index 224ce9af35..c25a34fb66 100644 --- a/core/src/mindustry/mod/Scripts.java +++ b/core/src/mindustry/mod/Scripts.java @@ -17,6 +17,7 @@ import java.net.*; import java.util.regex.*; public class Scripts implements Disposable{ + private final static Object[] emptyObjects = {}; private final Array blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk", "runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system", ".awt", "socket", "classloader", "oracle", "invoke", "arc.events", "java.util.function", "java.util.stream"); diff --git a/core/src/mindustry/ui/dialogs/PlanetDialog.java b/core/src/mindustry/ui/dialogs/PlanetDialog.java index 7eda1a76d1..dec25c616a 100644 --- a/core/src/mindustry/ui/dialogs/PlanetDialog.java +++ b/core/src/mindustry/ui/dialogs/PlanetDialog.java @@ -9,6 +9,7 @@ import arc.input.*; import arc.math.*; import arc.math.geom.*; import arc.scene.event.*; +import arc.scene.ui.*; import arc.scene.ui.TextButton.*; import arc.scene.ui.layout.*; import arc.struct.*; @@ -152,6 +153,17 @@ public class PlanetDialog extends BaseDialog{ shown(this::setup); } + /** show with no limitations, just as a map. */ + @Override + public Dialog show(){ + //TODO + return super.show(); + } + + public void show(Sector selected, int range){ + //TODO + } + void makeBloom(){ if(bloom != null){ bloom.dispose(); @@ -413,7 +425,7 @@ public class PlanetDialog extends BaseDialog{ stable.table(t -> { t.left(); - selected.save.meta.exportRates.each(entry -> { + selected.save.meta.secinfo.exportRates().each(entry -> { int total = (int)(entry.value * turnDuration / 60f); if(total > 1){ t.image(entry.key.icon(Cicon.small)).padRight(3); @@ -421,7 +433,24 @@ public class PlanetDialog extends BaseDialog{ t.row(); } }); - }); + }).row(); + } + + //stored resources + if(selected.hasBase() && selected.save.meta.secinfo.coreItems.size > 0){ + stable.add("Stored Resources:").row(); + stable.table(t -> { + t.left(); + + for(Item item : content.items()){ + int amount = selected.save.meta.secinfo.coreItems.get(item); + if(amount > 0){ + t.image(item.icon(Cicon.small)).padRight(3); + t.add(ui.formatAmount(amount)).color(Color.lightGray); + t.row(); + } + } + }).row(); } //display how many turns this sector has been attacked diff --git a/core/src/mindustry/ui/fragments/BlockConfigFragment.java b/core/src/mindustry/ui/fragments/BlockConfigFragment.java index 4ffa087897..2d1270e036 100644 --- a/core/src/mindustry/ui/fragments/BlockConfigFragment.java +++ b/core/src/mindustry/ui/fragments/BlockConfigFragment.java @@ -43,29 +43,31 @@ public class BlockConfigFragment extends Fragment{ } public void showConfig(Tilec tile){ - configTile = tile; + if(tile.configTapped()){ + configTile = tile; - table.visible(true); - table.clear(); - tile.buildConfiguration(table); - table.pack(); - table.setTransform(true); - table.actions(Actions.scaleTo(0f, 1f), Actions.visible(true), - Actions.scaleTo(1f, 1f, 0.07f, Interp.pow3Out)); + table.visible(true); + table.clear(); + tile.buildConfiguration(table); + table.pack(); + table.setTransform(true); + table.actions(Actions.scaleTo(0f, 1f), Actions.visible(true), + Actions.scaleTo(1f, 1f, 0.07f, Interp.pow3Out)); - table.update(() -> { - if(configTile != null && configTile.shouldHideConfigure(player)){ - hideConfig(); - return; - } + table.update(() -> { + if(configTile != null && configTile.shouldHideConfigure(player)){ + hideConfig(); + return; + } - table.setOrigin(Align.center); - if(configTile == null || configTile.block() == Blocks.air || !configTile.isValid()){ - hideConfig(); - }else{ - configTile.updateTableAlign(table); - } - }); + table.setOrigin(Align.center); + if(configTile == null || configTile.block() == Blocks.air || !configTile.isValid()){ + hideConfig(); + }else{ + configTile.updateTableAlign(table); + } + }); + } } public boolean hasConfigMouse(){ diff --git a/core/src/mindustry/ui/fragments/HudFragment.java b/core/src/mindustry/ui/fragments/HudFragment.java index fcfbf2a8f5..44eb0d4489 100644 --- a/core/src/mindustry/ui/fragments/HudFragment.java +++ b/core/src/mindustry/ui/fragments/HudFragment.java @@ -326,9 +326,9 @@ public class HudFragment extends Fragment{ c.clearChildren(); for(Item item : content.items()){ - if(state.stats.getExport(item) >= 1){ + if(state.secinfo.getExport(item) >= 1){ c.image(item.icon(Cicon.small)); - c.label(() -> (int)state.stats.getExport(item) + " /s").color(Color.lightGray); + c.label(() -> (int)state.secinfo.getExport(item) + " /s").color(Color.lightGray); c.row(); } } @@ -337,7 +337,7 @@ public class HudFragment extends Fragment{ c.update(() -> { boolean wrong = false; for(Item item : content.items()){ - boolean has = state.stats.getExport(item) >= 1; + boolean has = state.secinfo.getExport(item) >= 1; if(used.get(item.id) != has){ used.set(item.id, has); wrong = true; diff --git a/core/src/mindustry/world/blocks/campaign/CoreLauncher.java b/core/src/mindustry/world/blocks/campaign/CoreLauncher.java new file mode 100644 index 0000000000..c3d2f2520c --- /dev/null +++ b/core/src/mindustry/world/blocks/campaign/CoreLauncher.java @@ -0,0 +1,33 @@ +package mindustry.world.blocks.campaign; + +import mindustry.*; +import mindustry.gen.*; +import mindustry.world.*; + +public class CoreLauncher extends Block{ + + public CoreLauncher(String name){ + super(name); + + hasItems = true; + configurable = true; + } + + public class CoreLauncherEntity extends TileEntity{ + + @Override + public void updateTile(){ + super.updateTile(); + } + + @Override + public boolean configTapped(){ + //TODO show w/ sector + Vars.ui.planet.show(); + + return false; + } + + + } +} diff --git a/core/src/mindustry/world/blocks/storage/LaunchPad.java b/core/src/mindustry/world/blocks/campaign/LaunchPad.java similarity index 99% rename from core/src/mindustry/world/blocks/storage/LaunchPad.java rename to core/src/mindustry/world/blocks/campaign/LaunchPad.java index 592e9b2b47..7dbded1b5c 100644 --- a/core/src/mindustry/world/blocks/storage/LaunchPad.java +++ b/core/src/mindustry/world/blocks/campaign/LaunchPad.java @@ -1,4 +1,4 @@ -package mindustry.world.blocks.storage; +package mindustry.world.blocks.campaign; import arc.*; import arc.graphics.*; diff --git a/core/src/mindustry/world/blocks/production/ResearchBlock.java b/core/src/mindustry/world/blocks/campaign/ResearchBlock.java similarity index 96% rename from core/src/mindustry/world/blocks/production/ResearchBlock.java rename to core/src/mindustry/world/blocks/campaign/ResearchBlock.java index ec3de2fef1..9e10526f72 100644 --- a/core/src/mindustry/world/blocks/production/ResearchBlock.java +++ b/core/src/mindustry/world/blocks/campaign/ResearchBlock.java @@ -1,4 +1,4 @@ -package mindustry.world.blocks.production; +package mindustry.world.blocks.campaign; import arc.scene.ui.layout.*; import arc.util.ArcAnnotate.*;