Functional desktop schematic placement

This commit is contained in:
Anuken 2019-10-18 00:41:30 -04:00
parent 61d15782d0
commit 30bcfb6d5e
13 changed files with 116 additions and 51 deletions

View File

@ -104,7 +104,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
if(current.breaking){
entity.deconstruct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier);
}else{
if(entity.construct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier)){
if(entity.construct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier, current.hasConfig)){
if(current.hasConfig){
Call.onTileConfig(null, tile, current.config);
}
@ -267,18 +267,26 @@ public interface BuilderTrait extends Entity, TeamTrait{
/** Class for storing build requests. Can be either a place or remove request. */
class BuildRequest{
/** Position and rotation of this request. */
public int x, y, rotation;
/** Block being placed. If null, this is a breaking request.*/
public @Nullable Block block;
/** Whether this is a break request.*/
public boolean breaking;
/** Whether this request comes with a config int. If yes, any blocks placed with this request will not call playerPlaced.*/
public boolean hasConfig;
/** Config int. Not used unless hasConfig is true.*/
public int config;
/** Original position, only used in schematics.*/
public int originalX, originalY;
/** Last progress.*/
public float progress;
/** Whether construction has started for this request.*/
public boolean initialized;
//animation variables
/** Visual scale. Used only for rendering.*/
public float animScale = 0f;
public float animInvalid;
/** This creates a build request. */
public BuildRequest(int x, int y, int rotation, Block block){
@ -302,6 +310,29 @@ public interface BuilderTrait extends Entity, TeamTrait{
}
public BuildRequest copy(){
BuildRequest copy = new BuildRequest();
copy.x = x;
copy.y = y;
copy.rotation = rotation;
copy.block = block;
copy.breaking = breaking;
copy.hasConfig = hasConfig;
copy.config = config;
copy.originalX = originalX;
copy.originalY = originalY;
copy.progress = progress;
copy.initialized = initialized;
copy.animScale = animScale;
return copy;
}
public BuildRequest original(int x, int y){
originalX = x;
originalY = y;
return this;
}
public Rectangle bounds(Rectangle rect){
if(breaking){
return rect.set(-100f, -100f, 0f, 0f);

View File

@ -1,5 +1,6 @@
package io.anuke.mindustry.entities.type;
import io.anuke.mindustry.*;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.traits.Entity;
@ -14,6 +15,14 @@ public abstract class BaseEntity implements Entity{
id = lastid++;
}
public int tileX(){
return Vars.world.toTile(x);
}
public int tileY(){
return Vars.world.toTile(y);
}
@Override
public int getID(){
return id;

View File

@ -236,11 +236,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
return 0;
}
/** @return whether the config is a position that should be translated.*/
public boolean posConfig(){
return false;
}
@Override
public void removed(){
if(sound != null){

View File

@ -145,7 +145,7 @@ public class Schematics implements Loadable{
/** Creates an array of build requests from a schematic's data, centered on the provided x+y coordinates. */
public Array<BuildRequest> toRequests(Schematic schem, int x, int y){
return schem.tiles.map(t -> new BuildRequest(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block).configure(t.config));
return schem.tiles.map(t -> new BuildRequest(t.x + x - schem.width/2, t.y + y - schem.height/2, t.rotation, t.block).original(t.x, t.y).configure(t.config));
}
/** Adds a schematic to the list, also copying it into the files.*/
@ -209,7 +209,7 @@ public class Schematics implements Loadable{
if(tile != null && tile.entity != null){
int config = tile.entity.config();
if(tile.entity.posConfig()){
if(tile.block().posConfig){
config = Pos.get(Pos.x(config) + offsetX, Pos.y(config) + offsetY);
}
@ -240,7 +240,11 @@ public class Schematics implements Loadable{
//region IO methods
public static Schematic read(FileHandle file) throws IOException{
return read(new DataInputStream(file.read(1024)));
Schematic s = read(new DataInputStream(file.read(1024)));
if(!s.tags.containsKey("name")){
s.tags.put("name", file.nameWithoutExtension());
}
return s;
}
public static Schematic read(InputStream input) throws IOException{
@ -271,8 +275,6 @@ public class Schematics implements Loadable{
blocks.put(i, block == null ? Blocks.air : block);
}
Log.info(blocks);
int total = stream.readInt();
Array<Stile> tiles = new Array<>(total);
for(int i = 0; i < total; i++){

View File

@ -3,7 +3,6 @@ package io.anuke.mindustry.input;
import io.anuke.arc.*;
import io.anuke.arc.Graphics.*;
import io.anuke.arc.Graphics.Cursor.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.input.*;
import io.anuke.arc.math.*;
@ -14,7 +13,6 @@ import io.anuke.mindustry.core.GameState.*;
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Schematics.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.ui.*;
@ -30,7 +28,7 @@ public class DesktopInput extends InputHandler{
/** Position where the player started dragging a line. */
private int selectX, selectY, schemX, schemY;
/** Last known line positions.*/
private int lastLineX, lastLineY;
private int lastLineX, lastLineY, schematicX, schematicY;
/** Whether selecting mode is active. */
private PlaceMode mode;
/** Animation scale for line. */
@ -40,8 +38,6 @@ public class DesktopInput extends InputHandler{
/** Whether player is currently deleting removal requests. */
private boolean deleting = false;
private Schematic __REMOVE__;
@Override
public void buildUI(Group group){
group.fill(t -> {
@ -89,6 +85,12 @@ public class DesktopInput extends InputHandler{
}
}
//draw schematic requests
for(BuildRequest request : selectRequests){
request.animScale = 1f;
drawRequest(request);
}
if(sreq != null){
boolean valid = validPlace(sreq.x, sreq.y, sreq.block, sreq.rotation, sreq);
if(sreq.block.rotate){
@ -108,13 +110,6 @@ public class DesktopInput extends InputHandler{
}
Draw.reset();
if(__REMOVE__ != null){
Texture tex = schematics.getPreview(__REMOVE__, PreviewRes.low);
Draw.blend(Blending.disabled);
Draw.rect(Draw.wrap(tex), Core.camera.position.x, Core.camera.position.y, tex.getWidth() / 4f, tex.getHeight() / 4f);
Draw.blend();
}
}
@Override
@ -154,6 +149,10 @@ public class DesktopInput extends InputHandler{
mode = none;
}
if(mode != none){
selectRequests.clear();
}
if(player.isShooting && !canShoot()){
player.isShooting = false;
}
@ -182,7 +181,7 @@ public class DesktopInput extends InputHandler{
cursorType = cursor.block().getCursor(cursor);
if(isPlacing()){
if(isPlacing() || !selectRequests.isEmpty()){
cursorType = SystemCursor.hand;
}
@ -210,6 +209,16 @@ public class DesktopInput extends InputHandler{
cursorType = SystemCursor.arrow;
}
@Override
public void useSchematic(Schematic schem){
block = null;
schematicX = tileX(getMouseX());
schematicY = tileY(getMouseY());
selectRequests.addAll(schematics.toRequests(schem, schematicX, schematicY));
mode = none;
}
@Override
public boolean isBreaking(){
return mode == breaking;
@ -221,6 +230,18 @@ public class DesktopInput extends InputHandler{
int cursorY = tileY(Core.input.mouseY());
int rawCursorX = world.toTile(Core.input.mouseWorld().x), rawCursorY = world.toTile(Core.input.mouseWorld().y);
if(!selectRequests.isEmpty()){
int shiftX = rawCursorX - schematicX, shiftY = rawCursorY - schematicY;
selectRequests.each(s -> {
s.x += shiftX;
s.y += shiftY;
});
schematicX += shiftX;
schematicY += shiftY;
}
if(Core.input.keyTap(Binding.deselect)){
player.setMineTile(null);
}
@ -236,12 +257,12 @@ public class DesktopInput extends InputHandler{
if(Core.input.keyRelease(Binding.schematic)){
Schematic schem = schematics.create(schemX, schemY, rawCursorX, rawCursorY);
__REMOVE__ = schem;
schematics.add(schem);
useSchematic(schem);
}
//TODO remove
if(Core.input.keyTap(KeyCode.T)){
if(Core.input.keyTap(KeyCode.V)){
ui.schematics.show();
}
@ -270,7 +291,10 @@ public class DesktopInput extends InputHandler{
if(Core.input.keyTap(Binding.select) && !Core.scene.hasMouse()){
BuildRequest req = getRequest(cursorX, cursorY);
if(isPlacing()){
if(!selectRequests.isEmpty()){
flushRequests(selectRequests);
//selectRequests.clear();
}else if(isPlacing()){
selectX = cursorX;
selectY = cursorY;
lastLineX = cursorX;
@ -366,6 +390,7 @@ public class DesktopInput extends InputHandler{
mode = none;
block = null;
sreq = null;
selectRequests.clear();
}
}
}

View File

@ -19,6 +19,7 @@ import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.traits.BuilderTrait.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.Teams.*;
import io.anuke.mindustry.gen.*;
@ -219,6 +220,10 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
drawSelected(x, y, block, Pal.remove);
}
public void useSchematic(Schematic schem){
selectRequests.addAll(schematics.toRequests(schem, world.toTile(player.x), world.toTile(player.y)));
}
/** Returns the selection request that overlaps this position, or null. */
protected BuildRequest getRequest(int x, int y){
return getRequest(x, y, 1, null);
@ -310,7 +315,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
protected void flushSelectRequests(Array<BuildRequest> requests){
for(BuildRequest req : requests){
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
selectRequests.add(req);
selectRequests.add(req.copy());
}
}
}
@ -318,7 +323,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
protected void flushRequests(Array<BuildRequest> requests){
for(BuildRequest req : requests){
if(req.block != null && validPlace(req.x, req.y, req.block, req.rotation)){
player.addBuildRequest(req);
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);
}
}
}

View File

@ -243,7 +243,6 @@ public class MobileInput extends InputHandler implements GestureListener{
if(tile == null) continue;
request.animScale = Mathf.lerpDelta(request.animScale, 0f, 0.2f);
request.animInvalid = Mathf.lerpDelta(request.animInvalid, 0f, 0.2f);
if(request.breaking){
drawSelected(request.x, request.y, tile.block(), Pal.remove);
@ -263,10 +262,8 @@ public class MobileInput extends InputHandler implements GestureListener{
if((!request.breaking && validPlace(tile.x, tile.y, request.block, request.rotation))
|| (request.breaking && validBreak(tile.x, tile.y))){
request.animScale = Mathf.lerpDelta(request.animScale, 1f, 0.2f);
request.animInvalid = Mathf.lerpDelta(request.animInvalid, 0f, 0.2f);
}else{
request.animScale = Mathf.lerpDelta(request.animScale, 0.6f, 0.1f);
request.animInvalid = Mathf.lerpDelta(request.animInvalid, 0.9f, 0.2f);
}
Tmp.c1.set(Draw.getMixColor());

View File

@ -8,7 +8,7 @@ import io.anuke.mindustry.game.Schematics.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.ui.*;
import static io.anuke.mindustry.Vars.schematics;
import static io.anuke.mindustry.Vars.*;
public class SchematicsDialog extends FloatingDialog{
@ -40,7 +40,8 @@ public class SchematicsDialog extends FloatingDialog{
}
}.setScaling(Scaling.fit).setName("border"));
}, () -> {
control.input.useSchematic(s);
hide();
}).size(200f, 230f).pad(2).style(Styles.clearPartiali).get();
BorderImage image = sel.find("border");

View File

@ -87,6 +87,8 @@ public class Block extends BlockStorage{
public boolean configurable;
/** Whether this block consumes touchDown events when tapped. */
public boolean consumesTap;
/** Whether the config is positional and needs to be shifted. */
public boolean posConfig;
/**
* The color of this block when displayed on the minimap or map preview.
* Do not set manually! This is overriden when loading for most blocks.

View File

@ -56,7 +56,7 @@ public class BuildBlock extends Block{
}
@Remote(called = Loc.server)
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team){
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
if(tile == null) return;
float healthf = tile.entity == null ? 1f : tile.entity.healthf();
world.setBlock(tile, block, team, rotation);
@ -70,8 +70,10 @@ public class BuildBlock extends Block{
if(!headless && builderID == player.id){
//this is run delayed, since if this is called on the server, all clients need to recieve the onBuildFinish()
//event first before they can recieve the placed() event modification results
if(!skipConfig){
Core.app.post(() -> tile.block().playerPlaced(tile));
}
}
Core.app.post(() -> Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, false)));
Sounds.place.at(tile, Mathf.random(0.7f, 1.4f));
}
@ -185,7 +187,7 @@ public class BuildBlock extends Block{
private float[] accumulator;
private float[] totalAccumulator;
public boolean construct(Unit builder, @Nullable TileEntity core, float amount){
public boolean construct(Unit builder, @Nullable TileEntity core, float amount, boolean configured){
if(cblock == null){
kill();
return false;
@ -208,7 +210,7 @@ public class BuildBlock extends Block{
}
if(progress >= 1f || state.rules.infiniteResources){
Call.onConstructFinish(tile, cblock, builderID, tile.rotation(), builder.getTeam());
Call.onConstructFinish(tile, cblock, builderID, tile.rotation(), builder.getTeam(), configured);
return true;
}
return false;

View File

@ -37,6 +37,7 @@ public class ItemBridge extends Block{
layer = Layer.power;
expanded = true;
itemCapacity = 10;
posConfig = true;
configurable = true;
hasItems = true;
unloadable = false;
@ -385,11 +386,6 @@ public class ItemBridge extends Block{
return link;
}
@Override
public boolean posConfig(){
return true;
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -36,6 +36,7 @@ public class MassDriver extends Block{
super(name);
update = true;
solid = true;
posConfig = true;
configurable = true;
hasItems = true;
layer = Layer.turret;
@ -319,11 +320,6 @@ public class MassDriver extends Block{
return link;
}
@Override
public boolean posConfig(){
return true;
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -1,3 +1,3 @@
org.gradle.daemon=true
org.gradle.jvmargs=-Xms256m -Xmx1024m
archash=7f4239e462c07fb3d76a18262cff91dd877df5cc
archash=795ded7ccae9aeb15ee480e3b9f6d6af57148ea0