Merge branch 'master' of https://github.com/Anuken/Mindustry into crafting-rework
This commit is contained in:
@@ -51,8 +51,8 @@ public class BlockIndexer{
|
||||
|
||||
public BlockIndexer(){
|
||||
Events.on(TileChangeEvent.class, event -> {
|
||||
if(typeMap.get(event.tile.packedPosition()) != null){
|
||||
TileIndex index = typeMap.get(event.tile.packedPosition());
|
||||
if(typeMap.get(event.tile.pos()) != null){
|
||||
TileIndex index = typeMap.get(event.tile.pos());
|
||||
for(BlockFlag flag : index.flags){
|
||||
getFlagged(index.team)[flag.ordinal()].remove(event.tile);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class BlockIndexer{
|
||||
|
||||
process(tile);
|
||||
|
||||
if(tile.entity != null && tile.entity.healthf() < 0.9999f){
|
||||
if(tile.entity != null && tile.entity.damaged()){
|
||||
notifyTileDamaged(tile.entity);
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class BlockIndexer{
|
||||
|
||||
ObjectSet<Tile> set = damagedTiles[team.ordinal()];
|
||||
for(Tile tile : set){
|
||||
if(tile.entity == null || tile.entity.getTeam() != team || tile.entity.healthf() >= 0.9999f){
|
||||
if(tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()){
|
||||
returnArray.add(tile);
|
||||
}
|
||||
}
|
||||
@@ -230,7 +230,7 @@ public class BlockIndexer{
|
||||
|
||||
map[flag.ordinal()] = arr;
|
||||
}
|
||||
typeMap.put(tile.packedPosition(), new TileIndex(tile.block().flags, tile.getTeam()));
|
||||
typeMap.put(tile.pos(), new TileIndex(tile.block().flags, tile.getTeam()));
|
||||
}
|
||||
|
||||
if(ores == null) return;
|
||||
|
||||
@@ -10,9 +10,9 @@ import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.Waves;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.util.Structs;
|
||||
import io.anuke.ucore.util.GridBits;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Structs;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -21,7 +21,7 @@ import java.io.IOException;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class WaveSpawner{
|
||||
private static final int quadsize = 4;
|
||||
private static final int quadsize = 6;
|
||||
|
||||
private GridBits quadrants;
|
||||
|
||||
@@ -164,7 +164,7 @@ public class WaveSpawner{
|
||||
for(int y = quady * quadsize; y < world.height() && y < (quady + 1) * quadsize; y++){
|
||||
Tile tile = world.tile(x, y);
|
||||
|
||||
if(tile == null || tile.solid() || world.pathfinder.getValueforTeam(Team.red, x, y) == Float.MAX_VALUE){
|
||||
if(tile == null || tile.solid() || tile.getTeam() == defaultTeam || world.pathfinder.getValueforTeam(Team.red, x, y) == Float.MAX_VALUE || tile.floor().isLiquid){
|
||||
setQuad(quadx, quady, false);
|
||||
break outer;
|
||||
}
|
||||
@@ -217,8 +217,8 @@ public class WaveSpawner{
|
||||
|
||||
//TODO instead of randomly scattering locations around the map, find spawns close to each other
|
||||
private void findLocation(GroundSpawn spawn){
|
||||
spawn.x = -1;
|
||||
spawn.y = -1;
|
||||
spawn.x = Mathf.random(quadWidth()-1);
|
||||
spawn.y = Mathf.random(quadHeight()-1);
|
||||
|
||||
int shellWidth = quadWidth() * 2 + quadHeight() * 2 * 6;
|
||||
shellWidth = Math.min(quadWidth() * quadHeight() / 4, shellWidth);
|
||||
|
||||
@@ -83,7 +83,7 @@ public class Items implements ContentList{
|
||||
}};
|
||||
|
||||
biomatter = new Item("biomatter", Color.valueOf("648b55")){{
|
||||
flammability = 0.4f;
|
||||
flammability = 0.55f;
|
||||
fluxiness = 0.3f;
|
||||
}};
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Liquids implements ContentList{
|
||||
|
||||
lava = new Liquid("lava", Color.valueOf("e37341")){
|
||||
{
|
||||
temperature = 0.8f;
|
||||
temperature = 1f;
|
||||
viscosity = 0.8f;
|
||||
tier = 2;
|
||||
effect = StatusEffects.melting;
|
||||
|
||||
@@ -123,6 +123,7 @@ public class Mechs implements ContentList{
|
||||
speed = 0.44f;
|
||||
drag = 0.35f;
|
||||
boostSpeed = 0.8f;
|
||||
canHeal = true;
|
||||
weapon = Weapons.healBlaster;
|
||||
armor = 15f;
|
||||
trailColorTo = Palette.heal;
|
||||
@@ -287,8 +288,8 @@ public class Mechs implements ContentList{
|
||||
trident = new Mech("trident-ship", true){
|
||||
{
|
||||
drillPower = 2;
|
||||
speed = 0.12f;
|
||||
drag = 0.035f;
|
||||
speed = 0.14f;
|
||||
drag = 0.034f;
|
||||
mass = 2.5f;
|
||||
turnCursor = false;
|
||||
armor = 20f;
|
||||
|
||||
@@ -42,17 +42,23 @@ public class Recipes implements ContentList{
|
||||
new Recipe(defense, DefenseBlocks.surgeWall, new ItemStack(Items.surgealloy, 12));
|
||||
new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4));
|
||||
|
||||
new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
|
||||
new Recipe(effect, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
|
||||
|
||||
//core disabled due to being broken
|
||||
new Recipe(effect, StorageBlocks.core,
|
||||
new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500),
|
||||
new ItemStack(Items.silicon, 1500), new ItemStack(Items.thorium, 500),
|
||||
new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750)
|
||||
);
|
||||
|
||||
//projectors
|
||||
new Recipe(effect, DefenseBlocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180));
|
||||
new Recipe(effect, DefenseBlocks.overdriveProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
|
||||
new Recipe(effect, DefenseBlocks.forceProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
|
||||
|
||||
new Recipe(effect, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60));
|
||||
new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
|
||||
new Recipe(effect, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
|
||||
|
||||
new Recipe(effect, DefenseBlocks.shockMine, new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 25))
|
||||
.setDependencies(Items.blastCompound);
|
||||
.setDependencies(Items.blastCompound);
|
||||
|
||||
//TURRETS
|
||||
new Recipe(turret, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true);
|
||||
@@ -82,6 +88,7 @@ public class Recipes implements ContentList{
|
||||
new Recipe(distribution, DistributionBlocks.sorter, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 4));
|
||||
new Recipe(distribution, DistributionBlocks.overflowGate, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 8));
|
||||
new Recipe(distribution, DistributionBlocks.itemBridge, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8));
|
||||
new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60));
|
||||
new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.densealloy, 250), new ItemStack(Items.silicon, 150), new ItemStack(Items.lead, 250), new ItemStack(Items.thorium, 100));
|
||||
|
||||
//CRAFTING
|
||||
@@ -133,13 +140,6 @@ public class Recipes implements ContentList{
|
||||
new Recipe(power, PowerBlocks.thoriumReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.densealloy, 300), new ItemStack(Items.thorium, 300));
|
||||
new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasefabric, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100));
|
||||
|
||||
//core disabled due to being broken
|
||||
/*new Recipe(distribution, StorageBlocks.core,
|
||||
new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500),
|
||||
new ItemStack(Items.silicon, 1500), new ItemStack(Items.thorium, 500),
|
||||
new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750)
|
||||
);*/
|
||||
|
||||
//DRILLS, PRODUCERS
|
||||
new Recipe(production, ProductionBlocks.mechanicalDrill, new ItemStack(Items.copper, 45)).setAlwaysUnlocked(true);
|
||||
new Recipe(production, ProductionBlocks.pneumaticDrill, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 50));
|
||||
|
||||
@@ -11,7 +11,7 @@ import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
public class StatusEffects implements ContentList{
|
||||
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded;
|
||||
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked;
|
||||
|
||||
@Override
|
||||
public void load(){
|
||||
@@ -47,7 +47,8 @@ public class StatusEffects implements ContentList{
|
||||
freezing = new StatusEffect(5 * 60f){
|
||||
{
|
||||
oppositeScale = 0.4f;
|
||||
speedMultiplier = 0.5f;
|
||||
speedMultiplier = 0.6f;
|
||||
armorMultiplier = 0.8f;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +66,17 @@ public class StatusEffects implements ContentList{
|
||||
speedMultiplier = 0.9f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatusEntry getTransition(Unit unit, StatusEffect to, float time, float newTime, StatusEntry result){
|
||||
if(to == shocked){
|
||||
//get shocked when wet
|
||||
unit.damage(15f);
|
||||
return result.set(this, time);
|
||||
}
|
||||
|
||||
return super.getTransition(unit, to, time, newTime, result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Unit unit, float time){
|
||||
if(Mathf.chance(Timers.delta() * 0.15f)){
|
||||
@@ -145,6 +157,13 @@ public class StatusEffects implements ContentList{
|
||||
}
|
||||
};
|
||||
|
||||
shocked = new StatusEffect(1f){
|
||||
{
|
||||
armorMultiplier = 3f;
|
||||
}
|
||||
};
|
||||
|
||||
wet.setOpposites(shocked);
|
||||
melting.setOpposites(wet, freezing);
|
||||
wet.setOpposites(burning);
|
||||
freezing.setOpposites(burning, melting);
|
||||
|
||||
@@ -152,7 +152,7 @@ public class Weapons implements ContentList{
|
||||
bomberTrident = new Weapon("bomber"){{
|
||||
length = 0f;
|
||||
width = 2f;
|
||||
reload = 9f;
|
||||
reload = 8f;
|
||||
shots = 2;
|
||||
roundrobin = true;
|
||||
ejectEffect = Fx.none;
|
||||
|
||||
@@ -185,9 +185,9 @@ public class CraftingBlocks extends BlockList implements ContentList{
|
||||
biomatterCompressor = new Compressor("biomattercompressor"){{
|
||||
liquidCapacity = 60f;
|
||||
itemCapacity = 50;
|
||||
craftTime = 25f;
|
||||
craftTime = 20f;
|
||||
outputLiquid = Liquids.oil;
|
||||
outputLiquidAmount = 1.5f;
|
||||
outputLiquidAmount = 2.5f;
|
||||
size = 2;
|
||||
health = 320;
|
||||
hasLiquids = true;
|
||||
|
||||
@@ -92,8 +92,11 @@ public class DebugBlocks extends BlockList implements ContentList{
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
SorterEntity entity = tile.entity();
|
||||
if(entity.sortItem == null) return;
|
||||
|
||||
entity.items.set(entity.sortItem, 1);
|
||||
tryDump(tile, entity.sortItem);
|
||||
entity.items.set(entity.sortItem, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -50,10 +50,10 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
||||
}};
|
||||
|
||||
liquidRouter = new LiquidRouter("liquid-router"){{
|
||||
liquidCapacity = 40f;
|
||||
liquidCapacity = 20f;
|
||||
}};
|
||||
|
||||
liquidtank = new LiquidRouter("liquid-tank"){{
|
||||
liquidtank = new LiquidTank("liquid-tank"){{
|
||||
size = 3;
|
||||
liquidCapacity = 1500f;
|
||||
health = 500;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class PowerBlocks extends BlockList implements ContentList{
|
||||
thermalGenerator = new LiquidHeatGenerator("thermal-generator"){{
|
||||
maxLiquidGenerate = 2f;
|
||||
powerCapacity = 40f;
|
||||
powerPerLiquid = 0.3f;
|
||||
powerPerLiquid = 0.35f;
|
||||
generateEffect = BlockFx.redgeneratespark;
|
||||
size = 2;
|
||||
}};
|
||||
|
||||
@@ -99,13 +99,13 @@ public class ProductionBlocks extends BlockList implements ContentList{
|
||||
|
||||
cultivator = new Cultivator("cultivator"){{
|
||||
result = Items.biomatter;
|
||||
drillTime = 260;
|
||||
drillTime = 200;
|
||||
size = 2;
|
||||
hasLiquids = true;
|
||||
hasPower = true;
|
||||
|
||||
consumes.power(0.08f);
|
||||
consumes.liquid(Liquids.water, 0.2f);
|
||||
consumes.liquid(Liquids.water, 0.15f);
|
||||
}};
|
||||
|
||||
}
|
||||
|
||||
@@ -13,20 +13,21 @@ public class StorageBlocks extends BlockList implements ContentList{
|
||||
public void load(){
|
||||
core = new CoreBlock("core"){{
|
||||
health = 1100;
|
||||
itemCapacity = 3000;
|
||||
}};
|
||||
|
||||
vault = new Vault("vault"){{
|
||||
size = 3;
|
||||
itemCapacity = 900;
|
||||
itemCapacity = 1000;
|
||||
}};
|
||||
|
||||
container = new Vault("container"){{
|
||||
size = 2;
|
||||
itemCapacity = 200;
|
||||
itemCapacity = 300;
|
||||
}};
|
||||
|
||||
unloader = new SortedUnloader("unloader"){{
|
||||
speed = 12f;
|
||||
speed = 7f;
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
inaccuracy = 5f;
|
||||
shootCone = 50f;
|
||||
shootEffect = ShootFx.shootLiquid;
|
||||
range = 70f;
|
||||
range = 90f;
|
||||
health = 360;
|
||||
|
||||
drawer = (tile, entity) -> {
|
||||
|
||||
@@ -39,6 +39,8 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
lifetime = Lightning.lifetime;
|
||||
hiteffect = BulletFx.hitLancer;
|
||||
despawneffect = Fx.none;
|
||||
status = StatusEffects.shocked;
|
||||
statusIntensity = 1f;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -71,7 +73,7 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
super.hit(b);
|
||||
tile = tile.target();
|
||||
|
||||
if(tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){
|
||||
if(tile != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){
|
||||
Effects.effect(BlockFx.healBlockFull, Palette.heal, tile.drawx(), tile.drawy(), tile.block().size);
|
||||
tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth());
|
||||
}
|
||||
@@ -332,7 +334,7 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
lifetime = 200f;
|
||||
despawneffect = BlockFx.smeltsmoke;
|
||||
hiteffect = BulletFx.hitBulletBig;
|
||||
drag = 0.01f;
|
||||
drag = 0.005f;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,10 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.entities.EntityQuery;
|
||||
import io.anuke.ucore.modules.Module;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Atlas;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
import io.anuke.ucore.util.Strings;
|
||||
import io.anuke.ucore.util.Timer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -372,7 +375,7 @@ public class Control extends Module{
|
||||
}
|
||||
}
|
||||
|
||||
if(Inputs.keyTap("screenshot")){
|
||||
if(!mobile && Inputs.keyTap("screenshot") && !ui.chatfrag.chatOpen()){
|
||||
renderer.takeMapScreenshot();
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,9 @@ public class NetServer extends Module{
|
||||
|
||||
public NetServer(){
|
||||
Events.on(WorldLoadEvent.class, event -> {
|
||||
connections.clear();
|
||||
if(!headless){
|
||||
connections.clear();
|
||||
}
|
||||
});
|
||||
|
||||
Net.handleServer(Connect.class, (id, connect) -> {
|
||||
@@ -125,7 +127,7 @@ public class NetServer extends Module{
|
||||
return;
|
||||
}
|
||||
|
||||
if(packet.versionType == null || ((packet.version == -1 || !packet.versionType.equals("official")) && Version.build != -1 && !admins.allowsCustomClients())){
|
||||
if(packet.versionType == null || ((packet.version == -1 || !packet.versionType.equals(Version.type)) && Version.build != -1 && !admins.allowsCustomClients())){
|
||||
kick(id, KickReason.customClient);
|
||||
return;
|
||||
}
|
||||
@@ -279,6 +281,7 @@ public class NetServer extends Module{
|
||||
}
|
||||
player.remove();
|
||||
netServer.connections.remove(player.con.id);
|
||||
Log.info("&lc{0} has disconnected.", player.name);
|
||||
}
|
||||
|
||||
private static float compound(float speed, float drag){
|
||||
@@ -379,7 +382,7 @@ public class NetServer extends Module{
|
||||
return;
|
||||
}
|
||||
|
||||
if(other == null || (other.isAdmin && other != player)){ //fun fact: this means you can ban yourself
|
||||
if(other == null || ((other.isAdmin && !player.isLocal) && other != player)){
|
||||
Log.err("{0} attempted to perform admin action on nonexistant or admin player.", player.name);
|
||||
return;
|
||||
}
|
||||
@@ -490,7 +493,7 @@ public class NetServer extends Module{
|
||||
|
||||
//write all core inventory data
|
||||
for(Tile tile : cores){
|
||||
dataStream.writeInt(tile.packedPosition());
|
||||
dataStream.writeInt(tile.pos());
|
||||
tile.entity.items.write(dataStream);
|
||||
}
|
||||
|
||||
@@ -596,14 +599,18 @@ public class NetServer extends Module{
|
||||
}
|
||||
|
||||
void sync(){
|
||||
|
||||
try{
|
||||
|
||||
//iterate through each player
|
||||
for(Player player : connections.values()){
|
||||
for(int i = 0; i < playerGroup.size(); i ++){
|
||||
Player player = playerGroup.all().get(i);
|
||||
if(player.isLocal) continue;
|
||||
|
||||
NetConnection connection = player.con;
|
||||
|
||||
if(!connection.isConnected()){
|
||||
//player disconnected, ignore them
|
||||
if(!connection.isConnected() || !connections.containsKey(connection.id)){
|
||||
//player disconnected, call d/c event
|
||||
onDisconnect(player);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,9 +32,22 @@ public abstract class Platform {
|
||||
dialog.setFillParent(true);
|
||||
dialog.content().top();
|
||||
dialog.content().defaults().height(65f);
|
||||
|
||||
TextField[] use = {null};
|
||||
|
||||
dialog.content().addImageButton("icon-copy", "clear", 16*3, () -> use[0].copy())
|
||||
.visible(() -> !use[0].getSelection().isEmpty()).width(65f);
|
||||
|
||||
dialog.content().addImageButton("icon-paste", "clear", 16*3, () ->
|
||||
use[0].paste(Gdx.app.getClipboard().getContents(), false))
|
||||
.visible(() -> Gdx.app.getClipboard() != null && Gdx.app.getClipboard().getContents() != null && !Gdx.app.getClipboard().getContents().isEmpty()).width(65f);
|
||||
|
||||
TextField to = dialog.content().addField(field.getText(), t-> {}).pad(15).width(250f).get();
|
||||
to.setMaxLength(maxLength);
|
||||
to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick());
|
||||
|
||||
use[0] = to;
|
||||
|
||||
dialog.content().addButton("$text.ok", () -> {
|
||||
field.clearText();
|
||||
field.appendText(to.getText());
|
||||
|
||||
@@ -152,7 +152,7 @@ public class Renderer extends RendererModule{
|
||||
|
||||
if(players[0].isDead()){
|
||||
TileEntity core = players[0].getClosestCore();
|
||||
if(core != null && players[0].spawner == -1){
|
||||
if(core != null && players[0].spawner == Unit.noSpawner){
|
||||
smoothCamera(core.x, core.y, 0.08f);
|
||||
}else{
|
||||
smoothCamera(position.x + 0.0001f, position.y + 0.0001f, 0.08f);
|
||||
@@ -395,8 +395,8 @@ public class Renderer extends RendererModule{
|
||||
Graphics.getEffectSurface().setSize(w, h, true);
|
||||
Core.camera.viewportWidth = w;
|
||||
Core.camera.viewportHeight = h;
|
||||
Core.camera.position.x = w/2f;
|
||||
Core.camera.position.y = h/2f;
|
||||
Core.camera.position.x = w/2f + tilesize/2f;
|
||||
Core.camera.position.y = h/2f + tilesize/2f;
|
||||
|
||||
draw();
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.io.MapIO;
|
||||
import io.anuke.mindustry.maps.*;
|
||||
import io.anuke.mindustry.maps.generation.WorldGenerator;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||
import io.anuke.ucore.core.Events;
|
||||
@@ -30,8 +31,8 @@ public class World extends Module{
|
||||
public final Sectors sectors = new Sectors();
|
||||
public final WorldGenerator generator = new WorldGenerator();
|
||||
public final BlockIndexer indexer = new BlockIndexer();
|
||||
public final Pathfinder pathfinder = new Pathfinder();
|
||||
public final WaveSpawner spawner = new WaveSpawner();
|
||||
public final Pathfinder pathfinder = new Pathfinder();
|
||||
|
||||
private Map currentMap;
|
||||
private Sector currentSector;
|
||||
@@ -103,12 +104,8 @@ public class World extends Module{
|
||||
return tiles == null ? 0 : tiles[0].length;
|
||||
}
|
||||
|
||||
public int toPacked(int x, int y){
|
||||
return x + y * width();
|
||||
}
|
||||
|
||||
public Tile tile(int packed){
|
||||
return tiles == null ? null : tile(packed % width(), packed / width());
|
||||
public Tile tile(int pos){
|
||||
return tiles == null ? null : tile(Pos.x(pos), Pos.y(pos));
|
||||
}
|
||||
|
||||
public Tile tile(int x, int y){
|
||||
|
||||
@@ -567,16 +567,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
button.getImage().remove();
|
||||
button.update(() -> button.setChecked(editor.getDrawBlock() == block));
|
||||
group.add(button);
|
||||
content.add(button).size(60f);
|
||||
content.add(button).size(50f);
|
||||
|
||||
if(i++ % 3 == 2){
|
||||
if(++i % 4 == 0){
|
||||
content.row();
|
||||
}
|
||||
}
|
||||
|
||||
group.getButtons().get(2).setChecked(true);
|
||||
|
||||
table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().formalName).width(220f).center()).growX();
|
||||
table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().formalName).width(200f).center()).growX();
|
||||
table.row();
|
||||
table.add(pane).growY().fillX();
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
public boolean achievedFlight;
|
||||
public Color color = new Color();
|
||||
public Mech mech;
|
||||
public int spawner = -1;
|
||||
public int spawner = noSpawner;
|
||||
|
||||
public NetConnection con;
|
||||
public int playerIndex = 0;
|
||||
@@ -498,7 +498,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
updateRespawning();
|
||||
return;
|
||||
}else{
|
||||
spawner = -1;
|
||||
spawner = noSpawner;
|
||||
}
|
||||
|
||||
avoidOthers(1f);
|
||||
@@ -645,7 +645,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
}
|
||||
|
||||
protected void updateFlying(){
|
||||
if(Units.invalidateTarget(target, this)){
|
||||
if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
|
||||
mech.canHeal && distanceTo(target) < getWeapon().getAmmo().getRange())){
|
||||
target = null;
|
||||
}
|
||||
|
||||
@@ -726,11 +727,22 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
isShooting = false;
|
||||
if(Settings.getBool("autotarget")){
|
||||
target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().getRange());
|
||||
|
||||
if(mech.canHeal && target == null){
|
||||
target = Geometry.findClosest(x, y, world.indexer.getDamaged(Team.blue));
|
||||
if(target != null && distanceTo(target) > getWeapon().getAmmo().getRange()){
|
||||
target = null;
|
||||
}else if(target != null){
|
||||
target = ((Tile)target).entity;
|
||||
}
|
||||
}
|
||||
|
||||
if(target != null){
|
||||
setMineTile(null);
|
||||
}
|
||||
}
|
||||
}else if(target.isValid()){
|
||||
}else if(target.isValid() || (target instanceof TileEntity && ((TileEntity) target).damaged() && target.getTeam() == team &&
|
||||
mech.canHeal && distanceTo(target) < getWeapon().getAmmo().getRange())){
|
||||
//rotate toward and shoot the target
|
||||
if(mech.turnCursor){
|
||||
rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.2f);
|
||||
@@ -788,23 +800,23 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
|
||||
public void updateRespawning(){
|
||||
|
||||
if(spawner != -1 && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait){
|
||||
if(spawner != noSpawner && world.tile(spawner) != null && world.tile(spawner).entity instanceof SpawnerTrait){
|
||||
((SpawnerTrait) world.tile(spawner).entity).updateSpawning(this);
|
||||
}else{
|
||||
CoreEntity entity = (CoreEntity) getClosestCore();
|
||||
if(entity != null && !netServer.isWaitingForPlayers()){
|
||||
this.spawner = entity.tile.id();
|
||||
this.spawner = entity.tile.pos();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void beginRespawning(SpawnerTrait spawner){
|
||||
this.spawner = spawner.getTile().packedPosition();
|
||||
this.spawner = spawner.getTile().pos();
|
||||
this.dead = true;
|
||||
}
|
||||
|
||||
public void endRespawning(){
|
||||
spawner = -1;
|
||||
spawner = noSpawner;
|
||||
}
|
||||
|
||||
//endregion
|
||||
@@ -860,7 +872,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
buffer.writeByte(Bits.toByte(isAdmin) | (Bits.toByte(dead) << 1) | (Bits.toByte(isBoosting) << 2));
|
||||
buffer.writeInt(Color.rgba8888(color));
|
||||
buffer.writeByte(mech.id);
|
||||
buffer.writeInt(mining == null ? -1 : mining.packedPosition());
|
||||
buffer.writeInt(mining == null ? -1 : mining.pos());
|
||||
buffer.writeInt(spawner);
|
||||
buffer.writeShort((short) (baseRotation * 2));
|
||||
|
||||
|
||||
@@ -154,6 +154,10 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
}
|
||||
}
|
||||
|
||||
public boolean damaged(){
|
||||
return health < maxHealth() - 0.00001f;
|
||||
}
|
||||
|
||||
public Tile getTile(){
|
||||
return tile;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import io.anuke.mindustry.net.Interpolator;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.type.StatusEffect;
|
||||
import io.anuke.mindustry.type.Weapon;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
@@ -39,6 +40,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
public static final float velocityPercision = 8f;
|
||||
/**Maximum absolute value of a velocity vector component.*/
|
||||
public static final float maxAbsVelocity = 127f / velocityPercision;
|
||||
public static final int noSpawner = Pos.get(-1, 1);
|
||||
|
||||
private static final Rectangle queryRect = new Rectangle();
|
||||
private static final Vector2 moveVector = new Vector2();
|
||||
|
||||
@@ -48,7 +48,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
||||
public static void create(Tile tile){
|
||||
if(Net.client() || tile == null) return; //not clientside.
|
||||
|
||||
Fire fire = map.get(tile.packedPosition());
|
||||
Fire fire = map.get(tile.pos());
|
||||
|
||||
if(fire == null){
|
||||
fire = Pooling.obtain(Fire.class, Fire::new);
|
||||
@@ -56,7 +56,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
||||
fire.lifetime = baseLifetime;
|
||||
fire.set(tile.worldx(), tile.worldy());
|
||||
fire.add();
|
||||
map.put(tile.packedPosition(), fire);
|
||||
map.put(tile.pos(), fire);
|
||||
}else{
|
||||
fire.lifetime = baseLifetime;
|
||||
fire.time = 0f;
|
||||
@@ -75,8 +75,8 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
||||
* Attempts to extinguish a fire by shortening its life. If there is no fire here, does nothing.
|
||||
*/
|
||||
public static void extinguish(Tile tile, float intensity){
|
||||
if(tile != null && map.containsKey(tile.packedPosition())){
|
||||
map.get(tile.packedPosition()).time += intensity * Timers.delta();
|
||||
if(tile != null && map.containsKey(tile.pos())){
|
||||
map.get(tile.pos()).time += intensity * Timers.delta();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,7 +157,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
||||
|
||||
@Override
|
||||
public void writeSave(DataOutput stream) throws IOException{
|
||||
stream.writeInt(tile.packedPosition());
|
||||
stream.writeInt(tile.pos());
|
||||
stream.writeFloat(lifetime);
|
||||
stream.writeFloat(time);
|
||||
}
|
||||
@@ -202,7 +202,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
||||
@Override
|
||||
public void removed(){
|
||||
if(tile != null){
|
||||
map.remove(tile.packedPosition());
|
||||
map.remove(tile.pos());
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Effects.Effect;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.impl.EffectEntity;
|
||||
import io.anuke.ucore.function.EffectRenderer;
|
||||
import io.anuke.ucore.core.Effects.EffectRenderer;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
/**
|
||||
|
||||
@@ -91,7 +91,6 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time
|
||||
x += Angles.trnsx(rotation, hitRange/2f);
|
||||
y += Angles.trnsy(rotation, hitRange/2f);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
|
||||
/**Returns the puddle on the specified tile. May return null.*/
|
||||
public static Puddle getPuddle(Tile tile){
|
||||
return map.get(tile.packedPosition());
|
||||
return map.get(tile.pos());
|
||||
}
|
||||
|
||||
private static void deposit(Tile tile, Tile source, Liquid liquid, float amount, int generation){
|
||||
@@ -83,7 +83,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
reactPuddle(tile.floor().liquidDrop, liquid, amount, tile,
|
||||
(tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||
|
||||
Puddle p = map.get(tile.packedPosition());
|
||||
Puddle p = map.get(tile.pos());
|
||||
|
||||
if(generation == 0 && p != null && p.lastRipple <= Timers.time() - 40f){
|
||||
Effects.effect(BlockFx.ripple, tile.floor().liquidDrop.color,
|
||||
@@ -93,7 +93,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
return;
|
||||
}
|
||||
|
||||
Puddle p = map.get(tile.packedPosition());
|
||||
Puddle p = map.get(tile.pos());
|
||||
if(p == null){
|
||||
if(Net.client()) return; //not clientside.
|
||||
|
||||
@@ -104,7 +104,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
puddle.generation = (byte) generation;
|
||||
puddle.set((tile.worldx() + source.worldx()) / 2f, (tile.worldy() + source.worldy()) / 2f);
|
||||
puddle.add();
|
||||
map.put(tile.packedPosition(), puddle);
|
||||
map.put(tile.pos(), puddle);
|
||||
}else if(p.liquid == liquid){
|
||||
p.accepting = Math.max(amount, p.accepting);
|
||||
|
||||
@@ -249,7 +249,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
|
||||
@Override
|
||||
public void writeSave(DataOutput stream) throws IOException{
|
||||
stream.writeInt(tile.packedPosition());
|
||||
stream.writeInt(tile.pos());
|
||||
stream.writeFloat(x);
|
||||
stream.writeFloat(y);
|
||||
stream.writeByte(liquid.id);
|
||||
@@ -288,7 +288,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
map.remove(tile.packedPosition());
|
||||
map.remove(tile.pos());
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -298,7 +298,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
data.writeFloat(y);
|
||||
data.writeByte(liquid.id);
|
||||
data.writeShort((short) (amount * 4));
|
||||
data.writeInt(tile.packedPosition());
|
||||
data.writeInt(tile.pos());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -309,7 +309,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
||||
targetAmount = data.readShort() / 4f;
|
||||
tile = world.tile(data.readInt());
|
||||
|
||||
map.put(tile.packedPosition(), this);
|
||||
map.put(tile.pos(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.world.Build;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
@@ -27,7 +28,10 @@ import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Fill;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.graphics.Shapes;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -72,7 +76,7 @@ public interface BuilderTrait extends Entity{
|
||||
|
||||
if(request != null){
|
||||
output.writeByte(request.breaking ? 1 : 0);
|
||||
output.writeInt(world.toPacked(request.x, request.y));
|
||||
output.writeInt(Pos.get(request.x, request.y));
|
||||
output.writeFloat(request.progress);
|
||||
if(!request.breaking){
|
||||
output.writeByte(request.recipe.id);
|
||||
@@ -96,13 +100,13 @@ public interface BuilderTrait extends Entity{
|
||||
float progress = input.readFloat();
|
||||
BuildRequest request;
|
||||
|
||||
if(type == 1){ //remove
|
||||
request = new BuildRequest(position % world.width(), position / world.width());
|
||||
}else{ //place
|
||||
byte recipe = input.readByte();
|
||||
byte rotation = input.readByte();
|
||||
request = new BuildRequest(position % world.width(), position / world.width(), rotation, content.recipe(recipe));
|
||||
}
|
||||
if(type == 1){ //remove
|
||||
request = new BuildRequest(Pos.x(position), Pos.y(position));
|
||||
}else{ //place
|
||||
byte recipe = input.readByte();
|
||||
byte rotation = input.readByte();
|
||||
request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe));
|
||||
}
|
||||
|
||||
request.progress = progress;
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
protected boolean isWave;
|
||||
protected Squad squad;
|
||||
protected int spawner = -1;
|
||||
protected int spawner = noSpawner;
|
||||
|
||||
/**internal constructor used for deserialization, DO NOT USE*/
|
||||
public BaseUnit(){
|
||||
@@ -111,16 +111,8 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
return type;
|
||||
}
|
||||
|
||||
public Tile getSpawner(){
|
||||
return world.tile(spawner);
|
||||
}
|
||||
|
||||
public void setSpawner(Tile tile){
|
||||
this.spawner = tile.packedPosition();
|
||||
}
|
||||
|
||||
public void setIntSpawner(int pos){
|
||||
this.spawner = pos;
|
||||
this.spawner = tile.pos();
|
||||
}
|
||||
|
||||
/**Sets this to a 'wave' unit, which means it has slightly different AI and will not run out of ammo.*/
|
||||
@@ -143,7 +135,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
}
|
||||
|
||||
public void updateRespawning(){
|
||||
if(spawner == -1) return;
|
||||
if(spawner == noSpawner) return;
|
||||
|
||||
Tile tile = world.tile(spawner);
|
||||
if(tile != null && tile.entity != null){
|
||||
@@ -151,7 +143,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
((SpawnerTrait) tile.entity).updateSpawning(this);
|
||||
}
|
||||
}else{
|
||||
spawner = -1;
|
||||
spawner = noSpawner;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +297,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
avoidOthers(1.25f);
|
||||
|
||||
if(spawner != -1 && (world.tile(spawner) == null || world.tile(spawner).entity == null)){
|
||||
if(spawner != noSpawner && (world.tile(spawner) == null || world.tile(spawner).entity == null)){
|
||||
damage(health);
|
||||
}
|
||||
|
||||
@@ -336,7 +328,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
@Override
|
||||
public void removed(){
|
||||
spawner = -1;
|
||||
spawner = noSpawner;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -358,8 +358,8 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
@Override
|
||||
public void write(DataOutput data) throws IOException{
|
||||
super.write(data);
|
||||
data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.packedPosition());
|
||||
data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.packedPosition() : -1);
|
||||
data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.pos());
|
||||
data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : -1);
|
||||
writeBuilding(data);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package io.anuke.mindustry.game;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.function.Event;
|
||||
import io.anuke.ucore.core.Events.Event;
|
||||
|
||||
public class EventType{
|
||||
|
||||
|
||||
@@ -11,9 +11,8 @@ public enum GameMode{
|
||||
freebuild{{
|
||||
disableWaveTimer = true;
|
||||
}},
|
||||
noWaves{{
|
||||
attack{{
|
||||
disableWaves = true;
|
||||
hidden = true;
|
||||
enemyCheat = true;
|
||||
}},
|
||||
victory{{
|
||||
|
||||
@@ -127,6 +127,7 @@ public class Saves{
|
||||
saveMap.put(slot.index, slot);
|
||||
slot.meta = SaveIO.getData(slot.index);
|
||||
current = slot;
|
||||
slot.meta.sector = invalidSector;
|
||||
saveSlots();
|
||||
return slot;
|
||||
}
|
||||
@@ -164,26 +165,17 @@ public class Saves{
|
||||
|
||||
public void save(){
|
||||
long time = totalPlaytime;
|
||||
renderer.fog.writeFog();
|
||||
long prev = totalPlaytime;
|
||||
totalPlaytime = time;
|
||||
|
||||
threads.runGraphics(() -> {
|
||||
//Renderer fog needs to be written on graphics thread, but save() can run on logic thread
|
||||
//thus, runGraphics is required here
|
||||
renderer.fog.writeFog();
|
||||
SaveIO.saveToSlot(index);
|
||||
meta = SaveIO.getData(index);
|
||||
if(!state.is(State.menu)){
|
||||
current = this;
|
||||
}
|
||||
|
||||
//save on the logic thread
|
||||
threads.run(() -> {
|
||||
long prev = totalPlaytime;
|
||||
totalPlaytime = time;
|
||||
|
||||
SaveIO.saveToSlot(index);
|
||||
meta = SaveIO.getData(index);
|
||||
if(!state.is(State.menu)){
|
||||
current = this;
|
||||
}
|
||||
|
||||
totalPlaytime = prev;
|
||||
});
|
||||
});
|
||||
totalPlaytime = prev;
|
||||
}
|
||||
|
||||
public boolean isHidden(){
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.ObjectMap.Entry;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import io.anuke.mindustry.game.EventType.UnlockEvent;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
@@ -67,27 +65,8 @@ public class Unlocks{
|
||||
save();
|
||||
}
|
||||
|
||||
/**Loads 'legacy' unlocks. Will be removed in final release.*/
|
||||
public void tryLoadLegacy(){
|
||||
try{
|
||||
ObjectMap<String, ObjectMap<ContentType, Array<String>>> sets = Settings.getObject("content-sets", ObjectMap.class, ObjectMap::new);
|
||||
for(Entry<ContentType, Array<String>> entry : sets.get("root").entries()){
|
||||
unlocked.put(entry.key, new ObjectSet<>());
|
||||
unlocked.get(entry.key).addAll(entry.value);
|
||||
}
|
||||
}catch(Throwable t){
|
||||
t.printStackTrace();
|
||||
}
|
||||
Settings.prefs().remove("content-sets");
|
||||
Settings.save();
|
||||
}
|
||||
|
||||
public void load(){
|
||||
unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new);
|
||||
|
||||
if(Settings.has("content-sets")){
|
||||
tryLoadLegacy();
|
||||
}
|
||||
}
|
||||
|
||||
public void save(){
|
||||
|
||||
@@ -96,6 +96,14 @@ public class Waves{
|
||||
max = 10;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.fortress){{
|
||||
begin = 40;
|
||||
spacing = 5;
|
||||
unitAmount = 2;
|
||||
unitScaling = 3;
|
||||
max = 10;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.dagger){{
|
||||
begin = 35;
|
||||
spacing = 3;
|
||||
@@ -134,6 +142,15 @@ public class Waves{
|
||||
max = 8;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.revenant){{
|
||||
begin = 50;
|
||||
unitAmount = 4;
|
||||
unitScaling = 3;
|
||||
spacing = 5;
|
||||
groupAmount = 2;
|
||||
max = 8;
|
||||
}},
|
||||
|
||||
new SpawnGroup(UnitTypes.ghoul){{
|
||||
begin = 53;
|
||||
unitAmount = 2;
|
||||
|
||||
@@ -77,9 +77,11 @@ public class FogRenderer implements Disposable{
|
||||
|
||||
pixelBuffer.position(0);
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
int x = i % world.width();
|
||||
int y = i / world.width();
|
||||
byte r = pixelBuffer.get();
|
||||
if(r != 0){
|
||||
world.tile(i).setVisibility((byte)1);
|
||||
world.tile(x, y).setVisibility((byte)1);
|
||||
}
|
||||
pixelBuffer.position(pixelBuffer.position() + 3);
|
||||
}
|
||||
@@ -128,10 +130,12 @@ public class FogRenderer implements Disposable{
|
||||
changeQueue.clear();
|
||||
|
||||
if(dirty){
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i);
|
||||
if(tile.discovered()){
|
||||
Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize);
|
||||
for(int x = 0; x < world.width(); x++){
|
||||
for(int y = 0; y < world.height(); y++){
|
||||
Tile tile = world.tile(x, y);
|
||||
if(tile.discovered()){
|
||||
Fill.rect(tile.worldx(), tile.worldy(), tilesize, tilesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
dirty = false;
|
||||
|
||||
@@ -200,9 +200,10 @@ public class OverlayRenderer{
|
||||
}
|
||||
|
||||
void drawBar(Color color, float x, float y, float finion){
|
||||
if(finion > 0.9f) finion = 1f; //fixes precision errors
|
||||
finion = Mathf.clamp(finion);
|
||||
|
||||
if(finion > 0) finion = Mathf.clamp(finion + 0.2f, 0.24f, 1f);
|
||||
if(finion > 0.001f) finion = Mathf.clamp(finion, 0.24f, 1f);
|
||||
|
||||
float len = 3;
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ public abstract class InputHandler extends InputAdapter{
|
||||
ItemTransfer.create(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), () -> {
|
||||
if(tile.block() != block || tile.entity == null) return;
|
||||
if(tile.block() != block || tile.entity == null || tile.entity.items == null) return;
|
||||
|
||||
tile.block().handleStack(item, removed, tile, player);
|
||||
remaining[1] -= removed;
|
||||
|
||||
@@ -96,6 +96,9 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
TileEntity entity = tile.entity;
|
||||
player.setMineTile(null);
|
||||
player.target = entity;
|
||||
}else if(tile != null && player.mech.canHeal && tile.entity != null && tile.getTeam() == player.getTeam() && tile.entity.damaged()){
|
||||
player.setMineTile(null);
|
||||
player.target = tile.entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,11 +224,6 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
}
|
||||
}).update(l -> l.setChecked(mode == breaking));
|
||||
|
||||
//rotate button
|
||||
table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4))
|
||||
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center))
|
||||
.visible(() -> recipe != null && recipe.result.rotate);
|
||||
|
||||
//cancel button
|
||||
table.addImageButton("icon-cancel", "clear-partial", 16 * 2f, () -> {
|
||||
player.clearBuilding();
|
||||
@@ -233,6 +231,11 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
recipe = null;
|
||||
}).visible(() -> player.isBuilding() || recipe != null || mode == breaking);
|
||||
|
||||
//rotate button
|
||||
table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4))
|
||||
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center))
|
||||
.visible(() -> recipe != null && recipe.result.rotate);
|
||||
|
||||
//confirm button
|
||||
table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> {
|
||||
for(PlaceRequest request : selection){
|
||||
@@ -242,8 +245,10 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(tile != null){
|
||||
if(!request.remove){
|
||||
rotation = request.rotation;
|
||||
Recipe before = recipe;
|
||||
recipe = request.recipe;
|
||||
tryPlaceBlock(tile.x, tile.y);
|
||||
recipe = before;
|
||||
}else{
|
||||
tryBreakBlock(tile.x, tile.y);
|
||||
}
|
||||
@@ -596,6 +601,10 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
showGuide("construction");
|
||||
}
|
||||
|
||||
if(recipe == null && mode == placing){
|
||||
mode = none;
|
||||
}
|
||||
|
||||
//automatically switch to placing after a new recipe is selected
|
||||
if(lastRecipe != recipe && mode == breaking && recipe != null){
|
||||
mode = placing;
|
||||
|
||||
@@ -50,7 +50,7 @@ public abstract class SaveFileVersion{
|
||||
stream.writeShort(world.height());
|
||||
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i);
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
|
||||
stream.writeByte(tile.getFloorID());
|
||||
stream.writeByte(tile.getBlockID());
|
||||
@@ -73,7 +73,7 @@ public abstract class SaveFileVersion{
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
|
||||
Tile nextTile = world.tile(j);
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getElevation() != tile.getElevation()){
|
||||
break;
|
||||
@@ -89,13 +89,13 @@ public abstract class SaveFileVersion{
|
||||
|
||||
//write visibility, length-run encoded
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i);
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
boolean discovered = tile.discovered();
|
||||
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){
|
||||
Tile nextTile = world.tile(j);
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.discovered() != discovered){
|
||||
break;
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.zip.InflaterInputStream;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class SaveIO{
|
||||
public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56);
|
||||
public static final IntArray breakingVersions = IntArray.with(47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58);
|
||||
public static final IntMap<SaveFileVersion> versions = new IntMap<>();
|
||||
public static final Array<SaveFileVersion> versionArray = Array.with(
|
||||
new Save16()
|
||||
|
||||
@@ -18,6 +18,7 @@ import io.anuke.mindustry.net.Packets.AdminAction;
|
||||
import io.anuke.mindustry.net.Packets.KickReason;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Effects.Effect;
|
||||
@@ -52,6 +53,10 @@ public class TypeIO{
|
||||
|
||||
@WriteClass(Unit.class)
|
||||
public static void writeUnit(ByteBuffer buffer, Unit unit){
|
||||
if(unit.getGroup() == null){
|
||||
buffer.put((byte)-1);
|
||||
return;
|
||||
}
|
||||
buffer.put((byte) unit.getGroup().getID());
|
||||
buffer.putInt(unit.getID());
|
||||
}
|
||||
@@ -59,6 +64,7 @@ public class TypeIO{
|
||||
@ReadClass(Unit.class)
|
||||
public static Unit readUnit(ByteBuffer buffer){
|
||||
byte gid = buffer.get();
|
||||
if(gid == -1) return null;
|
||||
int id = buffer.getInt();
|
||||
return (Unit) Entities.getGroup(gid).getByID(id);
|
||||
}
|
||||
@@ -142,13 +148,12 @@ public class TypeIO{
|
||||
|
||||
@WriteClass(Tile.class)
|
||||
public static void writeTile(ByteBuffer buffer, Tile tile){
|
||||
buffer.putInt(tile == null ? -1 : tile.packedPosition());
|
||||
buffer.putInt(tile == null ? Pos.get(-1, -1) : tile.pos());
|
||||
}
|
||||
|
||||
@ReadClass(Tile.class)
|
||||
public static Tile readTile(ByteBuffer buffer){
|
||||
int position = buffer.getInt();
|
||||
return position == -1 ? null : world.tile(position);
|
||||
return world.tile(buffer.getInt());
|
||||
}
|
||||
|
||||
@WriteClass(Block.class)
|
||||
@@ -166,7 +171,7 @@ public class TypeIO{
|
||||
buffer.putShort((short)requests.length);
|
||||
for(BuildRequest request : requests){
|
||||
buffer.put(request.breaking ? (byte) 1 : 0);
|
||||
buffer.putInt(world.toPacked(request.x, request.y));
|
||||
buffer.putInt(Pos.get(request.x, request.y));
|
||||
if(!request.breaking){
|
||||
buffer.put(request.recipe.id);
|
||||
buffer.put((byte) request.rotation);
|
||||
@@ -184,11 +189,11 @@ public class TypeIO{
|
||||
BuildRequest currentRequest;
|
||||
|
||||
if(type == 1){ //remove
|
||||
currentRequest = new BuildRequest(position % world.width(), position / world.width());
|
||||
currentRequest = new BuildRequest(Pos.x(position), Pos.y(position));
|
||||
}else{ //place
|
||||
byte recipe = buffer.get();
|
||||
byte rotation = buffer.get();
|
||||
currentRequest = new BuildRequest(position % world.width(), position / world.width(), rotation, content.recipe(recipe));
|
||||
currentRequest = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.recipe(recipe));
|
||||
}
|
||||
|
||||
reqs[i] = (currentRequest);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class Save16 extends SaveFileVersion{
|
||||
stream.writeLong(TimeUtils.millis()); //last saved
|
||||
stream.writeLong(headless ? 0 : control.saves.getTotalPlaytime()); //playtime
|
||||
stream.writeInt(Version.build); //build
|
||||
stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().packedPosition()); //sector ID
|
||||
stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().pos()); //sector ID
|
||||
|
||||
//--GENERAL STATE--
|
||||
stream.writeByte(state.mode.ordinal()); //gamemode
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Sector{
|
||||
return !headless && control.saves.getByID(saveID) != null;
|
||||
}
|
||||
|
||||
public int packedPosition(){
|
||||
public int pos(){
|
||||
return Bits.packInt(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class Sectors{
|
||||
world.loadSector(sector);
|
||||
logic.play();
|
||||
if(!headless){
|
||||
sector.saveID = control.saves.addSave("sector-" + sector.packedPosition()).index;
|
||||
sector.saveID = control.saves.addSave("sector-" + sector.pos()).index;
|
||||
}
|
||||
world.sectors.save();
|
||||
world.setSector(sector);
|
||||
|
||||
@@ -17,6 +17,7 @@ import io.anuke.mindustry.maps.Sector;
|
||||
import io.anuke.mindustry.maps.missions.Mission;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||
@@ -86,7 +87,7 @@ public class WorldGenerator{
|
||||
Tile tile = tiles[x][y];
|
||||
|
||||
if(tile.block().isMultiblock()){
|
||||
multiblocks.add(tile.packedPosition());
|
||||
multiblocks.add(tile.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,8 +96,8 @@ public class WorldGenerator{
|
||||
for(int i = 0; i < multiblocks.size; i++){
|
||||
int pos = multiblocks.get(i);
|
||||
|
||||
int x = pos % tiles.length;
|
||||
int y = pos / tiles.length;
|
||||
int x = Pos.x(pos);
|
||||
int y = Pos.y(pos);
|
||||
|
||||
Block result = tiles[x][y].block();
|
||||
Team team = tiles[x][y].getTeam();
|
||||
|
||||
@@ -38,7 +38,7 @@ public class BattleMission extends MissionWithStartingCore{
|
||||
|
||||
@Override
|
||||
public GameMode getMode(){
|
||||
return GameMode.noWaves;
|
||||
return GameMode.attack;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,10 +2,8 @@ package io.anuke.mindustry.maps.missions;
|
||||
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.content.blocks.StorageBlocks;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.SpawnGroup;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.mindustry.maps.Sector;
|
||||
import io.anuke.mindustry.maps.generation.Generation;
|
||||
@@ -34,7 +32,7 @@ public abstract class Mission{
|
||||
}
|
||||
|
||||
public GameMode getMode(){
|
||||
return GameMode.noWaves;
|
||||
return GameMode.attack;
|
||||
}
|
||||
|
||||
/**Sets the message displayed on mission begin. Returns this mission for chaining.*/
|
||||
|
||||
@@ -42,6 +42,13 @@ public abstract class MissionWithStartingCore extends Mission{
|
||||
startingCoreTile.setBlock(StorageBlocks.core);
|
||||
startingCoreTile.setTeam(team);
|
||||
state.teams.get(team).cores.add(startingCoreTile);
|
||||
|
||||
//makes sure there's a flat area around core
|
||||
for(int dx = -2; dx <= 2; dx++){
|
||||
for(int dy = -2; dy <= 2; dy++){
|
||||
gen.tiles[startingCoreTile.x + dx][startingCoreTile.y + dy].setElevation(startingCoreTile.getElevation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -74,7 +74,7 @@ public class WaveMission extends MissionWithStartingCore{
|
||||
@Override
|
||||
public void update(){
|
||||
if(state.wave > target){
|
||||
state.mode = GameMode.noWaves;
|
||||
state.mode = GameMode.attack;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.anuke.mindustry.net;
|
||||
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
|
||||
public class Host{
|
||||
public final String name;
|
||||
public final String address;
|
||||
@@ -8,8 +10,9 @@ public class Host{
|
||||
public final int players;
|
||||
public final int version;
|
||||
public final String versionType;
|
||||
public final GameMode mode;
|
||||
|
||||
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType){
|
||||
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType, GameMode mode){
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.players = players;
|
||||
@@ -17,5 +20,6 @@ public class Host{
|
||||
this.wave = wave;
|
||||
this.version = version;
|
||||
this.versionType = versionType;
|
||||
this.mode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import io.anuke.ucore.util.Bits;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
@@ -32,7 +33,7 @@ public class NetworkIO{
|
||||
//--GENERAL STATE--
|
||||
stream.writeByte(state.mode.ordinal()); //gamemode
|
||||
stream.writeUTF(world.getMap().name); //map name
|
||||
stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().packedPosition()); //sector ID
|
||||
stream.writeInt(world.getSector() == null ? invalidSector : world.getSector().pos()); //sector ID
|
||||
stream.writeInt(world.getSector() == null ? 0 : world.getSector().completedMissions);
|
||||
|
||||
//write tags
|
||||
@@ -56,7 +57,7 @@ public class NetworkIO{
|
||||
stream.writeShort(world.height());
|
||||
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i);
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());
|
||||
|
||||
stream.writeByte(tile.getFloorID());
|
||||
stream.writeByte(tile.getBlockID());
|
||||
@@ -79,7 +80,7 @@ public class NetworkIO{
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){
|
||||
Tile nextTile = world.tile(j);
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());
|
||||
|
||||
if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getElevation() != tile.getElevation()){
|
||||
break;
|
||||
@@ -95,13 +96,13 @@ public class NetworkIO{
|
||||
|
||||
//write visibility, length-run encoded
|
||||
for(int i = 0; i < world.width() * world.height(); i++){
|
||||
Tile tile = world.tile(i);
|
||||
Tile tile = world.tile(i % world.width(), i / world.width());;
|
||||
boolean discovered = tile.discovered();
|
||||
|
||||
int consecutives = 0;
|
||||
|
||||
for(int j = i + 1; j < world.width() * world.height() && consecutives < 32767*2-1; j++){
|
||||
Tile nextTile = world.tile(j);
|
||||
Tile nextTile = world.tile(j % world.width(), j / world.width());;
|
||||
|
||||
if(nextTile.discovered() != discovered){
|
||||
break;
|
||||
@@ -129,7 +130,7 @@ public class NetworkIO{
|
||||
|
||||
stream.writeByte(data.cores.size);
|
||||
for(Tile tile : data.cores){
|
||||
stream.writeInt(tile.packedPosition());
|
||||
stream.writeInt(tile.pos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,24 +299,25 @@ public class NetworkIO{
|
||||
int maxlen = 32;
|
||||
|
||||
String host = (headless ? "Server" : players[0].name);
|
||||
String map = world.getMap().name;
|
||||
String map = world.getMap() == null ? "None" : world.getMap().name;
|
||||
|
||||
host = host.substring(0, Math.min(host.length(), maxlen));
|
||||
map = map.substring(0, Math.min(map.length(), maxlen));
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(128);
|
||||
|
||||
buffer.put((byte) host.getBytes().length);
|
||||
buffer.put(host.getBytes());
|
||||
buffer.put((byte) host.getBytes(StandardCharsets.UTF_8).length);
|
||||
buffer.put(host.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.put((byte) map.getBytes().length);
|
||||
buffer.put(map.getBytes());
|
||||
buffer.put((byte) map.getBytes(StandardCharsets.UTF_8).length);
|
||||
buffer.put(map.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
buffer.putInt(playerGroup.size());
|
||||
buffer.putInt(state.wave);
|
||||
buffer.putInt(Version.build);
|
||||
buffer.put((byte)Version.type.getBytes().length);
|
||||
buffer.put(Version.type.getBytes());
|
||||
buffer.put((byte)Version.type.getBytes(StandardCharsets.UTF_8).length);
|
||||
buffer.put(Version.type.getBytes(StandardCharsets.UTF_8));
|
||||
buffer.put((byte)state.mode.ordinal());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -328,8 +330,8 @@ public class NetworkIO{
|
||||
byte[] mb = new byte[mlength];
|
||||
buffer.get(mb);
|
||||
|
||||
String host = new String(hb);
|
||||
String map = new String(mb);
|
||||
String host = new String(hb, StandardCharsets.UTF_8);
|
||||
String map = new String(mb, StandardCharsets.UTF_8);
|
||||
|
||||
int players = buffer.getInt();
|
||||
int wave = buffer.getInt();
|
||||
@@ -337,8 +339,9 @@ public class NetworkIO{
|
||||
byte tlength = buffer.get();
|
||||
byte[] tb = new byte[tlength];
|
||||
buffer.get(tb);
|
||||
String vertype = new String(tb);
|
||||
String vertype = new String(tb, StandardCharsets.UTF_8);
|
||||
GameMode mode = GameMode.values()[buffer.get()];
|
||||
|
||||
return new Host(host, hostAddress, map, wave, players, version, vertype);
|
||||
return new Host(host, hostAddress, map, wave, players, version, vertype, mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ public class Mech extends UnlockableContent{
|
||||
public Color trailColorTo = Palette.boostTo;
|
||||
public int itemCapacity = 30;
|
||||
public boolean turnCursor = true;
|
||||
public boolean canHeal = false;
|
||||
|
||||
public float weaponOffsetX, weaponOffsetY;
|
||||
public Weapon weapon = Weapons.blaster;
|
||||
|
||||
@@ -41,17 +41,10 @@ public class AdminsDialog extends FloatingDialog{
|
||||
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> {
|
||||
netServer.admins.unAdminPlayer(info.id);
|
||||
playerGroup.forEach(player -> {
|
||||
if(player.uuid.equals(info.id)){
|
||||
if(player != null && player.uuid != null && player.uuid.equals(info.id)){
|
||||
player.isAdmin = false;
|
||||
}
|
||||
});
|
||||
/*
|
||||
for(Player player : playerGroup.all()){
|
||||
if(player.con != null){
|
||||
player.isAdmin = false;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
setup();
|
||||
});
|
||||
}).size(h).pad(-14f);
|
||||
|
||||
@@ -38,10 +38,6 @@ public class FileChooser extends FloatingDialog{
|
||||
private Consumer<FileHandle> selectListener;
|
||||
private boolean open;
|
||||
|
||||
public FileChooser(String title, boolean open, Consumer<FileHandle> result){
|
||||
this(title, defaultFilter, open, result);
|
||||
}
|
||||
|
||||
public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){
|
||||
super(title);
|
||||
this.open = open;
|
||||
@@ -127,7 +123,7 @@ public class FileChooser extends FloatingDialog{
|
||||
updateFiles(true);
|
||||
});
|
||||
|
||||
icontable.defaults().height(50).growX().uniform();
|
||||
icontable.defaults().height(50).growX().padTop(5).uniform();
|
||||
icontable.add(home);
|
||||
icontable.add(back);
|
||||
icontable.add(forward);
|
||||
@@ -202,7 +198,7 @@ public class FileChooser extends FloatingDialog{
|
||||
//macs are confined to the Downloads/ directory
|
||||
if(!OS.isMac){
|
||||
Image upimage = new Image("icon-folder-parent");
|
||||
TextButton upbutton = new TextButton(".." + directory.toString());
|
||||
TextButton upbutton = new TextButton(".." + directory.toString(), "clear-toggle");
|
||||
upbutton.clicked(() -> {
|
||||
directory = directory.parent();
|
||||
updateFiles(true);
|
||||
@@ -224,7 +220,7 @@ public class FileChooser extends FloatingDialog{
|
||||
|
||||
String filename = file.name();
|
||||
|
||||
TextButton button = new TextButton(shorten(filename), "toggle");
|
||||
TextButton button = new TextButton(shorten(filename), "clear-toggle");
|
||||
group.add(button);
|
||||
|
||||
button.clicked(() -> {
|
||||
|
||||
@@ -96,11 +96,11 @@ public class JoinDialog extends FloatingDialog{
|
||||
//why are java lambdas this bad
|
||||
TextButton[] buttons = {null};
|
||||
|
||||
TextButton button = buttons[0] = remote.addButton("[accent]" + server.displayIP(), () -> {
|
||||
TextButton button = buttons[0] = remote.addButton("[accent]" + server.displayIP(), "clear", () -> {
|
||||
if(!buttons[0].childrenPressed()){
|
||||
connect(server.ip, server.port);
|
||||
}
|
||||
}).width(targetWidth()).height(150f).pad(4f).get();
|
||||
}).width(targetWidth()).height(155f).pad(4f).get();
|
||||
|
||||
button.getLabel().setWrap(true);
|
||||
|
||||
@@ -156,10 +156,10 @@ public class JoinDialog extends FloatingDialog{
|
||||
versionString = Bundles.get("text.server.outdated");
|
||||
}else if(host.version < Version.build && Version.build != -1){
|
||||
versionString = Bundles.get("text.server.outdated") + "\n" +
|
||||
Bundles.format("text.server.version", host.version);
|
||||
Bundles.format("text.server.version", host.version, "");
|
||||
}else if(host.version > Version.build && Version.build != -1){
|
||||
versionString = Bundles.get("text.server.outdated.client") + "\n" +
|
||||
Bundles.format("text.server.version", host.version);
|
||||
Bundles.format("text.server.version", host.version, "");
|
||||
}else{
|
||||
versionString = Bundles.format("text.server.version", host.version, host.versionType);
|
||||
}
|
||||
@@ -268,12 +268,13 @@ public class JoinDialog extends FloatingDialog{
|
||||
if(totalHosts == 0){
|
||||
local.clear();
|
||||
}
|
||||
local.background((Drawable) null);
|
||||
totalHosts ++;
|
||||
float w = targetWidth();
|
||||
|
||||
local.row();
|
||||
|
||||
TextButton button = local.addButton("[accent]" + host.name, () -> connect(host.address, port))
|
||||
TextButton button = local.addButton("[accent]" + host.name, "clear", () -> connect(host.address, port))
|
||||
.width(w).height(80f).pad(4f).get();
|
||||
button.left();
|
||||
button.row();
|
||||
|
||||
@@ -161,6 +161,7 @@ public class LoadDialog extends FloatingDialog{
|
||||
control.saves.importSave(file);
|
||||
setup();
|
||||
}catch(IOException e){
|
||||
e.printStackTrace();
|
||||
ui.showError(Bundles.format("text.save.import.fail", Strings.parseException(e, false)));
|
||||
}
|
||||
}else{
|
||||
|
||||
@@ -24,9 +24,13 @@ import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.actions.Actions;
|
||||
import io.anuke.ucore.scene.event.Touchable;
|
||||
import io.anuke.ucore.scene.ui.*;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.ImageButton;
|
||||
import io.anuke.ucore.scene.ui.Label;
|
||||
import io.anuke.ucore.scene.ui.TextButton;
|
||||
import io.anuke.ucore.scene.ui.layout.Stack;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
@@ -347,7 +351,7 @@ public class HudFragment extends Fragment{
|
||||
if(shown){
|
||||
shown = false;
|
||||
blockfrag.toggle(dur, in);
|
||||
wavetable.actions(Actions.translateBy(0, (wavetable.getHeight() + dsize + 6) - wavetable.getTranslation().y, dur, in));
|
||||
wavetable.actions(Actions.translateBy(0, (wavetable.getHeight() + Unit.dp.scl(dsize) + Unit.dp.scl(6)) - wavetable.getTranslation().y, dur, in));
|
||||
infolabel.actions(Actions.translateBy(0, (wavetable.getHeight()) - wavetable.getTranslation().y, dur, in));
|
||||
}else{
|
||||
shown = true;
|
||||
|
||||
@@ -36,9 +36,11 @@ public class PlacementFragment extends Fragment{
|
||||
Tile hoverTile;
|
||||
Table blockTable, toggler, topTable;
|
||||
boolean shown = true;
|
||||
boolean lastGround;
|
||||
|
||||
public PlacementFragment(){
|
||||
Events.on(WorldLoadGraphicsEvent.class, event -> {
|
||||
currentCategory = Category.turret;
|
||||
Group group = toggler.getParent();
|
||||
toggler.remove();
|
||||
build(group);
|
||||
@@ -109,13 +111,14 @@ public class PlacementFragment extends Fragment{
|
||||
frame.table("button-edge-2", top -> {
|
||||
topTable = top;
|
||||
top.add(new Table()).growX().update(topTable -> {
|
||||
if((tileDisplayBlock() == null && lastDisplay == getSelected()) ||
|
||||
(tileDisplayBlock() != null && lastDisplay == tileDisplayBlock())) return;
|
||||
if((tileDisplayBlock() == null && lastDisplay == getSelected() && !lastGround) ||
|
||||
(tileDisplayBlock() != null && lastDisplay == tileDisplayBlock() && lastGround)) return;
|
||||
|
||||
topTable.clear();
|
||||
topTable.top().left().margin(5);
|
||||
|
||||
lastDisplay = getSelected();
|
||||
lastGround = tileDisplayBlock() != null;
|
||||
|
||||
if(lastDisplay != null){ //show selected recipe
|
||||
topTable.table(header -> {
|
||||
@@ -181,7 +184,7 @@ public class PlacementFragment extends Fragment{
|
||||
categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16*2, () -> {
|
||||
currentCategory = cat;
|
||||
rebuildCategory.run();
|
||||
}).group(group);
|
||||
}).group(group).update(i -> i.setChecked(currentCategory == cat));
|
||||
|
||||
if(cat.ordinal() %2 == 1) categories.row();
|
||||
}
|
||||
|
||||
@@ -104,19 +104,19 @@ public class PlayerListFragment extends Fragment{
|
||||
if((Net.server() || players[0].isAdmin) && !player.isLocal && (!player.isAdmin || Net.server())){
|
||||
button.add().growY();
|
||||
|
||||
float bs = (h + 14) / 2f;
|
||||
float bs = (h) / 2f;
|
||||
|
||||
button.table(t -> {
|
||||
t.defaults().size(bs);
|
||||
|
||||
t.addImageButton("icon-ban", 14 * 2,
|
||||
t.addImageButton("icon-ban", "clear-partial", 14 * 2,
|
||||
() -> ui.showConfirm("$text.confirm", "$text.confirmban", () -> Call.onAdminRequest(player, AdminAction.ban)));
|
||||
t.addImageButton("icon-cancel", 16 * 2,
|
||||
t.addImageButton("icon-cancel", "clear-partial", 16 * 2,
|
||||
() -> ui.showConfirm("$text.confirm", "$text.confirmkick", () -> Call.onAdminRequest(player, AdminAction.kick)));
|
||||
|
||||
t.row();
|
||||
|
||||
t.addImageButton("icon-admin", "toggle", 14 * 2, () -> {
|
||||
t.addImageButton("icon-admin", "clear-toggle-partial", 14 * 2, () -> {
|
||||
if(Net.client()) return;
|
||||
|
||||
String id = player.uuid;
|
||||
@@ -132,9 +132,9 @@ public class PlayerListFragment extends Fragment{
|
||||
.touchable(() -> Net.client() ? Touchable.disabled : Touchable.enabled)
|
||||
.checked(player.isAdmin);
|
||||
|
||||
t.addImageButton("icon-zoom-small", 14 * 2, () -> ui.showError("Currently unimplemented.")/*Call.onAdminRequest(player, AdminAction.trace)*/);
|
||||
t.addImageButton("icon-zoom-small", "clear-partial", 14 * 2, () -> ui.showError("Currently unimplemented.")/*Call.onAdminRequest(player, AdminAction.trace)*/);
|
||||
|
||||
}).padRight(12).padTop(-5).padLeft(0).padBottom(-10).size(bs + 10f, bs);
|
||||
}).padRight(12).size(bs + 10f, bs);
|
||||
}
|
||||
|
||||
content.add(button).padBottom(-6).width(350f).maxHeight(h + 14);
|
||||
|
||||
@@ -164,7 +164,7 @@ public class Block extends BaseBlock {
|
||||
for(int i = 0; i < tile.entity.power.links.size; i++){
|
||||
Tile other = world.tile(tile.entity.power.links.get(i));
|
||||
if(other != null && other.entity != null && other.entity.power != null){
|
||||
other.entity.power.links.removeValue(tile.packedPosition());
|
||||
other.entity.power.links.removeValue(tile.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +173,7 @@ public class Block extends BaseBlock {
|
||||
out.clear();
|
||||
for(Tile other : tile.entity.proximity()){
|
||||
if(other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower)
|
||||
&& !tile.entity.power.links.contains(other.packedPosition())){
|
||||
&& !tile.entity.power.links.contains(other.pos())){
|
||||
out.add(other);
|
||||
}
|
||||
}
|
||||
@@ -337,10 +337,8 @@ public class Block extends BaseBlock {
|
||||
|
||||
public void setBars(){
|
||||
if(hasPower) bars.add(new BlockBar(BarType.power, true, tile -> tile.entity.power.amount / powerCapacity));
|
||||
if(hasLiquids)
|
||||
bars.add(new BlockBar(BarType.liquid, true, tile -> tile.entity.liquids.total() / liquidCapacity));
|
||||
if(hasItems)
|
||||
bars.add(new BlockBar(BarType.inventory, true, tile -> (float) tile.entity.items.total() / itemCapacity));
|
||||
if(hasLiquids) bars.add(new BlockBar(BarType.liquid, true, tile -> tile.entity.liquids.total() / liquidCapacity));
|
||||
if(hasItems) bars.add(new BlockBar(BarType.inventory, true, tile -> (float) tile.entity.items.total() / itemCapacity));
|
||||
}
|
||||
|
||||
public String name(){
|
||||
@@ -543,16 +541,16 @@ public class Block extends BaseBlock {
|
||||
|
||||
public Array<Object> getDebugInfo(Tile tile){
|
||||
return Array.with(
|
||||
"block", tile.block().name,
|
||||
"floor", tile.floor().name,
|
||||
"x", tile.x,
|
||||
"y", tile.y,
|
||||
"entity.name", tile.entity.getClass(),
|
||||
"entity.x", tile.entity.x,
|
||||
"entity.y", tile.entity.y,
|
||||
"entity.id", tile.entity.id,
|
||||
"entity.items.total", hasItems ? tile.entity.items.total() : null,
|
||||
"entity.graph", tile.entity.power != null && tile.entity.power.graph != null ? tile.entity.power.graph.getID() : null
|
||||
"block", tile.block().name,
|
||||
"floor", tile.floor().name,
|
||||
"x", tile.x,
|
||||
"y", tile.y,
|
||||
"entity.name", tile.entity.getClass(),
|
||||
"entity.x", tile.entity.x,
|
||||
"entity.y", tile.entity.y,
|
||||
"entity.id", tile.entity.id,
|
||||
"entity.items.total", hasItems ? tile.entity.items.total() : null,
|
||||
"entity.graph", tile.entity.power != null && tile.entity.power.graph != null ? tile.entity.power.graph.getID() : null
|
||||
);
|
||||
}
|
||||
}
|
||||
20
core/src/io/anuke/mindustry/world/Pos.java
Normal file
20
core/src/io/anuke/mindustry/world/Pos.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package io.anuke.mindustry.world;
|
||||
|
||||
/**Methods for a packed position 'struct', contained in an int.*/
|
||||
public class Pos{
|
||||
|
||||
/**Returns packed position from an x/y position. The values must be within short limits.*/
|
||||
public static int get(int x, int y){
|
||||
return (((short)x) << 16) | (((short)y) & 0xFFFF);
|
||||
}
|
||||
|
||||
/**Returns the x component of a position.*/
|
||||
public static short x(int pos){
|
||||
return (short) (pos >>> 16);
|
||||
}
|
||||
|
||||
/**Returns the y component of a position.*/
|
||||
public static short y(int pos){
|
||||
return (short) (pos & 0xFFFF);
|
||||
}
|
||||
}
|
||||
@@ -71,8 +71,9 @@ public class Tile implements PosTrait, TargetTrait{
|
||||
return visibility > 0;
|
||||
}
|
||||
|
||||
public int packedPosition(){
|
||||
return x + y * world.width();
|
||||
/**Returns this tile's position as a {@link Pos}.*/
|
||||
public int pos(){
|
||||
return Pos.get(x, y);
|
||||
}
|
||||
|
||||
public byte getBlockID(){
|
||||
@@ -104,10 +105,6 @@ public class Tile implements PosTrait, TargetTrait{
|
||||
return (T) entity;
|
||||
}
|
||||
|
||||
public int id(){
|
||||
return x + y * world.width();
|
||||
}
|
||||
|
||||
public float worldx(){
|
||||
return x * tilesize;
|
||||
}
|
||||
|
||||
@@ -130,16 +130,16 @@ public class Floor extends Block{
|
||||
|
||||
@Override
|
||||
public void drawNonLayer(Tile tile){
|
||||
MathUtils.random.setSeed(tile.id());
|
||||
MathUtils.random.setSeed(tile.pos());
|
||||
|
||||
drawEdges(tile, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
MathUtils.random.setSeed(tile.id());
|
||||
MathUtils.random.setSeed(tile.pos());
|
||||
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
|
||||
if(tile.hasCliffs() && cliffRegions != null){
|
||||
for(int i = 0; i < 4; i++){
|
||||
|
||||
@@ -39,14 +39,14 @@ public class OreBlock extends Floor{
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.id(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy());
|
||||
|
||||
drawEdges(tile, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawNonLayer(Tile tile){
|
||||
MathUtils.random.setSeed(tile.id());
|
||||
MathUtils.random.setSeed(tile.pos());
|
||||
|
||||
base.drawEdges(tile, true);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public class Rock extends Block{
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
if(variants > 0){
|
||||
Draw.rect(regions[Mathf.randomSeed(tile.id(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy());
|
||||
Draw.rect(regions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy());
|
||||
}else{
|
||||
Draw.rect(region, tile.worldx(), tile.worldy());
|
||||
}
|
||||
@@ -28,7 +28,7 @@ public class Rock extends Block{
|
||||
@Override
|
||||
public void drawShadow(Tile tile){
|
||||
if(shadowRegions != null){
|
||||
Draw.rect(shadowRegions[(Mathf.randomSeed(tile.id(), 0, variants - 1))], tile.worldx(), tile.worldy());
|
||||
Draw.rect(shadowRegions[(Mathf.randomSeed(tile.pos(), 0, variants - 1))], tile.worldx(), tile.worldy());
|
||||
}else if(shadowRegion != null){
|
||||
Draw.rect(shadowRegion, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
@@ -4,43 +4,32 @@ import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
import io.anuke.ucore.function.Supplier;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.style.TextureRegionDrawable;
|
||||
import io.anuke.ucore.scene.ui.ButtonGroup;
|
||||
import io.anuke.ucore.scene.ui.ImageButton;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
import static io.anuke.mindustry.Vars.control;
|
||||
|
||||
public interface SelectionTrait{
|
||||
|
||||
default void buildItemTable(Table table, Supplier<Item> holder, Consumer<Item> consumer){
|
||||
buildItemTable(table, false, holder, consumer);
|
||||
}
|
||||
|
||||
default void buildItemTable(Table table, boolean nullItem, Supplier<Item> holder, Consumer<Item> consumer){
|
||||
|
||||
Array<Item> items = content.items();
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
group.setMinCheckCount(0);
|
||||
Table cont = new Table();
|
||||
cont.defaults().size(38);
|
||||
|
||||
int i = 0;
|
||||
|
||||
if(nullItem){
|
||||
ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> consumer.accept(null)).group(group).get();
|
||||
button.getStyle().imageUp = new TextureRegionDrawable(Draw.region("icon-nullitem"));
|
||||
button.setChecked(holder.get() == null);
|
||||
|
||||
i ++;
|
||||
}
|
||||
|
||||
for(Item item : items){
|
||||
if(!control.unlocks.isUnlocked(item)) continue;
|
||||
|
||||
ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> consumer.accept(item))
|
||||
.group(group).get();
|
||||
ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> {}).group(group).get();
|
||||
button.changed(() -> consumer.accept(button.isChecked() ? item : null));
|
||||
button.getStyle().imageUp = new TextureRegionDrawable(item.region);
|
||||
button.setChecked(holder.get() == item);
|
||||
|
||||
|
||||
@@ -83,10 +83,10 @@ public class MendProjector extends Block{
|
||||
if(other == null) continue;
|
||||
other = other.target();
|
||||
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null && other.entity.health < other.entity.maxHealth()){
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null && other.entity.health < other.entity.maxHealth()){
|
||||
other.entity.healBy(other.entity.maxHealth() * (healPercent + entity.phaseHeat*phaseBoost)/100f);
|
||||
Effects.effect(BlockFx.healBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
|
||||
healed.add(other.packedPosition());
|
||||
healed.add(other.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,11 +85,11 @@ public class OverdriveProjector extends Block{
|
||||
if(other == null) continue;
|
||||
other = other.target();
|
||||
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && other.entity != null){
|
||||
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null){
|
||||
other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f);
|
||||
other.entity.timeScale = Math.max(other.entity.timeScale, realBoost);
|
||||
Effects.effect(BlockFx.overdriveBlockFull, Hue.mix(color, phase, entity.phaseHeat), other.drawx(), other.drawy(), other.block().size);
|
||||
healed.add(other.packedPosition());
|
||||
healed.add(other.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Edges;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
@@ -58,8 +59,8 @@ public class ItemBridge extends Block{
|
||||
public static void linkItemBridge(Player player, Tile tile, Tile other){
|
||||
ItemBridgeEntity entity = tile.entity();
|
||||
ItemBridgeEntity oe = other.entity();
|
||||
entity.link = other.packedPosition();
|
||||
oe.incoming.add(tile.packedPosition());
|
||||
entity.link = other.pos();
|
||||
oe.incoming.add(tile.pos());
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
||||
@@ -68,7 +69,7 @@ public class ItemBridge extends Block{
|
||||
entity.link = -1;
|
||||
if(other != null){
|
||||
ItemBridgeEntity oe = other.entity();
|
||||
oe.incoming.remove(tile.packedPosition());
|
||||
oe.incoming.remove(tile.pos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,7 +91,7 @@ public class ItemBridge extends Block{
|
||||
Call.linkItemBridge(null, last, tile);
|
||||
}
|
||||
}
|
||||
lastPlaced = tile.packedPosition();
|
||||
lastPlaced = tile.pos();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,7 +123,7 @@ public class ItemBridge extends Block{
|
||||
for(int j = 0; j < 4; j++){
|
||||
Tile other = tile.getNearby(Geometry.d4[j].x * i, Geometry.d4[j].y * i);
|
||||
if(linkValid(tile, other)){
|
||||
boolean linked = other.packedPosition() == entity.link;
|
||||
boolean linked = other.pos() == entity.link;
|
||||
Draw.color(linked ? Palette.place : Palette.breakInvalid);
|
||||
|
||||
Lines.square(other.drawx(), other.drawy(),
|
||||
@@ -139,7 +140,7 @@ public class ItemBridge extends Block{
|
||||
ItemBridgeEntity entity = tile.entity();
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
if(entity.link == other.packedPosition()){
|
||||
if(entity.link == other.pos()){
|
||||
Call.unlinkItemBridge(null, tile, other);
|
||||
}else{
|
||||
Call.linkItemBridge(null, tile, other);
|
||||
@@ -254,7 +255,7 @@ public class ItemBridge extends Block{
|
||||
|
||||
if(rel == rel2) return false;
|
||||
}else{
|
||||
return source.block() instanceof ItemBridge && source.<ItemBridgeEntity>entity().link == tile.packedPosition() && tile.entity.items.total() < itemCapacity;
|
||||
return source.block() instanceof ItemBridge && source.<ItemBridgeEntity>entity().link == tile.pos() && tile.entity.items.total() < itemCapacity;
|
||||
}
|
||||
|
||||
return tile.entity.items.total() < itemCapacity;
|
||||
@@ -273,9 +274,7 @@ public class ItemBridge extends Block{
|
||||
|
||||
while(it.hasNext){
|
||||
int v = it.next();
|
||||
int x = v % world.width();
|
||||
int y = v / world.width();
|
||||
if(tile.absoluteRelativeTo(x, y) == i){
|
||||
if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -315,7 +314,7 @@ public class ItemBridge extends Block{
|
||||
return false;
|
||||
}
|
||||
|
||||
return other.block() == this && (!checkDouble || other.<ItemBridgeEntity>entity().link != tile.packedPosition());
|
||||
return other.block() == this && (!checkDouble || other.<ItemBridgeEntity>entity().link != tile.pos());
|
||||
}
|
||||
|
||||
public static class ItemBridgeEntity extends TileEntity{
|
||||
|
||||
@@ -3,6 +3,7 @@ package io.anuke.mindustry.world.blocks.distribution;
|
||||
import com.badlogic.gdx.utils.IntSet.IntSetIterator;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.Pos;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
@@ -65,9 +66,7 @@ public class LiquidExtendingBridge extends ExtendingItemBridge{
|
||||
|
||||
while(it.hasNext){
|
||||
int v = it.next();
|
||||
int x = v % world.width();
|
||||
int y = v / world.width();
|
||||
if(tile.absoluteRelativeTo(x, y) == i){
|
||||
if(tile.absoluteRelativeTo(Pos.x(v), Pos.y(v)) == i){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package io.anuke.mindustry.world.blocks.distribution;
|
||||
|
||||
public class LiquidTank extends LiquidRouter{
|
||||
|
||||
public LiquidTank(String name){
|
||||
super(name);
|
||||
}
|
||||
}
|
||||
@@ -225,11 +225,11 @@ public class MassDriver extends Block{
|
||||
|
||||
MassDriverEntity entity = tile.entity();
|
||||
|
||||
if(entity.link == other.packedPosition()){
|
||||
if(entity.link == other.pos()){
|
||||
Call.linkMassDriver(null, tile, -1);
|
||||
return false;
|
||||
}else if(other.block() instanceof MassDriver && other.distanceTo(tile) <= range){
|
||||
Call.linkMassDriver(null, tile, other.packedPosition());
|
||||
Call.linkMassDriver(null, tile, other.pos());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.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;
|
||||
@@ -12,7 +13,6 @@ import io.anuke.mindustry.world.meta.BlockGroup;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -40,15 +40,15 @@ public class Sorter extends Block implements SelectionTrait{
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastItem != null){
|
||||
threads.runDelay(() -> Call.setSorterItem(null, tile, lastItem));
|
||||
}
|
||||
threads.runDelay(() -> Call.setSorterItem(null, tile, lastItem));
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
public static void setSorterItem(Player player, Tile tile, Item item){
|
||||
SorterEntity entity = tile.entity();
|
||||
if(entity != null) entity.sortItem = item;
|
||||
if(entity != null){
|
||||
entity.sortItem = item;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,6 +56,7 @@ public class Sorter extends Block implements SelectionTrait{
|
||||
super.draw(tile);
|
||||
|
||||
SorterEntity entity = tile.entity();
|
||||
if(entity.sortItem == null) return;
|
||||
|
||||
Draw.color(entity.sortItem.color);
|
||||
Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f);
|
||||
@@ -130,16 +131,17 @@ public class Sorter extends Block implements SelectionTrait{
|
||||
}
|
||||
|
||||
public static class SorterEntity extends TileEntity{
|
||||
public Item sortItem = content.item(0);
|
||||
public Item sortItem;
|
||||
|
||||
@Override
|
||||
public void writeConfig(DataOutput stream) throws IOException{
|
||||
stream.writeByte(sortItem.id);
|
||||
stream.writeByte(sortItem == null ? -1 : sortItem.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readConfig(DataInput stream) throws IOException{
|
||||
sortItem = content.items().get(stream.readByte());
|
||||
byte b = stream.readByte();
|
||||
sortItem = b == -1 ? null : content.items().get(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ public class LiquidHeatGenerator extends LiquidGenerator{
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f, StatUnit.powerSecond);
|
||||
stats.add(BlockStat.basePowerGeneration, maxLiquidGenerate * powerPerLiquid * 60f * 0.5f, StatUnit.powerSecond);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -134,9 +134,9 @@ public class PowerGraph{
|
||||
child.entity.power.graph = this;
|
||||
add(child);
|
||||
for(Tile next : child.block().getPowerConnections(child, outArray2)){
|
||||
if(next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.packedPosition())){
|
||||
if(next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.pos())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.packedPosition());
|
||||
closedSet.add(next.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,9 +156,9 @@ public class PowerGraph{
|
||||
child.entity.power.graph = graph;
|
||||
graph.add(child);
|
||||
for(Tile next : child.block().getPowerConnections(child, outArray2)){
|
||||
if(next != tile && next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.packedPosition())){
|
||||
if(next != tile && next.entity.power != null && next.entity.power.graph == null && !closedSet.contains(next.pos())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.packedPosition());
|
||||
closedSet.add(next.pos());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,18 +47,19 @@ public class PowerNode extends PowerBlock{
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
||||
public static void linkPowerNodes(Player player, Tile tile, Tile other){
|
||||
if(tile.entity.power == null || !((PowerNode)tile.block()).linkValid(tile, other)) return;
|
||||
if(tile.entity.power == null || !((PowerNode)tile.block()).linkValid(tile, other)
|
||||
|| tile.entity.power.links.size >= ((PowerNode)tile.block()).maxNodes) return;
|
||||
|
||||
TileEntity entity = tile.entity();
|
||||
|
||||
if(!entity.power.links.contains(other.packedPosition())){
|
||||
entity.power.links.add(other.packedPosition());
|
||||
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.packedPosition())){
|
||||
other.entity.power.links.add(tile.packedPosition());
|
||||
if(!other.entity.power.links.contains(tile.pos())){
|
||||
other.entity.power.links.add(tile.pos());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ public class PowerNode extends PowerBlock{
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
||||
public static void unlinkPowerNodes(Player player, Tile tile, Tile other){
|
||||
if(tile.entity.power == null) return;
|
||||
if(tile.entity.power == null || other.entity == null || other.entity.power == null) return;
|
||||
|
||||
TileEntity entity = tile.entity();
|
||||
|
||||
@@ -75,8 +76,8 @@ public class PowerNode extends PowerBlock{
|
||||
PowerGraph tg = entity.power.graph;
|
||||
tg.clear();
|
||||
|
||||
entity.power.links.removeValue(other.packedPosition());
|
||||
other.entity.power.links.removeValue(tile.packedPosition());
|
||||
entity.power.links.removeValue(other.pos());
|
||||
other.entity.power.links.removeValue(tile.pos());
|
||||
|
||||
//reflow from this point, covering all tiles on this side
|
||||
tg.reflow(tile);
|
||||
@@ -99,14 +100,14 @@ public class PowerNode extends PowerBlock{
|
||||
if(linkValid(tile, before) && before.block() instanceof PowerNode){
|
||||
for(Tile near : before.entity.proximity()){
|
||||
if(near.target() == tile){
|
||||
lastPlaced = tile.packedPosition();
|
||||
lastPlaced = tile.pos();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Call.linkPowerNodes(null, tile, before);
|
||||
}
|
||||
|
||||
lastPlaced = tile.packedPosition();
|
||||
lastPlaced = tile.pos();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -202,7 +203,7 @@ public class PowerNode extends PowerBlock{
|
||||
for(int i = 0; i < entity.power.links.size; i++){
|
||||
Tile link = world.tile(entity.power.links.get(i));
|
||||
if(linkValid(tile, link) && (!(link.block() instanceof PowerNode)
|
||||
|| ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.id() < link.id())))){
|
||||
|| ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.pos() < link.pos())))){
|
||||
drawLaser(tile, link);
|
||||
}
|
||||
}
|
||||
@@ -211,7 +212,7 @@ public class PowerNode extends PowerBlock{
|
||||
}
|
||||
|
||||
protected boolean linked(Tile tile, Tile other){
|
||||
return tile.entity.power.links.contains(other.packedPosition());
|
||||
return tile.entity.power.links.contains(other.pos());
|
||||
}
|
||||
|
||||
protected boolean linkValid(Tile tile, Tile link){
|
||||
@@ -227,7 +228,7 @@ public class PowerNode extends PowerBlock{
|
||||
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize,
|
||||
((PowerNode) link.block()).laserRange * tilesize)
|
||||
+ (link.block().size - 1) * tilesize / 2f + (tile.block().size - 1) * tilesize / 2f &&
|
||||
(!checkMaxNodes || (oe.power.links.size < ((PowerNode) link.block()).maxNodes || oe.power.links.contains(tile.packedPosition())));
|
||||
(!checkMaxNodes || (oe.power.links.size < ((PowerNode) link.block()).maxNodes || oe.power.links.contains(tile.pos())));
|
||||
}else{
|
||||
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy())
|
||||
<= laserRange * tilesize + (link.block().size - 1) * tilesize;
|
||||
@@ -249,23 +250,9 @@ public class PowerNode extends PowerBlock{
|
||||
x2 += t2.x;
|
||||
y2 += t2.y;
|
||||
|
||||
float space = Vector2.dst(x1, y1, x2, y2);
|
||||
float scl = 4f, mag = 2f, tscl = 4f, segscl = 3f;
|
||||
|
||||
int segments = Mathf.ceil(space / segscl);
|
||||
|
||||
Draw.color(Palette.power, Palette.powerLight, Mathf.absin(Timers.time(), 5f, 1f));
|
||||
Lines.stroke(1f);
|
||||
|
||||
for(int i = 0; i < segments; i++){
|
||||
float f1 = (float)i / segments;
|
||||
float f2 = (float)(i+1) / segments;
|
||||
t1.trns(angle1 + 90f, Mathf.lerp(Mathf.sin(tile.entity.id * 124f + Timers.time()/tscl + f1 * space, scl, mag), 0f, Math.abs(f1 - 0.5f)*2f));
|
||||
t2.trns(angle1 + 90f, Mathf.lerp(Mathf.sin(tile.entity.id * 124f + Timers.time()/tscl + f2 * space, scl, mag), 0f, Math.abs(f2 - 0.5f)*2f));
|
||||
|
||||
Lines.line(x1 + (x2 - x1) * f1 + t1.x, y1 + (y2 - y1) * f1 + t1.y,
|
||||
x1 + (x2 - x1) * f2 + t2.x, y1 + (y2 - y1) * f2 + t2.y);
|
||||
}
|
||||
Draw.color(Palette.powerLight, Palette.power, Mathf.absin(Timers.time(), 8f, 1f));
|
||||
Lines.stroke(2f);
|
||||
Lines.line(x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class Cultivator extends Drill{
|
||||
|
||||
Draw.color(bottomColor, plantColorLight, entity.warmup);
|
||||
|
||||
random.setSeed(tile.packedPosition());
|
||||
random.setSeed(tile.pos());
|
||||
for(int i = 0; i < 12; i++){
|
||||
float offset = random.nextFloat() * 999999f;
|
||||
float x = random.range(4f), y = random.range(4f);
|
||||
|
||||
@@ -51,7 +51,6 @@ public class CoreBlock extends StorageBlock{
|
||||
update = true;
|
||||
size = 3;
|
||||
hasItems = true;
|
||||
itemCapacity = 2000;
|
||||
viewRange = 200f;
|
||||
flags = EnumSet.of(BlockFlag.resupplyPoint, BlockFlag.target);
|
||||
}
|
||||
@@ -83,8 +82,18 @@ public class CoreBlock extends StorageBlock{
|
||||
if(entity != null) entity.solid = solid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return itemCapacity * state.teams.get(tile.getTeam()).cores.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityUpdate(Tile tile) {
|
||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
||||
if(other != tile){
|
||||
tile.entity.items = other.entity.items;
|
||||
}
|
||||
}
|
||||
state.teams.get(tile.getTeam()).cores.add(tile);
|
||||
}
|
||||
|
||||
@@ -96,6 +105,11 @@ public class CoreBlock extends StorageBlock{
|
||||
@Override
|
||||
public void removed(Tile tile){
|
||||
state.teams.get(tile.getTeam()).cores.remove(tile);
|
||||
|
||||
int max = itemCapacity * state.teams.get(tile.getTeam()).cores.size;
|
||||
for(Item item : content.items()){
|
||||
tile.entity.items.set(item, Math.min(tile.entity.items.get(item), max));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,7 +236,7 @@ public class CoreBlock extends StorageBlock{
|
||||
return new CoreEntity();
|
||||
}
|
||||
|
||||
public class CoreEntity extends StorageEntity implements SpawnerTrait{
|
||||
public class CoreEntity extends TileEntity implements SpawnerTrait{
|
||||
public Unit currentUnit;
|
||||
int droneID = -1;
|
||||
boolean solid = true;
|
||||
|
||||
@@ -7,6 +7,7 @@ import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.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.SelectionTrait;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
@@ -17,15 +18,37 @@ import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
import static io.anuke.mindustry.Vars.threads;
|
||||
|
||||
public class SortedUnloader extends Unloader implements SelectionTrait{
|
||||
public class SortedUnloader extends Block implements SelectionTrait{
|
||||
protected float speed = 1f;
|
||||
protected final int timerUnload = timers++;
|
||||
|
||||
private static Item lastItem;
|
||||
|
||||
public SortedUnloader(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
solid = true;
|
||||
health = 70;
|
||||
hasItems = true;
|
||||
configurable = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Tile tile, Tile to, Item item){
|
||||
Block block = to.target().block();
|
||||
return !(block instanceof StorageBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
threads.runDelay(() -> Call.setSortedUnloaderItem(null, tile, lastItem));
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
public static void setSortedUnloaderItem(Player player, Tile tile, Item item){
|
||||
SortedUnloaderEntity entity = tile.entity();
|
||||
@@ -65,7 +88,10 @@ public class SortedUnloader extends Unloader implements SelectionTrait{
|
||||
@Override
|
||||
public void buildTable(Tile tile, Table table){
|
||||
SortedUnloaderEntity entity = tile.entity();
|
||||
buildItemTable(table, true, () -> entity.sortItem, item -> Call.setSortedUnloaderItem(null, tile, item));
|
||||
buildItemTable(table, () -> entity.sortItem, item -> {
|
||||
lastItem = item;
|
||||
Call.setSortedUnloaderItem(null, tile, item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,20 +1,10 @@
|
||||
package io.anuke.mindustry.world.blocks.storage;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.Unit;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.graphics.Shaders;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.BarType;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Fill;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
|
||||
public abstract class StorageBlock extends Block{
|
||||
|
||||
@@ -23,6 +13,16 @@ public abstract class StorageBlock extends Block{
|
||||
hasItems = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
return tile.entity.items.get(item) < getMaximumAccepted(tile, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){
|
||||
super.setBars();
|
||||
@@ -34,85 +34,6 @@ public abstract class StorageBlock extends Block{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityAdded(Tile tile){
|
||||
StorageEntity entity = tile.entity();
|
||||
entity.graph.set(tile);
|
||||
|
||||
for(Tile prox : tile.entity.proximity()){
|
||||
if(prox.block() instanceof StorageBlock){
|
||||
StorageEntity other = prox.entity();
|
||||
entity.graph.merge(other.graph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProximityRemoved(Tile tile){
|
||||
StorageEntity entity = tile.entity();
|
||||
entity.graph.remove(tile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
|
||||
StorageEntity entity = tile.entity();
|
||||
|
||||
if(entity.graph.getTiles().size > 1){
|
||||
|
||||
Shaders.outline.color.set(Palette.accent);
|
||||
Graphics.beginShaders(Shaders.outline);
|
||||
|
||||
for(Tile other : entity.graph.getTiles()){
|
||||
Fill.square(other.drawx(), other.drawy(), other.block().size * tilesize);
|
||||
}
|
||||
|
||||
Draw.color(Color.CLEAR);
|
||||
Graphics.endShaders();
|
||||
Draw.color();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
StorageEntity entity = tile.entity();
|
||||
return entity.graph.accept(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int acceptStack(Item item, int amount, Tile tile, Unit source){
|
||||
StorageEntity entity = tile.entity();
|
||||
if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){
|
||||
return Math.min(entity.graph.accept(item, amount), amount);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float inventoryScaling(Tile tile){
|
||||
StorageEntity entity = tile.entity();
|
||||
return 1f / entity.graph.getTiles().size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity newEntity(){
|
||||
return new StorageEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array<Object> getDebugInfo(Tile tile){
|
||||
Array<Object> arr = super.getDebugInfo(tile);
|
||||
|
||||
StorageEntity entity = tile.entity();
|
||||
arr.addAll("storage graph", entity.graph.getID(),
|
||||
"graph capacity", entity.graph.getCapacity(),
|
||||
"graph tiles", entity.graph.getTiles().size,
|
||||
"graph item ID", entity.graph.items().getID());
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item and returns it. If item is not null, it should return the item.
|
||||
* Returns null if no items are there.
|
||||
@@ -144,8 +65,4 @@ public abstract class StorageBlock extends Block{
|
||||
return entity.items.has(item);
|
||||
}
|
||||
}
|
||||
|
||||
public class StorageEntity extends TileEntity{
|
||||
public StorageGraph graph = new StorageGraph();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
package io.anuke.mindustry.world.blocks.storage;
|
||||
|
||||
import com.badlogic.gdx.utils.IntSet;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import com.badlogic.gdx.utils.Queue;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.storage.StorageBlock.StorageEntity;
|
||||
import io.anuke.mindustry.world.modules.ItemModule;
|
||||
|
||||
public class StorageGraph{
|
||||
private static IntSet closedSet = new IntSet();
|
||||
private static Queue<Tile> queue = new Queue<>();
|
||||
private static ObjectSet<ItemModule> itemSet = new ObjectSet<>();
|
||||
private static int lastID;
|
||||
|
||||
private final int id = lastID++;
|
||||
private ObjectSet<Tile> tiles = new ObjectSet<>();
|
||||
private ItemModule items = new ItemModule();
|
||||
private int capacity;
|
||||
|
||||
public void set(Tile tile){
|
||||
items.addAll(tile.entity.items);
|
||||
items.setID(tile.entity.items.getID());
|
||||
|
||||
add(tile);
|
||||
}
|
||||
|
||||
public void add(Tile tile){
|
||||
|
||||
if(!tiles.add(tile)) return;
|
||||
|
||||
StorageEntity e = tile.entity();
|
||||
e.graph = this;
|
||||
|
||||
capacity += tile.block().itemCapacity;
|
||||
|
||||
if(tile.entity.items != null && tile.entity.items.getID() != items.getID()){
|
||||
items.addAll(tile.entity.items);
|
||||
}
|
||||
|
||||
tile.entity.items = items;
|
||||
}
|
||||
|
||||
public void remove(Tile tile){
|
||||
if(!tiles.contains(tile)) return;
|
||||
|
||||
for(Tile other : tiles){
|
||||
if(other == tile) continue;
|
||||
|
||||
StorageEntity entity = other.entity();
|
||||
entity.graph = null;
|
||||
entity.items = new ItemModule();
|
||||
|
||||
float fraction = (float)other.block().itemCapacity / capacity;
|
||||
items.forEach((item, amount) -> {
|
||||
int added = (int)(fraction * amount);
|
||||
entity.items.add(item, added);
|
||||
items.remove(item, added);
|
||||
});
|
||||
}
|
||||
|
||||
//handle remaining items that didn't get added
|
||||
Item taken;
|
||||
while((taken = items.take()) != null){
|
||||
for(Tile other : tiles){
|
||||
if(other == tile) continue;
|
||||
|
||||
//insert item into first found block
|
||||
if(other.entity.items.get(taken) < other.block().itemCapacity){
|
||||
other.entity.items.add(taken, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items.clear();
|
||||
capacity = 0;
|
||||
|
||||
for(Tile other : tile.entity.proximity()){
|
||||
if(other.block() instanceof StorageBlock && other.<StorageEntity>entity().graph == null){
|
||||
StorageGraph graph = new StorageGraph();
|
||||
other.<StorageEntity>entity().graph = graph;
|
||||
graph.reflow(tile, other);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reflow(Tile base, Tile tile){
|
||||
queue.clear();
|
||||
queue.addLast(tile);
|
||||
closedSet.clear();
|
||||
itemSet.clear();
|
||||
|
||||
while(queue.size > 0){
|
||||
Tile child = queue.removeFirst();
|
||||
StorageEntity entity = child.entity();
|
||||
entity.graph = this;
|
||||
|
||||
if(!itemSet.add(child.entity.items)) child.entity.items = null;
|
||||
add(child);
|
||||
|
||||
for(Tile next : child.entity.proximity()){
|
||||
if(next != base && next.block() instanceof StorageBlock && next.<StorageEntity>entity().graph == null && !closedSet.contains(next.packedPosition())){
|
||||
queue.addLast(next);
|
||||
closedSet.add(next.packedPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void merge(StorageGraph other){
|
||||
if(this == other || other == null) return;
|
||||
|
||||
itemSet.clear();
|
||||
for(Tile tile : other.tiles){
|
||||
if(!itemSet.add(tile.entity.items)){
|
||||
tile.entity.items = null;
|
||||
}
|
||||
}
|
||||
|
||||
for(Tile tile : other.tiles){
|
||||
add(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean accept(Item item){
|
||||
return accept(item, 1) == 1;
|
||||
}
|
||||
|
||||
public int accept(Item item, int amount){
|
||||
return Math.min(capacity - items.get(item), amount);
|
||||
}
|
||||
|
||||
public ObjectSet<Tile> getTiles(){
|
||||
return tiles;
|
||||
}
|
||||
|
||||
public int getID(){
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getCapacity(){
|
||||
return capacity;
|
||||
}
|
||||
|
||||
public ItemModule items(){
|
||||
return items;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.anuke.mindustry.world.blocks.storage;
|
||||
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
|
||||
public abstract class Unloader extends Block{
|
||||
protected final int timerUnload = timers++;
|
||||
|
||||
public Unloader(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
solid = true;
|
||||
health = 70;
|
||||
hasItems = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canDump(Tile tile, Tile to, Item item){
|
||||
Block block = to.target().block();
|
||||
return !(block instanceof StorageBlock);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBars(){}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ public class Vault extends StorageBlock{
|
||||
solid = true;
|
||||
update = false;
|
||||
destructible = true;
|
||||
itemCapacity = 1000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public class Reconstructor extends Block{
|
||||
|
||||
if(other != null && other.block() instanceof Reconstructor){
|
||||
ReconstructorEntity oe = other.entity();
|
||||
if(oe.link == entity.tile.packedPosition()){
|
||||
if(oe.link == entity.tile.pos()){
|
||||
oe.link = -1;
|
||||
}
|
||||
}
|
||||
@@ -103,8 +103,8 @@ public class Reconstructor extends Block{
|
||||
unlink(entity);
|
||||
unlink(oe);
|
||||
|
||||
entity.link = other.packedPosition();
|
||||
oe.link = tile.packedPosition();
|
||||
entity.link = other.pos();
|
||||
oe.link = tile.pos();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public class Reconstructor extends Block{
|
||||
|
||||
ReconstructorEntity entity = tile.entity();
|
||||
|
||||
if(entity.link == other.packedPosition()){
|
||||
if(entity.link == other.pos()){
|
||||
Call.unlinkReconstructor(null, tile, other);
|
||||
return false;
|
||||
}else if(other.block() instanceof Reconstructor){
|
||||
|
||||
Reference in New Issue
Block a user