diff --git a/core/src/mindustry/entities/comp/BuildingComp.java b/core/src/mindustry/entities/comp/BuildingComp.java index 4a8e23e6cf..3a6c0ea8f0 100644 --- a/core/src/mindustry/entities/comp/BuildingComp.java +++ b/core/src/mindustry/entities/comp/BuildingComp.java @@ -348,6 +348,11 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc, //endregion //region handler methods + /** Called when an unloader takes an item. */ + public void itemTaken(Item item){ + + } + /** Called when this block is dropped as a payload. */ public void dropped(){ diff --git a/core/src/mindustry/game/SectorInfo.java b/core/src/mindustry/game/SectorInfo.java index dc56902c60..b66dc5bf95 100644 --- a/core/src/mindustry/game/SectorInfo.java +++ b/core/src/mindustry/game/SectorInfo.java @@ -10,6 +10,8 @@ import mindustry.world.*; import mindustry.world.blocks.storage.CoreBlock.*; import mindustry.world.modules.*; +import java.util.*; + import static mindustry.Vars.*; public class SectorInfo{ @@ -42,7 +44,15 @@ public class SectorInfo{ /** Counter refresh state. */ private transient Interval time = new Interval(); /** Core item storage to prevent spoofing. */ - private transient int[] lastCoreItems; + private transient int[] coreItemCounts; + + /** Handles core item changes. */ + public void handleCoreItem(Item item, int amount){ + if(coreItemCounts == null){ + coreItemCounts = new int[content.items().size]; + } + coreItemCounts[item.id] += amount; + } /** @return the real location items go when launched on this sector */ public Sector getRealDestination(){ @@ -105,12 +115,6 @@ public class SectorInfo{ universe.runTurn(); } - //create last stored core items - if(lastCoreItems == null){ - lastCoreItems = new int[content.items().size]; - updateCoreDeltas(); - } - CoreBuild ent = state.rules.defaultTeam.core(); //refresh throughput @@ -124,15 +128,16 @@ public class SectorInfo{ 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.means.add(Math.max(stat.counter, 0)); stat.counter = 0; stat.mean = stat.means.rawMean(); }); + if(coreItemCounts == null){ + coreItemCounts = new int[content.items().size]; + } + //refresh core items for(Item item : content.items()){ ExportStat stat = production.get(item, ExportStat::new); @@ -143,21 +148,14 @@ public class SectorInfo{ //get item delta //TODO is preventing negative production a good idea? - int delta = Math.max((ent == null ? 0 : ent.items.get(item)) - lastCoreItems[item.id], 0); + int delta = Math.max(ent == null ? 0 : coreItemCounts[item.id], 0); //store means stat.means.add(delta); stat.mean = stat.means.rawMean(); } - updateCoreDeltas(); - } - } - - private void updateCoreDeltas(){ - CoreBuild ent = state.rules.defaultTeam.core(); - for(int i = 0; i < lastCoreItems.length; i++){ - lastCoreItems[i] = ent == null ? 0 : ent.items.get(i); + Arrays.fill(coreItemCounts, 0); } } diff --git a/core/src/mindustry/game/Universe.java b/core/src/mindustry/game/Universe.java index b2c9c7d039..e64b4cfc07 100644 --- a/core/src/mindustry/game/Universe.java +++ b/core/src/mindustry/game/Universe.java @@ -158,10 +158,10 @@ public class Universe{ if(sector.save != null && sector.save.meta != null && sector.save.meta.secinfo != null && sector.save.meta.secinfo.destination != null){ Sector to = sector.save.meta.secinfo.destination; if(to.save != null){ - ItemSeq items = to.getExtraItems(); + ItemSeq items = new ItemSeq(); //calculated exported items to this sector sector.save.meta.secinfo.export.each((item, stat) -> items.add(item, (int)(stat.mean * newSecondsPassed))); - to.setExtraItems(items); + to.addItems(items); } } diff --git a/core/src/mindustry/type/Sector.java b/core/src/mindustry/type/Sector.java index 6d042296d1..21152cc954 100644 --- a/core/src/mindustry/type/Sector.java +++ b/core/src/mindustry/type/Sector.java @@ -143,9 +143,15 @@ public class Sector{ } public void removeItem(Item item, int amount){ + ItemSeq seq = new ItemSeq(); + seq.add(item, -amount); + addItems(seq); + } + + public void addItems(ItemSeq items){ if(isBeingPlayed()){ if(state.rules.defaultTeam.core() != null){ - state.rules.defaultTeam.items().remove(item, amount); + state.rules.defaultTeam.items().add(items); } }else{ ItemSeq recv = getExtraItems(); @@ -170,7 +176,7 @@ public class Sector{ }); } - recv.remove(item, amount); + recv.add(items); setExtraItems(recv); } diff --git a/core/src/mindustry/world/blocks/storage/CoreBlock.java b/core/src/mindustry/world/blocks/storage/CoreBlock.java index 295a127f2b..14d60280ee 100644 --- a/core/src/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/mindustry/world/blocks/storage/CoreBlock.java @@ -157,6 +157,7 @@ public class CoreBlock extends StorageBlock{ public int storageCapacity; //note that this unit is never actually used for control; the possession handler makes the player respawn when this unit is controlled public BlockUnitc unit = Nulls.blockUnit; + public boolean noEffect = false; @Override public void created(){ @@ -195,7 +196,7 @@ public class CoreBlock extends StorageBlock{ @Override public boolean acceptItem(Building source, Item item){ - return items.get(item) < getMaximumAccepted(item); + return items.get(item) < getMaximumAccepted(item) || incinerate(); } @Override @@ -264,6 +265,10 @@ public class CoreBlock extends StorageBlock{ return tile instanceof StorageBuild && (((StorageBuild)tile).linkedCore == core || ((StorageBuild)tile).linkedCore == null); } + public boolean incinerate(){ + return state.isCampaign(); + } + @Override public float handleDamage(float amount){ if(player != null && team == player.team()){ @@ -298,16 +303,35 @@ public class CoreBlock extends StorageBlock{ } } + @Override public void placed(){ super.placed(); state.teams.registerCore(this); } + @Override + public void itemTaken(Item item){ + if(state.isCampaign()){ + //update item taken amount + state.secinfo.handleCoreItem(item, -1); + } + } + @Override public void handleItem(Building source, Item item){ if(net.server() || !net.active()){ - super.handleItem(source, item); + + if(items.get(item) >= getMaximumAccepted(item)){ + //create item incineration effect at random intervals + if(!noEffect){ + incinerateEffect(this, source); + } + noEffect = false; + }else{ + super.handleItem(source, item); + } + if(state.rules.tutorial){ Events.fire(new CoreItemDeliverEvent()); } diff --git a/core/src/mindustry/world/blocks/storage/StorageBlock.java b/core/src/mindustry/world/blocks/storage/StorageBlock.java index 320d70868a..50eb65a270 100644 --- a/core/src/mindustry/world/blocks/storage/StorageBlock.java +++ b/core/src/mindustry/world/blocks/storage/StorageBlock.java @@ -1,10 +1,13 @@ package mindustry.world.blocks.storage; +import arc.math.*; import arc.struct.*; import arc.util.*; +import mindustry.content.*; import mindustry.gen.*; import mindustry.type.*; import mindustry.world.*; +import mindustry.world.blocks.storage.CoreBlock.*; import mindustry.world.meta.*; public class StorageBlock extends Block{ @@ -22,6 +25,16 @@ public class StorageBlock extends Block{ return false; } + public static void incinerateEffect(Building self, Building source){ + if(Mathf.chance(0.1)){ + Tile edge = Edges.getFacingEdge(source, self); + Tile edge2 = Edges.getFacingEdge(self, source); + if(edge != null && edge2 != null){ + Fx.fuelburn.at((edge.worldx() + edge2.worldx())/2f, (edge.worldy() + edge2.worldy())/2f); + } + } + } + public class StorageBuild extends Building{ protected @Nullable Building linkedCore; @@ -30,6 +43,17 @@ public class StorageBlock extends Block{ return linkedCore != null ? linkedCore.acceptItem(source, item) : items.get(item) < getMaximumAccepted(item); } + @Override + public void handleItem(Building source, Item item){ + if(linkedCore != null){ + incinerateEffect(this, source); + ((CoreBuild)linkedCore).noEffect = true; + linkedCore.handleItem(source, item); + }else{ + super.handleItem(source, item); + } + } + @Override public int getMaximumAccepted(Item item){ return itemCapacity; diff --git a/core/src/mindustry/world/blocks/storage/Unloader.java b/core/src/mindustry/world/blocks/storage/Unloader.java index 86ce15956e..524d6eb939 100644 --- a/core/src/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/mindustry/world/blocks/storage/Unloader.java @@ -66,6 +66,7 @@ public class Unloader extends Block{ }else{ other.items.remove(item, 1); } + other.itemTaken(item); } } }