mirror of
https://github.com/Anuken/Mindustry.git
synced 2025-01-03 13:30:25 +07:00
Fixed player dupes, new breaking system, multiplayer block edits
This commit is contained in:
parent
d5a58be440
commit
aca1001f9a
@ -156,7 +156,7 @@ public class RemoteWriteGenerator {
|
||||
String capName = typeName.equals("byte") ? "" : Character.toUpperCase(typeName.charAt(0)) + typeName.substring(1);
|
||||
//special case: method can be called from anywhere to anywhere
|
||||
//thus, only write the player when the SERVER is writing data, since the client is the only one who reads it
|
||||
boolean writePlayerSkipCheck = methodEntry.where == Loc.both && methodEntry.local == Loc.both && i == 0;
|
||||
boolean writePlayerSkipCheck = methodEntry.where == Loc.both && i == 0;
|
||||
|
||||
if(writePlayerSkipCheck){ //write begin check
|
||||
method.beginControlFlow("if(io.anuke.mindustry.net.Net.server())");
|
||||
|
@ -150,7 +150,7 @@ public class Vars{
|
||||
effectGroup = Entities.addGroup(EffectEntity.class, false);
|
||||
groundEffectGroup = Entities.addGroup(DrawTrait.class, false);
|
||||
puddleGroup = Entities.addGroup(Puddle.class, false);
|
||||
itemGroup = Entities.addGroup(ItemDrop.class);
|
||||
itemGroup = Entities.addGroup(ItemDrop.class).enableMapping();
|
||||
fireGroup = Entities.addGroup(Fire.class, false);
|
||||
unitGroups = new EntityGroup[Team.values().length];
|
||||
|
||||
|
@ -12,7 +12,7 @@ import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.*;
|
||||
|
||||
public class Blocks extends BlockList implements ContentList{
|
||||
public static Block air, spawn, blockpart, build1, build2, build3, build4, build5, build6, defaultFloor, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, iron, lead, coal, titanium, thorium, dirt, sand, ice, snow, grass, sandblock, snowblock, stoneblock, blackstoneblock, grassblock, mossblock, shrub, rock, icerock, blackrock, dirtblock;
|
||||
public static Block air, spawn, blockpart, defaultFloor, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, iron, lead, coal, titanium, thorium, dirt, sand, ice, snow, grass, sandblock, snowblock, stoneblock, blackstoneblock, grassblock, mossblock, shrub, rock, icerock, blackrock, dirtblock;
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
@ -23,17 +23,10 @@ public class Blocks extends BlockList implements ContentList{
|
||||
|
||||
blockpart = new BlockPart();
|
||||
|
||||
build1 = new BuildBlock("build1");
|
||||
|
||||
build2 = new BuildBlock("build2");
|
||||
|
||||
build3 = new BuildBlock("build3");
|
||||
|
||||
build4 = new BuildBlock("build4");
|
||||
|
||||
build5 = new BuildBlock("build5");
|
||||
|
||||
build6 = new BuildBlock("build6");
|
||||
for(int i = 1; i <= 6; i ++){
|
||||
new BuildBlock("build" + i);
|
||||
new BreakBlock("break" + i);
|
||||
}
|
||||
|
||||
defaultFloor = new Floor("defaultfloor");
|
||||
|
||||
|
@ -160,7 +160,6 @@ public class NetClient extends Module {
|
||||
void sync(){
|
||||
|
||||
if(timer.get(0, playerSyncTime)){
|
||||
Player player = players[0];
|
||||
|
||||
ClientSnapshotPacket packet = Pools.obtain(ClientSnapshotPacket.class);
|
||||
packet.lastSnapshot = lastSnapshotID;
|
||||
@ -211,6 +210,12 @@ public class NetClient extends Module {
|
||||
|
||||
//get data input for reading from the stream
|
||||
DataInputStream input = netClient.dataStream;
|
||||
|
||||
byte cores = input.readByte();
|
||||
for (int i = 0; i < cores; i++) {
|
||||
int pos = input.readInt();
|
||||
world.tile(pos).entity.items.read(input);
|
||||
}
|
||||
|
||||
byte totalGroups = input.readByte();
|
||||
//for each group...
|
||||
|
@ -1,5 +1,6 @@
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Base64Coder;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
@ -15,6 +16,7 @@ import io.anuke.mindustry.io.Version;
|
||||
import io.anuke.mindustry.net.*;
|
||||
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||
import io.anuke.mindustry.net.Packets.*;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
@ -136,7 +138,7 @@ public class NetServer extends Module{
|
||||
});
|
||||
|
||||
//update last recieved snapshot based on client snapshot
|
||||
Net.handleServer(ClientSnapshotPacket.class, (id, packet) ->{
|
||||
Net.handleServer(ClientSnapshotPacket.class, (id, packet) -> {
|
||||
Player player = connections.get(id);
|
||||
NetConnection connection = Net.getConnection(id);
|
||||
if(player == null || connection == null || packet.snapid < connection.lastRecievedSnapshot) return;
|
||||
@ -231,6 +233,16 @@ public class NetServer extends Module{
|
||||
if (!group.isEmpty() && (group.all().get(0) instanceof SyncTrait)) totalGroups ++;
|
||||
}
|
||||
|
||||
Array<Tile> cores = state.teams.get(player.getTeam()).cores;
|
||||
|
||||
dataStream.writeByte(cores.size);
|
||||
|
||||
//write all core inventory data
|
||||
for(Tile tile : cores){
|
||||
dataStream.writeInt(tile.packedPosition());
|
||||
tile.entity.items.write(dataStream);
|
||||
}
|
||||
|
||||
//write total amount of serializable groups
|
||||
dataStream.writeByte(totalGroups);
|
||||
|
||||
@ -244,20 +256,13 @@ public class NetServer extends Module{
|
||||
throw new RuntimeException("Entity group '" + group.getType() + "' contains SyncTrait entities, yet mapping is not enabled. In order for syncing to work, you must enable mapping for this group.");
|
||||
}
|
||||
|
||||
int size = group.size();
|
||||
|
||||
if(group.getType() == Player.class){
|
||||
size --;
|
||||
}
|
||||
|
||||
//write group ID + group size
|
||||
dataStream.writeByte(group.getID());
|
||||
dataStream.writeShort(size);
|
||||
dataStream.writeShort(group.size());
|
||||
//write timestamp
|
||||
dataStream.writeLong(TimeUtils.millis());
|
||||
|
||||
for(Entity entity : group.all()){
|
||||
if(entity == player) continue;
|
||||
//write all entities now
|
||||
dataStream.writeInt(entity.getID());
|
||||
((SyncTrait)entity).write(dataStream);
|
||||
|
@ -2,7 +2,6 @@ package io.anuke.mindustry.entities;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Pools;
|
||||
@ -23,6 +22,7 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Trail;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
import io.anuke.mindustry.world.blocks.storage.CoreBlock.CoreEntity;
|
||||
@ -30,9 +30,11 @@ import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.entities.trait.SolidTrait;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Fill;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.ThreadQueue;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@ -57,7 +59,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
|
||||
public String name = "name";
|
||||
public String uuid;
|
||||
public boolean isAdmin;
|
||||
public boolean isAdmin, isTransferring;
|
||||
public Color color = new Color();
|
||||
|
||||
public Array<Upgrade> upgrades = new Array<>();
|
||||
@ -342,28 +344,16 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
for (BuildRequest request : getPlaceQueue()) {
|
||||
|
||||
if(request.remove){
|
||||
Block block = world.tile(request.x, request.y).target().block();
|
||||
|
||||
//draw removal request
|
||||
Draw.color(Palette.remove);
|
||||
Draw.alpha(0.4f);
|
||||
Lines.stroke(1f);
|
||||
Draw.color(Palette.remove);
|
||||
|
||||
float progress = request.progress;
|
||||
Tile tile = world.tile(request.x, request.y);
|
||||
float size = tile.block().size * tilesize/2f;
|
||||
float ss = -(progress*2f-1f);
|
||||
Lines.stroke((1f-request.progress));
|
||||
|
||||
for(int i = 0; i < 4; i ++){
|
||||
GridPoint2 p = Geometry.d8edge(i);
|
||||
|
||||
Fill.tri(tile.drawx() + size*p.x, tile.drawy() + size * p.y,
|
||||
tile.drawx() + size*p.x*ss, tile.drawy() + size * p.y,
|
||||
tile.drawx() + size*p.x, tile.drawy() + size * p.y*ss);
|
||||
}
|
||||
|
||||
Draw.alpha(1f);
|
||||
|
||||
Lines.poly(tile.drawx(), tile.drawy(),
|
||||
4, tile.block().size * tilesize /2f * (1f-progress) + Mathf.absin(Timers.time(), 3f, 1f));
|
||||
Lines.poly(request.x * tilesize + block.offset(),
|
||||
request.y * tilesize + block.offset(),
|
||||
4, block.size * tilesize /2f, 45 + 15);
|
||||
}else{
|
||||
//draw place request
|
||||
Draw.color(Palette.accent);
|
||||
@ -398,6 +388,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
|
||||
if(!isLocal){
|
||||
interpolate();
|
||||
updateBuilding(this); //building happens even with non-locals
|
||||
return;
|
||||
}
|
||||
|
||||
@ -651,6 +642,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait {
|
||||
mech = Upgrade.getByID(buffer.readByte());
|
||||
interpolator.read(lastx, lasty, x, y, time, rotation);
|
||||
rotation = lastrot;
|
||||
|
||||
if(isLocal){
|
||||
x = lastx;
|
||||
y = lasty;
|
||||
}
|
||||
}
|
||||
|
||||
//endregion
|
||||
|
@ -1,10 +1,14 @@
|
||||
package io.anuke.mindustry.entities;
|
||||
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.gen.CallBlocks;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Wall;
|
||||
@ -92,7 +96,7 @@ public class TileEntity extends BaseEntity implements TargetTrait {
|
||||
public void write(DataOutputStream stream) throws IOException{}
|
||||
public void read(DataInputStream stream) throws IOException{}
|
||||
|
||||
public void onDeath(){
|
||||
private void onDeath(){
|
||||
if(!dead) {
|
||||
dead = true;
|
||||
Block block = tile.block();
|
||||
@ -102,7 +106,6 @@ public class TileEntity extends BaseEntity implements TargetTrait {
|
||||
block.afterDestroyed(tile, this);
|
||||
remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean collide(Bullet other){
|
||||
@ -115,10 +118,12 @@ public class TileEntity extends BaseEntity implements TargetTrait {
|
||||
|
||||
public void damage(float damage){
|
||||
if(dead) return;
|
||||
|
||||
float amount = tile.block().handleDamage(tile, damage);
|
||||
health -= amount;
|
||||
if(health <= 0) onDeath();
|
||||
|
||||
CallBlocks.onTileDamage(tile, health - tile.block().handleDamage(tile, damage));
|
||||
|
||||
if(health <= 0){
|
||||
CallBlocks.onTileDestroyed(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -153,4 +158,14 @@ public class TileEntity extends BaseEntity implements TargetTrait {
|
||||
public EntityGroup targetGroup() {
|
||||
return tileGroup;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.blocks)
|
||||
public static void onTileDamage(Tile tile, float health){
|
||||
tile.entity.health = health;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.blocks)
|
||||
public static void onTileDestroyed(Tile tile){
|
||||
tile.entity.onDeath();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package io.anuke.mindustry.entities;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.content.Items;
|
||||
import io.anuke.mindustry.type.AmmoEntry;
|
||||
import io.anuke.mindustry.type.AmmoType;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
@ -11,7 +12,7 @@ import java.io.*;
|
||||
public class UnitInventory {
|
||||
private Array<AmmoEntry> ammos = new Array<>();
|
||||
private int totalAmmo;
|
||||
private ItemStack item;
|
||||
private ItemStack item = new ItemStack(Items.stone, 0);
|
||||
//TODO move these somewhere else so they're not variables?
|
||||
private int capacity, ammoCapacity;
|
||||
private boolean infiniteAmmo;
|
||||
@ -30,32 +31,31 @@ public class UnitInventory {
|
||||
}
|
||||
|
||||
public void write(DataOutput stream) throws IOException {
|
||||
stream.writeInt(item == null ? 0 : item.amount);
|
||||
stream.writeByte(item == null ? 0 : item.item.id);
|
||||
stream.writeShort(item.amount);
|
||||
stream.writeByte(item.item.id);
|
||||
stream.writeBoolean(infiniteAmmo);
|
||||
stream.writeInt(totalAmmo);
|
||||
stream.writeShort(totalAmmo);
|
||||
stream.writeByte(ammos.size);
|
||||
for(int i = 0; i < ammos.size; i ++){
|
||||
stream.writeByte(ammos.get(i).type.id);
|
||||
stream.writeInt(ammos.get(i).amount);
|
||||
stream.writeShort(ammos.get(i).amount);
|
||||
}
|
||||
}
|
||||
|
||||
public void read(DataInput stream) throws IOException {
|
||||
int iamount = stream.readInt();
|
||||
short iamount = stream.readShort();
|
||||
byte iid = stream.readByte();
|
||||
infiniteAmmo = stream.readBoolean();
|
||||
this.totalAmmo = stream.readInt();
|
||||
this.totalAmmo = stream.readShort();
|
||||
byte ammoa = stream.readByte();
|
||||
for(int i = 0; i < ammoa; i ++){
|
||||
byte aid = stream.readByte();
|
||||
int am = stream.readInt();
|
||||
int am = stream.readShort();
|
||||
ammos.add(new AmmoEntry(AmmoType.getByID(aid), am));
|
||||
}
|
||||
|
||||
if(iamount != 0){
|
||||
item = new ItemStack(Item.getByID(iid), iamount);
|
||||
}
|
||||
item.item = Item.getByID(iid);
|
||||
item.amount = iamount;
|
||||
}
|
||||
|
||||
/**Returns ammo range, or MAX_VALUE if this inventory has no ammo.*/
|
||||
@ -116,7 +116,7 @@ public class UnitInventory {
|
||||
}
|
||||
|
||||
public boolean isEmpty(){
|
||||
return item == null;
|
||||
return item.amount == 0;
|
||||
}
|
||||
|
||||
public int itemCapacityUsed(Item type){
|
||||
@ -136,30 +136,29 @@ public class UnitInventory {
|
||||
}
|
||||
|
||||
public void clear(){
|
||||
item = null;
|
||||
item.amount = 0;
|
||||
ammos.clear();
|
||||
totalAmmo = 0;
|
||||
}
|
||||
|
||||
public void clearItem(){
|
||||
item = null;
|
||||
item.amount = 0;
|
||||
}
|
||||
|
||||
public boolean hasItem(){
|
||||
return item != null;
|
||||
return item.amount > 0;
|
||||
}
|
||||
|
||||
public boolean hasItem(Item i, int amount){
|
||||
return item.item == i && item.amount >= amount;
|
||||
}
|
||||
|
||||
public void addItem(Item item, int amount){
|
||||
if(hasItem()){
|
||||
getItem().amount = getItem().item == item ? getItem().amount + amount : amount;
|
||||
getItem().item = item;
|
||||
}else{
|
||||
this.item = new ItemStack(item, amount);
|
||||
}
|
||||
getItem().amount = getItem().item == item ? getItem().amount + amount : amount;
|
||||
getItem().item = item;
|
||||
}
|
||||
|
||||
public ItemStack getItem(){
|
||||
if(!hasItem()) throw new RuntimeException("This inventory has no item! Check hasItem() first.");
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,12 @@ import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.Pool.Poolable;
|
||||
import com.badlogic.gdx.utils.Pools;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.gen.CallEntity;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.net.Interpolator;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
@ -24,9 +28,7 @@ import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import static io.anuke.mindustry.Vars.itemGroup;
|
||||
import static io.anuke.mindustry.Vars.itemSize;
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, VelocityTrait, TimeTrait, Poolable {
|
||||
private static final float sinkLifetime = 80f;
|
||||
@ -50,6 +52,11 @@ public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, Veloc
|
||||
return drop;
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.entities)
|
||||
public static void onPickup(int itemid){
|
||||
itemGroup.removeByID(itemid);
|
||||
}
|
||||
|
||||
/**Internal use only!*/
|
||||
public ItemDrop(){
|
||||
hitbox.setSize(5f);
|
||||
@ -86,7 +93,7 @@ public class ItemDrop extends SolidEntity implements SyncTrait, DrawTrait, Veloc
|
||||
Player player = (Player)other;
|
||||
if(player.inventory.canAcceptItem(item, amount)){
|
||||
player.inventory.addItem(item, amount);
|
||||
remove();
|
||||
CallEntity.onPickup(getID());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@ import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.Build;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BreakBlock;
|
||||
import io.anuke.mindustry.world.blocks.BreakBlock.BreakEntity;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
@ -113,6 +115,7 @@ public interface BuilderTrait {
|
||||
if(unit.distanceTo(tile) > placeDistance) { //out of range, skip it.
|
||||
getPlaceQueue().removeFirst();
|
||||
}else if(current.remove){
|
||||
/*
|
||||
if(Build.validBreak(unit.getTeam(), current.x, current.y) && current.recipe == Recipe.getByResult(tile.block())){ //if it's valid, break it
|
||||
|
||||
float progress = 1f / tile.getBreakTime() * Timers.delta() * getBuildPower(tile);
|
||||
@ -138,18 +141,43 @@ public interface BuilderTrait {
|
||||
|
||||
if(current.progress >= 1f){
|
||||
//FIXME a player instace is required here, but the the builder may not be a player
|
||||
CallBlocks.breakBlock(unit instanceof Player ? (Player)unit : null, unit.getTeam(), current.x, current.y, true, true);
|
||||
CallBlocks.breakBlock((Player)unit, unit.getTeam(), current.x, current.y, true, true);
|
||||
}
|
||||
}else{
|
||||
//otherwise, skip it
|
||||
getPlaceQueue().removeFirst();
|
||||
}*/
|
||||
|
||||
if (!(tile.block() instanceof BreakBlock)) { //check if haven't started placing
|
||||
if(Build.validBreak(unit.getTeam(), current.x, current.y)){
|
||||
//if it's valid, place it
|
||||
//FIXME a player instance is required here, but the the builder may not be a player
|
||||
CallBlocks.breakBlock((Player)unit, unit.getTeam(), current.x, current.y);
|
||||
}else{
|
||||
//otherwise, skip it
|
||||
getPlaceQueue().removeFirst();
|
||||
}
|
||||
}else{
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
//if there is no core to build with, stop building!
|
||||
if(core == null){
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise, update it.
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
entity.addProgress(core, unit, 1f / entity.breakTime * Timers.delta() * getBuildPower(tile));
|
||||
unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(entity), 0.4f);
|
||||
getCurrentRequest().progress = entity.progress();
|
||||
}
|
||||
}else{
|
||||
if (!(tile.block() instanceof BuildBlock)) { //check if haven't started placing
|
||||
if(Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){
|
||||
//if it's valid, place it
|
||||
//FIXME a player instace is required here, but the the builder may not be a player
|
||||
CallBlocks.placeBlock(unit instanceof Player ? (Player)unit : null, unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
|
||||
//FIXME a player instance is required here, but the the builder may not be a player
|
||||
CallBlocks.placeBlock((Player)unit, unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
|
||||
|
||||
//fire build event
|
||||
threads.run(() -> Events.fire(BlockBuildEvent.class, unit.getTeam(), world.tile(current.x, current.y)));
|
||||
@ -278,8 +306,6 @@ public interface BuilderTrait {
|
||||
|
||||
public float progress;
|
||||
|
||||
private float[] removeAccumulator;
|
||||
|
||||
/**This creates a build request.*/
|
||||
public BuildRequest(int x, int y, int rotation, Recipe recipe) {
|
||||
this.x = x;
|
||||
@ -296,10 +322,6 @@ public interface BuilderTrait {
|
||||
this.rotation = -1;
|
||||
this.recipe = Recipe.getByResult(world.tile(x, y).block());
|
||||
this.remove = true;
|
||||
|
||||
if(this.recipe != null){
|
||||
this.removeAccumulator = new float[recipe.requirements.length];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,11 +2,18 @@ package io.anuke.mindustry.input;
|
||||
|
||||
import com.badlogic.gdx.InputAdapter;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.blocks.Blocks;
|
||||
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.effect.ItemDrop;
|
||||
import io.anuke.mindustry.entities.effect.ItemTransfer;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.gen.CallBlocks;
|
||||
import io.anuke.mindustry.gen.CallEntity;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.ValidateException;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.ui.fragments.OverlayFragment;
|
||||
@ -26,17 +33,19 @@ import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public abstract class InputHandler extends InputAdapter{
|
||||
/**Used for dropping items.*/
|
||||
final float playerSelectRange = mobile ? 17f : 11f;
|
||||
final static float playerSelectRange = mobile ? 17f : 11f;
|
||||
/**Maximum line length.*/
|
||||
final int maxLength = 100;
|
||||
final Translator stackTrns = new Translator();
|
||||
final static int maxLength = 100;
|
||||
final static Translator stackTrns = new Translator();
|
||||
/**Distance on the back from where items originate.*/
|
||||
final static float backTrns = 3f;
|
||||
|
||||
public final Player player;
|
||||
public final OverlayFragment frag = new OverlayFragment(this);
|
||||
|
||||
public Recipe recipe;
|
||||
public int rotation;
|
||||
public boolean droppingItem, transferring;
|
||||
public boolean droppingItem;
|
||||
public boolean shooting;
|
||||
|
||||
public InputHandler(Player player){
|
||||
@ -110,9 +119,11 @@ public abstract class InputHandler extends InputAdapter{
|
||||
}
|
||||
}
|
||||
|
||||
//TODO network event!
|
||||
//call tapped event
|
||||
if(tile.getTeam() == player.getTeam() && tile.block().tapped(tile, player)){
|
||||
CallBlocks.onTileTapped(player, tile);
|
||||
|
||||
//consume tap event if necessary
|
||||
if(tile.getTeam() == player.getTeam() && tile.block().consumesTap){
|
||||
consumed = true;
|
||||
}else if(tile.getTeam() == player.getTeam() && tile.block().synthetic() && tile.block().hasItems){
|
||||
frag.inv.showFor(tile);
|
||||
@ -201,52 +212,11 @@ public abstract class InputHandler extends InputAdapter{
|
||||
|
||||
ItemStack stack = player.inventory.getItem();
|
||||
|
||||
int accepted = tile.block().acceptStack(stack.item, stack.amount, tile, player);
|
||||
|
||||
if(accepted > 0){
|
||||
if(transferring) return;
|
||||
|
||||
transferring = true;
|
||||
boolean clear = stack.amount == accepted;
|
||||
|
||||
float backTrns = 3f;
|
||||
|
||||
int sent = Mathf.clamp(accepted/4, 1, 8);
|
||||
int removed = accepted/sent;
|
||||
int[] remaining = {accepted, accepted};
|
||||
|
||||
for(int i = 0; i < sent; i ++){
|
||||
boolean end = i == sent-1;
|
||||
Timers.run(i * 3, () -> {
|
||||
tile.block().getStackOffset(stack.item, tile, stackTrns);
|
||||
|
||||
ItemTransfer.create(stack.item,
|
||||
player.x + Angles.trnsx(rotation + 180f, backTrns), player.y + Angles.trnsy(rotation + 180f, backTrns),
|
||||
new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> {
|
||||
|
||||
tile.block().handleStack(stack.item, removed, tile, player);
|
||||
remaining[1] -= removed;
|
||||
|
||||
if(end && remaining[1] > 0) {
|
||||
tile.block().handleStack(stack.item, remaining[1], tile, player);
|
||||
}
|
||||
});
|
||||
|
||||
stack.amount -= removed;
|
||||
remaining[0] -= removed;
|
||||
|
||||
if(end){
|
||||
stack.amount -= remaining[0];
|
||||
if(clear) player.inventory.clearItem();
|
||||
transferring = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
if(tile.block().acceptStack(stack.item, stack.amount, tile, player) > 0){
|
||||
CallBlocks.transferInventory(player, tile);
|
||||
}else{
|
||||
ItemDrop.create(stack.item, stack.amount, player.x, player.y, player.angleTo(x, y));
|
||||
player.inventory.clearItem();
|
||||
CallEntity.dropItem(player, player.angleTo(x, y));
|
||||
}
|
||||
//TODO create drop on the ground otherwise
|
||||
}
|
||||
|
||||
public boolean cursorNear(){
|
||||
@ -292,4 +262,69 @@ public abstract class InputHandler extends InputAdapter{
|
||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, in = In.entities)
|
||||
public static void dropItem(Player player, float angle){
|
||||
if(Net.server() && !player.inventory.hasItem()){
|
||||
throw new ValidateException(player, "Player cannot drop an item.");
|
||||
}
|
||||
|
||||
ItemDrop.create(player.inventory.getItem().item, player.inventory.getItem().amount, player.x, player.y, angle);
|
||||
player.inventory.clearItem();
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
||||
public static void transferInventory(Player player, Tile tile){
|
||||
if(Net.server() && (!player.inventory.hasItem() || player.isTransferring)){
|
||||
throw new ValidateException(player, "Player cannot transfer an item.");
|
||||
}
|
||||
|
||||
player.isTransferring = true;
|
||||
|
||||
ItemStack stack = player.inventory.getItem();
|
||||
int accepted = tile.block().acceptStack(stack.item, stack.amount, tile, player);
|
||||
|
||||
boolean clear = stack.amount == accepted;
|
||||
int sent = Mathf.clamp(accepted/4, 1, 8);
|
||||
int removed = accepted/sent;
|
||||
int[] remaining = {accepted, accepted};
|
||||
|
||||
for(int i = 0; i < sent; i ++){
|
||||
boolean end = i == sent-1;
|
||||
Timers.run(i * 3, () -> {
|
||||
tile.block().getStackOffset(stack.item, tile, stackTrns);
|
||||
|
||||
ItemTransfer.create(stack.item,
|
||||
player.x + Angles.trnsx(player.rotation + 180f, backTrns), player.y + Angles.trnsy(player.rotation + 180f, backTrns),
|
||||
new Translator(tile.drawx() + stackTrns.x, tile.drawy() + stackTrns.y), () -> {
|
||||
|
||||
tile.block().handleStack(stack.item, removed, tile, player);
|
||||
remaining[1] -= removed;
|
||||
|
||||
if(end && remaining[1] > 0) {
|
||||
tile.block().handleStack(stack.item, remaining[1], tile, player);
|
||||
}
|
||||
});
|
||||
|
||||
stack.amount -= removed;
|
||||
remaining[0] -= removed;
|
||||
|
||||
if(end){
|
||||
stack.amount -= remaining[0];
|
||||
if(clear){
|
||||
player.inventory.clearItem();
|
||||
}
|
||||
player.isTransferring = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//ItemDrop.create(player.inventory.getItem().item, player.inventory.getItem().amount, player.x, player.y, angle);
|
||||
//player.inventory.clearItem();
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true, in = In.blocks)
|
||||
public static void onTileTapped(Player player, Tile tile){
|
||||
tile.block().tapped(tile, player);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ public class BlockInventoryFragment implements Fragment {
|
||||
for(int j = 0; j < Mathf.clamp(amount/3, 1, 8); j ++){
|
||||
Timers.run(j*3f, () -> ItemTransfer.create(item, tile.drawx(), tile.drawy(), player, () -> {}));
|
||||
}*/
|
||||
CallBlocks.requestItem(tile, item, amount);
|
||||
CallBlocks.requestItem(player, tile, item, amount);
|
||||
|
||||
});
|
||||
table.add(image);
|
||||
@ -148,7 +148,7 @@ public class BlockInventoryFragment implements Fragment {
|
||||
table.setPosition(v.x, v.y, Align.center);
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, targets = Loc.client, in = In.blocks)
|
||||
@Remote(called = Loc.server, targets = Loc.both, in = In.blocks)
|
||||
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
||||
int removed = tile.block().removeStack(tile, item, amount);
|
||||
|
||||
|
@ -121,6 +121,8 @@ public class Block extends BaseBlock implements UnlockableContent{
|
||||
public TextureRegion[] shadowRegions;
|
||||
/**Whether the block can be tapped and selected to configure.*/
|
||||
public boolean configurable;
|
||||
/**Whether this block consumes touchDown events when tapped.*/
|
||||
public boolean consumesTap;
|
||||
|
||||
public Block(String name) {
|
||||
this.name = name;
|
||||
@ -177,8 +179,8 @@ public class Block extends BaseBlock implements UnlockableContent{
|
||||
}
|
||||
|
||||
/**Called when the block is tapped.*/
|
||||
public boolean tapped(Tile tile, Player player){
|
||||
return false;
|
||||
public void tapped(Tile tile, Player player){
|
||||
|
||||
}
|
||||
|
||||
/**Returns whether or not a hand cursor should be shown over this block.*/
|
||||
|
@ -1,21 +1,20 @@
|
||||
package io.anuke.mindustry.world;
|
||||
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.blocks.Blocks;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.Units;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.ValidateException;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.blocks.BreakBlock;
|
||||
import io.anuke.mindustry.world.blocks.BreakBlock.BreakEntity;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
@ -24,81 +23,119 @@ import static io.anuke.mindustry.Vars.world;
|
||||
public class Build {
|
||||
private static final Rectangle rect = new Rectangle();
|
||||
private static final Rectangle hitrect = new Rectangle();
|
||||
private static Array<Tile> tempTiles = new Array<>();
|
||||
|
||||
/**Returns block type that was broken, or null if unsuccesful.*/
|
||||
@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
||||
public static Block breakBlock(Player player, Team team, int x, int y, boolean effect, boolean sound){
|
||||
|
||||
public static void breakBlock(Player player, Team team, int x, int y){
|
||||
if(Net.server() && !validBreak(team, x, y)){
|
||||
throw new ValidateException(player, "An invalid block has been broken.");
|
||||
return;
|
||||
//throw new ValidateException(player, "An invalid block has been broken.");
|
||||
}
|
||||
|
||||
Tile tile = world.tile(x, y);
|
||||
|
||||
if(tile == null) return null;
|
||||
//just in case
|
||||
if(tile == null) return;
|
||||
|
||||
Block block = tile.isLinked() ? tile.getLinked().block() : tile.block();
|
||||
tile = tile.target();
|
||||
|
||||
//todo add break results to core inventory
|
||||
Block previous = tile.block();
|
||||
|
||||
if(sound) Effects.sound("break", x * tilesize, y * tilesize);
|
||||
if(effect) Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
|
||||
|
||||
if(!tile.block().isMultiblock() && !tile.isLinked()){
|
||||
tile.setBlock(Blocks.air);
|
||||
}else{
|
||||
Tile target = tile.isLinked() ? tile.getLinked() : tile;
|
||||
Array<Tile> removals = target.getLinkedTiles(tempTiles);
|
||||
for(Tile toremove : removals){
|
||||
//note that setting a new block automatically unlinks it
|
||||
toremove.setBlock(Blocks.air);
|
||||
}
|
||||
//remote players only
|
||||
if(!player.isLocal){
|
||||
player.getPlaceQueue().clear();
|
||||
player.getPlaceQueue().addFirst(new BuildRequest(x, y));
|
||||
}
|
||||
|
||||
return block;
|
||||
Block sub = Block.getByName("break" + previous.size);
|
||||
|
||||
if(previous instanceof BuildBlock){
|
||||
BuildEntity build = tile.entity();
|
||||
|
||||
tile.setBlock(sub);
|
||||
tile.setTeam(team);
|
||||
|
||||
BreakEntity breake = tile.entity();
|
||||
breake.set(build.recipe.result);
|
||||
breake.progress = 1.0 - build.progress;
|
||||
}else {
|
||||
tile.setBlock(sub);
|
||||
tile.<BreakEntity>entity().set(previous);
|
||||
tile.setTeam(team);
|
||||
|
||||
if (previous.isMultiblock()) {
|
||||
int offsetx = -(previous.size - 1) / 2;
|
||||
int offsety = -(previous.size - 1) / 2;
|
||||
|
||||
for (int dx = 0; dx < previous.size; dx++) {
|
||||
for (int dy = 0; dy < previous.size; dy++) {
|
||||
int worldx = dx + offsetx + x;
|
||||
int worldy = dy + offsety + y;
|
||||
if (!(worldx == x && worldy == y)) {
|
||||
Tile toplace = world.tile(worldx, worldy);
|
||||
if (toplace != null) {
|
||||
toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety));
|
||||
toplace.setTeam(team);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**Places a BuildBlock at this location. Call validPlace first.*/
|
||||
@Remote(targets = Loc.both, forward = true, called = Loc.server, in = In.blocks)
|
||||
public static void placeBlock(Player player, Team team, int x, int y, Recipe recipe, int rotation){
|
||||
|
||||
if(Net.server() && !validPlace(team, x, y, recipe.result, rotation)){
|
||||
throw new ValidateException(player, "An invalid block has been placed.");
|
||||
return;
|
||||
//throw new ValidateException(player, "An invalid block has been placed.");
|
||||
}
|
||||
|
||||
Tile tile = world.tile(x, y);
|
||||
Block result = recipe.result;
|
||||
Block previous = tile.block();
|
||||
|
||||
//just in case
|
||||
if(tile == null) return;
|
||||
|
||||
//remote players only (?)
|
||||
if(false){
|
||||
Block result = recipe.result;
|
||||
Block previous = tile.block();
|
||||
|
||||
//remote players only
|
||||
if(!player.isLocal){
|
||||
player.getPlaceQueue().clear();
|
||||
player.getPlaceQueue().addFirst(new BuildRequest(x, y, rotation, recipe));
|
||||
}
|
||||
|
||||
Block sub = Block.getByName("build" + result.size);
|
||||
|
||||
tile.setBlock(sub, rotation);
|
||||
tile.<BuildEntity>entity().set(previous, recipe);
|
||||
tile.setTeam(team);
|
||||
if(previous instanceof BreakBlock){
|
||||
BreakEntity breake = tile.entity();
|
||||
|
||||
if(result.isMultiblock()){
|
||||
int offsetx = -(result.size-1)/2;
|
||||
int offsety = -(result.size-1)/2;
|
||||
tile.setBlock(sub);
|
||||
tile.setTeam(team);
|
||||
|
||||
for(int dx = 0; dx < result.size; dx ++){
|
||||
for(int dy = 0; dy < result.size; dy ++){
|
||||
int worldx = dx + offsetx + x;
|
||||
int worldy = dy + offsety + y;
|
||||
if(!(worldx == x && worldy == y)){
|
||||
Tile toplace = world.tile(worldx, worldy);
|
||||
if(toplace != null) {
|
||||
toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety));
|
||||
toplace.setTeam(team);
|
||||
BuildEntity build = tile.entity();
|
||||
build.set(breake.previous, recipe);
|
||||
build.progress = 1.0 - breake.progress;
|
||||
}else{
|
||||
tile.setBlock(sub, rotation);
|
||||
tile.<BuildEntity>entity().set(previous, recipe);
|
||||
tile.setTeam(team);
|
||||
|
||||
if (result.isMultiblock()) {
|
||||
int offsetx = -(result.size - 1) / 2;
|
||||
int offsety = -(result.size - 1) / 2;
|
||||
|
||||
for (int dx = 0; dx < result.size; dx++) {
|
||||
for (int dy = 0; dy < result.size; dy++) {
|
||||
int worldx = dx + offsetx + x;
|
||||
int worldy = dy + offsety + y;
|
||||
if (!(worldx == x && worldy == y)) {
|
||||
Tile toplace = world.tile(worldx, worldy);
|
||||
if (toplace != null) {
|
||||
toplace.setLinked((byte) (dx + offsetx), (byte) (dy + offsety));
|
||||
toplace.setTeam(team);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -171,7 +208,7 @@ public class Build {
|
||||
public static boolean validBreak(Team team, int x, int y) {
|
||||
Tile tile = world.tile(x, y);
|
||||
|
||||
return tile != null && !tile.block().unbreakable
|
||||
return tile != null && !tile.block().unbreakable && !(tile.target().block() instanceof BreakBlock)
|
||||
&& (!tile.isLinked() || !tile.getLinked().block().unbreakable) && tile.breakable() && (tile.getTeam() == Team.none || tile.getTeam() == team);
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package io.anuke.mindustry.world.blocks;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class BlockModule {
|
||||
public abstract void write(DataOutputStream stream) throws IOException;
|
||||
public abstract void read(DataInputStream stream) throws IOException;
|
||||
public abstract void write(DataOutput stream) throws IOException;
|
||||
public abstract void read(DataInput stream) throws IOException;
|
||||
}
|
||||
|
180
core/src/io/anuke/mindustry/world/blocks/BreakBlock.java
Normal file
180
core/src/io/anuke/mindustry/world/blocks/BreakBlock.java
Normal file
@ -0,0 +1,180 @@
|
||||
package io.anuke.mindustry.world.blocks;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.entities.effect.Rubble;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.gen.CallBlocks;
|
||||
import io.anuke.mindustry.graphics.Layer;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.BarType;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockBar;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class BreakBlock extends Block {
|
||||
private static final float decaySpeedScl = 6f;
|
||||
|
||||
public BreakBlock(String name) {
|
||||
super(name);
|
||||
solid = true;
|
||||
update = true;
|
||||
size = Integer.parseInt(name.charAt(name.length()-1) + "");
|
||||
health = 1;
|
||||
layer = Layer.placement;
|
||||
configurable = true;
|
||||
consumesTap = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tapped(Tile tile, Player player) {
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
player.clearBuilding();
|
||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){
|
||||
bars.replace(new BlockBar(BarType.health, true, tile -> (float)tile.<BreakEntity>entity().progress));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyed(Tile tile){
|
||||
Effects.effect(ExplosionFx.blockExplosionSmoke, tile);
|
||||
|
||||
if(!tile.floor().solid && !tile.floor().liquid){
|
||||
Rubble.create(tile.drawx(), tile.drawy(), size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterDestroyed(Tile tile, TileEntity e){
|
||||
BreakEntity entity = (BreakEntity)e;
|
||||
|
||||
if(entity.previous.synthetic()){
|
||||
tile.setBlock(entity.previous);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile) {
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
Shaders.blockbuild.color = Palette.remove;
|
||||
|
||||
for(TextureRegion region : entity.previous.getBlockIcon()){
|
||||
Shaders.blockbuild.region = region;
|
||||
Shaders.blockbuild.progress = (float)(1f-entity.progress); //progress reversed
|
||||
Shaders.blockbuild.apply();
|
||||
|
||||
Draw.rect(region, tile.drawx(), tile.drawy(), entity.previous.rotate ? tile.getRotation() * 90 : 0);
|
||||
|
||||
Graphics.flush();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawShadow(Tile tile) {
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
entity.previous.drawShadow(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile) {
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
CallBlocks.onBreakFinish(tile);
|
||||
}else if(entity.progress < 0f){
|
||||
CallBlocks.onBreakDeath(tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity getEntity() {
|
||||
return new BreakEntity();
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.blocks)
|
||||
public static void onBreakDeath(Tile tile){
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
Team team = tile.getTeam();
|
||||
tile.setBlock(entity.previous);
|
||||
tile.setTeam(team);
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.blocks)
|
||||
public static void onBreakFinish(Tile tile){
|
||||
BreakEntity entity = tile.entity();
|
||||
|
||||
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), entity.previous.size);
|
||||
world.removeBlock(tile);
|
||||
}
|
||||
|
||||
public class BreakEntity extends TileEntity{
|
||||
private double[] accumulator;
|
||||
|
||||
public double progress = 0;
|
||||
public Block previous;
|
||||
public float breakTime;
|
||||
|
||||
public void addProgress(TileEntity core, Unit unit, double add){
|
||||
Recipe recipe = Recipe.getByResult(previous);
|
||||
|
||||
if(recipe != null) {
|
||||
ItemStack[] requirements = recipe.requirements;
|
||||
|
||||
for (int i = 0; i < requirements.length; i++) {
|
||||
accumulator[i] += requirements[i].amount * add / 2f; //add scaled amount progressed to the accumulator
|
||||
int amount = (int) (accumulator[i]); //get amount
|
||||
|
||||
if (amount > 0) { //if it's positive, add it to the core
|
||||
int accepting = core.tile.block().acceptStack(requirements[i].item, amount, core.tile, unit);
|
||||
core.tile.block().handleStack(requirements[i].item, amount, core.tile, unit);
|
||||
|
||||
accumulator[i] -= accepting;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
progress += add;
|
||||
}
|
||||
|
||||
public float progress(){
|
||||
return (float)progress;
|
||||
}
|
||||
|
||||
public void set(Block previous){
|
||||
this.previous = previous;
|
||||
if(Recipe.getByResult(previous) != null){
|
||||
this.accumulator = new double[Recipe.getByResult(previous).requirements.length];
|
||||
this.breakTime = Recipe.getByResult(previous).cost;
|
||||
}else{
|
||||
this.breakTime = 20f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +1,26 @@
|
||||
package io.anuke.mindustry.world.blocks;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.content.fx.ExplosionFx;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.effect.Rubble;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.gen.CallBlocks;
|
||||
import io.anuke.mindustry.graphics.Layer;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.mindustry.net.In;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.BarType;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.meta.BlockBar;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.modules.InventoryModule;
|
||||
import io.anuke.mindustry.world.meta.BlockBar;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
@ -32,16 +36,15 @@ public class BuildBlock extends Block {
|
||||
health = 1;
|
||||
layer = Layer.placement;
|
||||
configurable = true;
|
||||
consumesTap = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tapped(Tile tile, Player player) {
|
||||
public void tapped(Tile tile, Player player) {
|
||||
BuildEntity entity = tile.entity();
|
||||
|
||||
player.clearBuilding();
|
||||
player.addBuildRequest(new BuildRequest(tile.x, tile.y, tile.getRotation(), entity.recipe));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -107,12 +110,9 @@ public class BuildBlock extends Block {
|
||||
BuildEntity entity = tile.entity();
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
Team team = tile.getTeam();
|
||||
tile.setBlock(entity.recipe.result);
|
||||
tile.setTeam(team);
|
||||
Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), size);
|
||||
CallBlocks.onBuildFinish(tile);
|
||||
}else if(entity.progress < 0f){
|
||||
entity.damage(entity.health + 1);
|
||||
CallBlocks.onBuildDeath(tile);
|
||||
}
|
||||
|
||||
if(!entity.updated){
|
||||
@ -127,13 +127,29 @@ public class BuildBlock extends Block {
|
||||
return new BuildEntity();
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.blocks)
|
||||
public static void onBuildDeath(Tile tile){
|
||||
tile.entity.damage(tile.entity.health + 1);
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server, in = In.blocks)
|
||||
public static void onBuildFinish(Tile tile){
|
||||
BuildEntity entity = tile.entity();
|
||||
|
||||
Team team = tile.getTeam();
|
||||
tile.setBlock(entity.recipe.result);
|
||||
tile.setTeam(team);
|
||||
Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), entity.recipe.result.size);
|
||||
}
|
||||
|
||||
public class BuildEntity extends TileEntity{
|
||||
public Recipe recipe;
|
||||
|
||||
private double progress = 0;
|
||||
public double progress = 0;
|
||||
public Block previous;
|
||||
|
||||
private double[] accumulator;
|
||||
private boolean updated;
|
||||
private Block previous;
|
||||
|
||||
public void addProgress(InventoryModule inventory, double amount){
|
||||
double maxProgress = amount;
|
||||
|
@ -26,6 +26,7 @@ public class Door extends Wall{
|
||||
super(name);
|
||||
solid = false;
|
||||
solidifes = true;
|
||||
consumesTap = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,11 +52,11 @@ public class Door extends Wall{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tapped(Tile tile, Player player){
|
||||
public void tapped(Tile tile, Player player){
|
||||
DoorEntity entity = tile.entity();
|
||||
|
||||
if(Units.anyEntities(tile) && entity.open){
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
entity.open = !entity.open;
|
||||
@ -64,8 +65,6 @@ public class Door extends Wall{
|
||||
}else{
|
||||
Effects.effect(openfx, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,9 +4,7 @@ import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.world.blocks.BlockModule;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class InventoryModule extends BlockModule{
|
||||
@ -76,7 +74,7 @@ public class InventoryModule extends BlockModule{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream stream) throws IOException {
|
||||
public void write(DataOutput stream) throws IOException {
|
||||
byte amount = 0;
|
||||
for(int i = 0; i < items.length; i ++){
|
||||
if(items[i] > 0) amount ++;
|
||||
@ -93,7 +91,7 @@ public class InventoryModule extends BlockModule{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream stream) throws IOException {
|
||||
public void read(DataInput stream) throws IOException {
|
||||
byte count = stream.readByte();
|
||||
|
||||
for(int j = 0; j < count; j ++){
|
||||
|
@ -4,8 +4,8 @@ import io.anuke.mindustry.content.Liquids;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.blocks.BlockModule;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class LiquidModule extends BlockModule {
|
||||
@ -14,13 +14,13 @@ public class LiquidModule extends BlockModule {
|
||||
public Liquid liquid = Liquids.none;
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream stream) throws IOException {
|
||||
public void write(DataOutput stream) throws IOException {
|
||||
stream.writeByte(liquid.id);
|
||||
stream.writeFloat(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream stream) throws IOException{
|
||||
public void read(DataInput stream) throws IOException{
|
||||
byte id = stream.readByte();
|
||||
liquid = Liquid.getByID(id);
|
||||
amount = stream.readFloat();
|
||||
|
@ -2,8 +2,8 @@ package io.anuke.mindustry.world.blocks.modules;
|
||||
|
||||
import io.anuke.mindustry.world.blocks.BlockModule;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
public class PowerModule extends BlockModule{
|
||||
@ -28,12 +28,12 @@ public class PowerModule extends BlockModule{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutputStream stream) throws IOException {
|
||||
public void write(DataOutput stream) throws IOException {
|
||||
stream.writeFloat(amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInputStream stream) throws IOException{
|
||||
public void read(DataInput stream) throws IOException{
|
||||
amount = stream.readFloat();
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ public class CoreBlock extends StorageBlock {
|
||||
|
||||
//instant build for fast testing.
|
||||
if(debug){
|
||||
// entity.progress = 1f;
|
||||
entity.progress = 1f;
|
||||
}
|
||||
|
||||
if(entity.progress >= 1f){
|
||||
|
Loading…
Reference in New Issue
Block a user