diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 7499fcd9c2..7bdc5d174a 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -14,6 +14,7 @@ import arc.scene.ui.layout.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; +import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.audio.*; import mindustry.content.*; @@ -29,8 +30,8 @@ import mindustry.logic.*; import mindustry.type.*; import mindustry.ui.*; import mindustry.world.*; -import mindustry.world.blocks.*; import mindustry.world.blocks.ConstructBlock.*; +import mindustry.world.blocks.*; import mindustry.world.blocks.environment.*; import mindustry.world.blocks.payloads.*; import mindustry.world.blocks.power.*; @@ -621,6 +622,7 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, * containers, it gets added to the block's inventory. */ public void offload(Item item){ + produced(item, 1); int dump = this.cdump; if(!net.client() && state.isCampaign() && team == state.rules.defaultTeam) item.unlock(); @@ -654,6 +656,14 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, return false; } + public void produced(Item item){ + produced(item, 1); + } + + public void produced(Item item, int amount){ + if(Vars.state.rules.sector != null && team == state.rules.defaultTeam) Vars.state.rules.sector.info.handleProduction(item, amount); + } + /** Try dumping any item near the */ public boolean dump(){ return dump(null); diff --git a/core/src/mindustry/entities/comp/MinerComp.java b/core/src/mindustry/entities/comp/MinerComp.java index 81aa812f61..b993815a36 100644 --- a/core/src/mindustry/entities/comp/MinerComp.java +++ b/core/src/mindustry/entities/comp/MinerComp.java @@ -76,6 +76,8 @@ abstract class MinerComp implements Itemsc, Posc, Teamc, Rotc, Drawc{ if(mineTimer >= 50f + item.hardness*15f){ mineTimer = 0; + if(state.rules.sector != null && team() == state.rules.defaultTeam) state.rules.sector.info.handleProduction(item, 1); + if(core != null && within(core, mineTransferRange) && core.acceptStack(item, 1, this) == 1 && offloadImmediately()){ //add item to inventory before it is transferred if(item() == item) addItem(item); diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index 2701fc1dcb..ed9c79b612 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -23,6 +23,8 @@ public class SectorInfo{ /** Core input statistics. */ public ObjectMap production = new ObjectMap<>(); + /** Raw item production statistics. */ + public ObjectMap rawProduction = new ObjectMap<>(); /** Export statistics. */ public ObjectMap export = new ObjectMap<>(); /** Items stored in all cores. */ @@ -77,15 +79,21 @@ public class SectorInfo{ /** Counter refresh state. */ private transient Interval time = new Interval(); - /** Core item storage to prevent spoofing. */ - private transient int[] coreItemCounts; + /** Core item storage input/output deltas. */ + private @Nullable transient int[] coreDeltas; + /** Core item storage input/output deltas. */ + private @Nullable transient int[] productionDeltas; /** Handles core item changes. */ public void handleCoreItem(Item item, int amount){ - if(coreItemCounts == null){ - coreItemCounts = new int[content.items().size]; - } - coreItemCounts[item.id] += amount; + if(coreDeltas == null) coreDeltas = new int[content.items().size]; + coreDeltas[item.id] += amount; + } + + /** Handles raw production stats. */ + public void handleProduction(Item item, int amount){ + if(productionDeltas == null) productionDeltas = new int[content.items().size]; + productionDeltas[item.id] += amount; } /** @return the real location items go when launched on this sector */ @@ -176,6 +184,11 @@ public class SectorInfo{ damage = 0; hasSpawns = spawner.countSpawns() > 0; + //cap production at raw production. + production.each((item, stat) -> { + stat.mean = Math.min(stat.mean, rawProduction.get(item, ExportStat::new).mean); + }); + if(state.rules.sector != null){ state.rules.sector.saveInfo(); } @@ -189,8 +202,6 @@ public class SectorInfo{ //updating in multiplayer as a client doesn't make sense if(net.client()) return; - CoreBuild ent = state.rules.defaultTeam.core(); - //refresh throughput if(time.get(refreshPeriod)){ @@ -208,30 +219,37 @@ public class SectorInfo{ stat.mean = stat.means.rawMean(); }); - if(coreItemCounts == null){ - coreItemCounts = new int[content.items().size]; - } + if(coreDeltas == null) coreDeltas = new int[content.items().size]; + if(productionDeltas == null) productionDeltas = new int[content.items().size]; //refresh core items for(Item item : content.items()){ - ExportStat stat = production.get(item, ExportStat::new); - if(!stat.loaded){ - stat.means.fill(stat.mean); - stat.loaded = true; - } + updateDelta(item, production, coreDeltas); + updateDelta(item, rawProduction, productionDeltas); - //get item delta - int delta = coreItemCounts[item.id]; - - //store means - stat.means.add(delta); - stat.mean = stat.means.rawMean(); + production.get(item).mean = Math.min(production.get(item).mean, rawProduction.get(item).mean); } - Arrays.fill(coreItemCounts, 0); + Arrays.fill(coreDeltas, 0); + Arrays.fill(productionDeltas, 0); } } + void updateDelta(Item item, ObjectMap map, int[] deltas){ + ExportStat stat = map.get(item, ExportStat::new); + if(!stat.loaded){ + stat.means.fill(stat.mean); + stat.loaded = true; + } + + //get item delta + int delta = deltas[item.id]; + + //store means + stat.means.add(delta); + stat.mean = stat.means.rawMean(); + } + public ObjectFloatMap exportRates(){ ObjectFloatMap map = new ObjectFloatMap<>(); export.each((item, value) -> map.put(item, value.mean));