mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-07-08 23:07:33 +07:00
Various request rendering optimizations
This commit is contained in:
@ -24,6 +24,20 @@ public class Units{
|
|||||||
private static int intResult;
|
private static int intResult;
|
||||||
private static Building buildResult;
|
private static Building buildResult;
|
||||||
|
|
||||||
|
//prevents allocations in anyEntities
|
||||||
|
private static boolean anyEntityGround;
|
||||||
|
private static float aeX, aeY, aeW, aeH;
|
||||||
|
private static final Cons<Unit> anyEntityLambda = unit -> {
|
||||||
|
if(boolResult) return;
|
||||||
|
if((unit.isGrounded() && !unit.hovering) == anyEntityGround){
|
||||||
|
unit.hitboxTile(hitrect);
|
||||||
|
|
||||||
|
if(hitrect.overlaps(aeX, aeY, aeW, aeH)){
|
||||||
|
boolResult = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@Remote(called = Loc.server)
|
@Remote(called = Loc.server)
|
||||||
public static void unitCapDeath(Unit unit){
|
public static void unitCapDeath(Unit unit){
|
||||||
if(unit != null){
|
if(unit != null){
|
||||||
@ -145,18 +159,13 @@ public class Units{
|
|||||||
|
|
||||||
public static boolean anyEntities(float x, float y, float width, float height, boolean ground){
|
public static boolean anyEntities(float x, float y, float width, float height, boolean ground){
|
||||||
boolResult = false;
|
boolResult = false;
|
||||||
|
anyEntityGround = ground;
|
||||||
|
aeX = x;
|
||||||
|
aeY = y;
|
||||||
|
aeW = width;
|
||||||
|
aeH = height;
|
||||||
|
|
||||||
nearby(x, y, width, height, unit -> {
|
nearby(x, y, width, height, anyEntityLambda);
|
||||||
if(boolResult) return;
|
|
||||||
if((unit.isGrounded() && !unit.hovering) == ground){
|
|
||||||
unit.hitboxTile(hitrect);
|
|
||||||
|
|
||||||
if(hitrect.overlaps(x, y, width, height)){
|
|
||||||
boolResult = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return boolResult;
|
return boolResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package mindustry.entities.units;
|
|||||||
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
|
import arc.math.geom.QuadTree.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
@ -10,7 +11,7 @@ import mindustry.world.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
/** Class for storing build requests. Can be either a place or remove request. */
|
/** Class for storing build requests. Can be either a place or remove request. */
|
||||||
public class BuildPlan implements Position{
|
public class BuildPlan implements Position, QuadTreeObject{
|
||||||
/** Position and rotation of this request. */
|
/** Position and rotation of this request. */
|
||||||
public int x, y, rotation;
|
public int x, y, rotation;
|
||||||
/** Block being placed. If null, this is a breaking request.*/
|
/** Block being placed. If null, this is a breaking request.*/
|
||||||
@ -157,6 +158,15 @@ public class BuildPlan implements Position{
|
|||||||
return world.build(x, y);
|
return world.build(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hitbox(Rect out){
|
||||||
|
if(block != null){
|
||||||
|
out.setCentered(x * tilesize + block.offset, y * tilesize + block.offset, block.size * tilesize);
|
||||||
|
}else{
|
||||||
|
out.setCentered(x * tilesize, y * tilesize, tilesize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getX(){
|
public float getX(){
|
||||||
return drawx();
|
return drawx();
|
||||||
|
@ -70,12 +70,30 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
public Seq<BuildPlan> lineRequests = new Seq<>();
|
public Seq<BuildPlan> lineRequests = new Seq<>();
|
||||||
public Seq<BuildPlan> selectRequests = new Seq<>();
|
public Seq<BuildPlan> selectRequests = new Seq<>();
|
||||||
|
|
||||||
|
private Seq<BuildPlan> plansOut = new Seq<>(BuildPlan.class);
|
||||||
|
private QuadTree<BuildPlan> playerPlanTree = new QuadTree<>(new Rect());
|
||||||
|
|
||||||
|
private final Eachable<BuildPlan> allRequests = cons -> {
|
||||||
|
player.unit().plans().each(cons);
|
||||||
|
selectRequests.each(cons);
|
||||||
|
lineRequests.each(cons);
|
||||||
|
};
|
||||||
|
|
||||||
|
private final Eachable<BuildPlan> allSelectLines = cons -> {
|
||||||
|
selectRequests.each(cons);
|
||||||
|
lineRequests.each(cons);
|
||||||
|
};
|
||||||
|
|
||||||
public InputHandler(){
|
public InputHandler(){
|
||||||
Events.on(UnitDestroyEvent.class, e -> {
|
Events.on(UnitDestroyEvent.class, e -> {
|
||||||
if(e.unit != null && e.unit.isPlayer() && e.unit.getPlayer().isLocal() && e.unit.type.weapons.contains(w -> w.bullet.killShooter)){
|
if(e.unit != null && e.unit.isPlayer() && e.unit.getPlayer().isLocal() && e.unit.type.weapons.contains(w -> w.bullet.killShooter)){
|
||||||
player.shooting = false;
|
player.shooting = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Events.on(WorldLoadEvent.class, e -> {
|
||||||
|
playerPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//methods to override
|
//methods to override
|
||||||
@ -439,7 +457,6 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
player.unit().clearCommand();
|
player.unit().clearCommand();
|
||||||
}else if(player.unit().type.commandLimit > 0){
|
}else if(player.unit().type.commandLimit > 0){
|
||||||
|
|
||||||
//TODO try out some other formations
|
|
||||||
player.unit().commandNearby(new CircleFormation());
|
player.unit().commandNearby(new CircleFormation());
|
||||||
Fx.commandSend.at(player, player.unit().type.commandRadius);
|
Fx.commandSend.at(player, player.unit().type.commandRadius);
|
||||||
}
|
}
|
||||||
@ -456,11 +473,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Eachable<BuildPlan> allRequests(){
|
public Eachable<BuildPlan> allRequests(){
|
||||||
return cons -> {
|
return allRequests;
|
||||||
for(BuildPlan request : player.unit().plans()) cons.get(request);
|
|
||||||
for(BuildPlan request : selectRequests) cons.get(request);
|
|
||||||
for(BuildPlan request : lineRequests) cons.get(request);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUsingSchematic(){
|
public boolean isUsingSchematic(){
|
||||||
@ -468,6 +481,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
|
playerPlanTree.clear();
|
||||||
|
player.unit().plans.each(playerPlanTree::insert);
|
||||||
|
|
||||||
player.typing = ui.chatfrag.shown();
|
player.typing = ui.chatfrag.shown();
|
||||||
|
|
||||||
if(player.dead()){
|
if(player.dead()){
|
||||||
@ -836,10 +852,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
Draw.reset();
|
Draw.reset();
|
||||||
Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime, 6f, 0.28f));
|
Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime, 6f, 0.28f));
|
||||||
Draw.alpha(1f);
|
Draw.alpha(1f);
|
||||||
request.block.drawRequestConfigTop(request, cons -> {
|
request.block.drawRequestConfigTop(request, allSelectLines);
|
||||||
selectRequests.each(cons);
|
|
||||||
lineRequests.each(cons);
|
|
||||||
});
|
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1209,15 +1222,22 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean validPlace(int x, int y, Block type, int rotation, BuildPlan ignore){
|
public boolean validPlace(int x, int y, Block type, int rotation, BuildPlan ignore){
|
||||||
//TODO with many requests, this is O(n * m), very laggy
|
if(player.unit().plans.size > 0){
|
||||||
for(BuildPlan req : player.unit().plans()){
|
Tmp.r1.setCentered(x * tilesize + type.offset, y * tilesize + type.offset, type.size * tilesize);
|
||||||
if(req != ignore
|
plansOut.clear();
|
||||||
&& !req.breaking
|
playerPlanTree.intersect(Tmp.r1, plansOut);
|
||||||
&& req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))
|
|
||||||
&& !(type.canReplace(req.block) && Tmp.r1.equals(Tmp.r2))){
|
for(int i = 0; i < plansOut.size; i++){
|
||||||
return false;
|
var req = plansOut.items[i];
|
||||||
|
if(req != ignore
|
||||||
|
&& !req.breaking
|
||||||
|
&& req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))
|
||||||
|
&& !(type.canReplace(req.block) && Tmp.r1.equals(Tmp.r2))){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Build.validPlace(type, player.team(), x, y, rotation);
|
return Build.validPlace(type, player.team(), x, y, rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user