Bugfixes / More 'req' cleanup

This commit is contained in:
Anuken
2022-02-22 16:36:40 -05:00
parent 040c43fe54
commit 1a22eae21a
4 changed files with 150 additions and 135 deletions

View File

@@ -26,7 +26,7 @@ public class BuildPlan implements Position, QuadTreeObject{
/** Last progress.*/
public float progress;
/** Whether construction has started for this plan, and other special variables.*/
public boolean initialized, worldContext = true, stuck;
public boolean initialized, worldContext = true, stuck, cachedValid;
/** Visual scale. Used only for rendering.*/
public float animScale = 0f;
@@ -81,7 +81,7 @@ public class BuildPlan implements Position, QuadTreeObject{
public static Object pointConfig(Block block, Object config, Cons<Point2> cons){
if(config instanceof Point2 point){
config = point.cpy();
cons.get(point);
cons.get((Point2)config);
}else if(config instanceof Point2[] points){
Point2[] result = new Point2[points.length];
int i = 0;

View File

@@ -39,7 +39,7 @@ public class DesktopInput extends InputHandler{
/** Animation scale for line. */
public float selectScale;
/** Selected build plan for movement. */
public @Nullable BuildPlan sreq;
public @Nullable BuildPlan splan;
/** Whether player is currently deleting removal plans. */
public boolean deleting = false, shouldShoot = false, panning = false;
/** Mouse pan speed. */
@@ -179,41 +179,50 @@ public class DesktopInput extends InputHandler{
int cursorX = tileX(Core.input.mouseX());
int cursorY = tileY(Core.input.mouseY());
//draw request being moved
if(sreq != null){
boolean valid = validPlace(sreq.x, sreq.y, sreq.block, sreq.rotation, sreq);
if(sreq.block.rotate){
drawArrow(sreq.block, sreq.x, sreq.y, sreq.rotation, valid);
//draw plan being moved
if(splan != null){
boolean valid = validPlace(splan.x, splan.y, splan.block, splan.rotation, splan);
if(splan.block.rotate){
drawArrow(splan.block, splan.x, splan.y, splan.rotation, valid);
}
sreq.block.drawPlan(sreq, allPlans(), valid);
splan.block.drawPlan(splan, allPlans(), valid);
drawSelected(sreq.x, sreq.y, sreq.block, getPlan(sreq.x, sreq.y, sreq.block.size, sreq) != null ? Pal.remove : Pal.accent);
drawSelected(splan.x, splan.y, splan.block, getPlan(splan.x, splan.y, splan.block.size, splan) != null ? Pal.remove : Pal.accent);
}
//draw hover plans
if(mode == none && !isPlacing()){
BuildPlan req = getPlan(cursorX, cursorY);
if(req != null){
drawSelected(req.x, req.y, req.breaking ? req.tile().block() : req.block, Pal.accent);
var plan = getPlan(cursorX, cursorY);
if(plan != null){
drawSelected(plan.x, plan.y, plan.breaking ? plan.tile().block() : plan.block, Pal.accent);
}
}
//draw schematic plans
selectPlans.each(req -> {
req.animScale = 1f;
drawPlan(req);
});
var items = selectPlans.items;
int size = selectPlans.size;
selectPlans.each(this::drawOverPlan);
//draw schematic plans
for(int i = 0; i < size; i++){
var plan = items[i];
plan.animScale = 1f;
drawPlan(plan);
}
//draw schematic plans - over version, cached results
for(int i = 0; i < size; i++){
var plan = items[i];
//use cached value from previous invocation
drawOverPlan(plan, plan.cachedValid);
}
if(player.isBuilder()){
//draw things that may be placed soon
if(mode == placing && block != null){
for(int i = 0; i < linePlans.size; i++){
BuildPlan req = linePlans.get(i);
if(i == linePlans.size - 1 && req.block.rotate){
drawArrow(block, req.x, req.y, req.rotation);
var plan = linePlans.get(i);
if(i == linePlans.size - 1 && plan.block.rotate){
drawArrow(block, plan.x, plan.y, plan.rotation);
}
drawPlan(linePlans.get(i));
}
@@ -373,8 +382,8 @@ public class DesktopInput extends InputHandler{
if(!Core.input.keyDown(Binding.diagonal_placement) && Math.abs((int)Core.input.axisTap(Binding.rotate)) > 0){
rotation = Mathf.mod(rotation + (int)Core.input.axisTap(Binding.rotate), 4);
if(sreq != null){
sreq.rotation = Mathf.mod(sreq.rotation + (int)Core.input.axisTap(Binding.rotate), 4);
if(splan != null){
splan.rotation = Mathf.mod(splan.rotation + (int)Core.input.axisTap(Binding.rotate), 4);
}
if(isPlacing() && mode == placing){
@@ -535,12 +544,12 @@ public class DesktopInput extends InputHandler{
}
}
if(sreq != null){
float offset = ((sreq.block.size + 2) % 2) * tilesize / 2f;
if(splan != null){
float offset = ((splan.block.size + 2) % 2) * tilesize / 2f;
float x = Core.input.mouseWorld().x + offset;
float y = Core.input.mouseWorld().y + offset;
sreq.x = (int)(x / tilesize);
sreq.y = (int)(y / tilesize);
splan.x = (int)(x / tilesize);
splan.y = (int)(y / tilesize);
}
if(block == null || mode != placing){
@@ -581,7 +590,7 @@ public class DesktopInput extends InputHandler{
if(Core.input.keyTap(Binding.select) && !Core.scene.hasMouse()){
tappedOne = false;
BuildPlan req = getPlan(cursorX, cursorY);
BuildPlan plan = getPlan(cursorX, cursorY);
if(Core.input.keyDown(Binding.break_block)){
mode = none;
@@ -594,9 +603,9 @@ public class DesktopInput extends InputHandler{
lastLineY = cursorY;
mode = placing;
updateLine(selectX, selectY);
}else if(req != null && !req.breaking && mode == none && !req.initialized){
sreq = req;
}else if(req != null && req.breaking){
}else if(plan != null && !plan.breaking && mode == none && !plan.initialized){
splan = plan;
}else if(plan != null && plan.breaking){
deleting = true;
}else if(commandMode){
commandRect = true;
@@ -630,9 +639,9 @@ public class DesktopInput extends InputHandler{
}
if(Core.input.keyDown(Binding.select) && mode == none && !isPlacing() && deleting){
BuildPlan req = getPlan(cursorX, cursorY);
if(req != null && req.breaking){
player.unit().plans().remove(req);
var plan = getPlan(cursorX, cursorY);
if(plan != null && plan.breaking){
player.unit().plans().remove(plan);
}
}else{
deleting = false;
@@ -671,11 +680,11 @@ public class DesktopInput extends InputHandler{
tryDropItems(selected == null ? null : selected.build, Core.input.mouseWorld().x, Core.input.mouseWorld().y);
if(sreq != null){
if(getPlan(sreq.x, sreq.y, sreq.block.size, sreq) != null){
player.unit().plans().remove(sreq, true);
if(splan != null){
if(getPlan(splan.x, splan.y, splan.block.size, splan) != null){
player.unit().plans().remove(splan, true);
}
sreq = null;
splan = null;
}
mode = none;
@@ -782,7 +791,7 @@ public class DesktopInput extends InputHandler{
droppingItem = false;
mode = none;
block = null;
sreq = null;
splan = null;
selectPlans.clear();
}
}

View File

@@ -73,10 +73,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public @Nullable Schematic lastSchematic;
public GestureDetector detector;
public PlaceLine line = new PlaceLine();
public BuildPlan resultreq;
public BuildPlan resultplan;
public BuildPlan bplan = new BuildPlan();
public Seq<BuildPlan> linePlans = new Seq<>();
public Seq<BuildPlan> selectPlans = new Seq<>();
public Seq<BuildPlan> selectPlans = new Seq<>(BuildPlan.class);
//for RTS controls
public Seq<Unit> selectedUnits = new Seq<>();
@@ -177,11 +177,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
//O(n^2) search here; no way around it
outer:
while(it.hasNext()){
BlockPlan req = it.next();
var plan = it.next();
for(int pos : positions){
if(req.x == Point2.x(pos) && req.y == Point2.y(pos)){
req.removed = true;
if(plan.x == Point2.x(pos) && plan.y == Point2.y(pos)){
plan.removed = true;
it.remove();
continue outer;
}
@@ -758,10 +758,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
public void rotatePlans(Seq<BuildPlan> plans, int direction){
int ox = schemOriginX(), oy = schemOriginY();
plans.each(req -> {
if(req.breaking) return;
plans.each(plan -> {
if(plan.breaking) return;
req.pointConfig(p -> {
plan.pointConfig(p -> {
int cx = p.x, cy = p.y;
int lx = cx;
@@ -776,7 +776,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
});
//rotate actual plan, centered on its multiblock position
float wx = (req.x - ox) * tilesize + req.block.offset, wy = (req.y - oy) * tilesize + req.block.offset;
float wx = (plan.x - ox) * tilesize + plan.block.offset, wy = (plan.y - oy) * tilesize + plan.block.offset;
float x = wx;
if(direction >= 0){
wx = -wy;
@@ -785,40 +785,40 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
wx = wy;
wy = -x;
}
req.x = World.toTile(wx - req.block.offset) + ox;
req.y = World.toTile(wy - req.block.offset) + oy;
req.rotation = Mathf.mod(req.rotation + direction, 4);
plan.x = World.toTile(wx - plan.block.offset) + ox;
plan.y = World.toTile(wy - plan.block.offset) + oy;
plan.rotation = Mathf.mod(plan.rotation + direction, 4);
});
}
public void flipPlans(Seq<BuildPlan> plans, boolean x){
int origin = (x ? schemOriginX() : schemOriginY()) * tilesize;
plans.each(req -> {
if(req.breaking) return;
plans.each(plan -> {
if(plan.breaking) return;
float value = -((x ? req.x : req.y) * tilesize - origin + req.block.offset) + origin;
float value = -((x ? plan.x : plan.y) * tilesize - origin + plan.block.offset) + origin;
if(x){
req.x = (int)((value - req.block.offset) / tilesize);
plan.x = (int)((value - plan.block.offset) / tilesize);
}else{
req.y = (int)((value - req.block.offset) / tilesize);
plan.y = (int)((value - plan.block.offset) / tilesize);
}
req.pointConfig(p -> {
int corigin = x ? req.originalWidth/2 : req.originalHeight/2;
plan.pointConfig(p -> {
int corigin = x ? plan.originalWidth/2 : plan.originalHeight/2;
int nvalue = -(x ? p.x : p.y);
if(x){
req.originalX = -(req.originalX - corigin) + corigin;
plan.originalX = -(plan.originalX - corigin) + corigin;
p.x = nvalue;
}else{
req.originalY = -(req.originalY - corigin) + corigin;
plan.originalY = -(plan.originalY - corigin) + corigin;
p.y = nvalue;
}
});
//flip rotation
req.block.flipRotation(req, x);
plan.block.flipRotation(plan, x);
});
}
@@ -840,17 +840,17 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
float offset = ((size + 1) % 2) * tilesize / 2f;
r2.setSize(tilesize * size);
r2.setCenter(x * tilesize + offset, y * tilesize + offset);
resultreq = null;
resultplan = null;
Boolf<BuildPlan> test = req -> {
if(req == skip) return false;
Tile other = req.tile();
Boolf<BuildPlan> test = plan -> {
if(plan == skip) return false;
Tile other = plan.tile();
if(other == null) return false;
if(!req.breaking){
r1.setSize(req.block.size * tilesize);
r1.setCenter(other.worldx() + req.block.offset, other.worldy() + req.block.offset);
if(!plan.breaking){
r1.setSize(plan.block.size * tilesize);
r1.setCenter(other.worldx() + plan.block.offset, other.worldy() + plan.block.offset);
}else{
r1.setSize(other.block().size * tilesize);
r1.setCenter(other.worldx() + other.block().offset, other.worldy() + other.block().offset);
@@ -859,8 +859,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
return r2.overlaps(r1);
};
for(BuildPlan req : player.unit().plans()){
if(test.get(req)) return req;
for(var plan : player.unit().plans()){
if(test.get(plan)) return plan;
}
return selectPlans.find(test);
@@ -884,24 +884,24 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Draw.color(Pal.remove);
Lines.stroke(1f);
for(BuildPlan req : player.unit().plans()){
if(req.breaking) continue;
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
drawBreaking(req);
for(var plan : player.unit().plans()){
if(plan.breaking) continue;
if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){
drawBreaking(plan);
}
}
for(BuildPlan req : selectPlans){
if(req.breaking) continue;
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
drawBreaking(req);
for(var plan : selectPlans){
if(plan.breaking) continue;
if(plan.bounds(Tmp.r2).overlaps(Tmp.r1)){
drawBreaking(plan);
}
}
for(BlockPlan req : player.team().data().blocks){
Block block = content.block(req.block);
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
drawSelected(req.x, req.y, content.block(req.block), Pal.remove);
for(BlockPlan plan : player.team().data().blocks){
Block block = content.block(plan.block);
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
drawSelected(plan.x, plan.y, content.block(plan.block), Pal.remove);
}
}
@@ -929,32 +929,34 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
protected void flushSelectPlans(Seq<BuildPlan> plans){
for(BuildPlan req : plans){
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
BuildPlan other = getPlan(req.x, req.y, req.block.size, null);
for(BuildPlan plan : plans){
if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){
BuildPlan other = getPlan(plan.x, plan.y, plan.block.size, null);
if(other == null){
selectPlans.add(req.copy());
}else if(!other.breaking && other.x == req.x && other.y == req.y && other.block.size == req.block.size){
selectPlans.add(plan.copy());
}else if(!other.breaking && other.x == plan.x && other.y == plan.y && other.block.size == plan.block.size){
selectPlans.remove(other);
selectPlans.add(req.copy());
selectPlans.add(plan.copy());
}
}
}
}
protected void flushPlans(Seq<BuildPlan> plans){
for(BuildPlan req : plans){
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
BuildPlan copy = req.copy();
req.block.onNewPlan(copy);
for(var plan : plans){
if(plan.block != null && validPlace(plan.x, plan.y, plan.block, plan.rotation)){
BuildPlan copy = plan.copy();
plan.block.onNewPlan(copy);
player.unit().addBuild(copy);
}
}
}
protected void drawOverPlan(BuildPlan plan){
boolean valid = validPlace(plan.x, plan.y, plan.block, plan.rotation);
drawOverPlan(plan, validPlace(plan.x, plan.y, plan.block, plan.rotation));
}
protected void drawOverPlan(BuildPlan plan, boolean valid){
Draw.reset();
Draw.mixcol(!valid ? Pal.breakInvalid : Color.white, (!valid ? 0.4f : 0.24f) + Mathf.absin(Time.globalTime, 6f, 0.28f));
Draw.alpha(1f);
@@ -963,7 +965,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
}
protected void drawPlan(BuildPlan plan){
plan.block.drawPlan(plan, allPlans(), validPlace(plan.x, plan.y, plan.block, plan.rotation));
drawPlan(plan, plan.cachedValid = validPlace(plan.x, plan.y, plan.block, plan.rotation));
}
protected void drawPlan(BuildPlan plan, boolean valid){
plan.block.drawPlan(plan, allPlans(), valid);
}
/** Draws a placement icon for a specific block. */
@@ -1013,16 +1019,16 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
Iterator<BuildPlan> it = player.unit().plans().iterator();
while(it.hasNext()){
BuildPlan req = it.next();
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
var plan = it.next();
if(!plan.breaking && plan.bounds(Tmp.r2).overlaps(Tmp.r1)){
it.remove();
}
}
it = selectPlans.iterator();
while(it.hasNext()){
BuildPlan req = it.next();
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
var plan = it.next();
if(!plan.breaking && plan.bounds(Tmp.r2).overlaps(Tmp.r1)){
it.remove();
}
}
@@ -1032,11 +1038,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
//remove blocks to rebuild
Iterator<BlockPlan> broken = player.team().data().blocks.iterator();
while(broken.hasNext()){
BlockPlan req = broken.next();
Block block = content.block(req.block);
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
removed.add(Point2.pack(req.x, req.y));
req.removed = true;
BlockPlan plan = broken.next();
Block block = content.block(plan.block);
if(block.bounds(plan.x, plan.y, Tmp.r2).overlaps(Tmp.r1)){
removed.add(Point2.pack(plan.x, plan.y));
plan.removed = true;
broken.remove();
}
}
@@ -1051,16 +1057,16 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
linePlans.clear();
iterateLine(x1, y1, x2, y2, l -> {
rotation = l.rotation;
BuildPlan req = new BuildPlan(l.x, l.y, l.rotation, block, block.nextConfig());
req.animScale = 1f;
linePlans.add(req);
var plan = new BuildPlan(l.x, l.y, l.rotation, block, block.nextConfig());
plan.animScale = 1f;
linePlans.add(plan);
});
if(Core.settings.getBool("blockreplace")){
linePlans.each(req -> {
Block replace = req.block.getReplacement(req, linePlans);
linePlans.each(plan -> {
Block replace = plan.block.getReplacement(plan, linePlans);
if(replace.unlockedNow()){
req.block = replace;
plan.block = replace;
}
});
@@ -1369,11 +1375,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
playerPlanTree.intersect(Tmp.r1, plansOut);
for(int i = 0; i < plansOut.size; i++){
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))){
var plan = plansOut.items[i];
if(plan != ignore
&& !plan.breaking
&& plan.block.bounds(plan.x, plan.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))
&& !(type.canReplace(plan.block) && Tmp.r1.equals(Tmp.r2))){
return false;
}
}

View File

@@ -113,26 +113,26 @@ public class MobileInput extends InputHandler implements GestureListener{
r2.setSize(block.size * tilesize);
r2.setCenter(x * tilesize + block.offset, y * tilesize + block.offset);
for(BuildPlan req : selectPlans){
Tile other = req.tile();
for(var plan : selectPlans){
Tile other = plan.tile();
if(other == null || req.breaking) continue;
if(other == null || plan.breaking) continue;
r1.setSize(req.block.size * tilesize);
r1.setCenter(other.worldx() + req.block.offset, other.worldy() + req.block.offset);
r1.setSize(plan.block.size * tilesize);
r1.setCenter(other.worldx() + plan.block.offset, other.worldy() + plan.block.offset);
if(r2.overlaps(r1)){
return true;
}
}
for(BuildPlan req : player.unit().plans()){
Tile other = world.tile(req.x, req.y);
for(var plan : player.unit().plans()){
Tile other = world.tile(plan.x, plan.y);
if(other == null || req.breaking) continue;
if(other == null || plan.breaking) continue;
r1.setSize(req.block.size * tilesize);
r1.setCenter(other.worldx() + req.block.offset, other.worldy() + req.block.offset);
r1.setSize(plan.block.size * tilesize);
r1.setCenter(other.worldx() + plan.block.offset, other.worldy() + plan.block.offset);
if(r2.overlaps(r1)){
return true;
@@ -146,21 +146,21 @@ public class MobileInput extends InputHandler implements GestureListener{
r2.setSize(tilesize);
r2.setCenter(tile.worldx(), tile.worldy());
for(BuildPlan req : selectPlans){
Tile other = req.tile();
for(var plan : selectPlans){
Tile other = plan.tile();
if(other == null) continue;
if(!req.breaking){
r1.setSize(req.block.size * tilesize);
r1.setCenter(other.worldx() + req.block.offset, other.worldy() + req.block.offset);
if(!plan.breaking){
r1.setSize(plan.block.size * tilesize);
r1.setCenter(other.worldx() + plan.block.offset, other.worldy() + plan.block.offset);
}else{
r1.setSize(other.block().size * tilesize);
r1.setCenter(other.worldx() + other.block().offset, other.worldy() + other.block().offset);
}
if(r2.overlaps(r1)) return req;
if(r2.overlaps(r1)) return plan;
}
return null;
}
@@ -822,10 +822,10 @@ public class MobileInput extends InputHandler implements GestureListener{
int shiftedY = (int)(shiftDeltaY / tilesize);
if(Math.abs(shiftedX) > 0 || Math.abs(shiftedY) > 0){
for(BuildPlan req : selectPlans){
if(req.breaking) continue; //don't shift removal plans
req.x += shiftedX;
req.y += shiftedY;
for(var plan : selectPlans){
if(plan.breaking) continue; //don't shift removal plans
plan.x += shiftedX;
plan.y += shiftedY;
}
shiftDeltaX %= tilesize;