mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-14 09:47:24 +07:00
Progress on sector state
This commit is contained in:
@ -222,6 +222,8 @@ public class EntityProcess extends BaseProcessor{
|
||||
Array<Svar> syncedFields = new Array<>();
|
||||
Array<Svar> 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);
|
||||
|
@ -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
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -242,10 +242,6 @@ public class Saves{
|
||||
return isSector();
|
||||
}
|
||||
|
||||
public ObjectFloatMap<Item> getProductionRates(){
|
||||
return meta.exportRates;
|
||||
}
|
||||
|
||||
public String getPlayTime(){
|
||||
return Strings.formatMillis(current == this ? totalPlaytime : meta.timePlayed);
|
||||
}
|
||||
|
124
core/src/mindustry/game/SectorInfo.java
Normal file
124
core/src/mindustry/game/SectorInfo.java
Normal file
@ -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<Item, ExportStat> export = new ObjectMap<>();
|
||||
/** Items stored in all cores. */
|
||||
public ObjectIntMap<Item> 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<Item> exportRates(){
|
||||
ObjectFloatMap<Item> 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;
|
||||
}
|
||||
}
|
@ -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<Item> 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<Item, ExportStat> export = new ObjectMap<>();
|
||||
/** Items stored in all cores. Used for the campaign. */
|
||||
public ObjectIntMap<Item> 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<Item> exportRates(){
|
||||
ObjectFloatMap<Item> 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Item> exportRates;
|
||||
public boolean hasProduction;
|
||||
|
||||
public SaveMeta(int version, long timestamp, long timePlayed, int build, String map, int wave, Rules rules, ObjectFloatMap<Item> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -17,6 +17,7 @@ import java.net.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
public class Scripts implements Disposable{
|
||||
private final static Object[] emptyObjects = {};
|
||||
private final Array<String> 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");
|
||||
|
@ -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
|
||||
|
@ -43,6 +43,7 @@ public class BlockConfigFragment extends Fragment{
|
||||
}
|
||||
|
||||
public void showConfig(Tilec tile){
|
||||
if(tile.configTapped()){
|
||||
configTile = tile;
|
||||
|
||||
table.visible(true);
|
||||
@ -67,6 +68,7 @@ public class BlockConfigFragment extends Fragment{
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasConfigMouse(){
|
||||
Element e = Core.scene.hit(Core.input.mouseX(), Core.graphics.getHeight() - Core.input.mouseY(), true);
|
||||
|
@ -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;
|
||||
|
33
core/src/mindustry/world/blocks/campaign/CoreLauncher.java
Normal file
33
core/src/mindustry/world/blocks/campaign/CoreLauncher.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks.storage;
|
||||
package mindustry.world.blocks.campaign;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
@ -1,4 +1,4 @@
|
||||
package mindustry.world.blocks.production;
|
||||
package mindustry.world.blocks.campaign;
|
||||
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.ArcAnnotate.*;
|
Reference in New Issue
Block a user