2019-12-25 01:39:38 -05:00
|
|
|
package mindustry.input;
|
2017-12-13 23:28:20 -05:00
|
|
|
|
2019-12-25 01:39:38 -05:00
|
|
|
import arc.*;
|
|
|
|
import mindustry.annotations.Annotations.*;
|
|
|
|
import arc.struct.*;
|
|
|
|
import arc.func.*;
|
|
|
|
import arc.graphics.*;
|
|
|
|
import arc.graphics.g2d.*;
|
|
|
|
import arc.input.*;
|
|
|
|
import arc.input.GestureDetector.*;
|
|
|
|
import arc.math.*;
|
|
|
|
import arc.math.geom.*;
|
|
|
|
import arc.scene.*;
|
|
|
|
import arc.scene.event.*;
|
|
|
|
import arc.scene.ui.layout.*;
|
|
|
|
import arc.util.ArcAnnotate.*;
|
|
|
|
import arc.util.*;
|
|
|
|
import mindustry.content.*;
|
|
|
|
import mindustry.entities.*;
|
|
|
|
import mindustry.entities.effect.*;
|
|
|
|
import mindustry.entities.traits.BuilderTrait.*;
|
|
|
|
import mindustry.entities.type.*;
|
|
|
|
import mindustry.game.EventType.*;
|
|
|
|
import mindustry.game.*;
|
|
|
|
import mindustry.game.Teams.*;
|
|
|
|
import mindustry.gen.*;
|
|
|
|
import mindustry.graphics.*;
|
|
|
|
import mindustry.input.Placement.*;
|
|
|
|
import mindustry.net.*;
|
|
|
|
import mindustry.type.*;
|
|
|
|
import mindustry.ui.fragments.*;
|
|
|
|
import mindustry.world.*;
|
|
|
|
import mindustry.world.blocks.*;
|
|
|
|
import mindustry.world.blocks.BuildBlock.*;
|
|
|
|
import mindustry.world.blocks.power.PowerNode;
|
2017-12-13 23:28:20 -05:00
|
|
|
|
2019-10-07 17:17:01 -04:00
|
|
|
import java.util.*;
|
|
|
|
|
2019-12-25 01:39:38 -05:00
|
|
|
import static mindustry.Vars.*;
|
2017-12-31 14:23:13 -05:00
|
|
|
|
2019-10-06 16:56:31 -04:00
|
|
|
public abstract class InputHandler implements InputProcessor, GestureListener{
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Used for dropping items. */
|
2018-06-09 23:23:14 -04:00
|
|
|
final static float playerSelectRange = mobile ? 17f : 11f;
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Maximum line length. */
|
2018-07-12 20:37:14 -04:00
|
|
|
final static int maxLength = 100;
|
2019-12-25 11:16:54 -05:00
|
|
|
final static Vec2 stackTrns = new Vec2();
|
2019-12-26 22:44:15 -05:00
|
|
|
final static Rect r1 = new Rect(), r2 = new Rect();
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Distance on the back from where items originate. */
|
2018-07-12 20:37:14 -04:00
|
|
|
final static float backTrns = 3f;
|
|
|
|
|
2019-07-02 18:40:39 -04:00
|
|
|
public final OverlayFragment frag = new OverlayFragment();
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-01-20 13:49:53 -05:00
|
|
|
public Block block;
|
2019-09-21 15:03:05 -07:00
|
|
|
public boolean overrideLineRotation;
|
2018-07-12 20:37:14 -04:00
|
|
|
public int rotation;
|
|
|
|
public boolean droppingItem;
|
2019-10-06 16:56:31 -04:00
|
|
|
public Group uiGroup;
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-10-18 11:38:00 -04:00
|
|
|
protected @Nullable Schematic lastSchematic;
|
2019-10-06 16:56:31 -04:00
|
|
|
protected GestureDetector detector;
|
|
|
|
protected PlaceLine line = new PlaceLine();
|
2019-10-07 19:51:52 -04:00
|
|
|
protected BuildRequest resultreq;
|
2019-10-06 16:56:31 -04:00
|
|
|
protected BuildRequest brequest = new BuildRequest();
|
|
|
|
protected Array<BuildRequest> lineRequests = new Array<>();
|
|
|
|
protected Array<BuildRequest> selectRequests = new Array<>();
|
2019-03-19 10:30:13 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
//methods to override
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-07-26 15:24:48 -04:00
|
|
|
@Remote(targets = Loc.client, called = Loc.server)
|
2018-07-12 20:37:14 -04:00
|
|
|
public static void dropItem(Player player, float angle){
|
2019-09-07 14:11:50 -04:00
|
|
|
if(net.server() && player.item().amount <= 0){
|
2018-07-12 20:37:14 -04:00
|
|
|
throw new ValidateException(player, "Player cannot drop an item.");
|
|
|
|
}
|
2018-04-15 13:05:18 -04:00
|
|
|
|
2019-09-09 16:22:29 -04:00
|
|
|
Effects.effect(Fx.dropItem, Color.white, player.x, player.y, angle, player.item().item);
|
2019-02-02 15:53:35 -05:00
|
|
|
player.clearItem();
|
2018-05-11 07:59:10 -07:00
|
|
|
}
|
|
|
|
|
2019-09-29 19:54:52 -04:00
|
|
|
@Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true)
|
|
|
|
public static void rotateBlock(Player player, Tile tile, boolean direction){
|
|
|
|
if(net.server() && !Units.canInteract(player, tile)){
|
|
|
|
throw new ValidateException(player, "Player cannot drop an item.");
|
|
|
|
}
|
|
|
|
|
|
|
|
tile.rotation(Mathf.mod(tile.rotation() + Mathf.sign(direction), 4));
|
|
|
|
|
|
|
|
if(tile.entity != null){
|
|
|
|
tile.entity.updateProximity();
|
|
|
|
tile.entity.noSleep();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-26 15:24:48 -04:00
|
|
|
@Remote(targets = Loc.both, forward = true, called = Loc.server)
|
2018-07-12 20:37:14 -04:00
|
|
|
public static void transferInventory(Player player, Tile tile){
|
2019-12-29 14:38:03 -05:00
|
|
|
if(player == null || player.timer == null) return;
|
2019-09-26 19:51:41 -04:00
|
|
|
if(net.server() && (player.item().amount <= 0 || player.isTransferring|| !Units.canInteract(player, tile))){
|
2018-07-12 20:37:14 -04:00
|
|
|
throw new ValidateException(player, "Player cannot transfer an item.");
|
|
|
|
}
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2019-09-08 15:08:55 -04:00
|
|
|
if(tile.entity == null) return;
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-12-21 21:33:05 -05:00
|
|
|
player.isTransferring = true;
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2019-02-02 15:53:35 -05:00
|
|
|
Item item = player.item().item;
|
|
|
|
int amount = player.item().amount;
|
2018-12-21 21:33:05 -05:00
|
|
|
int accepted = tile.block().acceptStack(item, amount, tile, player);
|
2019-02-02 15:53:35 -05:00
|
|
|
player.item().amount -= accepted;
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-12-21 21:33:05 -05:00
|
|
|
int sent = Mathf.clamp(accepted / 4, 1, 8);
|
|
|
|
int removed = accepted / sent;
|
|
|
|
int[] remaining = {accepted, accepted};
|
|
|
|
Block block = tile.block();
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-11-10 10:15:52 -05:00
|
|
|
Core.app.post(() -> Events.fire(new DepositEvent(tile, player, item, accepted)));
|
2019-08-08 21:26:50 -04:00
|
|
|
|
2018-12-21 21:33:05 -05:00
|
|
|
for(int i = 0; i < sent; i++){
|
|
|
|
boolean end = i == sent - 1;
|
|
|
|
Time.run(i * 3, () -> {
|
|
|
|
tile.block().getStackOffset(item, tile, stackTrns);
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2018-12-21 21:33:05 -05:00
|
|
|
ItemTransfer.create(item,
|
2019-04-08 09:03:18 -04:00
|
|
|
player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns),
|
2019-12-25 11:16:54 -05:00
|
|
|
new Vec2(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> {
|
2019-04-08 09:03:18 -04:00
|
|
|
if(tile.block() != block || tile.entity == null || tile.entity.items == null) return;
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
tile.block().handleStack(item, removed, tile, player);
|
|
|
|
remaining[1] -= removed;
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
if(end && remaining[1] > 0){
|
|
|
|
tile.block().handleStack(item, remaining[1], tile, player);
|
|
|
|
}
|
|
|
|
});
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2018-12-21 21:33:05 -05:00
|
|
|
remaining[0] -= removed;
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2018-12-21 21:33:05 -05:00
|
|
|
if(end){
|
|
|
|
player.isTransferring = false;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2018-05-29 00:15:24 -04:00
|
|
|
}
|
|
|
|
|
2018-07-26 15:24:48 -04:00
|
|
|
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
2018-07-12 20:37:14 -04:00
|
|
|
public static void onTileTapped(Player player, Tile tile){
|
|
|
|
if(tile == null || player == null) return;
|
2019-09-26 19:51:41 -04:00
|
|
|
if(!Units.canInteract(player, tile)) return;
|
2018-07-12 20:37:14 -04:00
|
|
|
tile.block().tapped(tile, player);
|
2019-11-09 04:58:24 +09:00
|
|
|
Core.app.post(() -> Events.fire(new TapEvent(tile, player)));
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2019-09-30 19:40:08 -04:00
|
|
|
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
2019-09-30 10:57:48 -04:00
|
|
|
public static void onTileConfig(Player player, Tile tile, int value){
|
|
|
|
if(tile == null || !Units.canInteract(player, tile)) return;
|
2019-09-30 19:40:08 -04:00
|
|
|
tile.block().configured(tile, player, value);
|
2019-11-09 04:58:24 +09:00
|
|
|
Core.app.post(() -> Events.fire(new TapConfigEvent(tile, player, value)));
|
2019-09-30 10:57:48 -04:00
|
|
|
}
|
|
|
|
|
2019-10-06 16:56:31 -04:00
|
|
|
public Eachable<BuildRequest> allRequests(){
|
|
|
|
return cons -> {
|
2019-10-29 15:57:25 -04:00
|
|
|
for(BuildRequest request : player.buildQueue()) cons.get(request);
|
|
|
|
for(BuildRequest request : selectRequests) cons.get(request);
|
|
|
|
for(BuildRequest request : lineRequests) cons.get(request);
|
2019-10-06 16:56:31 -04:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2018-09-19 22:17:58 -04:00
|
|
|
public OverlayFragment getFrag(){
|
|
|
|
return frag;
|
|
|
|
}
|
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public void update(){
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public float getMouseX(){
|
2018-12-22 22:17:28 -05:00
|
|
|
return Core.input.mouseX();
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-05-29 22:03:43 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public float getMouseY(){
|
2018-12-22 22:17:28 -05:00
|
|
|
return Core.input.mouseY();
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-05-29 22:03:43 -04:00
|
|
|
|
2019-10-06 16:56:31 -04:00
|
|
|
public void buildPlacementUI(Table table){
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
public void buildUI(Group group){
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2019-09-21 15:35:59 -04:00
|
|
|
public void updateState(){
|
2018-05-29 00:15:24 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-06-01 13:01:05 -04:00
|
|
|
|
2019-10-06 23:03:02 -04:00
|
|
|
public void drawBottom(){
|
2018-05-30 23:51:42 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public void drawTop(){
|
|
|
|
|
|
|
|
}
|
2018-05-30 18:32:01 -04:00
|
|
|
|
2019-10-07 17:17:01 -04:00
|
|
|
public void drawSelected(int x, int y, Block block, Color color){
|
2019-10-07 19:51:52 -04:00
|
|
|
Draw.color(color);
|
2019-10-07 17:17:01 -04:00
|
|
|
for(int i = 0; i < 4; i++){
|
|
|
|
Point2 p = Geometry.d8edge[i];
|
|
|
|
float offset = -Math.max(block.size - 1, 0) / 2f * tilesize;
|
|
|
|
Draw.rect("block-select",
|
|
|
|
x*tilesize + block.offset() + offset * p.x,
|
|
|
|
y*tilesize + block.offset() + offset * p.y, i * 90);
|
|
|
|
}
|
|
|
|
Draw.reset();
|
|
|
|
}
|
|
|
|
|
2019-10-06 23:03:02 -04:00
|
|
|
public void drawBreaking(BuildRequest request){
|
|
|
|
if(request.breaking){
|
|
|
|
drawBreaking(request.x, request.y);
|
|
|
|
}else{
|
2019-10-18 17:18:29 -04:00
|
|
|
drawSelected(request.x, request.y, request.block, Pal.remove);
|
2019-10-06 23:03:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-22 20:17:43 -04:00
|
|
|
public boolean requestMatches(BuildRequest request){
|
|
|
|
Tile tile = world.tile(request.x, request.y);
|
2019-12-08 18:34:23 -05:00
|
|
|
return tile != null && tile.block() instanceof BuildBlock && tile.<BuildEntity>ent().cblock == request.block;
|
2019-10-22 20:17:43 -04:00
|
|
|
}
|
|
|
|
|
2019-10-06 23:03:02 -04:00
|
|
|
public void drawBreaking(int x, int y){
|
|
|
|
Tile tile = world.ltile(x, y);
|
|
|
|
if(tile == null) return;
|
|
|
|
Block block = tile.block();
|
|
|
|
|
2019-10-07 17:17:01 -04:00
|
|
|
drawSelected(x, y, block, Pal.remove);
|
|
|
|
}
|
|
|
|
|
2019-10-18 00:41:30 -04:00
|
|
|
public void useSchematic(Schematic schem){
|
|
|
|
selectRequests.addAll(schematics.toRequests(schem, world.toTile(player.x), world.toTile(player.y)));
|
|
|
|
}
|
|
|
|
|
2019-10-31 22:44:07 -04:00
|
|
|
protected void showSchematicSave(){
|
|
|
|
if(lastSchematic == null) return;
|
|
|
|
|
|
|
|
ui.showTextInput("$schematic.add", "$name", "", text -> {
|
|
|
|
Schematic replacement = schematics.all().find(s -> s.name().equals(text));
|
|
|
|
if(replacement != null){
|
|
|
|
ui.showConfirm("$confirm", "$schematic.replace", () -> {
|
|
|
|
schematics.overwrite(replacement, lastSchematic);
|
|
|
|
ui.showInfoFade("$schematic.saved");
|
|
|
|
ui.schematics.showInfo(replacement);
|
|
|
|
});
|
|
|
|
}else{
|
|
|
|
lastSchematic.tags.put("name", text);
|
|
|
|
schematics.add(lastSchematic);
|
|
|
|
ui.showInfoFade("$schematic.saved");
|
|
|
|
ui.schematics.showInfo(lastSchematic);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-10-18 11:38:00 -04:00
|
|
|
public void rotateRequests(Array<BuildRequest> requests, int direction){
|
2019-10-31 22:44:07 -04:00
|
|
|
int ox = schemOriginX(), oy = schemOriginY();
|
2019-10-18 11:38:00 -04:00
|
|
|
|
|
|
|
requests.each(req -> {
|
2019-10-18 14:38:43 -04:00
|
|
|
//rotate config position
|
|
|
|
if(req.block.posConfig){
|
|
|
|
int cx = Pos.x(req.config) - req.originalX, cy = Pos.y(req.config) - req.originalY;
|
|
|
|
int lx = cx;
|
|
|
|
|
|
|
|
if(direction >= 0){
|
|
|
|
cx = -cy;
|
|
|
|
cy = lx;
|
|
|
|
}else{
|
|
|
|
cx = cy;
|
|
|
|
cy = -lx;
|
|
|
|
}
|
|
|
|
req.config = Pos.get(cx + req.originalX, cy + req.originalY);
|
|
|
|
}
|
|
|
|
|
|
|
|
//rotate actual request, centered on its multiblock position
|
2019-10-18 11:38:00 -04:00
|
|
|
float wx = (req.x - ox) * tilesize + req.block.offset(), wy = (req.y - oy) * tilesize + req.block.offset();
|
|
|
|
float x = wx;
|
|
|
|
if(direction >= 0){
|
|
|
|
wx = -wy;
|
|
|
|
wy = x;
|
|
|
|
}else{
|
|
|
|
wx = wy;
|
|
|
|
wy = -x;
|
|
|
|
}
|
|
|
|
req.x = world.toTile(wx - req.block.offset()) + ox;
|
|
|
|
req.y = world.toTile(wy - req.block.offset()) + oy;
|
2019-10-18 14:38:43 -04:00
|
|
|
req.rotation = Mathf.mod(req.rotation + direction, 4);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public void flipRequests(Array<BuildRequest> requests, boolean x){
|
2019-10-31 22:44:07 -04:00
|
|
|
int origin = (x ? schemOriginX() : schemOriginY()) * tilesize;
|
2019-10-18 14:38:43 -04:00
|
|
|
|
|
|
|
requests.each(req -> {
|
2019-10-20 20:39:58 -04:00
|
|
|
float value = -((x ? req.x : req.y) * tilesize - origin + req.block.offset()) + origin;
|
2019-10-18 14:38:43 -04:00
|
|
|
|
|
|
|
if(x){
|
2019-10-20 20:39:58 -04:00
|
|
|
req.x = (int)((value - req.block.offset()) / tilesize);
|
2019-10-18 14:38:43 -04:00
|
|
|
}else{
|
2019-10-20 20:39:58 -04:00
|
|
|
req.y = (int)((value - req.block.offset()) / tilesize);
|
2019-10-18 14:38:43 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if(req.block.posConfig){
|
|
|
|
int corigin = x ? req.originalWidth/2 : req.originalHeight/2;
|
|
|
|
int nvalue = -((x ? Pos.x(req.config) : Pos.y(req.config)) - corigin) + corigin;
|
|
|
|
if(x){
|
|
|
|
req.originalX = -(req.originalX - corigin) + corigin;
|
|
|
|
req.config = Pos.get(nvalue, Pos.y(req.config));
|
|
|
|
}else{
|
|
|
|
req.originalY = -(req.originalY - corigin) + corigin;
|
|
|
|
req.config = Pos.get(Pos.x(req.config), nvalue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//flip rotation
|
|
|
|
if(x == (req.rotation % 2 == 0)){
|
|
|
|
req.rotation = Mathf.mod(req.rotation + 2, 4);
|
|
|
|
}
|
2019-10-18 11:38:00 -04:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-10-31 22:44:07 -04:00
|
|
|
protected int schemOriginX(){
|
|
|
|
return rawTileX();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected int schemOriginY(){
|
|
|
|
return rawTileY();
|
|
|
|
}
|
|
|
|
|
2019-10-07 19:51:52 -04:00
|
|
|
/** Returns the selection request that overlaps this position, or null. */
|
|
|
|
protected BuildRequest getRequest(int x, int y){
|
|
|
|
return getRequest(x, y, 1, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Returns the selection request that overlaps this position, or null. */
|
|
|
|
protected BuildRequest getRequest(int x, int y, int size, BuildRequest skip){
|
|
|
|
float offset = ((size + 1) % 2) * tilesize / 2f;
|
|
|
|
r2.setSize(tilesize * size);
|
|
|
|
r2.setCenter(x * tilesize + offset, y * tilesize + offset);
|
|
|
|
resultreq = null;
|
|
|
|
|
2019-10-29 15:57:25 -04:00
|
|
|
Boolf<BuildRequest> test = req -> {
|
2019-10-07 19:51:52 -04:00
|
|
|
if(req == skip) return false;
|
|
|
|
Tile other = req.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());
|
|
|
|
}else{
|
|
|
|
r1.setSize(other.block().size * tilesize);
|
|
|
|
r1.setCenter(other.worldx() + other.block().offset(), other.worldy() + other.block().offset());
|
|
|
|
}
|
|
|
|
|
|
|
|
return r2.overlaps(r1);
|
|
|
|
};
|
|
|
|
|
|
|
|
for(BuildRequest req : player.buildQueue()){
|
2019-10-29 15:57:25 -04:00
|
|
|
if(test.get(req)) return req;
|
2019-10-07 19:51:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
for(BuildRequest req : selectRequests){
|
2019-10-29 15:57:25 -04:00
|
|
|
if(test.get(req)) return req;
|
2019-10-07 19:51:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-10-18 14:38:43 -04:00
|
|
|
protected void drawBreakSelection(int x1, int y1, int x2, int y2){
|
2019-11-02 14:09:16 -04:00
|
|
|
NormalizeDrawResult result = Placement.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, maxLength, 1f);
|
|
|
|
NormalizeResult dresult = Placement.normalizeArea(x1, y1, x2, y2, rotation, false, maxLength);
|
2019-10-07 17:17:01 -04:00
|
|
|
|
|
|
|
for(int x = dresult.x; x <= dresult.x2; x++){
|
|
|
|
for(int y = dresult.y; y <= dresult.y2; y++){
|
|
|
|
Tile tile = world.ltile(x, y);
|
|
|
|
if(tile == null || !validBreak(tile.x, tile.y)) continue;
|
|
|
|
|
|
|
|
drawBreaking(tile.x, tile.y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Tmp.r1.set(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
|
|
|
|
2019-10-06 23:03:02 -04:00
|
|
|
Draw.color(Pal.remove);
|
2019-10-07 17:17:01 -04:00
|
|
|
Lines.stroke(1f);
|
|
|
|
|
|
|
|
for(BuildRequest req : player.buildQueue()){
|
|
|
|
if(req.breaking) continue;
|
|
|
|
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
|
|
|
drawBreaking(req);
|
|
|
|
}
|
2019-10-06 23:03:02 -04:00
|
|
|
}
|
2019-10-07 17:17:01 -04:00
|
|
|
|
2019-10-10 22:13:45 -04:00
|
|
|
for(BuildRequest req : selectRequests){
|
|
|
|
if(req.breaking) continue;
|
|
|
|
if(req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
|
|
|
drawBreaking(req);
|
|
|
|
}
|
2019-11-02 10:45:23 -04:00
|
|
|
}
|
2019-10-10 22:13:45 -04:00
|
|
|
|
2019-12-26 20:08:53 -05:00
|
|
|
for(BrokenBlock req : player.getTeam().data().brokenBlocks){
|
2019-10-07 17:17:01 -04:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Lines.stroke(2f);
|
|
|
|
|
|
|
|
Draw.color(Pal.removeBack);
|
|
|
|
Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y);
|
|
|
|
Draw.color(Pal.remove);
|
|
|
|
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
2019-10-06 23:03:02 -04:00
|
|
|
}
|
|
|
|
|
2019-10-18 14:38:43 -04:00
|
|
|
protected void drawSelection(int x1, int y1, int x2, int y2, int maxLength){
|
2019-11-02 14:09:16 -04:00
|
|
|
NormalizeDrawResult result = Placement.normalizeDrawArea(Blocks.air, x1, y1, x2, y2, false, maxLength, 1f);
|
2019-10-18 14:38:43 -04:00
|
|
|
|
|
|
|
Lines.stroke(2f);
|
|
|
|
|
|
|
|
Draw.color(Pal.accentBack);
|
|
|
|
Lines.rect(result.x, result.y - 1, result.x2 - result.x, result.y2 - result.y);
|
|
|
|
Draw.color(Pal.accent);
|
|
|
|
Lines.rect(result.x, result.y, result.x2 - result.x, result.y2 - result.y);
|
|
|
|
}
|
|
|
|
|
2019-10-07 20:52:50 -04:00
|
|
|
protected void flushSelectRequests(Array<BuildRequest> requests){
|
|
|
|
for(BuildRequest req : requests){
|
|
|
|
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
2019-11-02 10:45:23 -04:00
|
|
|
BuildRequest other = getRequest(req.x, req.y, req.block.size, null);
|
|
|
|
if(other == null){
|
|
|
|
selectRequests.add(req.copy());
|
|
|
|
}else if(!other.breaking && other.x == req.x && other.y == req.y && other.block.size == req.block.size){
|
2019-10-25 12:58:07 -04:00
|
|
|
selectRequests.remove(other);
|
2019-11-02 10:45:23 -04:00
|
|
|
selectRequests.add(req.copy());
|
2019-10-25 12:58:07 -04:00
|
|
|
}
|
2019-10-07 20:52:50 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-06 16:56:31 -04:00
|
|
|
protected void flushRequests(Array<BuildRequest> requests){
|
|
|
|
for(BuildRequest req : requests){
|
|
|
|
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
|
2019-10-18 00:41:30 -04:00
|
|
|
BuildRequest copy = req.copy();
|
|
|
|
if(copy.hasConfig && copy.block.posConfig){
|
|
|
|
copy.config = Pos.get(Pos.x(copy.config) + copy.x - copy.originalX, Pos.y(copy.config) + copy.y - copy.originalY);
|
|
|
|
}
|
|
|
|
player.addBuildRequest(copy);
|
2019-10-06 16:56:31 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
protected void drawRequest(BuildRequest request){
|
2019-11-17 11:20:36 -05:00
|
|
|
request.block.drawRequest(request, allRequests(), validPlace(request.x, request.y, request.block, request.rotation));
|
2019-10-06 16:56:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Draws a placement icon for a specific block. */
|
|
|
|
protected void drawRequest(int x, int y, Block block, int rotation){
|
|
|
|
brequest.set(x, y, rotation, block);
|
2019-10-12 12:52:50 -04:00
|
|
|
brequest.animScale = 1f;
|
2019-10-06 16:56:31 -04:00
|
|
|
block.drawRequest(brequest, allRequests(), validPlace(x, y, block, rotation));
|
|
|
|
}
|
|
|
|
|
2019-10-07 17:17:01 -04:00
|
|
|
/** Remove everything from the queue in a selection. */
|
|
|
|
protected void removeSelection(int x1, int y1, int x2, int y2){
|
2019-10-08 19:01:04 -04:00
|
|
|
removeSelection(x1, y1, x2, y2, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Remove everything from the queue in a selection. */
|
|
|
|
protected void removeSelection(int x1, int y1, int x2, int y2, boolean flush){
|
2019-11-02 14:09:16 -04:00
|
|
|
NormalizeResult result = Placement.normalizeArea(x1, y1, x2, y2, rotation, false, maxLength);
|
2019-10-07 17:17:01 -04:00
|
|
|
for(int x = 0; x <= Math.abs(result.x2 - result.x); x++){
|
|
|
|
for(int y = 0; y <= Math.abs(result.y2 - result.y); y++){
|
|
|
|
int wx = x1 + x * Mathf.sign(x2 - x1);
|
|
|
|
int wy = y1 + y * Mathf.sign(y2 - y1);
|
|
|
|
|
2019-10-10 22:13:45 -04:00
|
|
|
Tile tile = world.ltile(wx, wy);
|
|
|
|
|
|
|
|
if(tile == null) continue;
|
|
|
|
|
2019-10-08 19:01:04 -04:00
|
|
|
if(!flush){
|
|
|
|
tryBreakBlock(wx, wy);
|
2019-10-10 22:13:45 -04:00
|
|
|
}else if(validBreak(tile.x, tile.y) && !selectRequests.contains(r -> r.tile() != null && r.tile().link() == tile)){
|
|
|
|
selectRequests.add(new BuildRequest(tile.x, tile.y));
|
2019-10-08 19:01:04 -04:00
|
|
|
}
|
2019-10-07 17:17:01 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//remove build requests
|
|
|
|
Tmp.r1.set(result.x * tilesize, result.y * tilesize, (result.x2 - result.x) * tilesize, (result.y2 - result.y) * tilesize);
|
2019-10-10 22:13:45 -04:00
|
|
|
|
2019-10-07 17:17:01 -04:00
|
|
|
Iterator<BuildRequest> it = player.buildQueue().iterator();
|
|
|
|
while(it.hasNext()){
|
|
|
|
BuildRequest req = it.next();
|
|
|
|
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
|
|
|
it.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-10 22:13:45 -04:00
|
|
|
it = selectRequests.iterator();
|
|
|
|
while(it.hasNext()){
|
|
|
|
BuildRequest req = it.next();
|
|
|
|
if(!req.breaking && req.bounds(Tmp.r2).overlaps(Tmp.r1)){
|
|
|
|
it.remove();
|
|
|
|
}
|
2019-11-02 10:45:23 -04:00
|
|
|
}
|
2019-10-10 22:13:45 -04:00
|
|
|
|
2019-10-07 17:17:01 -04:00
|
|
|
//remove blocks to rebuild
|
|
|
|
Iterator<BrokenBlock> broken = state.teams.get(player.getTeam()).brokenBlocks.iterator();
|
|
|
|
while(broken.hasNext()){
|
|
|
|
BrokenBlock req = broken.next();
|
|
|
|
Block block = content.block(req.block);
|
|
|
|
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
|
|
|
broken.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-07 20:52:50 -04:00
|
|
|
protected void updateLine(int x1, int y1, int x2, int y2){
|
2019-10-06 16:56:31 -04:00
|
|
|
lineRequests.clear();
|
2019-10-07 20:52:50 -04:00
|
|
|
iterateLine(x1, y1, x2, y2, l -> {
|
2019-10-06 16:56:31 -04:00
|
|
|
rotation = l.rotation;
|
2019-10-12 12:52:50 -04:00
|
|
|
BuildRequest req = new BuildRequest(l.x, l.y, l.rotation, block);
|
|
|
|
req.animScale = 1f;
|
|
|
|
lineRequests.add(req);
|
2019-10-06 16:56:31 -04:00
|
|
|
});
|
2019-11-01 17:30:09 -04:00
|
|
|
|
2019-11-02 14:09:16 -04:00
|
|
|
if(Core.settings.getBool("blockreplace")){
|
|
|
|
lineRequests.each(req -> {
|
|
|
|
Block replace = req.block.getReplacement(req, lineRequests);
|
|
|
|
if(replace.unlockedCur()){
|
|
|
|
req.block = replace;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2019-10-06 16:56:31 -04:00
|
|
|
}
|
|
|
|
|
2019-10-07 20:52:50 -04:00
|
|
|
protected void updateLine(int x1, int y1){
|
|
|
|
updateLine(x1, y1, tileX(getMouseX()), tileY(getMouseY()));
|
|
|
|
}
|
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Handles tile tap events that are not platform specific. */
|
2018-07-12 20:37:14 -04:00
|
|
|
boolean tileTapped(Tile tile){
|
2019-05-05 19:05:46 -04:00
|
|
|
tile = tile.link();
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-01-18 15:41:49 -05:00
|
|
|
boolean consumed = false, showedInventory = false;
|
2018-07-12 20:37:14 -04:00
|
|
|
|
|
|
|
//check if tapped block is configurable
|
2019-02-15 12:32:01 -05:00
|
|
|
if(tile.block().configurable && tile.interactable(player.getTeam())){
|
2018-07-12 20:37:14 -04:00
|
|
|
consumed = true;
|
|
|
|
if(((!frag.config.isShown() && tile.block().shouldShowConfigure(tile, player)) //if the config fragment is hidden, show
|
2019-04-08 09:03:18 -04:00
|
|
|
//alternatively, the current selected block can 'agree' to switch config tiles
|
|
|
|
|| (frag.config.isShown() && frag.config.getSelectedTile().block().onConfigureTileTapped(frag.config.getSelectedTile(), tile)))){
|
2019-08-12 23:29:24 -04:00
|
|
|
Sounds.click.at(tile);
|
2018-07-12 20:37:14 -04:00
|
|
|
frag.config.showConfig(tile);
|
|
|
|
}
|
|
|
|
//otherwise...
|
|
|
|
}else if(!frag.config.hasConfigMouse()){ //make sure a configuration fragment isn't on the cursor
|
|
|
|
//then, if it's shown and the current block 'agrees' to hide, hide it.
|
|
|
|
if(frag.config.isShown() && frag.config.getSelectedTile().block().onConfigureTileTapped(frag.config.getSelectedTile(), tile)){
|
|
|
|
consumed = true;
|
|
|
|
frag.config.hideConfig();
|
|
|
|
}
|
2018-10-15 02:05:25 -03:00
|
|
|
|
|
|
|
if(frag.config.isShown()){
|
|
|
|
consumed = true;
|
|
|
|
}
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
//call tapped event
|
2019-02-15 12:32:01 -05:00
|
|
|
if(!consumed && tile.interactable(player.getTeam())){
|
2018-07-26 15:24:48 -04:00
|
|
|
Call.onTileTapped(player, tile);
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-06-09 23:23:14 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
//consume tap event if necessary
|
2019-02-15 12:32:01 -05:00
|
|
|
if(tile.interactable(player.getTeam()) && tile.block().consumesTap){
|
2018-07-12 20:37:14 -04:00
|
|
|
consumed = true;
|
2019-02-15 12:32:01 -05:00
|
|
|
}else if(tile.interactable(player.getTeam()) && tile.block().synthetic() && !consumed){
|
2018-07-12 20:37:14 -04:00
|
|
|
if(tile.block().hasItems && tile.entity.items.total() > 0){
|
|
|
|
frag.inv.showFor(tile);
|
|
|
|
consumed = true;
|
|
|
|
showedInventory = true;
|
|
|
|
}
|
|
|
|
}
|
2018-06-02 21:45:07 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
if(!showedInventory){
|
|
|
|
frag.inv.hide();
|
|
|
|
}
|
2018-05-30 23:51:42 -04:00
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
return consumed;
|
|
|
|
}
|
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Tries to select the player to drop off items, returns true if successful. */
|
2018-07-12 20:37:14 -04:00
|
|
|
boolean tryTapPlayer(float x, float y){
|
|
|
|
if(canTapPlayer(x, y)){
|
|
|
|
droppingItem = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean canTapPlayer(float x, float y){
|
2019-02-02 15:53:35 -05:00
|
|
|
return Mathf.dst(x, y, player.x, player.y) <= playerSelectRange && player.item().amount > 0;
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Tries to begin mining a tile, returns true if successful. */
|
2018-07-12 20:37:14 -04:00
|
|
|
boolean tryBeginMine(Tile tile){
|
|
|
|
if(canMine(tile)){
|
|
|
|
//if a block is clicked twice, reset it
|
|
|
|
player.setMineTile(player.getMineTile() == tile ? null : tile);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
boolean canMine(Tile tile){
|
2018-12-22 22:17:28 -05:00
|
|
|
return !Core.scene.hasMouse()
|
2019-04-08 09:03:18 -04:00
|
|
|
&& tile.drop() != null && tile.drop().hardness <= player.mech.drillPower
|
2019-04-12 23:03:34 -04:00
|
|
|
&& !(tile.floor().playerUnmineable && tile.overlay().itemDrop == null)
|
2019-04-08 09:03:18 -04:00
|
|
|
&& player.acceptsItem(tile.drop())
|
|
|
|
&& tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Player.mineDistance;
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
/** Returns the tile at the specified MOUSE coordinates. */
|
2018-07-12 20:37:14 -04:00
|
|
|
Tile tileAt(float x, float y){
|
2018-10-13 17:47:58 -04:00
|
|
|
return world.tile(tileX(x), tileY(y));
|
|
|
|
}
|
|
|
|
|
2019-10-18 14:38:43 -04:00
|
|
|
int rawTileX(){
|
|
|
|
return world.toTile(Core.input.mouseWorld().x);
|
|
|
|
}
|
|
|
|
|
|
|
|
int rawTileY(){
|
|
|
|
return world.toTile(Core.input.mouseWorld().y);
|
|
|
|
}
|
|
|
|
|
2018-10-13 17:47:58 -04:00
|
|
|
int tileX(float cursorX){
|
2019-12-25 11:16:54 -05:00
|
|
|
Vec2 vec = Core.input.mouseWorld(cursorX, 0);
|
2018-10-22 22:21:22 -04:00
|
|
|
if(selectedBlock()){
|
2019-01-20 13:49:53 -05:00
|
|
|
vec.sub(block.offset(), block.offset());
|
2018-10-13 17:47:58 -04:00
|
|
|
}
|
|
|
|
return world.toTile(vec.x);
|
|
|
|
}
|
|
|
|
|
|
|
|
int tileY(float cursorY){
|
2019-12-25 11:16:54 -05:00
|
|
|
Vec2 vec = Core.input.mouseWorld(0, cursorY);
|
2018-10-22 22:21:22 -04:00
|
|
|
if(selectedBlock()){
|
2019-01-20 13:49:53 -05:00
|
|
|
vec.sub(block.offset(), block.offset());
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
2018-10-13 17:47:58 -04:00
|
|
|
return world.toTile(vec.y);
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
2018-10-22 22:21:22 -04:00
|
|
|
public boolean selectedBlock(){
|
|
|
|
return isPlacing();
|
|
|
|
}
|
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public boolean isPlacing(){
|
2019-01-20 13:49:53 -05:00
|
|
|
return block != null;
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
2019-10-14 23:43:13 -04:00
|
|
|
public boolean isBreaking(){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public float mouseAngle(float x, float y){
|
2018-12-22 22:17:28 -05:00
|
|
|
return Core.input.mouseWorld(getMouseX(), getMouseY()).sub(x, y).angle();
|
2018-05-13 20:48:44 -07:00
|
|
|
}
|
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public void remove(){
|
2018-12-21 21:33:05 -05:00
|
|
|
Core.input.removeProcessor(this);
|
2018-07-12 20:37:14 -04:00
|
|
|
frag.remove();
|
2019-09-21 15:54:34 -04:00
|
|
|
if(Core.scene != null){
|
|
|
|
Table table = (Table)Core.scene.find("inputTable");
|
|
|
|
if(table != null){
|
|
|
|
table.clear();
|
|
|
|
}
|
|
|
|
}
|
2019-10-06 16:56:31 -04:00
|
|
|
if(detector != null){
|
|
|
|
Core.input.removeProcessor(detector);
|
|
|
|
}
|
|
|
|
if(uiGroup != null){
|
|
|
|
uiGroup.remove();
|
|
|
|
uiGroup = null;
|
|
|
|
}
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
2019-09-21 15:35:59 -04:00
|
|
|
public void add(){
|
2019-10-06 16:56:31 -04:00
|
|
|
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
|
2019-09-21 15:35:59 -04:00
|
|
|
Core.input.addProcessor(this);
|
2019-09-21 15:54:34 -04:00
|
|
|
if(Core.scene != null){
|
|
|
|
Table table = (Table)Core.scene.find("inputTable");
|
|
|
|
if(table != null){
|
|
|
|
table.clear();
|
2019-10-06 16:56:31 -04:00
|
|
|
buildPlacementUI(table);
|
2019-09-21 15:54:34 -04:00
|
|
|
}
|
2019-10-06 16:56:31 -04:00
|
|
|
|
|
|
|
uiGroup = new WidgetGroup();
|
|
|
|
uiGroup.touchable(Touchable.childrenOnly);
|
|
|
|
uiGroup.setFillParent(true);
|
|
|
|
ui.hudGroup.addChild(uiGroup);
|
|
|
|
buildUI(uiGroup);
|
2019-10-09 17:36:57 -04:00
|
|
|
|
|
|
|
frag.add();
|
2019-09-21 15:54:34 -04:00
|
|
|
}
|
2019-10-07 20:26:08 -04:00
|
|
|
|
|
|
|
if(player != null){
|
|
|
|
player.isBuilding = true;
|
|
|
|
}
|
2019-09-21 15:35:59 -04:00
|
|
|
}
|
|
|
|
|
2018-07-12 20:37:14 -04:00
|
|
|
public boolean canShoot(){
|
2019-01-20 13:49:53 -05:00
|
|
|
return block == null && !Core.scene.hasMouse() && !onConfigurable() && !isDroppingItem();
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean onConfigurable(){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isDroppingItem(){
|
|
|
|
return droppingItem;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void tryDropItems(Tile tile, float x, float y){
|
2019-12-29 14:38:03 -05:00
|
|
|
if(!droppingItem || player.item().amount <= 0 || canTapPlayer(x, y) || state.isPaused() ){
|
2018-07-12 20:37:14 -04:00
|
|
|
droppingItem = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
droppingItem = false;
|
|
|
|
|
2019-02-02 15:53:35 -05:00
|
|
|
ItemStack stack = player.item();
|
2018-07-12 20:37:14 -04:00
|
|
|
|
2019-09-10 20:53:31 -04:00
|
|
|
if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0 && tile.interactable(player.getTeam()) && tile.block().hasItems && player.item().amount > 0 && !player.isTransferring && tile.interactable(player.getTeam())){
|
2018-07-26 15:24:48 -04:00
|
|
|
Call.transferInventory(player, tile);
|
2018-07-12 20:37:14 -04:00
|
|
|
}else{
|
2018-07-26 15:24:48 -04:00
|
|
|
Call.dropItem(player.angleTo(x, y));
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void tryPlaceBlock(int x, int y){
|
2019-03-24 19:58:51 -04:00
|
|
|
if(block != null && validPlace(x, y, block, rotation)){
|
2019-01-20 13:49:53 -05:00
|
|
|
placeBlock(x, y, block, rotation);
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void tryBreakBlock(int x, int y){
|
2019-03-24 19:58:51 -04:00
|
|
|
if(validBreak(x, y)){
|
2018-07-12 20:37:14 -04:00
|
|
|
breakBlock(x, y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean validPlace(int x, int y, Block type, int rotation){
|
2019-10-06 16:56:31 -04:00
|
|
|
return validPlace(x, y, type, rotation, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean validPlace(int x, int y, Block type, int rotation, BuildRequest ignore){
|
|
|
|
for(BuildRequest req : player.buildQueue()){
|
2019-10-18 23:23:23 +02:00
|
|
|
if(req != ignore
|
|
|
|
&& !req.breaking
|
|
|
|
&& req.block.bounds(req.x, req.y, Tmp.r1).overlaps(type.bounds(x, y, Tmp.r2))
|
2019-11-02 09:40:41 -04:00
|
|
|
&& !(type.canReplace(req.block) && Tmp.r1.equals(Tmp.r2))){
|
2019-10-06 16:56:31 -04:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2019-03-24 19:58:51 -04:00
|
|
|
return Build.validPlace(player.getTeam(), x, y, type, rotation);
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public boolean validBreak(int x, int y){
|
2019-07-14 12:54:24 -04:00
|
|
|
return Build.validBreak(player.getTeam(), x, y);
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
2019-01-20 13:49:53 -05:00
|
|
|
public void placeBlock(int x, int y, Block block, int rotation){
|
2019-10-18 23:23:23 +02:00
|
|
|
BuildRequest req = getRequest(x, y);
|
|
|
|
if(req != null){
|
|
|
|
player.buildQueue().remove(req);
|
|
|
|
}
|
2019-01-20 13:49:53 -05:00
|
|
|
player.addBuildRequest(new BuildRequest(x, y, rotation, block));
|
2018-07-12 20:37:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
public void breakBlock(int x, int y){
|
2019-05-05 19:05:46 -04:00
|
|
|
Tile tile = world.ltile(x, y);
|
2018-07-12 20:37:14 -04:00
|
|
|
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
|
|
|
}
|
2018-06-09 23:23:14 -04:00
|
|
|
|
2019-09-29 19:54:52 -04:00
|
|
|
public void drawArrow(Block block, int x, int y, int rotation){
|
|
|
|
drawArrow(block, x, y, rotation, validPlace(x, y, block, rotation));
|
|
|
|
}
|
|
|
|
|
|
|
|
public void drawArrow(Block block, int x, int y, int rotation, boolean valid){
|
|
|
|
Draw.color(!valid ? Pal.removeBack : Pal.accentBack);
|
2019-03-19 15:26:30 -04:00
|
|
|
Draw.rect(Core.atlas.find("place-arrow"),
|
|
|
|
x * tilesize + block.offset(),
|
|
|
|
y * tilesize + block.offset() - 1,
|
|
|
|
Core.atlas.find("place-arrow").getWidth() * Draw.scl,
|
|
|
|
Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90);
|
|
|
|
|
2019-09-29 19:54:52 -04:00
|
|
|
Draw.color(!valid ? Pal.remove : Pal.accent);
|
2019-03-19 15:26:30 -04:00
|
|
|
Draw.rect(Core.atlas.find("place-arrow"),
|
|
|
|
x * tilesize + block.offset(),
|
|
|
|
y * tilesize + block.offset(),
|
|
|
|
Core.atlas.find("place-arrow").getWidth() * Draw.scl,
|
|
|
|
Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90);
|
|
|
|
}
|
|
|
|
|
2019-10-29 15:57:25 -04:00
|
|
|
void iterateLine(int startX, int startY, int endX, int endY, Cons<PlaceLine> cons){
|
2019-03-19 15:26:30 -04:00
|
|
|
Array<Point2> points;
|
|
|
|
boolean diagonal = Core.input.keyDown(Binding.diagonal_placement);
|
2019-11-08 18:28:49 +01:00
|
|
|
|
2019-11-02 10:49:21 -04:00
|
|
|
if(Core.settings.getBool("swapdiagonal") && mobile){
|
2019-03-19 15:26:30 -04:00
|
|
|
diagonal = !diagonal;
|
|
|
|
}
|
|
|
|
|
2019-11-08 18:28:49 +01:00
|
|
|
if(block instanceof PowerNode){
|
|
|
|
diagonal = !diagonal;
|
|
|
|
}
|
|
|
|
|
2019-03-19 15:26:30 -04:00
|
|
|
if(diagonal){
|
2019-11-02 14:09:16 -04:00
|
|
|
points = Placement.pathfindLine(block != null && block.conveyorPlacement, startX, startY, endX, endY);
|
2019-03-19 15:26:30 -04:00
|
|
|
}else{
|
2019-11-02 14:09:16 -04:00
|
|
|
points = Placement.normalizeLine(startX, startY, endX, endY);
|
2019-03-19 15:26:30 -04:00
|
|
|
}
|
|
|
|
|
2019-11-08 18:28:49 +01:00
|
|
|
if(block instanceof PowerNode){
|
|
|
|
Array<Point2> skip = new Array<>();
|
|
|
|
|
|
|
|
for(int i = 1; i < points.size; i++){
|
|
|
|
int overlaps = 0;
|
2019-11-08 13:04:24 -05:00
|
|
|
Point2 point = points.get(i);
|
2019-11-08 18:28:49 +01:00
|
|
|
|
2019-11-08 13:04:24 -05:00
|
|
|
//check with how many powernodes the *next* tile will overlap
|
|
|
|
for(int j = 0; j < i; j++){
|
|
|
|
if(!skip.contains(points.get(j)) && ((PowerNode)block).overlaps(world.ltile(point.x, point.y), world.ltile(points.get(j).x, points.get(j).y))){
|
2019-11-08 18:28:49 +01:00
|
|
|
overlaps++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-08 13:04:24 -05:00
|
|
|
//if it's more than one, it can bridge the gap
|
2019-11-08 18:28:49 +01:00
|
|
|
if(overlaps > 1){
|
|
|
|
skip.add(points.get(i-1));
|
|
|
|
}
|
|
|
|
}
|
2019-11-08 13:04:24 -05:00
|
|
|
//remove skipped points
|
2019-11-08 18:28:49 +01:00
|
|
|
points.removeAll(skip);
|
|
|
|
}
|
|
|
|
|
2019-03-19 15:26:30 -04:00
|
|
|
float angle = Angles.angle(startX, startY, endX, endY);
|
2019-09-21 15:03:05 -07:00
|
|
|
int baseRotation = rotation;
|
2019-10-06 17:30:11 -04:00
|
|
|
if(!overrideLineRotation || diagonal){
|
2019-10-06 23:03:02 -04:00
|
|
|
baseRotation = (startX == endX && startY == endY) ? rotation : ((int)((angle + 45) / 90f)) % 4;
|
2019-09-21 15:03:05 -07:00
|
|
|
}
|
2019-03-19 15:26:30 -04:00
|
|
|
|
2019-03-19 19:25:48 -04:00
|
|
|
Tmp.r3.set(-1, -1, 0, 0);
|
|
|
|
|
2019-03-19 15:26:30 -04:00
|
|
|
for(int i = 0; i < points.size; i++){
|
|
|
|
Point2 point = points.get(i);
|
2019-03-19 19:25:48 -04:00
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
if(block != null && Tmp.r2.setSize(block.size * tilesize).setCenter(point.x * tilesize + block.offset(), point.y * tilesize + block.offset()).overlaps(Tmp.r3)){
|
2019-03-19 19:25:48 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2019-03-19 15:26:30 -04:00
|
|
|
Point2 next = i == points.size - 1 ? null : points.get(i + 1);
|
|
|
|
line.x = point.x;
|
|
|
|
line.y = point.y;
|
2019-10-06 17:30:11 -04:00
|
|
|
if(!overrideLineRotation || diagonal){
|
2019-09-21 15:03:05 -07:00
|
|
|
line.rotation = next != null ? Tile.relativeTo(point.x, point.y, next.x, next.y) : baseRotation;
|
|
|
|
}else{
|
|
|
|
line.rotation = rotation;
|
|
|
|
}
|
2019-03-19 15:26:30 -04:00
|
|
|
line.last = next == null;
|
2019-10-29 15:57:25 -04:00
|
|
|
cons.get(line);
|
2019-03-19 19:25:48 -04:00
|
|
|
|
2019-04-08 09:03:18 -04:00
|
|
|
Tmp.r3.setSize(block.size * tilesize).setCenter(point.x * tilesize + block.offset(), point.y * tilesize + block.offset());
|
2019-03-19 15:26:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class PlaceLine{
|
|
|
|
public int x, y, rotation;
|
|
|
|
public boolean last;
|
2019-03-19 11:46:00 -04:00
|
|
|
}
|
2017-12-13 23:28:20 -05:00
|
|
|
}
|