Merge branches 'config-int' and 'master' of https://github.com/Anuken/Mindustry

This commit is contained in:
Anuken
2019-09-30 21:35:07 -04:00
31 changed files with 388 additions and 205 deletions

View File

@ -1646,13 +1646,13 @@ public class Blocks implements ContentList{
}};
phantomFactory = new UnitFactory("phantom-factory"){{
requirements(Category.units, ItemStack.with(Items.titanium, 45, Items.thorium, 40, Items.lead, 55, Items.silicon, 105));
requirements(Category.units, ItemStack.with(Items.titanium, 50, Items.thorium, 60, Items.lead, 65, Items.silicon, 105));
type = UnitTypes.phantom;
produceTime = 3650;
produceTime = 4400;
size = 2;
maxSpawn = 2;
consumes.power(2f);
consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 20), new ItemStack(Items.titanium, 10));
maxSpawn = 1;
consumes.power(2.5f);
consumes.items(new ItemStack(Items.silicon, 50), new ItemStack(Items.lead, 30), new ItemStack(Items.titanium, 20));
}};
commandCenter = new CommandCenter("command-center"){{

View File

@ -61,9 +61,8 @@ public class UnitTypes implements ContentList{
maxVelocity = 1.9f;
range = 70f;
itemCapacity = 70;
health = 220;
buildPower = 0.9f;
minePower = 1.1f;
health = 400;
buildPower = 1f;
engineOffset = 6.5f;
toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium);
weapon = new Weapon("heal-blaster"){{

View File

@ -16,6 +16,7 @@ import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.blocks.BuildBlock.*;
import io.anuke.mindustry.world.blocks.power.*;
import static io.anuke.mindustry.Vars.*;
@ -43,7 +44,11 @@ public class Logic implements ApplicationListener{
//blocks that get broken are appended to the team's broken block queue
Tile tile = event.tile;
Block block = tile.block();
//skip null entities or nukes, for obvious reasons
if(tile.entity == null || tile.block() instanceof NuclearReactor) return;
if(block instanceof BuildBlock){
BuildEntity entity = tile.entity();
//update block to reflect the fact that something was being constructed
@ -56,7 +61,7 @@ public class Logic implements ApplicationListener{
}
TeamData data = state.teams.get(tile.getTeam());
data.brokenBlocks.addFirst(BrokenBlock.get(tile.x, tile.y, tile.rotation(), block.id));
data.brokenBlocks.addFirst(new BrokenBlock(tile.x, tile.y, tile.rotation(), block.id, tile.entity.config()));
});
}

View File

@ -20,6 +20,7 @@ public class Units{
private static float cdist;
private static boolean boolResult;
/** @return whether this player can interact with a specific tile. if either of these are null, returns true.*/
public static boolean canInteract(Player player, Tile tile){
return player == null || tile == null || tile.interactable(player.getTeam());
}

View File

@ -104,7 +104,11 @@ public interface BuilderTrait extends Entity, TeamTrait{
if(current.breaking){
entity.deconstruct(unit, core, 1f / entity.buildCost * Time.delta() * getBuildPower(tile) * state.rules.buildSpeedMultiplier);
}else{
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)){
if(current.hasConfig){
Call.onTileConfig(null, tile, current.config);
}
}
}
current.progress = entity.progress;
@ -257,6 +261,8 @@ public interface BuilderTrait extends Entity, TeamTrait{
public final int x, y, rotation;
public final Block block;
public final boolean breaking;
public boolean hasConfig;
public int config;
public float progress;
public boolean initialized;
@ -279,6 +285,12 @@ public interface BuilderTrait extends Entity, TeamTrait{
this.breaking = true;
}
public BuildRequest configure(int config){
this.config = config;
this.hasConfig = true;
return this;
}
public Tile tile(){
return world.tile(x, y);
}

View File

@ -43,8 +43,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
private boolean dead = false;
private boolean sleeping;
private float sleepTime;
private @Nullable
SoundLoop sound;
private @Nullable SoundLoop sound;
@Remote(called = Loc.server, unreliable = true)
public static void onTileDamage(Tile tile, float health){
@ -232,6 +231,11 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
return proximity;
}
/** Tile configuration. Defaults to 0. Used for block rebuilding. */
public int config(){
return 0;
}
@Override
public void removed(){
if(sound != null){

View File

@ -1,23 +1,19 @@
package io.anuke.mindustry.entities.type.base;
import io.anuke.arc.Core;
import io.anuke.arc.Events;
import io.anuke.arc.collection.IntIntMap;
import io.anuke.arc.collection.Queue;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.math.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.EntityGroup;
import io.anuke.mindustry.entities.traits.BuilderTrait;
import io.anuke.mindustry.entities.traits.TargetTrait;
import io.anuke.mindustry.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
import io.anuke.mindustry.game.Teams.TeamData;
import io.anuke.mindustry.gen.BrokenBlock;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.BuildBlock;
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
import io.anuke.mindustry.entities.units.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.Teams.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.blocks.BuildBlock.*;
import java.io.*;
@ -45,7 +41,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
BuildEntity entity = (BuildEntity)target;
TileEntity core = getClosestCore();
if(isBuilding() && entity == null && isRebuild()){
if(isBuilding() && entity == null && canRebuild()){
target = world.tile(buildRequest().x, buildRequest().y);
circle(placeDistance * 0.7f);
target = null;
@ -100,9 +96,9 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
incDrones(playerTarget);
TargetTrait prev = target;
target = playerTarget;
float dst = 90f + (id % 4)*30;
float dst = 90f + (id % 10)*3;
float tdst = dst(target);
float scale = (Mathf.lerp(1f, 0.77f, 1f - Mathf.clamp((tdst - dst) / dst)));
float scale = (Mathf.lerp(1f, 0.2f, 1f - Mathf.clamp((tdst - dst) / dst)));
circle(dst);
velocity.scl(scale);
target = prev;
@ -151,9 +147,8 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
}
}
boolean isRebuild(){
//disabled until further notice, reason being that it's too annoying when playing enemies and too broken for ally use
return false; //Vars.state.rules.enemyCheat && team == waveTeam;
boolean canRebuild(){
return true;
}
@Override
@ -188,12 +183,12 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
}
}
if(isRebuild() && !isBuilding()){
if(timer.get(timerTarget, 80) && Units.closestEnemy(getTeam(), x, y, 100f, u -> !(u instanceof BaseDrone)) == null && !isBuilding()){
TeamData data = Vars.state.teams.get(team);
if(!data.brokenBlocks.isEmpty()){
long block = data.brokenBlocks.removeLast();
BrokenBlock block = data.brokenBlocks.removeLast();
placeQueue.addFirst(new BuildRequest(BrokenBlock.x(block), BrokenBlock.y(block), BrokenBlock.rotation(block), content.block(BrokenBlock.block(block))));
placeQueue.addFirst(new BuildRequest(block.x, block.y, block.rotation, content.block(block.block)).configure(block.config));
setState(build);
}
}

View File

@ -1,9 +1,8 @@
package io.anuke.mindustry.game;
import io.anuke.annotations.Annotations.Struct;
import io.anuke.arc.collection.*;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.*;
import io.anuke.mindustry.world.*;
/** Class for various team-based utilities. */
public class Teams{
@ -52,7 +51,7 @@ public class Teams{
public final ObjectSet<Tile> cores = new ObjectSet<>();
public final EnumSet<Team> enemies;
public final Team team;
public LongQueue brokenBlocks = new LongQueue();
public Queue<BrokenBlock> brokenBlocks = new Queue<>();
public TeamData(Team team, EnumSet<Team> enemies){
this.team = team;
@ -62,8 +61,16 @@ public class Teams{
/** Represents a block made by this team that was destroyed somewhere on the map.
* This does not include deconstructed blocks.*/
@Struct
public class BrokenBlockStruct{
public short x, y, rotation, block;
public static class BrokenBlock{
public final short x, y, rotation, block;
public final int config;
public BrokenBlock(short x, short y, short rotation, short block, int config){
this.x = x;
this.y = y;
this.rotation = rotation;
this.block = block;
this.config = config;
}
}
}

View File

@ -128,11 +128,10 @@ public abstract class InputHandler implements InputProcessor{
tile.block().tapped(tile, player);
}
@Remote(targets = Loc.both, called = Loc.server, forward = true)
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void onTileConfig(Player player, Tile tile, int value){
if(tile == null || !Units.canInteract(player, tile)) return;
//TODO
//tile.block().cofigured(tile, player, value);
tile.block().configured(tile, player, value);
}
public OverlayFragment getFrag(){

View File

@ -1,12 +1,10 @@
package io.anuke.mindustry.io;
import io.anuke.arc.collection.*;
import io.anuke.arc.util.serialization.*;
import io.anuke.arc.util.serialization.Json.*;
import io.anuke.mindustry.*;
import io.anuke.mindustry.content.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.Teams.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
@ -98,6 +96,7 @@ public class JsonIO{
}
});
/*
json.setSerializer(TeamData.class, new Serializer<TeamData>(){
@Override
public void write(Json json, TeamData object, Class knownType){
@ -115,7 +114,7 @@ public class JsonIO{
out.brokenBlocks = new LongQueue(blocks);
return out;
}
});
});*/
json.setSerializer(ItemStack.class, new Serializer<ItemStack>(){
@Override

View File

@ -5,8 +5,7 @@ import io.anuke.arc.files.FileHandle;
import io.anuke.arc.util.io.CounterInputStream;
import io.anuke.arc.util.io.FastDeflaterOutputStream;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.io.versions.Save1;
import io.anuke.mindustry.io.versions.Save2;
import io.anuke.mindustry.io.versions.*;
import io.anuke.mindustry.world.WorldContext;
import java.io.*;
@ -19,7 +18,7 @@ public class SaveIO{
/** Format header. This is the string 'MSAV' in ASCII. */
public static final byte[] header = {77, 83, 65, 86};
public static final IntMap<SaveVersion> versions = new IntMap<>();
public static final Array<SaveVersion> versionArray = Array.with(new Save1(), new Save2());
public static final Array<SaveVersion> versionArray = Array.with(new Save1(), new Save2(), new Save3());
static{
for(SaveVersion version : versionArray){

View File

@ -6,7 +6,7 @@ import io.anuke.arc.util.io.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.game.Teams.*;
import io.anuke.mindustry.maps.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
@ -16,7 +16,7 @@ import java.io.*;
import static io.anuke.mindustry.Vars.*;
public abstract class SaveVersion extends SaveFileReader{
public final int version;
public int version;
//HACK stores the last read build of the save file, valid after read meta call
protected int lastReadBuild;
@ -208,6 +208,21 @@ public abstract class SaveVersion extends SaveFileReader{
}
public void writeEntities(DataOutput stream) throws IOException{
//write team data with entities.
Array<TeamData> data = state.teams.getActive();
stream.writeInt(data.size);
for(TeamData team : data){
stream.writeInt(team.team.ordinal());
stream.writeInt(team.brokenBlocks.size);
for(BrokenBlock block : team.brokenBlocks){
stream.writeShort(block.x);
stream.writeShort(block.y);
stream.writeShort(block.rotation);
stream.writeShort(block.block);
stream.writeInt(block.config);
}
}
//write entity chunk
int groups = 0;
@ -236,6 +251,16 @@ public abstract class SaveVersion extends SaveFileReader{
}
public void readEntities(DataInput stream) throws IOException{
int teamc = stream.readInt();
for(int i = 0; i < teamc; i++){
Team team = Team.all[stream.readInt()];
TeamData data = state.teams.get(team);
int blocks = stream.readInt();
for(int j = 0; j < blocks; j++){
data.brokenBlocks.addLast(new BrokenBlock(stream.readShort(), stream.readShort(), stream.readShort(), stream.readShort(), stream.readInt()));
}
}
byte groups = stream.readByte();
for(int i = 0; i < groups; i++){
@ -292,17 +317,4 @@ public abstract class SaveVersion extends SaveFileReader{
}
}
}
/** sometimes it's necessary to remap IDs after the content header is read.*/
public void remapContent(){
for(Team team : Team.all){
if(state.teams.isActive(team)){
LongQueue queue = state.teams.get(team).brokenBlocks;
for(int i = 0; i < queue.size; i++){
//remap broken block IDs
queue.set(i, BrokenBlock.block(queue.get(i), content.block(BrokenBlock.block(queue.get(i))).id));
}
}
}
}
}

View File

@ -1,16 +1,14 @@
package io.anuke.mindustry.io.versions;
import io.anuke.arc.function.Supplier;
import io.anuke.mindustry.entities.traits.SaveTrait;
import io.anuke.mindustry.io.SaveVersion;
import io.anuke.arc.function.*;
import io.anuke.mindustry.entities.traits.*;
import java.io.DataInput;
import java.io.IOException;
import java.io.*;
public class Save1 extends SaveVersion{
public class Save1 extends Save2{
public Save1(){
super(1);
version = 1;
}
@Override

View File

@ -1,9 +1,35 @@
package io.anuke.mindustry.io.versions;
import io.anuke.mindustry.io.SaveVersion;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.io.*;
import io.anuke.mindustry.type.*;
import java.io.*;
import static io.anuke.mindustry.Vars.content;
public class Save2 extends SaveVersion{
public Save2(){
super(2);
}
@Override
public void readEntities(DataInput stream) throws IOException{
byte groups = stream.readByte();
for(int i = 0; i < groups; i++){
int amount = stream.readInt();
for(int j = 0; j < amount; j++){
//TODO throw exception on read fail
readChunk(stream, true, in -> {
byte typeid = in.readByte();
byte version = in.readByte();
SaveTrait trait = (SaveTrait)content.<TypeID>getByID(ContentType.typeid, typeid).constructor.get();
trait.readSave(in, version);
});
}
}
}
}

View File

@ -0,0 +1,9 @@
package io.anuke.mindustry.io.versions;
import io.anuke.mindustry.io.*;
public class Save3 extends SaveVersion{
public Save3(){
super(3);
}
}

View File

@ -66,7 +66,7 @@ public class Packets{
public static class ConnectPacket implements Packet{
public int version;
public String versionType;
public Array<String> mods = new Array<>();
public Array<String> mods;
public String name, uuid, usid;
public boolean mobile;
public int color;
@ -98,6 +98,7 @@ public class Packets{
buffer.get(idbytes);
uuid = new String(Base64Coder.encode(idbytes));
int totalMods = buffer.getInt();
mods = new Array<>(totalMods);
for(int i = 0; i < totalMods; i++){
mods.add(TypeIO.readString(buffer));
}

View File

@ -15,11 +15,11 @@ import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.arc.util.pooling.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.effect.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.type.Bullet;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
@ -315,7 +315,10 @@ public class Block extends BlockStorage{
});
tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
if(!tempTiles.isEmpty()){
Call.linkPowerNodes(null, tempTiles.first(), tile);
Tile toLink = tempTiles.first();
if(!toLink.entity.power.links.contains(tile.pos())){
toLink.configure(tile.pos());
}
}
}
}
@ -433,6 +436,11 @@ public class Block extends BlockStorage{
}
/** Called when arbitrary configuration is applied to a tile. */
public void configured(Tile tile, @Nullable Player player, int value){
}
/** Returns whether or not a hand cursor should be shown over this block. */
public Cursor getCursor(Tile tile){
return configurable ? SystemCursor.hand : SystemCursor.arrow;

View File

@ -8,6 +8,7 @@ import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.traits.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.modules.*;
@ -87,6 +88,11 @@ public class Tile implements Position, TargetTrait{
return -1;
}
/** Configure a tile with the current, local player. */
public void configure(int value){
Call.onTileConfig(player, this, value);
}
@SuppressWarnings("unchecked")
public <T extends TileEntity> T entity(){
return (T)entity;

View File

@ -188,10 +188,10 @@ public class BuildBlock extends Block{
private float[] accumulator;
private float[] totalAccumulator;
public void construct(Unit builder, @Nullable TileEntity core, float amount){
public boolean construct(Unit builder, @Nullable TileEntity core, float amount){
if(cblock == null){
kill();
return;
return false;
}
float maxProgress = core == null ? amount : checkRequired(core.items, amount, false);
@ -212,7 +212,9 @@ public class BuildBlock extends Block{
if(progress >= 1f || state.rules.infiniteResources){
Call.onConstructFinish(tile, cblock, builderID, tile.rotation(), builder.getTeam());
return true;
}
return false;
}
public void deconstruct(Unit builder, @Nullable TileEntity core, float amount){

View File

@ -1,6 +1,5 @@
package io.anuke.mindustry.world.blocks.distribution;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.collection.IntSet.*;
@ -9,9 +8,7 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
@ -43,24 +40,20 @@ public class ItemBridge extends Block{
group = BlockGroup.transportation;
}
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void linkItemBridge(Player player, Tile tile, Tile other){
if(!Units.canInteract(player, tile)) return;
@Override
public void configured(Tile tile, Player player, int value){
ItemBridgeEntity entity = tile.entity();
ItemBridgeEntity oe = other.entity();
entity.link = other.pos();
oe.incoming.add(tile.pos());
}
@Remote(targets = Loc.both, called = Loc.server, forward = true)
public static void unlinkItemBridge(Player player, Tile tile, Tile other){
if(!Units.canInteract(player, tile)) return;
ItemBridgeEntity entity = tile.entity();
entity.link = -1;
if(other != null){
ItemBridgeEntity oe = other.entity();
if(world.tile(entity.link) != null && world.tile(entity.link).entity instanceof ItemBridgeEntity){
ItemBridgeEntity oe = world.tile(entity.link).entity();
oe.incoming.remove(tile.pos());
}
entity.link = value;
if(world.tile(value) != null && world.tile(value).entity instanceof ItemBridgeEntity){
((ItemBridgeEntity)world.tile(value).entity).incoming.add(tile.pos());
}
}
@Override
@ -76,7 +69,7 @@ public class ItemBridge extends Block{
public void playerPlaced(Tile tile){
Tile link = findLink(tile.x, tile.y);
if(linkValid(tile, link)){
Call.linkItemBridge(null, link, tile);
link.configure(tile.pos());
}
lastPlaced = tile.pos();
@ -148,9 +141,9 @@ public class ItemBridge extends Block{
if(linkValid(tile, other)){
if(entity.link == other.pos()){
Call.unlinkItemBridge(null, tile, other);
tile.configure(Pos.invalid);
}else{
Call.linkItemBridge(null, tile, other);
tile.configure(other.pos());
}
return false;
}
@ -175,7 +168,6 @@ public class ItemBridge extends Block{
Tile other = world.tile(entity.link);
if(!linkValid(tile, other)){
entity.link = Pos.invalid;
tryDump(tile);
entity.uptime = 0f;
}else{
@ -364,6 +356,11 @@ public class ItemBridge extends Block{
public float time2;
public float cycleSpeed = 1f;
@Override
public int config(){
return link;
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -1,6 +1,5 @@
package io.anuke.mindustry.world.blocks.distribution;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.g2d.*;
@ -12,7 +11,6 @@ import io.anuke.mindustry.content.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
@ -45,11 +43,17 @@ public class MassDriver extends Block{
outlineIcon = true;
}
/*
@Remote(targets = Loc.both, called = Loc.server, forward = true)
public static void linkMassDriver(Player player, Tile tile, int position){
if(!Units.canInteract(player, tile)) return;
MassDriverEntity entity = tile.entity();
entity.link = position;
}*/
@Override
public void configured(Tile tile, Player player, int value){
tile.<MassDriverEntity>entity().link = value;
}
@Override
@ -192,10 +196,10 @@ public class MassDriver extends Block{
MassDriverEntity entity = tile.entity();
if(entity.link == other.pos()){
Call.linkMassDriver(null, tile, -1);
tile.configure(-1);
return false;
}else if(other.block() instanceof MassDriver && other.dst(tile) <= range && other.getTeam() == tile.getTeam()){
Call.linkMassDriver(null, tile, other.pos());
tile.configure(other.pos());
return false;
}
@ -310,6 +314,11 @@ public class MassDriver extends Block{
((MassDriver)block).handlePayload(this, bullet, data);
}
@Override
public int config(){
return link;
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -1,17 +1,15 @@
package io.anuke.mindustry.world.blocks.distribution;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.Core;
import io.anuke.arc.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.Mathf;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.entities.*;
import io.anuke.arc.math.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.ItemSelection;
import io.anuke.mindustry.world.meta.BlockGroup;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.meta.*;
import java.io.*;
@ -37,9 +35,12 @@ public class Sorter extends Block{
@Override
public void playerPlaced(Tile tile){
Core.app.post(() -> Call.setSorterItem(null, tile, lastItem));
if(lastItem != null){
Core.app.post(() -> tile.configure(lastItem.id));
}
}
/*
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setSorterItem(Player player, Tile tile, Item item){
if(!Units.canInteract(player, tile)) return;
@ -47,6 +48,11 @@ public class Sorter extends Block{
if(entity != null){
entity.sortItem = item;
}
}*/
@Override
public void configured(Tile tile, Player player, int value){
tile.<SorterEntity>entity().sortItem = content.item(value);
}
@Override
@ -127,7 +133,7 @@ public class Sorter extends Block{
SorterEntity entity = tile.entity();
ItemSelection.buildItemTable(table, () -> entity.sortItem, item -> {
lastItem = item;
Call.setSorterItem(null, tile, item);
tile.configure(item == null ? -1 : item.id);
});
}
@ -138,7 +144,12 @@ public class Sorter extends Block{
public class SorterEntity extends TileEntity{
Item sortItem;
@Nullable Item sortItem;
@Override
public int config(){
return sortItem == null ? -1 : sortItem.id;
}
@Override
public byte version(){

View File

@ -1,6 +1,5 @@
package io.anuke.mindustry.world.blocks.power;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.function.*;
@ -9,9 +8,7 @@ import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.math.*;
import io.anuke.arc.math.geom.*;
import io.anuke.arc.util.*;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.*;
@ -36,7 +33,7 @@ public class PowerNode extends PowerBlock{
consumesPower = false;
outputsPower = false;
}
/*
@Remote(targets = Loc.both, called = Loc.server, forward = true)
public static void linkPowerNodes(Player player, Tile tile, Tile other){
if(tile.entity == null || other == null || tile.entity.power == null || !((PowerNode)tile.block()).linkValid(tile, other)
@ -82,6 +79,47 @@ public class PowerNode extends PowerBlock{
}
}
*/
@Override
public void configured(Tile tile, Player player, int value){
TileEntity entity = tile.entity;
Tile other = world.tile(value);
boolean contains = entity.power.links.contains(value), valid = other != null && other.entity != null && other.entity.power != null;
if(contains){
//unlink
entity.power.links.removeValue(value);
if(valid) other.entity.power.links.removeValue(tile.pos());
PowerGraph newgraph = new PowerGraph();
//reflow from this point, covering all tiles on this side
newgraph.reflow(tile);
if(valid && other.entity.power.graph != newgraph){
//create new graph for other end
PowerGraph og = new PowerGraph();
//reflow from other end
og.reflow(other);
}
}else if(linkValid(tile, other) && valid && entity.power.links.size < maxNodes){
if(!entity.power.links.contains(other.pos())){
entity.power.links.add(other.pos());
}
if(other.getTeamID() == tile.getTeamID()){
if(!other.entity.power.links.contains(tile.pos())){
other.entity.power.links.add(tile.pos());
}
}
entity.power.graph.add(other.entity.power.graph);
}
}
@Override
public void load(){
super.load();
@ -122,7 +160,11 @@ public class PowerNode extends PowerBlock{
});
tempTiles.sort(Structs.comparingFloat(t -> t.dst2(tile)));
tempTiles.each(valid, other -> Call.linkPowerNodes(null, tile, other));
tempTiles.each(valid, other -> {
if(!tile.entity.power.links.contains(other.pos())){
tile.configure(other.pos());
}
});
super.placed(tile);
}
@ -169,11 +211,7 @@ public class PowerNode extends PowerBlock{
Tile result = other;
if(linkValid(tile, other)){
if(linked(tile, other)){
Call.unlinkPowerNodes(null, tile, result);
}else if(entity.power.links.size < maxNodes){
Call.linkPowerNodes(null, tile, result);
}
tile.configure(other.pos());
return false;
}
return true;

View File

@ -1,19 +1,13 @@
package io.anuke.mindustry.world.blocks.sandbox;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.ItemSelection;
import io.anuke.mindustry.world.meta.BlockGroup;
import io.anuke.arc.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.mindustry.world.meta.*;
import java.io.*;
@ -31,18 +25,16 @@ public class ItemSource extends Block{
configurable = true;
}
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setItemSourceItem(Player player, Tile tile, Item item){
if(!Units.canInteract(player, tile)) return;
ItemSourceEntity entity = tile.entity();
if(entity != null){
entity.outputItem = item;
}
@Override
public void configured(Tile tile, Player player, int value){
tile.<ItemSourceEntity>entity().outputItem = content.item(value);
}
@Override
public void playerPlaced(Tile tile){
Core.app.post(() -> Call.setItemSourceItem(null, tile, lastItem));
if(lastItem != null){
Core.app.post(() -> tile.configure(lastItem.id));
}
}
@Override
@ -83,7 +75,7 @@ public class ItemSource extends Block{
ItemSourceEntity entity = tile.entity();
ItemSelection.buildItemTable(table, () -> entity.outputItem, item -> {
lastItem = item;
Call.setItemSourceItem(null, tile, item);
tile.configure(item == null ? -1 : item.id);
});
}
@ -100,6 +92,11 @@ public class ItemSource extends Block{
public class ItemSourceEntity extends TileEntity{
Item outputItem;
@Override
public int config(){
return outputItem == null ? -1 : outputItem.id;
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -1,27 +1,21 @@
package io.anuke.mindustry.world.blocks.sandbox;
import io.anuke.annotations.Annotations.Loc;
import io.anuke.annotations.Annotations.Remote;
import io.anuke.arc.Core;
import io.anuke.arc.collection.Array;
import io.anuke.arc.graphics.g2d.Draw;
import io.anuke.arc.scene.style.TextureRegionDrawable;
import io.anuke.arc.scene.ui.ButtonGroup;
import io.anuke.arc.scene.ui.ImageButton;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.type.Player;
import io.anuke.mindustry.entities.type.TileEntity;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.style.*;
import io.anuke.arc.scene.ui.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.arc.util.ArcAnnotate.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.type.Liquid;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.*;
import java.io.*;
import static io.anuke.mindustry.Vars.content;
import static io.anuke.mindustry.Vars.control;
import static io.anuke.mindustry.Vars.*;
public class LiquidSource extends Block{
private static Liquid lastLiquid;
@ -38,7 +32,9 @@ public class LiquidSource extends Block{
@Override
public void playerPlaced(Tile tile){
if(lastLiquid != null) Core.app.post(() -> Call.setLiquidSourceLiquid(null, tile, lastLiquid));
if(lastLiquid != null){
Core.app.post(() -> tile.configure(lastLiquid.id));
}
}
@Override
@ -87,7 +83,7 @@ public class LiquidSource extends Block{
final int f = i;
ImageButton button = cont.addImageButton(Tex.clear, Styles.clearToggleTransi, 24, () -> control.input.frag.config.hideConfig()).size(38).group(group).get();
button.changed(() -> {
Call.setLiquidSourceLiquid(null, tile, button.isChecked() ? items.get(f) : null);
tile.configure(button.isChecked() ? items.get(f).id : -1);
control.input.frag.config.hideConfig();
lastLiquid = items.get(f);
});
@ -107,15 +103,18 @@ public class LiquidSource extends Block{
return new LiquidSourceEntity();
}
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setLiquidSourceLiquid(Player player, Tile tile, Liquid liquid){
if(!Units.canInteract(player, tile)) return;
LiquidSourceEntity entity = tile.entity();
if(entity != null) entity.source = liquid;
@Override
public void configured(Tile tile, Player player, int value){
tile.<LiquidSourceEntity>entity().source = content.liquid(value);
}
class LiquidSourceEntity extends TileEntity{
public Liquid source = null;
public @Nullable Liquid source = null;
@Override
public int config(){
return source == null ? -1 : source.id;
}
@Override
public void write(DataOutput stream) throws IOException{

View File

@ -1,16 +1,13 @@
package io.anuke.mindustry.world.blocks.storage;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.Core;
import io.anuke.arc.graphics.Color;
import io.anuke.arc.*;
import io.anuke.arc.graphics.*;
import io.anuke.arc.graphics.g2d.*;
import io.anuke.arc.scene.ui.layout.Table;
import io.anuke.mindustry.entities.*;
import io.anuke.arc.scene.ui.layout.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.blocks.ItemSelection;
import io.anuke.mindustry.world.blocks.*;
import java.io.*;
@ -44,20 +41,20 @@ public class Unloader extends Block{
@Override
public void playerPlaced(Tile tile){
Core.app.post(() -> Call.setSortedUnloaderItem(null, tile, lastItem));
if(lastItem != null){
Core.app.post(() -> tile.configure(lastItem.id));
}
}
@Remote(targets = Loc.both, called = Loc.both, forward = true)
public static void setSortedUnloaderItem(Player player, Tile tile, Item item){
if(!Units.canInteract(player, tile)) return;
SortedUnloaderEntity entity = tile.entity();
entity.items.clear();
entity.sortItem = item;
@Override
public void configured(Tile tile, Player player, int value){
tile.entity.items.clear();
tile.<UnloaderEntity>entity().sortItem = content.item(value);
}
@Override
public void update(Tile tile){
SortedUnloaderEntity entity = tile.entity();
UnloaderEntity entity = tile.entity();
if(tile.entity.timer.get(timerUnload, speed / entity.timeScale) && tile.entity.items.total() == 0){
for(Tile other : tile.entity.proximity()){
@ -109,7 +106,7 @@ public class Unloader extends Block{
public void draw(Tile tile){
super.draw(tile);
SortedUnloaderEntity entity = tile.entity();
UnloaderEntity entity = tile.entity();
Draw.color(entity.sortItem == null ? Color.clear : entity.sortItem.color);
Fill.square(tile.worldx(), tile.worldy(), 1f);
@ -118,21 +115,26 @@ public class Unloader extends Block{
@Override
public void buildTable(Tile tile, Table table){
SortedUnloaderEntity entity = tile.entity();
UnloaderEntity entity = tile.entity();
ItemSelection.buildItemTable(table, () -> entity.sortItem, item -> {
lastItem = item;
Call.setSortedUnloaderItem(null, tile, item);
tile.configure(item == null ? -1 : item.id);
});
}
@Override
public TileEntity newEntity(){
return new SortedUnloaderEntity();
return new UnloaderEntity();
}
public static class SortedUnloaderEntity extends TileEntity{
public static class UnloaderEntity extends TileEntity{
public Item sortItem = null;
@Override
public int config(){
return sortItem == null ? -1 : sortItem.id;
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -1,6 +1,5 @@
package io.anuke.mindustry.world.blocks.units;
import io.anuke.annotations.Annotations.*;
import io.anuke.arc.*;
import io.anuke.arc.collection.*;
import io.anuke.arc.graphics.*;
@ -13,9 +12,8 @@ import io.anuke.mindustry.entities.*;
import io.anuke.mindustry.entities.Effects.*;
import io.anuke.mindustry.entities.type.*;
import io.anuke.mindustry.entities.units.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.gen.*;
import io.anuke.mindustry.game.*;
import io.anuke.mindustry.graphics.*;
import io.anuke.mindustry.ui.*;
import io.anuke.mindustry.world.*;
@ -95,7 +93,7 @@ public class CommandCenter extends Block{
Table buttons = new Table();
for(UnitCommand cmd : UnitCommand.all){
buttons.addImageButton(Core.atlas.drawable("icon-command-" + cmd.name() + "-small"), Styles.clearToggleTransi, () -> Call.onCommandCenterSet(player, tile, cmd))
buttons.addImageButton(Core.atlas.drawable("icon-command-" + cmd.name() + "-small"), Styles.clearToggleTransi, () -> tile.configure(cmd.ordinal()))
.size(44).group(group).update(b -> b.setChecked(entity.command == cmd));
}
table.add(buttons);
@ -103,10 +101,9 @@ public class CommandCenter extends Block{
table.label(() -> entity.command.localized()).style(Styles.outlineLabel).center().growX().get().setAlignment(Align.center);
}
@Remote(called = Loc.server, forward = true, targets = Loc.both)
public static void onCommandCenterSet(Player player, Tile tile, UnitCommand command){
if(player == null || tile == null || !Units.canInteract(player, tile)) return;
@Override
public void configured(Tile tile, Player player, int value){
UnitCommand command = UnitCommand.all[value];
Effects.effect(((CommandCenter)tile.block()).effect, tile);
for(Tile center : indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter)){
@ -133,6 +130,11 @@ public class CommandCenter extends Block{
public class CommandCenterEntity extends TileEntity{
public UnitCommand command = UnitCommand.attack;
@Override
public int config(){
return command.ordinal();
}
@Override
public void write(DataOutput stream) throws IOException{
super.write(stream);

View File

@ -0,0 +1,15 @@
- Fixed iOS/Android having frozen multiplayer
- Fixed Veins map not having a silicon source
- Fixed inaccurate enemy shoot prediction
- Fixed server crash exploit
- Fixed panes not scrolling with mousewheel [Desktop]
- Fixed incorrect PvP team assignment
- Fixed not being able to tap 'ok' in UI scale changed dialog
- Fixed not being able to play on PvP maps without orange team
- Fixed error message on exiting server after saved map
- Fixed attack map completion displaying low rank
- Possibly fixed Mac version not starting
- Switched to TCP from UDP - experimental
- Added descriptive display when failing to connect due to version mismatch
- Improved smoothness of multiplayer building, rotation and collision
- Improved power node linking

View File

@ -0,0 +1,11 @@
- Added new spawn animations w/ progress bar and names
- Added configurable server whitelist based on player UUID
- Added many new events for plugins
- Added core land animation
- Added player limit for servers
- Added gamemode display for server/save lists
- Added new filechooser for Android, fixes file access on Android 10
- Added core storage space increase via adjacent vaults or containers
- Made unloader be able to take items from any block
- Improved votekick sensitivity
- Fixed many various bugs

View File

@ -0,0 +1,8 @@
- Fixed tutorial displaying Desktop text on Android
- Fixed common crash related to status effects
- Fixed launch pads launching entire core contents
- Fixed new maps overwriting old ones without warning
- Fixed phase conveyors operating on near-0 power
- Fixed incorrect message dialog layout
- Fixed some crashes
- Reverted removal of router passback

View File

@ -0,0 +1,12 @@
- Fixed zone exploit caused by import of zone saves
- Reverted to old file chooser when possible [Android]
- New multithreaded pathfinding implementation
- Made attack command have units move toward enemy spawnpoints in survival
- Made votekick still tempban people after disconnection
- Added 'rally' command to command center, replaces old patrol command
- Added full Android keyboard support, completely removes any touch input, adds desktop keys
- Added ability to rotate lines while placing [Desktop] [Contributed by Synray]
- Added votekick button
- Added display of power capacity in power graphs
- Added armored conveyors - more armor than titanium, don't accept items from sides
- Added message blocks - editable text