Massive optimizations to build plan rendering (~100x)
This commit is contained in:
@@ -3911,9 +3911,10 @@ public class Blocks{
|
||||
);
|
||||
size = 3;
|
||||
reload = 3f;
|
||||
shoot = new ShootAlternate(4f);
|
||||
shoot.shots = 2;
|
||||
velocityRnd = 0.1f;
|
||||
inaccuracy = 4f;
|
||||
inaccuracy = 3f;
|
||||
recoil = 1f;
|
||||
shootCone = 45f;
|
||||
liquidCapacity = 40f;
|
||||
|
||||
@@ -700,6 +700,7 @@ public class Control implements ApplicationListener, Loadable{
|
||||
|
||||
if(state.isGame()){
|
||||
input.update();
|
||||
input.updateSelectQuadtree();
|
||||
if(!state.isPaused()){
|
||||
indicators.update();
|
||||
}
|
||||
|
||||
@@ -285,7 +285,6 @@ public class Logic implements ApplicationListener{
|
||||
Events.fire(new ResetEvent());
|
||||
world.tiles = new Tiles(0, 0);
|
||||
|
||||
//save settings on reset
|
||||
Core.settings.manualSave();
|
||||
}
|
||||
|
||||
|
||||
@@ -220,23 +220,6 @@ abstract class BuilderComp implements Posc, Statusc, Teamc, Rotc{
|
||||
}
|
||||
}
|
||||
|
||||
/** Draw all current build plans. Does not draw the beam effect, only the positions. */
|
||||
void drawBuildPlans(){
|
||||
|
||||
for(int i = 0; i < 2; i++){
|
||||
for(BuildPlan plan : plans){
|
||||
if(plan.progress > 0.01f || (buildPlan() == plan && plan.initialized && (within(plan.x * tilesize, plan.y * tilesize, type.buildRange) || state.isEditor()))) continue;
|
||||
if(i == 0){
|
||||
drawPlan(plan, 1f);
|
||||
}else{
|
||||
drawPlanTop(plan, 1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
void drawPlan(BuildPlan plan, float alpha){
|
||||
plan.animScale = 1f;
|
||||
if(plan.breaking){
|
||||
|
||||
@@ -23,6 +23,7 @@ import mindustry.game.EventType.*;
|
||||
import mindustry.game.Schematic.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.input.InputHandler.*;
|
||||
import mindustry.input.Placement.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.io.TypeIO.*;
|
||||
@@ -251,14 +252,16 @@ public class Schematics implements Loadable{
|
||||
//scale each plan to fit schematic
|
||||
Draw.trans().scale(resolution / tilesize, resolution / tilesize).translate(tilesize*1.5f, tilesize*1.5f);
|
||||
|
||||
QueryEachable eachPlans = new QueryEachable(null, plans);
|
||||
|
||||
//draw plans
|
||||
plans.each(req -> {
|
||||
req.animScale = 1f;
|
||||
req.worldContext = false;
|
||||
req.block.drawPlanRegion(req, plans);
|
||||
req.block.drawPlanRegion(req, eachPlans);
|
||||
});
|
||||
|
||||
plans.each(req -> req.block.drawPlanConfigTop(req, plans));
|
||||
plans.each(req -> req.block.drawPlanConfigTop(req, eachPlans));
|
||||
|
||||
Draw.flush();
|
||||
Draw.trans().idt();
|
||||
|
||||
@@ -78,7 +78,7 @@ public class OverlayRenderer{
|
||||
if(player.dead()) return;
|
||||
|
||||
if(player.isBuilder()){
|
||||
player.unit().drawBuildPlans();
|
||||
input.drawBuildPlans();
|
||||
}
|
||||
|
||||
input.drawBottom();
|
||||
|
||||
@@ -159,7 +159,7 @@ public class DesktopInput extends InputHandler{
|
||||
drawArrow(splan.block, splan.x, splan.y, splan.rotation, valid);
|
||||
}
|
||||
|
||||
splan.block.drawPlan(splan, allPlans(), valid);
|
||||
splan.block.drawPlan(splan, allPlans, valid);
|
||||
|
||||
drawSelected(splan.x, splan.y, splan.block, getPlan(splan.x, splan.y, splan.block.size, splan) != null ? Pal.remove : Pal.accent);
|
||||
}
|
||||
@@ -214,7 +214,7 @@ public class DesktopInput extends InputHandler{
|
||||
Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime, 6f, 0.28f));
|
||||
bplan.set(cursorX, cursorY, rot, block);
|
||||
bplan.config = block.lastConfig;
|
||||
block.drawPlanConfig(bplan, allPlans());
|
||||
block.drawPlanConfig(bplan, allPlans);
|
||||
bplan.config = null;
|
||||
Draw.reset();
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
private Seq<BuildPlan> plansOut = new Seq<>(BuildPlan.class);
|
||||
private QuadTree<BuildPlan> playerPlanTree = new QuadTree<>(new Rect());
|
||||
private QuadTree<BuildPlan> selectPlanTree = new QuadTree<>(new Rect());
|
||||
|
||||
public final BlockInventoryFragment inv;
|
||||
public final BlockConfigFragment config;
|
||||
@@ -125,18 +126,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
private WidgetGroup group = new WidgetGroup();
|
||||
|
||||
private final Eachable<BuildPlan> allPlans = cons -> {
|
||||
if(!player.dead()){
|
||||
player.unit().plans().each(cons);
|
||||
}
|
||||
selectPlans.each(cons);
|
||||
linePlans.each(cons);
|
||||
};
|
||||
|
||||
private final Eachable<BuildPlan> allSelectLines = cons -> {
|
||||
selectPlans.each(cons);
|
||||
linePlans.each(cons);
|
||||
};
|
||||
protected Eachable<BuildPlan> allPlans, allSelectLines, allRenderPlansConfig;
|
||||
|
||||
public InputHandler(){
|
||||
group.touchable = Touchable.childrenOnly;
|
||||
@@ -144,6 +134,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
config = new BlockConfigFragment();
|
||||
planConfig = new PlanConfigFragment();
|
||||
|
||||
createPlanLists();
|
||||
|
||||
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)){
|
||||
player.shooting = false;
|
||||
@@ -152,6 +144,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
Events.on(WorldLoadEvent.class, e -> {
|
||||
playerPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight()));
|
||||
selectPlanTree = new QuadTree<>(new Rect(0f, 0f, world.unitWidth(), world.unitHeight()));
|
||||
createPlanLists();
|
||||
});
|
||||
|
||||
Events.on(ResetEvent.class, e -> {
|
||||
@@ -853,6 +847,27 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
player.deathTimer = Player.deathDelay + 1f; //for instant respawn
|
||||
}
|
||||
|
||||
protected void createPlanLists(){
|
||||
allPlans = new QueryEachable(playerPlanTree, linePlans){
|
||||
@Override
|
||||
public BuildPlan find(int x, int y, int size, Boolf<BuildPlan> check){
|
||||
BuildPlan plan = super.find(x, y, size, check);
|
||||
if(plan != null) return plan;
|
||||
|
||||
return selectPlanTree.find(x * tilesize - tilesize/2f * size, y * tilesize - tilesize/2f * size, size * tilesize, size * tilesize, check);
|
||||
}
|
||||
};
|
||||
allSelectLines = new QueryEachable(null, selectPlans, linePlans);
|
||||
allRenderPlansConfig = new QueryEachable(playerPlanTree, selectPlans);
|
||||
}
|
||||
|
||||
public void updateSelectQuadtree(){
|
||||
selectPlanTree.clear();
|
||||
for(var plan : selectPlans){
|
||||
selectPlanTree.insert(plan);
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds an input lock; if this function returns true, input is locked. Used for mod 'cutscenes' or custom camera panning. */
|
||||
public void addLock(Boolp lock){
|
||||
inputLocks.add(lock);
|
||||
@@ -1329,6 +1344,43 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
}
|
||||
|
||||
public void drawBuildPlans(){
|
||||
if(!player.isBuilder()) return;
|
||||
|
||||
Unit u = player.unit();
|
||||
BuildPlan current = u.buildPlan();
|
||||
|
||||
camera.bounds(Tmp.r1);
|
||||
plansOut.clear();
|
||||
playerPlanTree.intersect(Tmp.r1, plansOut);
|
||||
|
||||
for(BuildPlan plan : plansOut){
|
||||
if(plan.progress > 0.01f || (current == plan && plan.initialized && (u.within(plan.x * tilesize, plan.y * tilesize, u.type.buildRange) || state.isEditor()))) continue;
|
||||
|
||||
plan.animScale = 1f;
|
||||
if(plan.breaking){
|
||||
drawBreaking(plan);
|
||||
}else{
|
||||
plan.block.drawPlan(plan, allPlans, Build.validPlace(plan.block, player.team(), plan.x, plan.y, plan.rotation) || planMatches(plan), 1f);
|
||||
}
|
||||
}
|
||||
|
||||
camera.bounds(Tmp.r3);
|
||||
|
||||
Draw.reset();
|
||||
|
||||
//TODO: cannot query for links that are offscreen
|
||||
for(BuildPlan plan : u.plans){
|
||||
if(plan.progress > 0.01f || plan.breaking || (current == plan && plan.initialized && (u.within(plan.x * tilesize, plan.y * tilesize, u.type.buildRange) || state.isEditor()))) continue;
|
||||
|
||||
if(Tmp.r2.setCentered(plan.drawx(), plan.drawy(), plan.block.planConfigClipSize()).overlaps(Tmp.r3)){
|
||||
Draw.mixcol(Color.white, 0.24f + Mathf.absin(Time.globalTime, 6f, 0.28f));
|
||||
plan.block.drawPlanConfigTop(plan, allRenderPlansConfig);
|
||||
Draw.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void drawBottom(){
|
||||
|
||||
}
|
||||
@@ -1669,6 +1721,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
BuildPlan copy = plan.copy();
|
||||
plan.block.onNewPlan(copy);
|
||||
player.unit().addBuild(copy, false);
|
||||
playerPlanTree.insert(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1679,6 +1732,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
BuildPlan copy = plan.copy();
|
||||
plan.block.onNewPlan(copy);
|
||||
player.unit().addBuild(copy);
|
||||
playerPlanTree.insert(copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1700,7 +1754,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
|
||||
protected void drawPlan(BuildPlan plan, boolean valid){
|
||||
plan.block.drawPlan(plan, allPlans(), valid);
|
||||
plan.block.drawPlan(plan, allPlans, valid);
|
||||
}
|
||||
|
||||
/** Draws a placement icon for a specific block. */
|
||||
@@ -1710,7 +1764,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
bplan.config = block.lastConfig;
|
||||
}
|
||||
bplan.animScale = 1f;
|
||||
block.drawPlan(bplan, allPlans(), validPlace(x, y, block, rotation));
|
||||
block.drawPlan(bplan, allPlans, validPlace(x, y, block, rotation));
|
||||
}
|
||||
|
||||
/** Remove everything from the queue in a selection. */
|
||||
@@ -2353,4 +2407,43 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
public int x, y, rotation;
|
||||
public boolean last;
|
||||
}
|
||||
|
||||
/**
|
||||
* In the interest of preserving compatibility, this implementation replaces Eachable with its own methods, and requires blocks to cast it to use it properly.
|
||||
* It's a massive hack.
|
||||
* */
|
||||
public static class QueryEachable implements Eachable<BuildPlan>{
|
||||
final QuadTree<BuildPlan> tree;
|
||||
final Seq[] fallback;
|
||||
|
||||
public QueryEachable(QuadTree<BuildPlan> tree, Seq<BuildPlan>... fallback){
|
||||
this.tree = tree;
|
||||
this.fallback = fallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void each(Cons<? super BuildPlan> cons){
|
||||
//you're not supposed to use this method anymore
|
||||
}
|
||||
|
||||
public BuildPlan find(int x, int y, Boolf<BuildPlan> check){
|
||||
return find(x, y, 1, check);
|
||||
}
|
||||
|
||||
public BuildPlan find(int x, int y, int size, Boolf<BuildPlan> check){
|
||||
if(tree != null){
|
||||
BuildPlan plan = tree.find(x * tilesize - tilesize/2f * size, y * tilesize - tilesize/2f * size, size * tilesize, size * tilesize, check);
|
||||
if(plan != null){
|
||||
return plan;
|
||||
}
|
||||
}
|
||||
for(var fallback : fallback){
|
||||
var result = fallback.find(check);
|
||||
if(result != null){
|
||||
return (BuildPlan)result;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(plan.breaking){
|
||||
drawSelected(plan.x, plan.y, tile.block(), Pal.remove);
|
||||
}else{
|
||||
plan.block.drawPlan(plan, allPlans(), true);
|
||||
plan.block.drawPlan(plan, allPlans, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(i == linePlans.size - 1 && plan.block.rotate && plan.block.drawArrow){
|
||||
drawArrow(block, plan.x, plan.y, plan.rotation);
|
||||
}
|
||||
plan.block.drawPlan(plan, allPlans(), validPlace(plan.x, plan.y, plan.block, plan.rotation) && getPlan(plan.x, plan.y, plan.block.size, null) == null);
|
||||
plan.block.drawPlan(plan, allPlans, validPlace(plan.x, plan.y, plan.block, plan.rotation) && getPlan(plan.x, plan.y, plan.block.size, null) == null);
|
||||
drawSelected(plan.x, plan.y, plan.block, Pal.accent);
|
||||
}
|
||||
linePlans.each(this::drawOverPlan);
|
||||
@@ -464,7 +464,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(plan.breaking){
|
||||
drawSelected(plan.x, plan.y, plan.tile().block(), Pal.remove);
|
||||
}else{
|
||||
plan.block.drawPlan(plan, allPlans(), validPlace(plan.x, plan.y, plan.block, plan.rotation));
|
||||
plan.block.drawPlan(plan, allPlans, validPlace(plan.x, plan.y, plan.block, plan.rotation));
|
||||
drawSelected(plan.x, plan.y, plan.block, Pal.accent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.graphics.MultiPacker.*;
|
||||
import mindustry.input.InputHandler.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.mod.*;
|
||||
import mindustry.type.*;
|
||||
@@ -829,6 +830,17 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
drawPlanConfig(plan, list);
|
||||
}
|
||||
|
||||
public static BuildPlan findPlan(Eachable<BuildPlan> list, int x, int y, Boolf<BuildPlan> predicate){
|
||||
return findPlan(list, x, y, 1, predicate);
|
||||
}
|
||||
|
||||
public static BuildPlan findPlan(Eachable<BuildPlan> list, int x, int y, int size, Boolf<BuildPlan> predicate){
|
||||
if(list instanceof QueryEachable q){
|
||||
return q.find(x, y, size, predicate);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public TextureRegion getPlanRegion(BuildPlan plan, Eachable<BuildPlan> list){
|
||||
return fullIcon;
|
||||
}
|
||||
@@ -860,6 +872,10 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
|
||||
}
|
||||
|
||||
public float planConfigClipSize(){
|
||||
return clipSize;
|
||||
}
|
||||
|
||||
/** Transforms the internal position of this config using the specified function, and return the result. */
|
||||
public Object pointConfig(Object config, Cons<Point2> transformer){
|
||||
return config;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
@@ -18,6 +19,23 @@ public interface Autotiler{
|
||||
class AutotilerHolder{
|
||||
static final int[] blendresult = new int[5];
|
||||
static final BuildPlan[] directionals = new BuildPlan[4];
|
||||
|
||||
static BuildPlan plan;
|
||||
static final Boolf<BuildPlan> blendFinder = other -> {
|
||||
if(other.breaking || other == plan) return false;
|
||||
|
||||
int i = 0;
|
||||
for(Point2 point : Geometry.d4){
|
||||
int x = plan.x + point.x, y = plan.y + point.y;
|
||||
if(x >= other.x -(other.block.size - 1) / 2 && x <= other.x + (other.block.size / 2) && y >= other.y -(other.block.size - 1) / 2 && y <= other.y + (other.block.size / 2)){
|
||||
directionals[i] = other;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
//this technically doesn't "find" anything, since it needs to scan up to 4 conveyors in every direction.
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,26 +74,15 @@ public interface Autotiler{
|
||||
return region;
|
||||
}
|
||||
|
||||
default @Nullable int[] getTiling(BuildPlan req, Eachable<BuildPlan> list){
|
||||
if(req.tile() == null) return null;
|
||||
default @Nullable int[] getTiling(BuildPlan plan, Eachable<BuildPlan> list){
|
||||
if(plan.tile() == null) return null;
|
||||
BuildPlan[] directionals = AutotilerHolder.directionals;
|
||||
|
||||
Arrays.fill(directionals, null);
|
||||
//TODO this is O(n^2), very slow, should use quadtree or intmap or something instead
|
||||
list.each(other -> {
|
||||
if(other.breaking || other == req) return;
|
||||
AutotilerHolder.plan = plan;
|
||||
Block.findPlan(list, plan.x, plan.y, plan.block.size + 2, AutotilerHolder.blendFinder);
|
||||
|
||||
int i = 0;
|
||||
for(Point2 point : Geometry.d4){
|
||||
int x = req.x + point.x, y = req.y + point.y;
|
||||
if(x >= other.x -(other.block.size - 1) / 2 && x <= other.x + (other.block.size / 2) && y >= other.y -(other.block.size - 1) / 2 && y <= other.y + (other.block.size / 2)){
|
||||
directionals[i] = other;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
});
|
||||
|
||||
return buildBlending(req.tile(), req.rotation, directionals, req.worldContext);
|
||||
return buildBlending(plan.tile(), plan.rotation, directionals, plan.worldContext);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
@@ -19,7 +20,6 @@ import mindustry.world.meta.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class DirectionBridge extends Block{
|
||||
private static BuildPlan otherReq;
|
||||
private int otherDst = 0;
|
||||
|
||||
public @Load("@-bridge") TextureRegion bridgeRegion;
|
||||
@@ -56,23 +56,27 @@ public class DirectionBridge extends Block{
|
||||
Draw.rect(dirRegion, plan.drawx(), plan.drawy(), plan.rotation * 90);
|
||||
}
|
||||
|
||||
private BuildPlan currentPlan, otherPlan;
|
||||
private Boolf<BuildPlan> planFinder = other -> {
|
||||
if(other.block == this && currentPlan != other && Mathf.clamp(other.x - currentPlan.x, -1, 1) == Geometry.d4x(currentPlan.rotation) && Mathf.clamp(other.y - currentPlan.y, -1, 1) == Geometry.d4y(currentPlan.rotation)){
|
||||
int dst = Math.max(Math.abs(other.x - currentPlan.x), Math.abs(other.y - currentPlan.y));
|
||||
if(dst <= otherDst){
|
||||
otherPlan = other;
|
||||
otherDst = dst;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
@Override
|
||||
public void drawPlanConfigTop(BuildPlan plan, Eachable<BuildPlan> list){
|
||||
otherReq = null;
|
||||
otherDst = range;
|
||||
Point2 d = Geometry.d4(plan.rotation);
|
||||
list.each(other -> {
|
||||
if(other.block == this && plan != other && Mathf.clamp(other.x - plan.x, -1, 1) == d.x && Mathf.clamp(other.y - plan.y, -1, 1) == d.y){
|
||||
int dst = Math.max(Math.abs(other.x - plan.x), Math.abs(other.y - plan.y));
|
||||
if(dst <= otherDst){
|
||||
otherReq = other;
|
||||
otherDst = dst;
|
||||
}
|
||||
}
|
||||
});
|
||||
otherPlan = null;
|
||||
currentPlan = plan;
|
||||
findPlan(list, plan.x, plan.y, range * 2 + 1, planFinder);
|
||||
|
||||
if(otherReq != null){
|
||||
drawBridge(plan.rotation, plan.drawx(), plan.drawy(), otherReq.drawx(), otherReq.drawy(), null);
|
||||
if(otherPlan != null){
|
||||
drawBridge(plan.rotation, plan.drawx(), plan.drawy(), otherPlan.drawx(), otherPlan.drawy(), null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
@@ -21,8 +22,6 @@ import mindustry.world.meta.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class ItemBridge extends Block{
|
||||
private static BuildPlan otherReq;
|
||||
|
||||
public final int timerCheckMoved = timers ++;
|
||||
|
||||
public int range;
|
||||
@@ -75,17 +74,21 @@ public class ItemBridge extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
static int currentFindX, currentFindY;
|
||||
static BuildPlan currentPlan;
|
||||
static final Boolf<BuildPlan> planFinder = other -> other.block == currentPlan.block && currentPlan != other && currentFindX == other.x && currentFindY == other.y;
|
||||
|
||||
@Override
|
||||
public void drawPlanConfigTop(BuildPlan plan, Eachable<BuildPlan> list){
|
||||
otherReq = null;
|
||||
list.each(other -> {
|
||||
if(other.block == this && plan != other && plan.config instanceof Point2 p && p.equals(other.x - plan.x, other.y - plan.y)){
|
||||
otherReq = other;
|
||||
}
|
||||
});
|
||||
if(plan.config instanceof Point2 p){
|
||||
currentFindX = plan.x + p.x;
|
||||
currentFindY = plan.y + p.y;
|
||||
currentPlan = plan;
|
||||
var otherReq = findPlan(list, currentFindX, currentFindY, planFinder);
|
||||
|
||||
if(otherReq != null){
|
||||
drawBridge(plan, otherReq.drawx(), otherReq.drawy(), 0);
|
||||
if(otherReq != null){
|
||||
drawBridge(plan, otherReq.drawx(), otherReq.drawy(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -85,8 +85,7 @@ public class CanvasBlock extends Block{
|
||||
|
||||
tempBlend = 0;
|
||||
|
||||
//O(N^2), awful
|
||||
list.each(other -> {
|
||||
findPlan(list, plan.x, plan.y, size + 1, other -> {
|
||||
if(other.block == this){
|
||||
for(int i = 0; i < 4; i++){
|
||||
if(other.x == plan.x + Geometry.d4x(i) * size && other.y == plan.y + Geometry.d4y(i) * size){
|
||||
@@ -94,6 +93,7 @@ public class CanvasBlock extends Block{
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
int blending = tempBlend;
|
||||
|
||||
@@ -23,7 +23,6 @@ import mindustry.world.modules.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class PowerNode extends PowerBlock{
|
||||
protected static BuildPlan otherReq;
|
||||
protected static int returnInt = 0;
|
||||
protected final static ObjectSet<PowerGraph> graphs = new ObjectSet<>();
|
||||
/** The maximum range of all power nodes on the map */
|
||||
@@ -316,25 +315,22 @@ public class PowerNode extends PowerBlock{
|
||||
});
|
||||
}
|
||||
|
||||
static int currentFindX, currentFindY;
|
||||
static BuildPlan currentPlan;
|
||||
static final Boolf<BuildPlan> planFinder = other -> other.block != null
|
||||
&& (currentFindX >= other.x - ((other.block.size - 1) / 2) && currentFindY >= other.y - ((other.block.size - 1) / 2) && currentFindX <= other.x + other.block.size / 2 && currentFindY <= other.y + other.block.size / 2)
|
||||
&& other != currentPlan && other.block.hasPower;
|
||||
|
||||
@Override
|
||||
public void drawPlanConfigTop(BuildPlan plan, Eachable<BuildPlan> list){
|
||||
if(plan.config instanceof Point2[] ps){
|
||||
setupColor(1f);
|
||||
for(Point2 point : ps){
|
||||
int px = plan.x + point.x, py = plan.y + point.y;
|
||||
otherReq = null;
|
||||
list.each(other -> {
|
||||
if(other.block != null
|
||||
&& (px >= other.x - ((other.block.size-1)/2) && py >= other.y - ((other.block.size-1)/2) && px <= other.x + other.block.size/2 && py <= other.y + other.block.size/2)
|
||||
&& other != plan && other.block.hasPower){
|
||||
otherReq = other;
|
||||
}
|
||||
});
|
||||
currentFindX = plan.x + point.x;
|
||||
currentFindY = plan.y + point.y;
|
||||
currentPlan = plan;
|
||||
|
||||
//uncomment for debugging connection translation issues in schematics
|
||||
//Draw.color(Color.red);
|
||||
//Lines.line(plan.drawx(), plan.drawy(), px * tilesize, py * tilesize);
|
||||
//Draw.color();
|
||||
var otherReq = findPlan(list, currentFindX, currentFindY, planFinder);
|
||||
|
||||
if(otherReq == null || otherReq.block == null) continue;
|
||||
|
||||
@@ -344,6 +340,11 @@ public class PowerNode extends PowerBlock{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float planConfigClipSize(){
|
||||
return laserRange * tilesize * 2f + size * tilesize;
|
||||
}
|
||||
|
||||
public boolean linkValid(Building tile, Building link){
|
||||
return linkValid(tile, link, true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user