diff --git a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java index c088aa6d6e..0143af6c7f 100644 --- a/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java +++ b/annotations/src/main/java/mindustry/annotations/entity/EntityProcess.java @@ -416,15 +416,17 @@ public void process(RoundEnvironment env) throws Exception{ //add all methods from components for(ObjectMap.Entry> entry : methods){ - if(entry.value.contains(m -> m.has(Replace.class))){ - //check replacements - if(entry.value.count(m -> m.has(Replace.class)) > 1){ - err("Type " + type + " has multiple components replacing method " + entry.key + "."); + Smethod replacement = null; + for(Smethod method : entry.value){ + if(method.has(Replace.class)){ + if(replacement == null) replacement = method; + else{ //multiple replacements for one method + err("Type " + type + " has multiple components replacing method " + entry.key + "."); + break; + } } - Smethod base = entry.value.find(m -> m.has(Replace.class)); - entry.value.clear(); - entry.value.add(base); } + if(replacement != null) entry.value.clear().add(replacement); //check multi return if(entry.value.count(m -> !m.isAny(Modifier.NATIVE, Modifier.ABSTRACT) && !m.isVoid()) > 1){ diff --git a/core/src/mindustry/ai/BaseRegistry.java b/core/src/mindustry/ai/BaseRegistry.java index d37f7b8826..79f71974bb 100644 --- a/core/src/mindustry/ai/BaseRegistry.java +++ b/core/src/mindustry/ai/BaseRegistry.java @@ -33,6 +33,7 @@ public Seq forResource(Content item){ } public void load(){ + Time.mark(); cores.clear(); parts.clear(); reqParts.clear(); @@ -111,6 +112,7 @@ public void load(){ cores.sort(b -> b.tier); parts.sort(); reqParts.each((key, arr) -> arr.sort()); + Log.debug("Bases in @ms", Time.elapsed()); } public static class BasePart implements Comparable{ diff --git a/core/src/mindustry/client/navigation/AStarNavigator.kt b/core/src/mindustry/client/navigation/AStarNavigator.kt index a9ad7e1d0a..38b4029fd8 100644 --- a/core/src/mindustry/client/navigation/AStarNavigator.kt +++ b/core/src/mindustry/client/navigation/AStarNavigator.kt @@ -13,7 +13,7 @@ import kotlin.math.* // and modified object AStarNavigator : Navigator() { - private val pool = Pools.get(PositionWaypoint::class.java) { PositionWaypoint() } + private val pool = Pools.get(PositionWaypoint::class.java, ::PositionWaypoint) private var grid: Array = emptyArray() private var gridSize = Point2() private var open = BinaryHeap(65_536, false) diff --git a/core/src/mindustry/client/navigation/AStarNavigatorOptimised.kt b/core/src/mindustry/client/navigation/AStarNavigatorOptimised.kt index 36c1b85519..b2c3281306 100644 --- a/core/src/mindustry/client/navigation/AStarNavigatorOptimised.kt +++ b/core/src/mindustry/client/navigation/AStarNavigatorOptimised.kt @@ -18,7 +18,7 @@ import kotlin.math.* // https://arxiv.org/ftp/arxiv/papers/1506/1506.01864.pdf the stuff looks familiar object AStarNavigatorOptimised : Navigator() { - private val pool = Pools.get(PositionWaypoint::class.java) { PositionWaypoint() } + private val pool = Pools.get(PositionWaypoint::class.java, ::PositionWaypoint) private var grid: Array = emptyArray() private var gridSize = Point2() private var open = BinaryHeap(65_536, false) diff --git a/core/src/mindustry/client/navigation/Navigator.kt b/core/src/mindustry/client/navigation/Navigator.kt index 1cd2a5fa5a..08141381c5 100644 --- a/core/src/mindustry/client/navigation/Navigator.kt +++ b/core/src/mindustry/client/navigation/Navigator.kt @@ -39,13 +39,14 @@ abstract class Navigator { start.clamp(0f, 0f, world.unitWidth().toFloat(), world.unitHeight().toFloat()) end.clamp(0f, 0f, world.unitWidth().toFloat(), world.unitHeight().toFloat()) val additionalRadius = player.unit().hitSize / 2 + tilesize + val pool = Pools.get(Circle::class.java, ::Circle) // Turrets and units FINISHME: Turrets should probably not use this system if (player.unit().type.targetable(player.unit(), player.team()) && player.unit().type.hittable(player.unit())) { for (turret in obstacles) { if (turret.isObstacle()) { realObstacles.add( - Pools.obtain(Circle::class.java) { Circle() }.set( + pool.obtain().set( turret.x(), turret.y(), turret.range() + additionalRadius @@ -59,7 +60,7 @@ abstract class Navigator { if (state.hasSpawns()) { spawner.spawns.each { spawn -> // Use .each() as this is on the client thread and the iterator isn't thread safe. Each works fine as this Seq should never be edited at runtime. This might actually be a bad assumption to make? Idk realObstacles.add( - Pools.obtain(Circle::class.java) { Circle() }.set( + pool.obtain().set( spawn.worldx(), spawn.worldy(), state.rules.dropZoneRadius + additionalRadius @@ -69,13 +70,13 @@ abstract class Navigator { } // Shield projectors - for (team in state.teams.active) { - if (team === player.team()) continue - arrayOf(team.getBuildings(Blocks.shieldProjector), team.getBuildings(Blocks.largeShieldProjector)).forEach { shields -> - val radius = ((shields.firstOpt()?.block ?: return@forEach) as BaseShield).radius + additionalRadius - for (shield in shields) { + state.teams.active.each { team -> + if (team === player.team()) return@each + for (block in BaseShield.baseShields) { + val radius = block.radius + additionalRadius + team.getBuildings(block).each { shield -> realObstacles.add( - Pools.obtain(Circle::class.java) { Circle() }.set( + pool.obtain().set( shield.x, shield.y, radius @@ -112,7 +113,7 @@ abstract class Navigator { !canBoost && solidity?.solid(x, y) ?: false && // Units that cannot hover will check for solid blocks world.tiles.getn(x, y).run { build === null || build.team !== player.team() || !block().teamPassable } // Ignore teamPassable blocks such as erekir blastDoors } - Pools.freeAll(realObstacles) + Pools.freeAll(realObstacles, true) realObstacles.clear() return ret } diff --git a/core/src/mindustry/client/navigation/Path.kt b/core/src/mindustry/client/navigation/Path.kt index 4e10e2386e..ed61e158ea 100644 --- a/core/src/mindustry/client/navigation/Path.kt +++ b/core/src/mindustry/client/navigation/Path.kt @@ -50,7 +50,7 @@ abstract class Path { // } // } val path = Navigation.navigator.navigate(v1, v2.set(destX, destY), Navigation.getEnts()) - Pools.freeAll(filter) + Pools.freeAll(filter, true) filter.clear() if (!Vars.player.unit().isNull) v1.set(Vars.player.unit()) if (path.isNotEmpty() && (targetPos.within(destX, destY, 1F) || (Navigation.currentlyFollowing != null && Navigation.currentlyFollowing !is WaypointPath<*>))) { // Same destination diff --git a/core/src/mindustry/entities/units/BuildPlan.java b/core/src/mindustry/entities/units/BuildPlan.java index f9eac61339..b8f5c67f9d 100644 --- a/core/src/mindustry/entities/units/BuildPlan.java +++ b/core/src/mindustry/entities/units/BuildPlan.java @@ -233,16 +233,8 @@ public void hitbox(Rect out){ } } - public Rect bounds(Rect rect) { - return bounds(rect, false); - } - - public Rect bounds(Rect rect, boolean allowBreak){ - if(breaking && !allowBreak){ - return rect.set(-100f, -100f, 0f, 0f); - }else{ - return block.bounds(x, y, rect); - } + public Rect bounds(Rect rect){ + return block.bounds(x, y, rect); } @Override diff --git a/core/src/mindustry/input/InputHandler.java b/core/src/mindustry/input/InputHandler.java index 76ff11e4d0..a615dabfc8 100644 --- a/core/src/mindustry/input/InputHandler.java +++ b/core/src/mindustry/input/InputHandler.java @@ -1241,15 +1241,13 @@ protected void drawFreezeSelection(int x1, int y1, int x2, int y2, int maxLength Draw.color(Pal.freeze); Lines.stroke(1f); - for(BuildPlan plan: player.unit().plans()){ - if(plan.breaking) continue; - if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ + for(BuildPlan plan : player.unit().plans()){ + if(!plan.breaking && plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ drawFreezing(plan); } } - for(BuildPlan plan: selectPlans){ - if(plan.breaking) continue; - if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ + for(BuildPlan plan : selectPlans){ + if(!plan.breaking && plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ drawFreezing(plan); } } @@ -1276,15 +1274,13 @@ protected void drawBreakSelection(int x1, int y1, int x2, int y2, int maxLength) Lines.stroke(1f); for(var plan : player.unit().plans()){ - if(plan.breaking) continue; - if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ + if(!plan.breaking && plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ drawBreaking(plan); } } for(var plan : selectPlans){ - if(plan.breaking) continue; - if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ + if(!plan.breaking && plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ drawBreaking(plan); } } @@ -1385,10 +1381,11 @@ public void flushPlans(Seq plans, boolean freeze, boolean force, bool if (plan.block == null) continue; if (removeFrozen) { + plan.bounds(Tmp.r1); Iterator it = frozenPlans.iterator(); while(it.hasNext()){ BuildPlan frz = it.next(); - if(plan.bounds(Tmp.r1, true).overlaps(frz.bounds(Tmp.r2, true))){ + if(Tmp.r1.overlaps(frz.bounds(Tmp.r2))){ it.remove(); } } @@ -1594,7 +1591,7 @@ protected void removeSelectionPlans(int x1, int y1, int x2, int y2, int maxLengt Iterator it = player.unit().plans().iterator(); while(it.hasNext()){ BuildPlan plan = it.next(); - if(plan.bounds(Tmp.r2, true).overlaps(Tmp.r1)){ + if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ it.remove(); } } @@ -1602,7 +1599,7 @@ protected void removeSelectionPlans(int x1, int y1, int x2, int y2, int maxLengt it = selectPlans.iterator(); while(it.hasNext()){ BuildPlan plan = it.next(); - if(plan.bounds(Tmp.r2, true).overlaps(Tmp.r1)){ + if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){ it.remove(); } } @@ -1611,7 +1608,7 @@ protected void removeSelectionPlans(int x1, int y1, int x2, int y2, int maxLengt it = frozenPlans.iterator(); while (it.hasNext()) { BuildPlan plan = it.next(); - if (plan.bounds(Tmp.r2, true).overlaps(Tmp.r1)) it.remove(); + if (plan.bounds(Tmp.r2).overlaps(Tmp.r1)) it.remove(); } } } @@ -1637,25 +1634,23 @@ protected void freezeSelection(int x1, int y1, int x2, int y2, boolean flush, in Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize); for(BuildPlan plan : player.unit().plans()){ - if(plan.bounds(Tmp.r2, true).overlaps(Tmp.r1)) tmpFrozenPlans.add(plan); + if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)) tmpFrozenPlans.add(plan); } for(BuildPlan plan : selectPlans){ - if(plan.bounds(Tmp.r2, true).overlaps(Tmp.r1)) tmpFrozenPlans.add(plan); + if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)) tmpFrozenPlans.add(plan); } Seq unfreeze = new Seq<>(); for(BuildPlan plan : frozenPlans){ - if(plan.bounds(Tmp.r2, true).overlaps(Tmp.r1)) unfreeze.add(plan); + if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)) unfreeze.add(plan); } - Iterator it1, it2; - if(unfreeze.size > tmpFrozenPlans.size) flushPlans(unfreeze, false, false, true); - else{ - it1 = player.unit().plans().iterator(); - it2 = selectPlans.iterator(); - for (BuildPlan frz : tmpFrozenPlans) { - if(checkFreezeSelectionHasNext(frz, it1)) continue; + if(unfreeze.size > tmpFrozenPlans.size) flushPlans(unfreeze, false, false, true); // Unfreeze the selection when there's more frozen blocks in the area + else{ // If there's fewer frozen blocks than unfrozen ones, we freeze the selection + Iterator it1 = player.unit().plans().iterator(), it2 = selectPlans.iterator(); + for(BuildPlan frz : tmpFrozenPlans){ + if(checkFreezeSelectionHasNext(frz, it1)) continue; // Player plans contains frz: remove it and continue. if(/*!itHasNext implied*/ it2 != null){ it1 = it2; it2 = null; // swap it2 into it1, continue iterating through without changing frz diff --git a/core/src/mindustry/world/blocks/defense/BaseShield.java b/core/src/mindustry/world/blocks/defense/BaseShield.java index 32bc077e8f..c8dcc71c4a 100644 --- a/core/src/mindustry/world/blocks/defense/BaseShield.java +++ b/core/src/mindustry/world/blocks/defense/BaseShield.java @@ -4,6 +4,7 @@ import arc.graphics.*; import arc.graphics.g2d.*; import arc.math.*; +import arc.struct.*; import arc.util.*; import arc.util.io.*; import mindustry.content.*; @@ -20,6 +21,8 @@ public class BaseShield extends Block{ public float radius = 200f; public int sides = 24; + public static Seq baseShields = new Seq<>(2); + protected static BaseShieldBuild paramBuild; //protected static Effect paramEffect; protected static final Cons bulletConsumer = bullet -> { @@ -60,6 +63,9 @@ public BaseShield(String name){ hasPower = true; update = solid = true; rebuildable = false; + + baseShields.add(this); + if(baseShields.size > 2) baseShields.shrink(); // Modded shields will grow the seq, we may as well just keep it as small as we can } @Override