Merge branch 'master' of https://github.com/Anuken/Mindustry into new-sectors

This commit is contained in:
Anuken
2018-10-30 22:18:07 -04:00
155 changed files with 1581 additions and 2452 deletions

View File

@@ -78,8 +78,6 @@ public class Vars{
public static boolean mobile;
public static boolean ios;
public static boolean android;
//shorthand for whether or not this is running on GWT
public static boolean gwt;
//main data directory
public static FileHandle dataDirectory;
//directory for user-created map data
@@ -139,7 +137,7 @@ public class Vars{
}
}
Arrays.sort(locales, (l1, l2) -> Platform.instance.getLocaleName(l1).compareTo(Platform.instance.getLocaleName(l2)));
Arrays.sort(locales, (l1, l2) -> l1.getDisplayName(l1).compareTo(l2.getDisplayName(l2)));
Version.init();
content = new ContentLoader();
@@ -166,18 +164,15 @@ public class Vars{
});
}
threads = new ThreadHandler(Platform.instance.getThreadProvider());
threads = new ThreadHandler();
mobile = Gdx.app.getType() == ApplicationType.Android || Gdx.app.getType() == ApplicationType.iOS || testMobile;
ios = Gdx.app.getType() == ApplicationType.iOS;
android = Gdx.app.getType() == ApplicationType.Android;
gwt = Gdx.app.getType() == ApplicationType.WebGL;
if(!gwt){
dataDirectory = OS.getAppDataDirectory(appName);
customMapDirectory = dataDirectory.child("maps/");
saveDirectory = dataDirectory.child("saves/");
}
dataDirectory = OS.getAppDataDirectory(appName);
customMapDirectory = dataDirectory.child("maps/");
saveDirectory = dataDirectory.child("saves/");
fontScale = Math.max(Unit.dp.scl(1f) / 2f, 0.5f);
baseCameraScale = Math.round(Unit.dp.scl(4));

View File

@@ -128,7 +128,11 @@ public class BlockIndexer{
for(int ty = ry * structQuadrantSize; ty < (ry + 1) * structQuadrantSize && ty < world.height(); ty++){
Tile other = world.tile(tx, ty);
if(other == null || other.entity == null || other.getTeam() != team || !pred.test(other) || !other.block().targetable) continue;
if(other == null) continue;
other = other.target();
if(other.entity == null || other.getTeam() != team || !pred.test(other) || !other.block().targetable) continue;
TileEntity e = other.entity;

View File

@@ -7,7 +7,7 @@ import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemType;
public class Items implements ContentList{
public static Item stone, copper, lead, densealloy, coal, titanium, thorium, silicon, plastanium, phasematter, surgealloy,
public static Item stone, copper, lead, densealloy, coal, titanium, thorium, silicon, plastanium, phasefabric, surgealloy,
biomatter, sand, blastCompound, pyratite;
@Override
@@ -71,9 +71,11 @@ public class Items implements ContentList{
cost = 1.6f;
}};
phasematter = new Item("phase-matter", Color.valueOf("f4ba6e")){{
phasefabric = new Item("phase-fabric", Color.valueOf("f4ba6e")){{
type = ItemType.material;
cost = 1.5f;
fluxiness = 0.9f;
radioactivity = 0.3f;
}};
surgealloy = new Item("surge-alloy", Color.valueOf("f3e979")){{
@@ -82,7 +84,7 @@ public class Items implements ContentList{
biomatter = new Item("biomatter", Color.valueOf("648b55")){{
flammability = 0.4f;
fluxiness = 0.2f;
fluxiness = 0.3f;
}};
sand = new Item("sand", Color.valueOf("e3d39e")){{

View File

@@ -36,8 +36,8 @@ public class Recipes implements ContentList{
new Recipe(defense, DefenseBlocks.thoriumWall, new ItemStack(Items.thorium, 12));
new Recipe(defense, DefenseBlocks.thoriumWallLarge, new ItemStack(Items.thorium, 12 * 4));
new Recipe(defense, DefenseBlocks.phaseWall, new ItemStack(Items.phasematter, 12));
new Recipe(defense, DefenseBlocks.phaseWallLarge, new ItemStack(Items.phasematter, 12 * 4));
new Recipe(defense, DefenseBlocks.phaseWall, new ItemStack(Items.phasefabric, 12));
new Recipe(defense, DefenseBlocks.phaseWallLarge, new ItemStack(Items.phasefabric, 12 * 4));
new Recipe(defense, DefenseBlocks.surgeWall, new ItemStack(Items.surgealloy, 12));
new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4));
@@ -68,7 +68,7 @@ public class Recipes implements ContentList{
//DISTRIBUTION
new Recipe(distribution, DistributionBlocks.conveyor, new ItemStack(Items.copper, 1)).setAlwaysUnlocked(true);
new Recipe(distribution, DistributionBlocks.titaniumconveyor, new ItemStack(Items.copper, 2), new ItemStack(Items.titanium, 1));
new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20));
new Recipe(distribution, DistributionBlocks.phaseConveyor, new ItemStack(Items.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20));
//starter lead transportation
new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2)).setAlwaysUnlocked(true);
@@ -125,11 +125,11 @@ public class Recipes implements ContentList{
//generators - solar
new Recipe(power, PowerBlocks.solarPanel, new ItemStack(Items.lead, 20), new ItemStack(Items.silicon, 30));
new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasematter, 30));
new Recipe(power, PowerBlocks.largeSolarPanel, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 290), new ItemStack(Items.phasefabric, 30));
//generators - nuclear
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.phasematter, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100));
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));
new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.densealloy, 40), new ItemStack(Items.silicon, 50));
new Recipe(distribution, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
@@ -138,7 +138,7 @@ public class Recipes implements ContentList{
/*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.phasematter, 750)
new ItemStack(Items.surgealloy, 500), new ItemStack(Items.phasefabric, 750)
);*/
//DRILLS, PRODUCERS
@@ -156,7 +156,7 @@ public class Recipes implements ContentList{
//bodies
new Recipe(units, UpgradeBlocks.dartPad, new ItemStack(Items.lead, 150), new ItemStack(Items.copper, 150), new ItemStack(Items.silicon, 200), new ItemStack(Items.titanium, 240)).setVisible(RecipeVisibility.desktopOnly);
new Recipe(units, UpgradeBlocks.tridentPad, new ItemStack(Items.lead, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250), new ItemStack(Items.titanium, 300), new ItemStack(Items.plastanium, 200));
new Recipe(units, UpgradeBlocks.javelinPad, new ItemStack(Items.lead, 350), new ItemStack(Items.silicon, 450), new ItemStack(Items.titanium, 500), new ItemStack(Items.plastanium, 400), new ItemStack(Items.phasematter, 200));
new Recipe(units, UpgradeBlocks.javelinPad, new ItemStack(Items.lead, 350), new ItemStack(Items.silicon, 450), new ItemStack(Items.titanium, 500), new ItemStack(Items.plastanium, 400), new ItemStack(Items.phasefabric, 200));
new Recipe(units, UpgradeBlocks.glaivePad, new ItemStack(Items.lead, 450), new ItemStack(Items.silicon, 650), new ItemStack(Items.titanium, 700), new ItemStack(Items.plastanium, 600), new ItemStack(Items.surgealloy, 200));
new Recipe(units, UpgradeBlocks.alphaPad, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 100), new ItemStack(Items.copper, 150)).setVisible(RecipeVisibility.mobileOnly);
@@ -170,7 +170,7 @@ public class Recipes implements ContentList{
new Recipe(units, UnitBlocks.daggerFactory, new ItemStack(Items.lead, 90), new ItemStack(Items.silicon, 70));
new Recipe(units, UnitBlocks.titanFactory, new ItemStack(Items.thorium, 90), new ItemStack(Items.lead, 140), new ItemStack(Items.silicon, 90));
new Recipe(units, UnitBlocks.fortressFactory, new ItemStack(Items.thorium, 200), new ItemStack(Items.lead, 220), new ItemStack(Items.silicon, 150), new ItemStack(Items.surgealloy, 100), new ItemStack(Items.phasematter, 50));
new Recipe(units, UnitBlocks.fortressFactory, new ItemStack(Items.thorium, 200), new ItemStack(Items.lead, 220), new ItemStack(Items.silicon, 150), new ItemStack(Items.surgealloy, 100), new ItemStack(Items.phasefabric, 50));
new Recipe(units, UnitBlocks.wraithFactory, new ItemStack(Items.titanium, 60), new ItemStack(Items.lead, 80), new ItemStack(Items.silicon, 90));
new Recipe(units, UnitBlocks.ghoulFactory, new ItemStack(Items.plastanium, 80), new ItemStack(Items.titanium, 100), new ItemStack(Items.lead, 130), new ItemStack(Items.silicon, 220));
@@ -182,7 +182,7 @@ public class Recipes implements ContentList{
//LIQUIDS
new Recipe(liquid, LiquidBlocks.conduit, new ItemStack(Items.lead, 1)).setDependencies(CraftingBlocks.smelter);
new Recipe(liquid, LiquidBlocks.pulseConduit, new ItemStack(Items.titanium, 1), new ItemStack(Items.lead, 1));
new Recipe(liquid, LiquidBlocks.phaseConduit, new ItemStack(Items.phasematter, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.titanium, 20));
new Recipe(liquid, LiquidBlocks.phaseConduit, new ItemStack(Items.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.titanium, 20));
new Recipe(liquid, LiquidBlocks.liquidRouter, new ItemStack(Items.titanium, 4), new ItemStack(Items.lead, 4));
new Recipe(liquid, LiquidBlocks.liquidtank, new ItemStack(Items.titanium, 50), new ItemStack(Items.lead, 50));

View File

@@ -52,7 +52,6 @@ public class UnitTypes implements ContentList{
drag = 0.4f;
hitsize = 8f;
mass = 1.75f;
range = 40f;
weapon = Weapons.chainBlaster;
health = 130;
}};
@@ -62,7 +61,6 @@ public class UnitTypes implements ContentList{
speed = 0.18f;
drag = 0.4f;
mass = 3.5f;
range = 10f;
hitsize = 9f;
rotatespeed = 0.1f;
weapon = Weapons.flamethrower;
@@ -75,7 +73,6 @@ public class UnitTypes implements ContentList{
drag = 0.4f;
mass = 5f;
hitsize = 10f;
range = 10f;
rotatespeed = 0.06f;
weaponOffsetX = 1;
targetAir = false;
@@ -111,6 +108,7 @@ public class UnitTypes implements ContentList{
speed = 0.14f;
maxVelocity = 1.3f;
drag = 0.01f;
range = 80f;
isFlying = true;
weapon = Weapons.laserBurster;
}};

View File

@@ -16,7 +16,7 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf;
public class Blocks extends BlockList implements ContentList{
public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, oil, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock;
public static Block air, blockpart, spawn, space, metalfloor, deepwater, water, lava, tar, stone, blackstone, dirt, sand, ice, snow, grass, shrub, rock, icerock, blackrock;
@Override
@@ -100,11 +100,11 @@ public class Blocks extends BlockList implements ContentList{
minimapColor = Color.valueOf("ed5334");
}};
oil = new Floor("oil"){{
tar = new Floor("tar"){{
liquidColor = Color.valueOf("292929");
status = StatusEffects.tarred;
statusIntensity = 1f;
speedMultiplier = 0.2f;
speedMultiplier = 0.19f;
variants = 0;
liquidDrop = Liquids.oil;
isLiquid = true;

View File

@@ -75,7 +75,7 @@ public class CraftingBlocks extends BlockList implements ContentList{
phaseWeaver = new PhaseWeaver("phase-weaver"){{
craftEffect = BlockFx.smeltsmoke;
result = Items.phasematter;
result = Items.phasefabric;
craftTime = 120f;
powerCapacity = 50f;
size = 2;

View File

@@ -22,8 +22,8 @@ import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.layout.Table;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -182,12 +182,12 @@ public class DebugBlocks extends BlockList implements ContentList{
public Liquid source = Liquids.water;
@Override
public void write(DataOutputStream stream) throws IOException{
public void writeConfig(DataOutput stream) throws IOException{
stream.writeByte(source.id);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void readConfig(DataInput stream) throws IOException{
source = content.liquid(stream.readByte());
}
}

View File

@@ -73,19 +73,19 @@ public class DefenseBlocks extends BlockList implements ContentList{
mendProjector = new MendProjector("mend-projector"){{
consumes.power(0.2f);
size = 2;
consumes.item(Items.phasematter).optional(true);
consumes.item(Items.phasefabric).optional(true);
}};
overdriveProjector = new OverdriveProjector("overdrive-projector"){{
consumes.power(0.35f);
size = 2;
consumes.item(Items.phasematter).optional(true);
consumes.item(Items.phasefabric).optional(true);
}};
forceProjector = new ForceProjector("force-projector"){{
consumes.power(0.2f);
size = 3;
consumes.item(Items.phasematter).optional(true);
consumes.item(Items.phasefabric).optional(true);
}};
shockMine = new ShockMine("shock-mine"){{

View File

@@ -38,7 +38,7 @@ public class ProductionBlocks extends BlockList implements ContentList{
updateEffect = BlockFx.pulverizeMedium;
drillEffect = BlockFx.mineBig;
consumes.power(0.16f);
consumes.power(0.11f);
}};
blastDrill = new Drill("blast-drill"){{
@@ -80,7 +80,7 @@ public class ProductionBlocks extends BlockList implements ContentList{
liquidCapacity = 30f;
rotateSpeed = 1.4f;
consumes.power(0.1f);
consumes.power(0.09f);
}};
oilExtractor = new Fracker("oil-extractor"){{

View File

@@ -35,6 +35,7 @@ import io.anuke.ucore.util.ThreadArray;
@SuppressWarnings("unchecked")
public class ContentLoader{
private boolean loaded = false;
private boolean verbose = true;
private ObjectMap<String, MappableContent>[] contentNameMap = new ObjectMap[ContentType.values().length];
private Array<Content>[] contentMap = new Array[ContentType.values().length];
@@ -152,12 +153,14 @@ public class ContentLoader{
throw new ImpendingDoomException("THE TIME HAS COME. More than 256 blocks have been created.");
}
Log.info("--- CONTENT INFO ---");
for(int k = 0; k < contentMap.length; k ++){
Log.info("[{0}]: loaded {1}", ContentType.values()[k].name(), contentMap[k].size);
if(verbose){
Log.info("--- CONTENT INFO ---");
for(int k = 0; k < contentMap.length; k++){
Log.info("[{0}]: loaded {1}", ContentType.values()[k].name(), contentMap[k].size);
}
Log.info("Total content loaded: {0}", total);
Log.info("-------------------");
}
Log.info("Total content loaded: {0}", total);
Log.info("-------------------");
loaded = true;
}
@@ -175,6 +178,10 @@ public class ContentLoader{
initialization.add(callable);
}
public void verbose(boolean verbose){
this.verbose = verbose;
}
public void dispose(){
//clear all content, currently not needed
}
@@ -203,7 +210,7 @@ public class ContentLoader{
if(id < 0) id += 256;
if(temporaryMapper != null && temporaryMapper[type.ordinal()] != null && temporaryMapper[type.ordinal()].length != 0){
if(temporaryMapper[type.ordinal()][id] == null){
if(temporaryMapper[type.ordinal()].length <= id || temporaryMapper[type.ordinal()][id] == null){
return getByID(type, 0); //default value is always ID 0
}
return (T)temporaryMapper[type.ordinal()][id];

View File

@@ -26,10 +26,7 @@ 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.Atlas;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Strings;
import io.anuke.ucore.util.Timer;
import io.anuke.ucore.util.*;
import java.io.IOException;
@@ -60,7 +57,7 @@ public class Control extends Module{
saves = new Saves();
unlocks = new Unlocks();
Inputs.useControllers(!gwt);
Inputs.useControllers(true);
Gdx.input.setCatchBackKey(true);
@@ -397,7 +394,7 @@ public class Control extends Module{
}
}else{
if(!state.is(State.paused) || Net.active()){
if(!state.isPaused()){
Timers.update();
}
}

View File

@@ -10,6 +10,7 @@ import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Teams;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.world.Tile;
@@ -21,7 +22,6 @@ import io.anuke.ucore.entities.EntityQuery;
import io.anuke.ucore.modules.Module;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.gen.Call;
/**
* Logic module.
@@ -159,16 +159,13 @@ public class Logic extends Module{
if(!state.is(State.menu)){
if(!state.is(State.paused) || Net.active()){
Timers.update();
}
if(!Net.client() && !world.isInvalidMap()){
updateSectors();
checkGameOver();
}
if(!state.is(State.paused) || Net.active()){
if(!state.isPaused()){
Timers.update();
if(!state.mode.disableWaveTimer && !state.mode.disableWaves){
state.wavetime -= Timers.delta();

View File

@@ -21,7 +21,6 @@ import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.NetworkIO;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.net.TraceInfo;
import io.anuke.mindustry.net.ValidateException;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.modules.ItemModule;
@@ -207,12 +206,6 @@ public class NetClient extends Module{
players[0].y = y;
}
@Remote(variants = Variant.one)
public static void onTraceInfo(TraceInfo info){
Player player = playerGroup.getByID(info.playerid);
ui.traces.show(player, info);
}
@Remote
public static void onPlayerDisconnect(int playerid){
playerGroup.removeByID(playerid);

View File

@@ -106,11 +106,9 @@ public class NetServer extends Module{
connection.hasBegunConnecting = true;
TraceInfo trace = admins.getTraceByID(uuid);
PlayerInfo info = admins.getInfo(uuid);
trace.uuid = uuid;
trace.ip = connection.address;
trace.android = packet.mobile;
connection.mobile = packet.mobile;
if(admins.isIDBanned(uuid)){
kick(id, KickReason.banned);
@@ -150,7 +148,7 @@ public class NetServer extends Module{
return;
}
Log.info("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, trace.ip);
Log.info("Recieved connect packet for player '{0}' / UUID {1} / IP {2}", packet.name, uuid, connection.address);
String ip = Net.getConnection(id).address;
@@ -162,7 +160,7 @@ public class NetServer extends Module{
}
if(packet.version == -1){
trace.modclient = true;
connection.modclient = true;
}
Player player = new Player();
@@ -207,8 +205,6 @@ public class NetServer extends Module{
connections.put(id, player);
trace.playerid = player.id;
sendWorldData(player, id);
Platform.instance.updateRPC();
@@ -327,9 +323,9 @@ public class NetServer extends Module{
player.getPlaceQueue().clear();
for(BuildRequest req : requests){
//auto-skip done requests
if(req.remove && world.tile(req.x, req.y).block() == Blocks.air){
if(req.breaking && world.tile(req.x, req.y).block() == Blocks.air){
continue;
}else if(!req.remove && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){
}else if(!req.breaking && world.tile(req.x, req.y).block() == req.recipe.result && (!req.recipe.result.rotate || world.tile(req.x, req.y).getRotation() == req.rotation)){
continue;
}
player.getPlaceQueue().addLast(req);
@@ -395,11 +391,11 @@ public class NetServer extends Module{
netServer.kick(other.con.id, KickReason.kick);
Log.info("&lc{0} has kicked {1}.", player.name, other.name);
}else if(action == AdminAction.trace){
//TODO
//TODO implement
if(player.con != null){
Call.onTraceInfo(player.con.id, netServer.admins.getTraceByID(other.uuid));
//Call.onTraceInfo(player.con.id, other.con.trace);
}else{
NetClient.onTraceInfo(netServer.admins.getTraceByID(other.uuid));
//NetClient.onTraceInfo(other.con.trace);
}
Log.info("&lc{0} has requested trace info of {1}.", player.name, other.name);
}
@@ -424,7 +420,6 @@ public class NetServer extends Module{
if(!headless && !closing && Net.server() && state.is(State.menu)){
closing = true;
reset();
threads.runGraphics(() -> ui.loadfrag.show("$text.server.closing"));
Timers.runTask(5f, () -> {
Net.closeServer();
@@ -438,10 +433,6 @@ public class NetServer extends Module{
}
}
public void reset(){
admins.clearTraces();
}
public void kickAll(KickReason reason){
for(NetConnection con : Net.getConnections()){
kick(con.id, reason);

View File

@@ -2,13 +2,11 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Base64Coder;
import io.anuke.mindustry.core.ThreadHandler.ThreadProvider;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.scene.ui.TextField;
import java.util.Date;
import java.util.Locale;
import java.util.Random;
public abstract class Platform {
@@ -36,10 +34,6 @@ public abstract class Platform {
public boolean canDonate(){
return false;
}
/**Return the localized name for the locale. This is basically a workaround for GWT not supporting getName().*/
public String getLocaleName(Locale locale){
return locale.toString();
}
/**Must be a base64 string 8 bytes in length.*/
public String getUUID(){
String uuid = Settings.getString("uuid", "");
@@ -55,8 +49,6 @@ public abstract class Platform {
}
/**Only used for iOS or android: open the share menu for a map or save.*/
public void shareFile(FileHandle file){}
/**Download a file. Only used on GWT backend.*/
public void downloadFile(String name, byte[] bytes){}
/**Show a file chooser. Desktop only.
*
@@ -67,17 +59,6 @@ public abstract class Platform {
* @param filetype File extension to filter
*/
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){}
/**Use the default thread provider from the kryonet module for this.*/
public ThreadProvider getThreadProvider(){
return new ThreadProvider() {
@Override public boolean isOnThread() {return true;}
@Override public void sleep(long ms) {}
@Override public void start(Runnable run) {}
@Override public void stop() {}
@Override public void notify(Object object) {}
@Override public void wait(Object object) {}
};
}
/**Forces the app into landscape mode. Currently Android only.*/
public void beginForceLandscape(){}

View File

@@ -6,13 +6,15 @@ import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Threads;
import io.anuke.ucore.util.Threads.ThreadInfoProvider;
import static io.anuke.mindustry.Vars.control;
import static io.anuke.mindustry.Vars.logic;
public class ThreadHandler{
public class ThreadHandler implements ThreadInfoProvider{
private final Queue<Runnable> toRun = new Queue<>();
private final ThreadProvider impl;
private Thread thread, graphicsThread;
private final Object updateLock = new Object();
private float delta = 1f;
private float smoothDelta = 1f;
@@ -22,11 +24,12 @@ public class ThreadHandler{
private boolean rendered = true;
private long lastFrameTime;
public ThreadHandler(ThreadProvider impl){
this.impl = impl;
public ThreadHandler(){
Threads.setThreadInfoProvider(this);
graphicsThread = Thread.currentThread();
Timers.setDeltaProvider(() -> {
float result = impl.isOnThread() ? delta : Gdx.graphics.getDeltaTime() * 60f;
float result = isOnThread() ? delta : Gdx.graphics.getDeltaTime() * 60f;
return Math.min(Float.isNaN(result) ? 1f : result, 15f);
});
}
@@ -86,7 +89,7 @@ public class ThreadHandler{
long elapsed = TimeUtils.timeSinceMillis(lastFrameTime);
if(elapsed < target){
try{
impl.sleep(target - elapsed);
Thread.sleep(target - elapsed);
}catch(InterruptedException e){
e.printStackTrace();
}
@@ -99,7 +102,7 @@ public class ThreadHandler{
synchronized(updateLock){
rendered = true;
impl.notify(updateLock);
updateLock.notify();
}
}
@@ -111,12 +114,25 @@ public class ThreadHandler{
if(enabled){
logic.doUpdate = false;
Timers.runTask(2f, () -> {
impl.start(this::runLogic);
if(thread != null){
thread.interrupt();
thread = null;
}
thread = new Thread(this::runLogic);
thread.setDaemon(true);
thread.setName("Update Thread");
thread.start();
Log.info("Starting logic thread.");
this.enabled = true;
});
}else{
this.enabled = false;
impl.stop();
if(thread != null){
thread.interrupt();
thread = null;
}
Timers.runTask(2f, () -> {
logic.doUpdate = true;
});
@@ -128,7 +144,17 @@ public class ThreadHandler{
}
public boolean isOnThread(){
return impl.isOnThread();
return Thread.currentThread() == thread;
}
@Override
public boolean isOnLogicThread() {
return !enabled || Thread.currentThread() == thread;
}
@Override
public boolean isOnGraphicsThread() {
return !enabled || Thread.currentThread() == graphicsThread;
}
private void runLogic(){
@@ -157,12 +183,12 @@ public class ThreadHandler{
long target = (long) ((1000) / 60f);
if(elapsed < target){
impl.sleep(target - elapsed);
Thread.sleep(target - elapsed);
}
synchronized(updateLock){
while(!rendered){
impl.wait(updateLock);
updateLock.wait();
}
rendered = false;
}
@@ -184,18 +210,4 @@ public class ThreadHandler{
control.setError(ex);
}
}
public interface ThreadProvider{
boolean isOnThread();
void sleep(long ms) throws InterruptedException;
void start(Runnable run);
void stop();
void wait(Object object) throws InterruptedException;
void notify(Object object);
}
}

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.core;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Colors;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.utils.Align;
import io.anuke.mindustry.Vars;
@@ -25,7 +26,6 @@ import io.anuke.ucore.scene.ui.TextField.TextFieldFilter;
import io.anuke.ucore.scene.ui.TooltipManager;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Structs;
import static io.anuke.mindustry.Vars.*;
import static io.anuke.ucore.scene.actions.Actions.*;
@@ -108,12 +108,11 @@ public class UI extends SceneModule{
@Override
protected void loadSkin(){
skin = new Skin(Gdx.files.internal("ui/uiskin.json"), Core.atlas);
Structs.each(font -> {
for(BitmapFont font : skin.getAll(BitmapFont.class).values()){
font.setUseIntegerPositions(false);
font.getData().setScale(Vars.fontScale);
font.getData().down += Unit.dp.scl(3f);
font.getData().lineHeight -= Unit.dp.scl(3f);
}, skin.font(), skin.getFont("default-font-chat"), skin.getFont("trad-chinese"), skin.getFont("simp-chinese"));
}
}
@Override

View File

@@ -243,7 +243,7 @@ public class World extends Module{
EntityQuery.resizeTree(0, 0, width * tilesize, height * tilesize);
try{
generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), 0);
generator.loadTileData(tiles, MapIO.readTileData(map, true), map.meta.hasOreGen(), Mathf.random(99999));
} catch(Exception e){
Log.err(e);
if(!headless){
@@ -257,6 +257,8 @@ public class World extends Module{
endMapLoad();
invalidMap = false;
if(!headless){
if(state.teams.get(players[0].getTeam()).cores.size == 0){
ui.showError("$text.map.nospawn");

View File

@@ -38,7 +38,6 @@ import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Strings;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -113,73 +112,40 @@ public class MapEditorDialog extends Dialog implements Disposable{
}, true, mapExtension);
},
"$text.editor.importimage", "$text.editor.importimage.description", "icon-file-image", (Runnable)() -> {
if(gwt){
ui.showError("$text.web.unsupported");
}else {
Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> {
ui.loadGraphics(() -> {
try{
MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file));
Platform.instance.showFileChooser("$text.loadimage", "Image Files", file -> {
ui.loadGraphics(() -> {
try{
MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file));
editor.beginEdit(data, editor.getTags(), false);
view.clearStack();
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
});
}, true, "png");
}
editor.beginEdit(data, editor.getTags(), false);
view.clearStack();
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
});
}, true, "png");
}));
t.addImageTextButton("$text.editor.export", "icon-save-map", isize, () -> createDialog("$text.editor.export",
"$text.editor.exportfile", "$text.editor.exportfile.description", "icon-file", (Runnable) () -> {
if(!gwt){
Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> {
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
FileHandle result = file;
ui.loadGraphics(() -> {
Platform.instance.showFileChooser("$text.saveimage", "Map Files", file -> {
file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension);
FileHandle result = file;
ui.loadGraphics(() -> {
try{
if(!editor.getTags().containsKey("name")){
editor.getTags().put("name", result.nameWithoutExtension());
}
MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap());
}catch(Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
Log.err(e);
try{
if(!editor.getTags().containsKey("name")){
editor.getTags().put("name", result.nameWithoutExtension());
}
});
}, false, mapExtension);
}else{
try{
ByteArrayOutputStream ba = new ByteArrayOutputStream();
MapIO.writeMap(ba, editor.getTags(), editor.getMap());
Platform.instance.downloadFile(editor.getTags().get("name", "unknown") + "." + mapExtension, ba.toByteArray());
}catch(IOException e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
Log.err(e);
}
}
}/*,
"$text.editor.exportimage", "$text.editor.exportimage.description", "icon-file-image", (Listenable)() -> {
if(gwt){
ui.showError("$text.web.unsupported");
}else{
Platform.instance.showFileChooser("$text.saveimage", "Image Files", file -> {
file = file.parent().child(file.nameWithoutExtension() + ".png");
FileHandle result = file;
ui.loadGraphics(() -> {
try{
Pixmaps.write(MapIO.generatePixmap(editor.getMap()), result);
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
Log.err(e);
}
});
}, false, "png");
}
}*/));
MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap());
}catch(Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
Log.err(e);
}
});
}, false, mapExtension);
}));
t.row();
@@ -475,6 +441,14 @@ public class MapEditorDialog extends Dialog implements Disposable{
mid.table("button", t -> {
Slider slider = new Slider(0, MapEditor.brushSizes.length - 1, 1, false);
slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int) (float) f]));
slider.update(() -> {
for(int j = 0; j < MapEditor.brushSizes.length; j++){
if(editor.getBrushSize() == j){
slider.setValue(j);
return;
}
}
});
t.top();
t.add("$text.editor.brush");

View File

@@ -1,5 +1,6 @@
package io.anuke.mindustry.editor;
import com.badlogic.gdx.utils.Scaling;
import io.anuke.mindustry.maps.Map;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
@@ -58,7 +59,7 @@ public class MapLoadDialog extends FloatingDialog{
for(Map map : world.maps.all()){
TextButton button = new TextButton(map.getDisplayName(), "toggle");
button.add(new BorderImage(map.texture, 2f)).size(16 * 4f);
button.add(new BorderImage(map.texture, 2f).setScaling(Scaling.fit)).size(16 * 4f);
button.getCells().reverse();
button.clicked(() -> selected = map);
button.getLabelCell().grow().left().padLeft(5f);

View File

@@ -295,7 +295,7 @@ public class MapView extends Element implements GestureListener{
}
//todo is it really math.max?
float scaling = zoom * Math.min(width, height) / Math.max(editor.getMap().width(), editor.getMap().height());
float scaling = zoom * Math.min(width, height) / editor.getMap().width();
Draw.color(Palette.accent);
Lines.stroke(Unit.dp.scl(1f * zoom));

View File

@@ -420,7 +420,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
for(BuildRequest request : getPlaceQueue()){
if(getCurrentRequest() == request) continue;
if(request.remove){
if(request.breaking){
Block block = world.tile(request.x, request.y).target().block();
//draw removal request

View File

@@ -28,8 +28,8 @@ import io.anuke.ucore.entities.trait.HealthTrait;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Timer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tileGroup;
@@ -120,11 +120,13 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
return dead || tile.entity != this;
}
public void write(DataOutputStream stream) throws IOException{
}
public void write(DataOutput stream) throws IOException{}
public void read(DataInputStream stream) throws IOException{
}
public void writeConfig(DataOutput stream) throws IOException{}
public void read(DataInput stream) throws IOException{}
public void readConfig(DataInput stream) throws IOException{}
public boolean collide(Bullet other){
return true;

View File

@@ -41,16 +41,12 @@ public class Units{
return target == null || (range != Float.MAX_VALUE && target.distanceTo(x, y) > range) || target.getTeam() == team || !target.isValid();
}
/**
* See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}
*/
/**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/
public static boolean invalidateTarget(TargetTrait target, Team team, float x, float y){
return invalidateTarget(target, team, x, y, Float.MAX_VALUE);
}
/**
* See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}
*/
/**See {@link #invalidateTarget(TargetTrait, Team, float, float, float)}*/
public static boolean invalidateTarget(TargetTrait target, Unit targeter){
return invalidateTarget(target, targeter.team, targeter.x, targeter.y, targeter.getWeapon().getAmmo().getRange());
}
@@ -129,16 +125,12 @@ public class Units{
return value[0];
}
/**
* Returns the neareset ally tile in a range.
*/
/**Returns the neareset ally tile in a range.*/
public static TileEntity findAllyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
return world.indexer.findTile(team, x, y, range, pred);
}
/**
* Returns the neareset enemy tile in a range.
*/
/**Returns the neareset enemy tile in a range.*/
public static TileEntity findEnemyTile(Team team, float x, float y, float range, Predicate<Tile> pred){
for(Team enemy : state.teams.enemiesOf(team)){
TileEntity entity = world.indexer.findTile(enemy, x, y, range, pred);
@@ -149,9 +141,7 @@ public class Units{
return null;
}
/**
* Iterates over all units on all teams, including players.
*/
/**Iterates over all units on all teams, including players.*/
public static void allUnits(Consumer<Unit> cons){
//check all unit groups first
for(EntityGroup<BaseUnit> group : unitGroups){
@@ -183,9 +173,7 @@ public class Units{
}
}
/**
* Returns the closest enemy of this team. Filter by predicate.
*/
/**Returns the closest enemy of this team. Filter by predicate.*/
public static Unit getClosestEnemy(Team team, float x, float y, float range, Predicate<Unit> predicate){
result = null;
cdist = 0f;
@@ -208,9 +196,7 @@ public class Units{
return result;
}
/**
* Returns the closest ally of this team. Filter by predicate.
*/
/**Returns the closest ally of this team. Filter by predicate.*/
public static Unit getClosest(Team team, float x, float y, float range, Predicate<Unit> predicate){
result = null;
cdist = 0f;
@@ -233,9 +219,7 @@ public class Units{
return result;
}
/**
* Iterates over all units in a rectangle.
*/
/**Iterates over all units in a rectangle.*/
public static void getNearby(Team team, Rectangle rect, Consumer<Unit> cons){
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
@@ -249,9 +233,7 @@ public class Units{
});
}
/**
* Iterates over all units in a circle around this position.
*/
/**Iterates over all units in a circle around this position.*/
public static void getNearby(Team team, float x, float y, float radius, Consumer<Unit> cons){
rect.setSize(radius * 2).setCenter(x, y);
@@ -272,9 +254,7 @@ public class Units{
});
}
/**
* Iterates over all units in a rectangle.
*/
/**Iterates over all units in a rectangle.*/
public static void getNearby(Rectangle rect, Consumer<Unit> cons){
for(Team team : Team.all){
@@ -288,9 +268,7 @@ public class Units{
EntityQuery.getNearby(playerGroup, rect, player -> cons.accept((Unit) player));
}
/**
* Iterates over all units that are enemies of this team.
*/
/**Iterates over all units that are enemies of this team.*/
public static void getNearbyEnemies(Team team, Rectangle rect, Consumer<Unit> cons){
EnumSet<Team> targets = state.teams.enemiesOf(team);
@@ -309,9 +287,7 @@ public class Units{
});
}
/**
* Iterates over all units.
*/
/**Iterates over all units.*/
public static void getAllUnits(Consumer<Unit> cons){
for(Team team : Team.all){
@@ -327,5 +303,4 @@ public class Units{
}
}
}

View File

@@ -57,29 +57,21 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
private float accepting;
private byte generation;
/**
* Deserialization use only!
*/
/**Deserialization use only!*/
public Puddle(){
}
/**
* Deposists a puddle between tile and source.
*/
/**Deposists a puddle between tile and source.*/
public static void deposit(Tile tile, Tile source, Liquid liquid, float amount){
deposit(tile, source, liquid, amount, 0);
}
/**
* Deposists a puddle at a tile.
*/
/**Deposists a puddle at a tile.*/
public static void deposit(Tile tile, Liquid liquid, float amount){
deposit(tile, tile, liquid, amount, 0);
}
/**
* Returns the puddle on the specified tile. May return null.
*/
/**Returns the puddle on the specified tile. May return null.*/
public static Puddle getPuddle(Tile tile){
return map.get(tile.packedPosition());
}
@@ -119,7 +111,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
p.lastRipple = Timers.time();
}
}else{
p.amount -= reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y);
p.amount += reactPuddle(p.liquid, liquid, amount, p.tile, p.x, p.y);
}
}
@@ -131,9 +123,7 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
return liquid == Liquids.oil && other == Liquids.water;
}
/**
* Reacts two liquids together at a location.
*/
/**Reacts two liquids together at a location.*/
private static float reactPuddle(Liquid dest, Liquid liquid, float amount, Tile tile, float x, float y){
if((dest.flammability > 0.3f && liquid.temperature > 0.7f) ||
(liquid.flammability > 0.3f && dest.temperature > 0.7f)){ //flammable liquid + hot liquid

View File

@@ -8,6 +8,7 @@ import io.anuke.mindustry.content.fx.BlockFx;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.net.Net;
@@ -18,6 +19,7 @@ import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.BuildBlock;
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.trait.Entity;
import io.anuke.ucore.graphics.Draw;
@@ -65,10 +67,10 @@ public interface BuilderTrait extends Entity{
BuildRequest request = getCurrentRequest();
if(request != null){
output.writeByte(request.remove ? 1 : 0);
output.writeByte(request.breaking ? 1 : 0);
output.writeInt(world.toPacked(request.x, request.y));
output.writeFloat(request.progress);
if(!request.remove){
if(!request.breaking){
output.writeByte(request.recipe.id);
output.writeByte(request.rotation);
}
@@ -181,18 +183,16 @@ public interface BuilderTrait extends Entity{
setMineTile(null);
}
Tile tile = world.tile(current.x, current.y);
if(unit.distanceTo(tile) > placeDistance){
return;
}
if(!(tile.block() instanceof BuildBlock) ){
if(canCreateBlocks() && !current.remove && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){
if(!(tile.block() instanceof BuildBlock)){
if(canCreateBlocks() && !current.breaking && Build.validPlace(unit.getTeam(), current.x, current.y, current.recipe.result, current.rotation)){
Build.beginPlace(unit.getTeam(), current.x, current.y, current.recipe, current.rotation);
}else if(canCreateBlocks() && current.remove && Build.validBreak(unit.getTeam(), current.x, current.y)){
}else if(canCreateBlocks() && current.breaking && Build.validBreak(unit.getTeam(), current.x, current.y)){
Build.beginBreak(unit.getTeam(), current.x, current.y);
}else{
getPlaceQueue().removeFirst();
@@ -222,7 +222,7 @@ public interface BuilderTrait extends Entity{
//progress is synced, thus not updated clientside
if(!Net.client()){
//deconstructing is 2x as fast
if(current.remove){
if(current.breaking){
entity.deconstruct(unit, core, 2f / entity.buildCost * Timers.delta() * getBuildPower(tile));
}else{
entity.construct(unit, core, 1f / entity.buildCost * Timers.delta() * getBuildPower(tile));
@@ -232,6 +232,11 @@ public interface BuilderTrait extends Entity{
}else{
entity.progress = current.progress;
}
if(!current.initialized){
Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking));
current.initialized = true;
}
}
/**Do not call directly.*/
@@ -352,9 +357,10 @@ public interface BuilderTrait extends Entity{
class BuildRequest{
public final int x, y, rotation;
public final Recipe recipe;
public final boolean remove;
public final boolean breaking;
public float progress;
public boolean initialized;
/**This creates a build request.*/
public BuildRequest(int x, int y, int rotation, Recipe recipe){
@@ -362,7 +368,7 @@ public interface BuilderTrait extends Entity{
this.y = y;
this.rotation = rotation;
this.recipe = recipe;
this.remove = false;
this.breaking = false;
}
/**This creates a remove request.*/
@@ -371,7 +377,7 @@ public interface BuilderTrait extends Entity{
this.y = y;
this.rotation = -1;
this.recipe = Recipe.getByResult(world.tile(x, y).block());
this.remove = true;
this.breaking = true;
}
}
}

View File

@@ -9,9 +9,10 @@ import io.anuke.ucore.core.Effects;
import io.anuke.ucore.entities.trait.SolidTrait;
public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{
@Remote(called = Loc.both, targets = Loc.both, forward = true)
static void dropSelf(Player player){
if(player.getCarrier() != null){
if(player != null && player.getCarrier() != null){
player.getCarrier().dropCarry();
}
}
@@ -40,24 +41,16 @@ public interface CarryTrait extends TeamTrait, SolidTrait, TargetTrait{
}
}
/**
* Returns the thing this carrier is carrying.
*/
/**Returns the thing this carrier is carrying.*/
CarriableTrait getCarry();
/**
* Sets the carrying unit. Internal use only! Use {@link #carry(CarriableTrait)} to set state.
*/
/**Sets the carrying unit. Internal use only! Use {@link #carry(CarriableTrait)} to set state.*/
void setCarry(CarriableTrait unit);
/**
* Returns maximum mass this carrier can carry.
*/
/**Returns maximum mass this carrier can carry.*/
float getCarryWeight();
/**
* Drops the unit that is being carried, if applicable.
*/
/**Drops the unit that is being carried, if applicable.*/
default void dropCarry(){
carry(null);
}

View File

@@ -190,7 +190,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
}
public void targetClosest(){
target = Units.getClosestTarget(team, x, y, getWeapon().getAmmo().getRange(), u -> type.targetAir || !u.isFlying());
target = Units.getClosestTarget(team, x, y, Math.max(getWeapon().getAmmo().getRange(), type.range), u -> type.targetAir || !u.isFlying());
}
public TileEntity getClosestEnemyCore(){

View File

@@ -76,7 +76,7 @@ public abstract class FlyingUnit extends BaseUnit implements CarryTrait{
attack(150f);
if((Mathf.angNear(angleTo(target), rotation, 15f) || !getWeapon().getAmmo().bullet.keepVelocity) //bombers don't care about rotation
&& distanceTo(target) < getWeapon().getAmmo().getRange()){
&& distanceTo(target) < Math.max(getWeapon().getAmmo().getRange(), type.range)){
AmmoType ammo = getWeapon().getAmmo();
Vector2 to = Predict.intercept(FlyingUnit.this, target, ammo.bullet.speed);

View File

@@ -29,7 +29,7 @@ public class UnitType extends UnlockableContent{
public float hitsize = 7f;
public float hitsizeTile = 4f;
public float speed = 0.4f;
public float range = 160;
public float range = 0;
public float rotatespeed = 0.2f;
public float baseRotateSpeed = 0.1f;
public float mass = 1f;

View File

@@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Queue;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.content.fx.BlockFx;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.entities.traits.BuilderTrait;
@@ -12,7 +13,7 @@ import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.entities.units.FlyingUnit;
import io.anuke.mindustry.entities.units.UnitCommand;
import io.anuke.mindustry.entities.units.UnitState;
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
import io.anuke.mindustry.game.EventType.BuildSelectEvent;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.net.Net;
@@ -35,7 +36,8 @@ import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
import static io.anuke.mindustry.Vars.unitGroups;
import static io.anuke.mindustry.Vars.world;
public class Drone extends FlyingUnit implements BuilderTrait{
protected static float discoverRange = 120f;
@@ -44,6 +46,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
protected Item targetItem;
protected Tile mineTile;
protected Queue<BuildRequest> placeQueue = new ThreadQueue<>();
protected boolean isBreaking;
public final UnitState
@@ -66,9 +69,13 @@ public class Drone extends FlyingUnit implements BuilderTrait{
if(core == null) return;
if(entity.progress() < 1f && entity.tile.block() instanceof BuildBlock){ //building is valid
if((entity.progress() < 1f || entity.progress() > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid
if(!isBuilding() && distanceTo(target) < placeDistance * 0.9f){ //within distance, begin placing
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe));
if(isBreaking){
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y));
}else{
getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.getRotation(), entity.recipe));
}
}
//if it's missing requirements, try and mine them
@@ -234,27 +241,39 @@ public class Drone extends FlyingUnit implements BuilderTrait{
};
static{
Events.on(BlockBuildEvent.class, event -> {
Events.on(BuildSelectEvent.class, event -> {
EntityGroup<BaseUnit> group = unitGroups[event.team.ordinal()];
if(!(event.tile.entity instanceof BuildEntity)) return;
if(!(event.builder instanceof Player) || !(event.tile.entity instanceof BuildEntity)) return;
BuildEntity entity = event.tile.entity();
for(BaseUnit unit : group.all()){
if(unit instanceof Drone){
((Drone) unit).notifyPlaced(entity);
Drone drone = (Drone)unit;
synchronized(drone.getPlaceQueue()){
if(drone.isBuilding()){
//stop building if opposite building begins.
BuildRequest req = drone.getCurrentRequest();
if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){
drone.clearBuilding();
drone.setState(drone.repair);
}
}
}
drone.notifyPlaced(entity, event.breaking);
}
}
});
}
private void notifyPlaced(BuildEntity entity){
float timeToBuild = entity.recipe.cost;
private void notifyPlaced(BuildEntity entity, boolean isBreaking){
float dist = Math.min(entity.distanceTo(x, y) - placeDistance, 0);
if(dist / type.maxVelocity < timeToBuild * 0.9f){
//Call.onDroneBeginBuild(this, entity.tile, entity.recipe);
if(!state.is(build) && dist / type.maxVelocity < entity.buildCost * 0.9f){
target = entity;
this.isBreaking = isBreaking;
setState(build);
}
}

View File

@@ -1,6 +1,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;
@@ -76,14 +77,33 @@ public class EventType{
}
}
/**Called when block building begins. The tile's block will nearly always be a BuildBlock.*/
public static class BlockBuildEvent implements Event{
/**Called when block building begins by placing down the BuildBlock.
* The tile's block will nearly always be a BuildBlock.*/
public static class BlockBuildBeginEvent implements Event{
public final Tile tile;
public final Team team;
public final boolean breaking;
public BlockBuildEvent(Tile tile, Team team){
public BlockBuildBeginEvent(Tile tile, Team team, boolean breaking){
this.tile = tile;
this.team = team;
this.breaking = breaking;
}
}
/**Called when a player or drone begins building something.
* This does not necessarily happen when a new BuildBlock is created.*/
public static class BuildSelectEvent implements Event{
public final Tile tile;
public final Team team;
public final BuilderTrait builder;
public final boolean breaking;
public BuildSelectEvent(Tile tile, Team team, BuilderTrait builder, boolean breaking){
this.tile = tile;
this.team = team;
this.builder = builder;
this.breaking = breaking;
}
}

View File

@@ -256,9 +256,7 @@ public class Saves{
}
public void delete(){
if(!gwt){ //can't delete files
SaveIO.fileFor(index).delete();
}
SaveIO.fileFor(index).delete();
saves.removeValue(this, true);
saveMap.remove(index);
if(this == current){

View File

@@ -60,14 +60,15 @@ public class Palette{
bar = Color.SLATE,
interact = Color.ORANGE,
accent = Color.valueOf("f4ba6e"),
accentBack = new Color(accent.r * 0.8f, accent.g * 0.8f, accent.b * 0.8f, 1f),
accentBack = Color.valueOf("d58c4b"),
place = Color.valueOf("6335f8"),
remove = Color.valueOf("e55454"),
removeBack = Color.valueOf("a73e3e"),
placeRotate = accent,
breakInvalid = Color.valueOf("d44b3d"),
range = Color.valueOf("f4ba6e"),
power = Color.valueOf("fbd367"),
power = Color.valueOf("fbad67"),
powerLight = Color.valueOf("fbd367"),
placing = Color.valueOf("616161"),
lightTrail = Color.valueOf("ffe2a9"),

View File

@@ -222,7 +222,7 @@ public class DesktopInput extends InputHandler{
player.isShooting = true;
}
}else if(Inputs.keyTap(section, "deselect") && (recipe != null || mode != none || player.isBuilding()) &&
!(player.getCurrentRequest() != null && player.getCurrentRequest().remove && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){
!(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && KeyBinds.get(section, "deselect") == KeyBinds.get(section, "break"))){
if(recipe == null){
player.clearBuilding();
}

View File

@@ -14,6 +14,7 @@ import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.ValidateException;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.mindustry.type.Recipe;
import io.anuke.mindustry.ui.fragments.OverlayFragment;
@@ -76,10 +77,11 @@ public abstract class InputHandler extends InputAdapter{
player.isTransferring = true;
ItemStack stack = player.inventory.getItem();
int accepted = tile.block().acceptStack(stack.item, stack.amount, tile, player);
Item item = player.inventory.getItem().item;
int amount = player.inventory.getItem().amount;
int accepted = tile.block().acceptStack(item, amount, tile, player);
player.inventory.getItem().amount -= accepted;
boolean clear = stack.amount == accepted;
int sent = Mathf.clamp(accepted / 4, 1, 8);
int removed = accepted / sent;
int[] remaining = {accepted, accepted};
@@ -88,29 +90,24 @@ public abstract class InputHandler extends InputAdapter{
for(int i = 0; i < sent; i++){
boolean end = i == sent - 1;
Timers.run(i * 3, () -> {
tile.block().getStackOffset(stack.item, tile, stackTrns);
tile.block().getStackOffset(item, tile, stackTrns);
ItemTransfer.create(stack.item,
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;
tile.block().handleStack(stack.item, removed, tile, player);
tile.block().handleStack(item, removed, tile, player);
remaining[1] -= removed;
if(end && remaining[1] > 0){
tile.block().handleStack(stack.item, remaining[1], tile, player);
tile.block().handleStack(item, remaining[1], tile, player);
}
});
stack.amount -= removed;
remaining[0] -= removed;
if(end){
stack.amount -= remaining[0];
if(clear){
player.inventory.clearItem();
}
player.isTransferring = false;
}
});

View File

@@ -67,6 +67,7 @@ public abstract class SaveFileVersion{
if(tile.entity.liquids != null) tile.entity.liquids.write(stream);
if(tile.entity.cons != null) tile.entity.cons.write(stream);
tile.entity.writeConfig(stream);
tile.entity.write(stream);
}else if(tile.block() == Blocks.air){
int consecutives = 0;
@@ -152,6 +153,7 @@ public abstract class SaveFileVersion{
if(tile.entity.liquids != null) tile.entity.liquids.read(stream);
if(tile.entity.cons != null) tile.entity.cons.read(stream);
tile.entity.readConfig(stream);
tile.entity.read(stream);
if(tile.block() == StorageBlocks.core){

View File

@@ -2,12 +2,10 @@ package io.anuke.mindustry.io;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.IntArray;
import com.badlogic.gdx.utils.IntMap;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.io.versions.Save16;
import io.anuke.ucore.core.Settings;
import java.io.*;
import java.util.zip.DeflaterOutputStream;
@@ -33,40 +31,23 @@ public class SaveIO{
}
public static void saveToSlot(int slot){
if(gwt){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
write(stream);
Settings.putString("save-" + slot + "-data", new String(Base64Coder.encode(stream.toByteArray())));
Settings.save();
}else{
FileHandle file = fileFor(slot);
boolean exists = file.exists();
if(exists) file.moveTo(file.sibling(file.name() + "-backup." + file.extension()));
try{
write(fileFor(slot));
}catch(Exception e){
if(exists) file.sibling(file.name() + "-backup." + file.extension()).moveTo(file);
throw new RuntimeException(e);
}
FileHandle file = fileFor(slot);
boolean exists = file.exists();
if(exists) file.moveTo(file.sibling(file.name() + "-backup." + file.extension()));
try{
write(fileFor(slot));
}catch(Exception e){
if(exists) file.sibling(file.name() + "-backup." + file.extension()).moveTo(file);
throw new RuntimeException(e);
}
}
public static void loadFromSlot(int slot){
if(gwt){
load(getSlotStream(slot));
}else{
load(fileFor(slot));
}
load(fileFor(slot));
}
public static DataInputStream getSlotStream(int slot){
if(gwt){
String string = Settings.getString("save-" + slot + "-data", "");
byte[] bytes = Base64Coder.decode(string);
return new DataInputStream(new ByteArrayInputStream(bytes));
}else{
return new DataInputStream(new InflaterInputStream(fileFor(slot).read()));
}
return new DataInputStream(new InflaterInputStream(fileFor(slot).read()));
}
public static boolean isSaveValid(int slot){
@@ -165,6 +146,7 @@ public class SaveIO{
stream.close();
}catch(Exception e){
content.setTemporaryMapper(null);
throw new RuntimeException(e);
}
}

View File

@@ -1,7 +1,6 @@
package io.anuke.mindustry.io;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.utils.Base64Coder;
import io.anuke.annotations.Annotations.ReadClass;
import io.anuke.annotations.Annotations.WriteClass;
import io.anuke.mindustry.entities.Player;
@@ -17,7 +16,6 @@ import io.anuke.mindustry.entities.units.UnitCommand;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.mindustry.net.Packets.KickReason;
import io.anuke.mindustry.net.TraceInfo;
import io.anuke.mindustry.type.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
@@ -26,13 +24,14 @@ import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.entities.Entities;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.charset.Charset;
import static io.anuke.mindustry.Vars.*;
/** Class for specifying read/write methods for code generation.*/
@SuppressWarnings("unused")
public class TypeIO{
private static final Charset charset = Charset.forName("UTF-8");
@WriteClass(Player.class)
public static void writePlayer(ByteBuffer buffer, Player player){
@@ -164,9 +163,9 @@ public class TypeIO{
public static void writeRequests(ByteBuffer buffer, BuildRequest[] requests){
buffer.putShort((short)requests.length);
for(BuildRequest request : requests){
buffer.put(request.remove ? (byte) 1 : 0);
buffer.put(request.breaking ? (byte) 1 : 0);
buffer.putInt(world.toPacked(request.x, request.y));
if(!request.remove){
if(!request.breaking){
buffer.put(request.recipe.id);
buffer.put((byte) request.rotation);
}
@@ -330,7 +329,7 @@ public class TypeIO{
@WriteClass(String.class)
public static void writeString(ByteBuffer buffer, String string){
if(string != null){
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
byte[] bytes = string.getBytes(charset);
buffer.putShort((short) bytes.length);
buffer.put(bytes);
}else{
@@ -344,7 +343,7 @@ public class TypeIO{
if(length != -1){
byte[] bytes = new byte[length];
buffer.get(bytes);
return new String(bytes, StandardCharsets.UTF_8);
return new String(bytes, charset);
}else{
return null;
}
@@ -363,45 +362,4 @@ public class TypeIO{
buffer.get(bytes);
return bytes;
}
@WriteClass(TraceInfo.class)
public static void writeTrace(ByteBuffer buffer, TraceInfo info){
buffer.putInt(info.playerid);
buffer.putShort((short) info.ip.getBytes().length);
buffer.put(info.ip.getBytes());
buffer.put(info.modclient ? (byte) 1 : 0);
buffer.put(info.android ? (byte) 1 : 0);
buffer.putInt(info.totalBlocksBroken);
buffer.putInt(info.structureBlocksBroken);
buffer.putInt(info.lastBlockBroken.id);
buffer.putInt(info.totalBlocksPlaced);
buffer.putInt(info.lastBlockPlaced.id);
buffer.put(Base64Coder.decode(info.uuid));
}
@ReadClass(TraceInfo.class)
public static TraceInfo readTrace(ByteBuffer buffer){
int id = buffer.getInt();
short iplen = buffer.getShort();
byte[] ipb = new byte[iplen];
buffer.get(ipb);
TraceInfo info = new TraceInfo(new String(ipb));
info.playerid = id;
info.modclient = buffer.get() == 1;
info.android = buffer.get() == 1;
info.totalBlocksBroken = buffer.getInt();
info.structureBlocksBroken = buffer.getInt();
info.lastBlockBroken = content.block(buffer.getInt());
info.totalBlocksPlaced = buffer.getInt();
info.lastBlockPlaced = content.block(buffer.getInt());
byte[] uuid = new byte[8];
buffer.get(uuid);
info.uuid = new String(Base64Coder.encode(uuid));
return info;
}
}

View File

@@ -4,16 +4,16 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Base64Coder;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.io.MapIO;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.function.Supplier;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.ThreadArray;
import java.io.*;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import static io.anuke.mindustry.Vars.*;
@@ -29,8 +29,6 @@ public class Maps implements Disposable{
private Array<Map> allMaps = new ThreadArray<>();
/**Temporary array used for returning things.*/
private Array<Map> returnArray = new ThreadArray<>();
/**Used for storing a list of custom map names for GWT.*/
private Array<String> customMapNames;
/**Returns a list of all maps, including custom ones.*/
public Array<Map> all(){
@@ -76,25 +74,14 @@ public class Maps implements Disposable{
/**Save a map. This updates all values and stored data necessary.*/
public void saveMap(String name, MapTileData data, ObjectMap<String, String> tags){
try {
try{
//create copy of tags to prevent mutation later
ObjectMap<String, String> newTags = new ObjectMap<>();
newTags.putAll(tags);
tags = newTags;
if (!gwt) {
FileHandle file = customMapDirectory.child(name + "." + mapExtension);
MapIO.writeMap(file.write(false), tags, data);
} else {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
MapIO.writeMap(stream, tags, data);
Settings.putString("map-data-" + name, new String(Base64Coder.encode(stream.toByteArray())));
if(!customMapNames.contains(name, false)){
customMapNames.add(name);
Settings.putObject("custom-maps", customMapNames);
}
Settings.save();
}
FileHandle file = customMapDirectory.child(name + "." + mapExtension);
MapIO.writeMap(file.write(false), tags, data);
if(maps.containsKey(name)){
if(maps.get(name).texture != null) {
@@ -105,7 +92,7 @@ public class Maps implements Disposable{
}
Map map = new Map(name, new MapMeta(version, tags, data.width(), data.height(), null), true, getStreamFor(name));
if (!headless){
if(!headless){
map.texture = new Texture(MapIO.generatePixmap(data));
}
allMaps.add(map);
@@ -126,14 +113,7 @@ public class Maps implements Disposable{
maps.remove(map.name);
allMaps.removeValue(map, true);
if (!gwt) {
customMapDirectory.child(map.name + "." + mapExtension).delete();
} else {
customMapNames.removeValue(map.name, false);
Settings.putString("map-data-" + map.name, "");
Settings.putObject("custom-maps", customMapNames);
Settings.save();
}
customMapDirectory.child(map.name + "." + mapExtension).delete();
}
private void loadMap(String name, Supplier<InputStream> supplier, boolean custom) throws IOException{
@@ -151,43 +131,21 @@ public class Maps implements Disposable{
}
private void loadCustomMaps(){
if(!gwt){
for(FileHandle file : customMapDirectory.list()){
try{
if(file.extension().equalsIgnoreCase(mapExtension)){
loadMap(file.nameWithoutExtension(), file::read, true);
}
}catch (Exception e){
Log.err("Failed to load custom map file '{0}'!", file);
Log.err(e);
}
}
}else{
customMapNames = Settings.getObject("custom-maps", Array.class, Array::new);
for(String name : customMapNames){
try{
String data = Settings.getString("map-data-" + name, "");
byte[] bytes = Base64Coder.decode(data);
loadMap(name, () -> new ByteArrayInputStream(bytes), true);
}catch (Exception e){
Log.err("Failed to load custom map '{0}'!", name);
Log.err(e);
for(FileHandle file : customMapDirectory.list()){
try{
if(file.extension().equalsIgnoreCase(mapExtension)){
loadMap(file.nameWithoutExtension(), file::read, true);
}
}catch (Exception e){
Log.err("Failed to load custom map file '{0}'!", file);
Log.err(e);
}
}
}
/**Returns an input stream supplier for a given map name.*/
private Supplier<InputStream> getStreamFor(String name){
if(!gwt){
return customMapDirectory.child(name + "." + mapExtension)::read;
}else{
String data = Settings.getString("map-data-" + name, "");
byte[] bytes = Base64Coder.decode(data);
return () -> new ByteArrayInputStream(bytes);
}
return customMapDirectory.child(name + "." + mapExtension)::read;
}
@Override

View File

@@ -52,7 +52,7 @@ public class BlockLocMission extends Mission{
float rot = players[0].angleTo(x * tilesize + block.offset(), y * tilesize + block.offset());
float len = 12f;
Draw.color(Palette.accent.r * 0.8f,Palette.accent.g * 0.8f,Palette.accent.b * 0.8f);
Draw.color(Palette.accentBack);
Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len), rot);
Draw.color(Palette.accent);
Draw.rect("icon-arrow", players[0].x + Angles.trnsx(rot, len), players[0].y + Angles.trnsy(rot, len) + 1f, rot);

View File

@@ -2,6 +2,7 @@ package io.anuke.mindustry.net;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.ObjectSet;
import io.anuke.annotations.Annotations.Serialize;
import io.anuke.ucore.core.Settings;
@@ -11,8 +12,6 @@ public class Administration{
/**All player info. Maps UUIDs to info. This persists throughout restarts.*/
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
/**Maps UUIDs to trace infos. This is wiped when a player logs off.*/
private ObjectMap<String, TraceInfo> traceInfo = new ObjectMap<>();
private Array<String> bannedIPs = new Array<>();
public Administration(){
@@ -41,9 +40,7 @@ public class Administration{
Settings.save();
}
/**
* Call when a player joins to update their information here.
*/
/**Call when a player joins to update their information here.*/
public void updatePlayerJoined(String id, String ip, String name){
PlayerInfo info = getCreateInfo(id);
info.lastName = name;
@@ -53,17 +50,8 @@ public class Administration{
if(!info.ips.contains(ip, false)) info.ips.add(ip);
}
/**
* Returns trace info by UUID.
*/
public TraceInfo getTraceByID(String uuid){
if(!traceInfo.containsKey(uuid)) traceInfo.put(uuid, new TraceInfo(uuid));
return traceInfo.get(uuid);
}
public void clearTraces(){
traceInfo.clear();
public boolean banPlayer(String uuid){
return banPlayerID(uuid) || banPlayerIP(getInfo(uuid).lastIP);
}
/**
@@ -86,9 +74,7 @@ public class Administration{
return true;
}
/**
* Bans a player by UUID; returns whether this player was already banned.
*/
/**Bans a player by UUID; returns whether this player was already banned.*/
public boolean banPlayerID(String id){
if(playerInfo.containsKey(id) && playerInfo.get(id).banned)
return false;
@@ -215,11 +201,13 @@ public class Administration{
return info.admin && usip.equals(info.adminUsid);
}
public Array<PlayerInfo> findByName(String name, boolean last){
Array<PlayerInfo> result = new Array<>();
/**Finds player info by IP, UUID and name.*/
public ObjectSet<PlayerInfo> findByName(String name){
ObjectSet<PlayerInfo> result = new ObjectSet<>();
for(PlayerInfo info : playerInfo.values()){
if(info.lastName.toLowerCase().equals(name.toLowerCase()) || (last && info.names.contains(name, false))){
if(info.lastName.toLowerCase().equals(name.toLowerCase()) || (info.names.contains(name, false))
|| info.ips.contains(name, false) || info.id.equals(name)){
result.add(info);
}
}
@@ -287,8 +275,6 @@ public class Administration{
public String adminUsid;
public int timesKicked;
public int timesJoined;
public int totalBlockPlaced;
public int totalBlocksBroken;
public boolean banned, admin;
public long lastKicked; //last kicked timestamp

View File

@@ -17,13 +17,14 @@ import io.anuke.mindustry.net.Streamable.StreamBuilder;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.function.BiConsumer;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Pooling;
import io.anuke.ucore.util.Threads;
import java.io.IOException;
import static io.anuke.mindustry.Vars.headless;
import static io.anuke.mindustry.Vars.ui;
import static io.anuke.mindustry.Vars.*;
public class Net{
private static boolean server;
@@ -46,15 +47,43 @@ public class Net{
return serverProvider != null;
}
/**
* Display a network error.
*/
public static void showError(String text){
/**Display a network error. Call on the graphics thread.*/
public static void showError(Throwable e){
if(!headless){
ui.showError(text);
}else{
Log.err(text);
Threads.assertGraphics();
Throwable t = e;
while(t.getCause() != null){
t = t.getCause();
}
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
String type = error.getClass().toString().toLowerCase();
if(error.equals("mismatch")){
error = Bundles.get("text.error.mismatch");
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address"))){
error = Bundles.get("text.error.invalidaddress");
}else if(error.contains("connection refused") || error.contains("route to host") || type.contains("unknownhost")){
error = Bundles.get("text.error.unreachable");
}else if(type.contains("timeout")){
error = Bundles.get("text.error.timeout");
}else if(error.equals("alreadyconnected")){
error = Bundles.get("text.error.alreadyconnected");
}else if(!error.isEmpty()){
error = Bundles.get("text.error.any");
}
ui.showText("", Bundles.format("text.connectfail", error));
ui.loadfrag.hide();
if(Net.client()){
netClient.disconnectQuietly();
}
}
Log.err(e);
}
/**
@@ -77,14 +106,18 @@ public class Net{
/**
* Connect to an address.
*/
public static void connect(String ip, int port) throws IOException{
lastIP = ip + ":" + port;
if(!active){
clientProvider.connect(ip, port);
active = true;
server = false;
}else{
throw new IOException("Already connected!");
public static void connect(String ip, int port, Runnable success){
try{
lastIP = ip + ":" + port;
if(!active){
clientProvider.connect(ip, port, success);
active = true;
server = false;
}else{
throw new IOException("alreadyconnected");
}
}catch(IOException e){
showError(e);
}
}
@@ -132,7 +165,7 @@ public class Net{
}
/**
* Starts discovering servers on a different thread. Does not work with GWT.
* Starts discovering servers on a different thread.
* Callback is run on the main libGDX thread.
*/
public static void discoverServers(Consumer<Host> cons, Runnable done){
@@ -346,7 +379,7 @@ public class Net{
/**Client implementation.*/
public interface ClientProvider{
/**Connect to a server.*/
void connect(String ip, int port) throws IOException;
void connect(String ip, int port, Runnable success) throws IOException;
/**Send an object to the server.*/
void send(Object object, SendMode mode);

View File

@@ -6,6 +6,9 @@ public abstract class NetConnection{
public final int id;
public final String address;
public boolean modclient;
public boolean mobile;
public int lastSentSnapshotID = -1;
/**ID of last recieved client snapshot.*/

View File

@@ -73,6 +73,7 @@ public class NetworkIO{
if(tile.entity.liquids != null) tile.entity.liquids.write(stream);
if(tile.entity.cons != null) tile.entity.cons.write(stream);
tile.entity.writeConfig(stream);
tile.entity.write(stream);
}else if(tile.block() == Blocks.air){
int consecutives = 0;
@@ -229,6 +230,7 @@ public class NetworkIO{
if(tile.entity.liquids != null) tile.entity.liquids.read(stream);
if(tile.entity.cons != null) tile.entity.cons.read(stream);
tile.entity.readConfig(stream);
tile.entity.read(stream);
}else if(wallid == 0){
int consecutives = stream.readUnsignedByte();

View File

@@ -1,27 +0,0 @@
package io.anuke.mindustry.net;
import com.badlogic.gdx.utils.IntIntMap;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.world.Block;
public class TraceInfo{
public int playerid;
public String ip;
public boolean modclient;
public boolean android;
public IntIntMap fastShots = new IntIntMap();
public int totalBlocksBroken;
public int structureBlocksBroken;
public Block lastBlockBroken = Blocks.air;
public int totalBlocksPlaced;
public Block lastBlockPlaced = Blocks.air;
public String uuid;
public TraceInfo(String uuid){
this.uuid = uuid;
}
}

View File

@@ -13,6 +13,7 @@ public class BorderImage extends Image{
private float thickness = 3f;
public BorderImage(){
}
public BorderImage(Texture texture){

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.ui;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import io.anuke.mindustry.type.ItemStack;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.function.Supplier;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.layout.Stack;
@@ -14,7 +15,7 @@ public class ItemImage extends Stack{
public ItemImage(TextureRegion region, Supplier<CharSequence> text){
Table t = new Table().left().bottom();
t.label(text).color(Color.DARK_GRAY).padBottom(-20).get().setFontScale(Unit.dp.scl(0.5f));
t.label(text).color(Color.DARK_GRAY).padBottom(-Core.skin.font().getData().capHeight * 2).get().setFontScale(Unit.dp.scl(0.5f));
t.row();
t.label(text).get().setFontScale(Unit.dp.scl(0.5f));
@@ -25,7 +26,7 @@ public class ItemImage extends Stack{
public ItemImage(ItemStack stack){
Table t = new Table().left().bottom();
t.add(stack.amount + "").color(Color.DARK_GRAY).padBottom(-20).get().setFontScale(Unit.dp.scl(0.5f));
t.add(stack.amount + "").color(Color.DARK_GRAY).padBottom(-Core.skin.font().getData().capHeight * 2).get().setFontScale(Unit.dp.scl(0.5f));
t.row();
t.add(stack.amount + "").get().setFontScale(Unit.dp.scl(0.5f));

View File

@@ -20,8 +20,6 @@ public class AdminsDialog extends FloatingDialog{
private void setup(){
content().clear();
if(gwt) return;
float w = 400f, h = 80f;
Table table = new Table();

View File

@@ -21,8 +21,6 @@ public class BansDialog extends FloatingDialog{
private void setup(){
content().clear();
if(gwt) return;
float w = 400f, h = 80f;
Table table = new Table();

View File

@@ -3,6 +3,7 @@ package io.anuke.mindustry.ui.dialogs;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Scaling;
import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.maps.Map;
@@ -48,7 +49,7 @@ public class CustomGameDialog extends FloatingDialog{
modes.marginBottom(5);
for(GameMode mode : GameMode.values()){
if(mode.hidden || (mode.isPvp && gwt)) continue;
if(mode.hidden) continue;
modes.addButton("$mode." + mode.name() + ".name", "toggle", () -> state.mode = mode)
.update(b -> b.setChecked(state.mode == mode)).group(group).size(140f, 54f).padBottom(-5);
@@ -106,6 +107,7 @@ public class CustomGameDialog extends FloatingDialog{
image.label((() -> Bundles.format("text.level.highscore", Settings.getInt("hiscore" + map.name, 0)))).pad(3f);
BorderImage border = new BorderImage(map.texture, 3f);
border.setScaling(Scaling.fit);
image.replaceImage(border);
image.clicked(() -> {

View File

@@ -21,15 +21,13 @@ import io.anuke.ucore.util.Pooling;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.gwt;
public class FileChooser extends FloatingDialog{
public static Predicate<FileHandle> pngFilter = file -> file.extension().equalsIgnoreCase("png");
public static Predicate<FileHandle> mapFilter = file -> file.extension().equalsIgnoreCase(Vars.mapExtension);
public static Predicate<FileHandle> jpegFilter = file -> file.extension().equalsIgnoreCase("png") || file.extension().equalsIgnoreCase("jpg") || file.extension().equalsIgnoreCase("jpeg");
public static Predicate<FileHandle> defaultFilter = file -> true;
private Table files;
private FileHandle homeDirectory = gwt ? Gdx.files.internal("") : Gdx.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" :
private FileHandle homeDirectory = Gdx.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" :
Gdx.files.getExternalStoragePath());
private FileHandle directory = homeDirectory;
private ScrollPane pane;
@@ -175,7 +173,7 @@ public class FileChooser extends FloatingDialog{
Arrays.sort(handles, (a, b) -> {
if(a.isDirectory() && !b.isDirectory()) return -1;
if(!a.isDirectory() && b.isDirectory()) return 1;
return a.name().toUpperCase().compareTo(b.name().toUpperCase());
return String.CASE_INSENSITIVE_ORDER.compare(a.name(), b.name());
});
return handles;
}

View File

@@ -18,7 +18,6 @@ import io.anuke.ucore.scene.ui.layout.Cell;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.scene.utils.UIUtils;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Strings;
import static io.anuke.mindustry.Vars.*;
@@ -248,16 +247,14 @@ public class JoinDialog extends FloatingDialog{
}
void refreshLocal(){
if(!Vars.gwt){
totalHosts = 0;
totalHosts = 0;
local.clear();
local.background((Drawable)null);
local.table("button", t -> {
t.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + Strings.animated(4, 10f, ".")).pad(10f);
}).growX();
Net.discoverServers(this::addLocalHost, this::finishLocalHosts);
}
local.clear();
local.background((Drawable)null);
local.table("button", t -> {
t.label(() -> "[accent]" + Bundles.get("text.hosts.discovering") + Strings.animated(4, 10f, ".")).pad(10f);
}).growX();
Net.discoverServers(this::addLocalHost, this::finishLocalHosts);
}
void finishLocalHosts(){
@@ -300,34 +297,11 @@ public class JoinDialog extends FloatingDialog{
});
Timers.runTask(2f, () -> {
try{
Vars.netClient.beginConnecting();
Net.connect(ip, port);
Vars.netClient.beginConnecting();
Net.connect(ip, port, () -> {
hide();
add.hide();
}catch(Exception e){
Throwable t = e;
while(t.getCause() != null){
t = t.getCause();
}
//TODO localize
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
if(error.contains("connection refused")){
error = "connection refused";
}else if(error.contains("port out of range")){
error = "invalid port!";
}else if(error.contains("invalid argument")){
error = "invalid IP or port!";
}else if(t.getClass().toString().toLowerCase().contains("sockettimeout")){
error = "timed out!\nmake sure the host has port forwarding set up,\nand that the address is correct!";
}else{
error = Strings.parseException(e, false);
}
ui.showError(Bundles.format("text.connectfail", error));
ui.loadfrag.hide();
Log.err(e);
}
});
});
}

View File

@@ -1,6 +1,5 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.mindustry.core.Platform;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.ScrollPane;
@@ -31,7 +30,7 @@ public class LanguageDialog extends FloatingDialog{
ButtonGroup<TextButton> group = new ButtonGroup<>();
for(Locale loc : locales){
TextButton button = new TextButton(Platform.instance.getLocaleName(loc), "toggle");
TextButton button = new TextButton(loc.getDisplayName(loc), "toggle");
button.clicked(() -> {
if(getLocale().equals(loc)) return;
Settings.putString("locale", loc.toString());

View File

@@ -86,28 +86,27 @@ public class LoadDialog extends FloatingDialog{
});
}).size(14 * 3).right();
if(!gwt){
t.addImageButton("icon-save", "empty", 14 * 3, () -> {
if(!ios){
Platform.instance.showFileChooser(Bundles.get("text.save.export"), "Mindustry Save", file -> {
try{
slot.exportFile(file);
setup();
}catch(IOException e){
ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
}
}, false, saveExtension);
}else{
t.addImageButton("icon-save", "empty", 14 * 3, () -> {
if(!ios){
Platform.instance.showFileChooser(Bundles.get("text.save.export"), "Mindustry Save", file -> {
try{
FileHandle file = Gdx.files.local("save-" + slot.getName() + "." + Vars.saveExtension);
slot.exportFile(file);
Platform.instance.shareFile(file);
}catch(Exception e){
setup();
}catch(IOException e){
ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
}
}, false, saveExtension);
}else{
try{
FileHandle file = Gdx.files.local("save-" + slot.getName() + "." + Vars.saveExtension);
slot.exportFile(file);
Platform.instance.shareFile(file);
}catch(Exception e){
ui.showError(Bundles.format("text.save.export.fail", Strings.parseException(e, false)));
}
}).size(14 * 3).right();
}
}
}).size(14 * 3).right();
}).padRight(-10).growX();
@@ -153,7 +152,7 @@ public class LoadDialog extends FloatingDialog{
slots.row();
if(gwt || ios) return;
if(ios) return;
slots.addImageTextButton("$text.save.import", "icon-add", "clear", 14 * 3, () -> {
Platform.instance.showFileChooser(Bundles.get("text.save.import"), "Mindustry Save", file -> {

View File

@@ -93,7 +93,7 @@ public class MapsDialog extends FloatingDialog{
button.row();
button.addImage("white").growX().pad(4).color(Color.GRAY);
button.row();
((Image) button.stack(new Image(map.texture), new BorderImage(map.texture)).size(mapsize - 20f).get().getChildren().first()).setScaling(Scaling.fit);
button.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize - 20f);
button.row();
button.add(map.custom ? "$text.custom" : "$text.builtin").color(Color.GRAY).padTop(3);
@@ -114,7 +114,7 @@ public class MapsDialog extends FloatingDialog{
float mapsize = UIUtils.portrait() ? 160f : 300f;
Table table = dialog.content();
((Image) table.stack(new Image(map.texture), new BorderImage(map.texture)).size(mapsize).get().getChildren().first()).setScaling(Scaling.fit);
table.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize);
table.table("clear", desc -> {
desc.top();

View File

@@ -61,25 +61,14 @@ public class PausedDialog extends FloatingDialog{
content().addButton("$text.settings", ui.settings::show);
content().row();
content().addButton("$text.savegame", () -> {
save.show();
}).disabled(s -> world.getSector() != null);
content().addButton("$text.savegame", save::show).disabled(s -> world.getSector() != null);
content().row();
content().addButton("$text.loadgame", () -> {
load.show();
}).disabled(b -> Net.active());
content().addButton("$text.loadgame", load::show).disabled(b -> Net.active());
content().row();
content().addButton("$text.hostserver", () -> {
if(!gwt){
ui.host.show();
}else{
ui.showInfo("$text.web.unsupported");
}
}).disabled(b -> Net.active());
content().addButton("$text.hostserver", ui.host::show).disabled(b -> Net.active());
content().row();

View File

@@ -175,11 +175,8 @@ public class SettingsMenuDialog extends SettingsDialog{
Settings.prefs().put(map);
Settings.save();
if(!gwt){
Settings.prefs().clear();
for(FileHandle file : dataDirectory.list()){
file.deleteDirectory();
}
for(FileHandle file : dataDirectory.list()){
file.deleteDirectory();
}
Gdx.app.exit();
@@ -193,19 +190,15 @@ public class SettingsMenuDialog extends SettingsDialog{
}
});
if(!gwt){
graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s)));
graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Bundles.get("setting.fpscap.none") : Bundles.format("setting.fpscap.text", s)));
graphics.checkPref("multithread", mobile, threads::setEnabled);
if(Settings.getBool("multithread")){
threads.setEnabled(true);
}
if(!gwt){
graphics.checkPref("multithread", mobile, threads::setEnabled);
if(Settings.getBool("multithread")){
threads.setEnabled(true);
}
}
if(!mobile && !gwt){
if(!mobile){
graphics.checkPref("vsync", true, b -> Gdx.graphics.setVSync(b));
graphics.checkPref("fullscreen", false, b -> {
if(b){

View File

@@ -1,10 +1,5 @@
package io.anuke.mindustry.ui.dialogs;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.net.TraceInfo;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles;
public class TraceDialog extends FloatingDialog{
public TraceDialog(){
@@ -12,14 +7,15 @@ public class TraceDialog extends FloatingDialog{
addCloseButton();
}
public void show(Player player, TraceInfo info){
/*
public void show(Player player, SessionInfo info){
content().clear();
Table table = new Table("clear");
table.margin(14);
table.defaults().pad(1);
/*
table.defaults().left();
table.add(Bundles.format("text.trace.playername", player.name));
table.row();
@@ -50,10 +46,10 @@ public class TraceDialog extends FloatingDialog{
table.add(Bundles.format("text.trace.totalblocksplaced", info.totalBlocksPlaced));
table.row();
table.add(Bundles.format("text.trace.lastblockplaced", info.lastBlockPlaced.formalName));
table.row();*/
table.row();
content().add(table);
show();
}
}*/
}

View File

@@ -127,7 +127,7 @@ public class HudFragment extends Fragment{
t.label(() -> tps.get(threads.getTPS())).visible(() -> threads.isEnabled());
t.row();
if(Net.hasClient()){
t.label(() -> ping.get(Net.getPing())).visible(() -> Net.client() && !gwt).colspan(2);
t.label(() -> ping.get(Net.getPing())).visible(Net::client).colspan(2);
}
}).size(-1).visible(() -> Settings.getBool("fps")).update(t -> t.setTranslation(0, (!waves.isVisible() ? wavetable.getHeight() : Math.min(wavetable.getTranslation().y, wavetable.getHeight())) )).get();

View File

@@ -132,9 +132,7 @@ public class MenuFragment extends Fragment{
out.row();
if(!gwt){
out.add(new MenuButton("icon-exit", "$text.quit", Gdx.app::exit)).width(bw).colspan(2);
}
out.add(new MenuButton("icon-exit", "$text.quit", Gdx.app::exit)).width(bw).colspan(2);
});
}
@@ -153,12 +151,8 @@ public class MenuFragment extends Fragment{
dialog.content().row();
dialog.content().add(new MenuButton("icon-add", "$text.joingame", () -> {
if(!gwt){
ui.join.show();
dialog.hide();
}else{
ui.showInfo("$text.web.unsupported");
}
ui.join.show();
dialog.hide();
}));
dialog.content().add(new MenuButton("icon-editor", "$text.customgame", () -> {

View File

@@ -3,14 +3,12 @@ package io.anuke.mindustry.ui.fragments;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.g2d.Batch;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetConnection;
import io.anuke.mindustry.net.Packets.AdminAction;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.scene.Group;
@@ -73,7 +71,7 @@ public class PlayerListFragment extends Fragment{
float h = 74f;
playerGroup.forEach(player -> {
NetConnection connection = gwt ? null : player.con;
NetConnection connection = player.con;
if(connection == null && Net.server() && !player.isLocal) return;
@@ -119,7 +117,7 @@ public class PlayerListFragment extends Fragment{
t.addImageButton("icon-admin", "toggle", 14 * 2, () -> {
if(Net.client()) return;
String id = netServer.admins.getTraceByID(player.uuid).uuid;
String id = player.uuid;
if(netServer.admins.isAdmin(id, connection.address)){
ui.showConfirm("$text.confirm", "$text.confirmunadmin", () -> netServer.admins.unAdminPlayer(id));

View File

@@ -40,9 +40,7 @@ public abstract class BaseBlock extends MappableContent{
return true;
}
/**
* Returns the amount of items this block can accept.
*/
/**Returns the amount of items this block can accept.*/
public int acceptStack(Item item, int amount, Tile tile, Unit source){
if(acceptItem(item, tile, tile) && hasItems && (source == null || source.getTeam() == tile.getTeam())){
return Math.min(getMaximumAccepted(tile, item), amount);
@@ -52,12 +50,10 @@ public abstract class BaseBlock extends MappableContent{
}
public int getMaximumAccepted(Tile tile, Item item){
return itemCapacity - (tile.entity.items.total() - tile.entity.items.get(item));
return itemCapacity;
}
/**
* Remove a stack from this inventory, and return the amount removed.
*/
/**Remove a stack from this inventory, and return the amount removed.*/
public int removeStack(Tile tile, Item item, int amount){
tile.entity.noSleep();
tile.entity.items.remove(item, amount);
@@ -88,7 +84,8 @@ public abstract class BaseBlock extends MappableContent{
}
public boolean acceptItem(Item item, Tile tile, Tile source){
return tile.entity != null && consumes.has(ConsumeItem.class) && consumes.item() == item && tile.entity.items.get(item) < getMaximumAccepted(tile, item);
return tile.entity != null && consumes.has(ConsumeItem.class) && consumes.item() == item &&
tile.entity.items.get(item) < getMaximumAccepted(tile, item);
}
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){

View File

@@ -5,7 +5,7 @@ import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.content.blocks.Blocks;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.game.EventType.BlockBuildEvent;
import io.anuke.mindustry.game.EventType.BlockBuildBeginEvent;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.type.ContentType;
import io.anuke.mindustry.type.Recipe;
@@ -59,6 +59,8 @@ public class Build{
}
}
Tile ftile = tile;
threads.runDelay(() -> Events.fire(new BlockBuildBeginEvent(ftile, team, true)));
}
/**Places a BuildBlock at this location.*/
@@ -100,8 +102,7 @@ public class Build{
}
}
threads.runDelay(() -> Events.fire(new BlockBuildEvent(tile, team)));
threads.runDelay(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false)));
}
/**Returns whether a tile can be placed at this location by this team.*/
@@ -131,7 +132,7 @@ public class Build{
if(tile == null) return false;
if(type.isMultiblock()){
if(type.canReplace(tile.block()) && tile.block().size == type.size){
if(type.canReplace(tile.block()) && tile.block().size == type.size && type.canPlaceOn(tile)){
return true;
}

View File

@@ -38,7 +38,7 @@ public class LegacyColorMapper implements ContentList{
map("f7feff", Blocks.snow, 1);
map("6e501e", Blocks.dirt, 0);
map("ed5334", Blocks.lava, 0);
map("292929", Blocks.oil, 0);
map("292929", Blocks.tar, 0);
map("c3a490", OreBlocks.get(Blocks.stone, Items.copper), 0);
map("161616", OreBlocks.get(Blocks.stone, Items.coal), 0);
map("6277bc", OreBlocks.get(Blocks.stone, Items.titanium), 0);

View File

@@ -28,8 +28,8 @@ import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -302,7 +302,7 @@ public class BuildBlock extends Block{
}
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(progress);
stream.writeShort(previous == null ? -1 : previous.id);
stream.writeShort(recipe == null ? -1 : recipe.result.id);
@@ -319,7 +319,7 @@ public class BuildBlock extends Block{
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
progress = stream.readFloat();
short pid = stream.readShort();
short rid = stream.readShort();

View File

@@ -12,8 +12,8 @@ import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.graphics.Draw;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.threads;
@@ -89,14 +89,12 @@ public class Door extends Wall{
public boolean open = false;
@Override
public void write(DataOutputStream stream) throws IOException{
super.write(stream);
public void write(DataOutput stream) throws IOException{
stream.writeBoolean(open);
}
@Override
public void read(DataInputStream stream) throws IOException{
super.read(stream);
public void read(DataInput stream) throws IOException{
open = stream.readBoolean();
}
}

View File

@@ -25,17 +25,17 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
public class ForceProjector extends Block {
protected int timerUse = timers ++;
protected float phaseUseTime = 250f;
protected float phaseUseTime = 350f;
protected float phaseRadiusBoost = 60f;
protected float phaseRadiusBoost = 80f;
protected float radius = 100f;
protected float breakage = 550f;
protected float cooldownNormal = 1.75f;
@@ -89,7 +89,7 @@ public class ForceProjector extends Block {
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f);
if(!entity.broken && entity.timer.get(timerUse, phaseUseTime) && entity.items.total() > 0){
if(entity.cons.valid() && !entity.broken && entity.timer.get(timerUse, phaseUseTime) && entity.items.total() > 0){
entity.items.remove(consumes.item(), 1);
}
@@ -197,7 +197,7 @@ public class ForceProjector extends Block {
float phaseHeat;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeBoolean(broken);
stream.writeFloat(buildup);
stream.writeFloat(radscl);
@@ -206,7 +206,7 @@ public class ForceProjector extends Block {
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
broken = stream.readBoolean();
buildup = stream.readFloat();
radscl = stream.readFloat();

View File

@@ -16,8 +16,8 @@ import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tilesize;
@@ -35,8 +35,8 @@ public class MendProjector extends Block{
protected float range = 50f;
protected float healPercent = 6f;
protected float phaseBoost = 12f;
protected float phaseRangeBoost = 40f;
protected float useTime = 300f;
protected float phaseRangeBoost = 50f;
protected float useTime = 400f;
public MendProjector(String name){
super(name);
@@ -61,7 +61,7 @@ public class MendProjector extends Block{
entity.phaseHeat = Mathf.lerpDelta(entity.phaseHeat, (float)entity.items.get(consumes.item()) / itemCapacity, 0.1f);
if(entity.timer.get(timerUse, useTime) && entity.items.total() > 0){
if(entity.cons.valid() && entity.timer.get(timerUse, useTime) && entity.items.total() > 0){
entity.items.remove(consumes.item(), 1);
}
@@ -71,27 +71,25 @@ public class MendProjector extends Block{
Effects.effect(BlockFx.healWaveMend, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange);
entity.charge = 0f;
Timers.run(10f, () -> {
int tileRange = (int)(realRange / tilesize);
healed.clear();
int tileRange = (int)(realRange / tilesize);
healed.clear();
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue;
for(int x = -tileRange + tile.x; x <= tileRange + tile.x; x++){
for(int y = -tileRange + tile.y; y <= tileRange + tile.y; y++){
if(Vector2.dst(x, y, tile.x, tile.y) > realRange) continue;
Tile other = world.tile(x, y);
Tile other = world.tile(x, y);
if(other == null) continue;
other = other.target();
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()){
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());
}
if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.packedPosition()) && 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());
}
}
});
}
}
}
@@ -133,13 +131,13 @@ public class MendProjector extends Block{
float phaseHeat;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(heat);
stream.writeFloat(phaseHeat);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
heat = stream.readFloat();
phaseHeat = stream.readFloat();
}

View File

@@ -16,8 +16,8 @@ import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tilesize;
@@ -34,8 +34,8 @@ public class OverdriveProjector extends Block{
protected float reload = 260f;
protected float range = 80f;
protected float speedBoost = 1.5f;
protected float speedBoostPhase = 0.5f;
protected float useTime = 300f;
protected float speedBoostPhase = 0.75f;
protected float useTime = 400f;
public OverdriveProjector(String name){
super(name);
@@ -133,13 +133,13 @@ public class OverdriveProjector extends Block{
float phaseHeat;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(heat);
stream.writeFloat(phaseHeat);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
heat = stream.readFloat();
phaseHeat = stream.readFloat();
}

View File

@@ -122,7 +122,7 @@ public abstract class LiquidTurret extends Turret{
@Override
public boolean acceptLiquid(Tile tile, Tile source, Liquid liquid, float amount){
return super.acceptLiquid(tile, source, liquid, amount) && liquidAmmoMap.get(liquid) != null
&& (tile.entity.liquids.current() == liquid || tile.entity.liquids.get(tile.entity.liquids.current()) < 0.01f);
&& (tile.entity.liquids.current() == liquid || (liquidAmmoMap.containsKey(tile.entity.liquids.current()) && tile.entity.liquids.get(tile.entity.liquids.current()) <= liquidAmmoMap.get(tile.entity.liquids.current()).quantityMultiplier + 0.001f));
}
}

View File

@@ -31,8 +31,8 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.content;
@@ -354,7 +354,7 @@ public abstract class Turret extends Block{
public TargetTrait target;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeByte(ammo.size);
for(AmmoEntry entry : ammo){
stream.writeByte(entry.type.id);
@@ -363,7 +363,7 @@ public abstract class Turret extends Block{
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
byte amount = stream.readByte();
for(int i = 0; i < amount; i++){
AmmoType type = content.getByID(ContentType.ammo, stream.readByte());

View File

@@ -9,8 +9,8 @@ import io.anuke.mindustry.world.modules.LiquidModule;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class Conduit extends LiquidBlock{
@@ -136,12 +136,12 @@ public class Conduit extends LiquidBlock{
int blendshadowrot;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(smoothLiquid);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
smoothLiquid = stream.readFloat();
}
}

View File

@@ -16,8 +16,8 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.*;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -159,7 +159,7 @@ public class Conveyor extends Block{
if(pos.item == null) continue;
tr1.trns(rotation * 90, tilesize, 0);
tr2.trns(rotation * 90, -tilesize / 2, pos.x * tilesize / 2);
tr2.trns(rotation * 90, -tilesize / 2f, pos.x * tilesize / 2f);
Draw.rect(pos.item.region,
(int) (tile.x * tilesize + tr1.x * pos.y + tr2.x),
@@ -384,7 +384,7 @@ public class Conveyor extends Block{
float clogHeat = 0f;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeInt(convey.size);
for(int i = 0; i < convey.size; i++){
@@ -393,7 +393,7 @@ public class Conveyor extends Block{
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
convey.clear();
int amount = stream.readInt();
convey.ensureCapacity(amount);

View File

@@ -23,8 +23,8 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tilesize;
@@ -325,7 +325,7 @@ public class ItemBridge extends Block{
public float cycleSpeed = 1f;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeInt(link);
stream.writeFloat(uptime);
stream.writeByte(incoming.size);
@@ -338,7 +338,7 @@ public class ItemBridge extends Block{
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
link = stream.readInt();
uptime = stream.readFloat();
byte links = stream.readByte();

View File

@@ -30,8 +30,8 @@ import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Pooling;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -322,13 +322,13 @@ public class MassDriver extends Block{
}
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeInt(link);
stream.writeFloat(rotation);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
link = stream.readInt();
rotation = stream.readFloat();
}

View File

@@ -14,8 +14,8 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -122,12 +122,12 @@ public class Sorter extends Block implements SelectionTrait{
public Item sortItem = content.item(0);
@Override
public void write(DataOutputStream stream) throws IOException{
public void writeConfig(DataOutput stream) throws IOException{
stream.writeByte(sortItem.id);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void readConfig(DataInput stream) throws IOException{
sortItem = content.items().get(stream.readByte());
}
}

View File

@@ -27,8 +27,8 @@ import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tilesize;
@@ -342,7 +342,7 @@ public class WarpGate extends PowerBlock{
public float time;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeByte(color);
stream.writeBoolean(active);
stream.writeFloat(activeScl);
@@ -351,7 +351,7 @@ public class WarpGate extends PowerBlock{
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
color = stream.readByte();
active = stream.readBoolean();
activeScl = stream.readFloat();

View File

@@ -17,8 +17,8 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tilesize;
@@ -121,12 +121,12 @@ public abstract class ItemGenerator extends PowerGenerator{
public float explosiveness;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(efficiency);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
efficiency = stream.readFloat();
}
}

View File

@@ -20,8 +20,8 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Translator;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.tilesize;
@@ -202,14 +202,12 @@ public class NuclearReactor extends PowerGenerator{
public float flash;
@Override
public void write(DataOutputStream stream) throws IOException{
super.write(stream);
public void write(DataOutput stream) throws IOException{
stream.writeFloat(heat);
}
@Override
public void read(DataInputStream stream) throws IOException{
super.read(stream);
public void read(DataInput stream) throws IOException{
heat = stream.readFloat();
}
}

View File

@@ -8,7 +8,6 @@ import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.gen.Call;
import io.anuke.mindustry.graphics.Layer;
import io.anuke.mindustry.graphics.Palette;
import io.anuke.mindustry.world.Edges;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.PowerBlock;
import io.anuke.mindustry.world.meta.BlockStat;
@@ -17,7 +16,6 @@ import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.graphics.Shapes;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Translator;
@@ -99,6 +97,12 @@ public class PowerNode extends PowerBlock{
public void playerPlaced(Tile tile){
Tile before = world.tile(lastPlaced);
if(linkValid(tile, before) && before.block() instanceof PowerNode){
for(Tile near : before.entity.proximity()){
if(near.target() == tile){
lastPlaced = tile.packedPosition();
return;
}
}
Call.linkPowerNodes(null, tile, before);
}
@@ -139,11 +143,10 @@ public class PowerNode extends PowerBlock{
public void drawSelect(Tile tile){
super.drawSelect(tile);
Draw.color(Palette.power);
Lines.stroke(1f);
Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize / 2, tile.worldy() - tilesize / 2, tilesize);
Draw.color(Palette.accent);
Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize);
Draw.reset();
}
@@ -154,14 +157,10 @@ public class PowerNode extends PowerBlock{
Draw.color(Palette.accent);
Lines.stroke(1f);
Lines.square(tile.drawx(), tile.drawy(),
Lines.circle(tile.drawx(), tile.drawy(),
tile.block().size * tilesize / 2f + 1f + Mathf.absin(Timers.time(), 4f, 1f));
Lines.stroke(1f);
Lines.poly(Edges.getPixelPolygon(laserRange), tile.worldx() - tilesize / 2, tile.worldy() - tilesize / 2, tilesize);
Draw.color(Palette.power);
Lines.poly(tile.drawx(), tile.drawy(), 50, laserRange*tilesize);
for(int x = (int) (tile.x - laserRange); x <= tile.x + laserRange; x++){
for(int y = (int) (tile.y - laserRange); y <= tile.y + laserRange; y++){
@@ -172,7 +171,7 @@ public class PowerNode extends PowerBlock{
boolean linked = linked(tile, link);
Draw.color(linked ? Palette.place : Palette.breakInvalid);
Lines.square(link.drawx(), link.drawy(),
Lines.circle(link.drawx(), link.drawy(),
link.block().size * tilesize / 2f + 1f + (linked ? 0f : Mathf.absin(Timers.time(), 4f, 1f)));
if((entity.power.links.size >= maxNodes || (link.block() instanceof PowerNode && link.entity.power.links.size >= ((PowerNode) link.block()).maxNodes)) && !linked){
@@ -188,11 +187,9 @@ public class PowerNode extends PowerBlock{
@Override
public void drawPlace(int x, int y, int rotation, boolean valid){
Draw.color(Palette.placing);
Lines.stroke(1f);
Lines.poly(Edges.getPixelPolygon(laserRange), x * tilesize - tilesize / 2, y * tilesize - tilesize / 2, tilesize);
Draw.color(Palette.placing);
Lines.poly(x * tilesize + offset(), y * tilesize + offset(), 50, laserRange*tilesize);
Draw.reset();
}
@@ -202,14 +199,15 @@ public class PowerNode extends PowerBlock{
TileEntity entity = tile.entity();
Draw.color(Palette.powerLaserFrom, Palette.powerLaserTo, 0f * (1f - flashScl) + Mathf.sin(Timers.time(), 1.7f, flashScl));
for(int i = 0; i < entity.power.links.size; i++){
Tile link = world.tile(entity.power.links.get(i));
if(linkValid(tile, link)) drawLaser(tile, link);
if(linkValid(tile, link) && (!(link.block() instanceof PowerNode)
|| ((tile.block().size > link.block().size) || (tile.block().size == link.block().size && tile.id() < link.id())))){
drawLaser(tile, link);
}
}
Draw.color();
Draw.reset();
}
protected boolean linked(Tile tile, Tile other){
@@ -227,12 +225,12 @@ public class PowerNode extends PowerBlock{
TileEntity oe = link.entity();
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy()) <= Math.max(laserRange * tilesize,
((PowerNode) link.block()).laserRange * tilesize) - tilesize / 2f
((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())));
}else{
return Vector2.dst(tile.drawx(), tile.drawy(), link.drawx(), link.drawy())
<= laserRange * tilesize - tilesize / 2f + (link.block().size - 1) * tilesize;
<= laserRange * tilesize + (link.block().size - 1) * tilesize;
}
}
@@ -243,11 +241,31 @@ public class PowerNode extends PowerBlock{
float angle1 = Angles.angle(x1, y1, x2, y2);
float angle2 = angle1 + 180f;
t1.trns(angle1, tile.block().size * tilesize / 2f + 1f);
t2.trns(angle2, target.block().size * tilesize / 2f + 1f);
t1.trns(angle1, tile.block().size * tilesize / 2f - 1f);
t2.trns(angle2, target.block().size * tilesize / 2f - 1f);
Shapes.laser("laser", "laser-end", x1 + t1.x, y1 + t1.y,
x2 + t2.x, y2 + t2.y, thicknessScl);
x1 += t1.x;
y1 += t1.y;
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);
}
}
}

View File

@@ -15,8 +15,8 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.SeedRandom;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class Cultivator extends Drill{
@@ -113,12 +113,12 @@ public class Cultivator extends Drill{
public float warmup;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(warmup);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
warmup = stream.readFloat();
}
}

View File

@@ -18,8 +18,8 @@ import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class GenericCrafter extends Block{
@@ -125,13 +125,13 @@ public class GenericCrafter extends Block{
public float warmup;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(progress);
stream.writeFloat(warmup);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
progress = stream.readFloat();
warmup = stream.readFloat();
}

View File

@@ -19,8 +19,8 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Fill;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -172,7 +172,7 @@ public class PowerSmelter extends PowerBlock{
@Override
public int getMaximumAccepted(Tile tile, Item item){
return itemCapacity - tile.entity.items.get(item);
return itemCapacity;
}
@Override
@@ -210,12 +210,12 @@ public class PowerSmelter extends PowerBlock{
public float craftTime;
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(heat);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
heat = stream.readFloat();
}
}

View File

@@ -154,7 +154,7 @@ public class Smelter extends Block{
@Override
public int getMaximumAccepted(Tile tile, Item item){
return itemCapacity - tile.entity.items.get(item);
return itemCapacity;
}
@Override

View File

@@ -30,8 +30,8 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.EnumSet;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -246,13 +246,13 @@ public class CoreBlock extends StorageBlock{
}
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeBoolean(solid);
stream.writeInt(droneID);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
solid = stream.readBoolean();
droneID = stream.readInt();
}

View File

@@ -12,8 +12,8 @@ import io.anuke.mindustry.world.blocks.SelectionTrait;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.scene.ui.layout.Table;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -75,12 +75,12 @@ public class SortedUnloader extends Unloader implements SelectionTrait{
public Item sortItem = null;
@Override
public void write(DataOutputStream stream) throws IOException{
public void writeConfig(DataOutput stream) throws IOException{
stream.writeByte(sortItem == null ? -1 : sortItem.id);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void readConfig(DataInput stream) throws IOException{
byte id = stream.readByte();
sortItem = id == -1 ? null : content.items().get(id);
}

View File

@@ -24,8 +24,8 @@ import io.anuke.ucore.scene.ui.ImageButton;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.EnumSet;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -115,12 +115,12 @@ public class CommandCenter extends Block{
public UnitCommand command = UnitCommand.attack;
@Override
public void write(DataOutputStream stream) throws IOException{
public void writeConfig(DataOutput stream) throws IOException{
stream.writeByte(command.ordinal());
}
@Override
public void read(DataInputStream stream) throws IOException{
public void readConfig(DataInput stream) throws IOException{
command = UnitCommand.values()[stream.readByte()];
}
}

View File

@@ -1,28 +0,0 @@
package io.anuke.mindustry.world.blocks.units;
import io.anuke.mindustry.type.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
public class DropPoint extends Block{
public DropPoint(String name){
super(name);
hasItems = true;
solid = true;
update = true;
}
@Override
public boolean acceptItem(Item item, Tile tile, Tile source){
return false;
}
@Override
public void update(Tile tile){
if(tile.entity.items.total() > 0){
tryDump(tile);
}
}
}

View File

@@ -27,8 +27,8 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Geometry;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.mobile;
@@ -237,14 +237,14 @@ public class MechPad extends Block{
}
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(progress);
stream.writeFloat(time);
stream.writeFloat(heat);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
progress = stream.readFloat();
time = stream.readFloat();
heat = stream.readFloat();

View File

@@ -23,8 +23,8 @@ import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import static io.anuke.mindustry.Vars.*;
@@ -329,12 +329,12 @@ public class Reconstructor extends Block{
}
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeInt(link);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
link = stream.readInt();
}
}

View File

@@ -30,8 +30,8 @@ import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.util.EnumSet;
import io.anuke.ucore.util.Mathf;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
public class UnitFactory extends Block{
@@ -227,13 +227,13 @@ public class UnitFactory extends Block{
public float warmup; //only for enemy spawners
@Override
public void write(DataOutputStream stream) throws IOException{
public void write(DataOutput stream) throws IOException{
stream.writeFloat(buildTime);
stream.writeFloat(warmup);
}
@Override
public void read(DataInputStream stream) throws IOException{
public void read(DataInput stream) throws IOException{
buildTime = stream.readFloat();
warmup = stream.readFloat();
}

View File

@@ -4,8 +4,8 @@ import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**A class that represents compartmentalized tile entity state.*/
public abstract class BlockModule{
public abstract void write(DataOutput stream) throws IOException;
public abstract void read(DataInput stream) throws IOException;
}

View File

@@ -9,26 +9,9 @@ import java.io.IOException;
public class PowerModule extends BlockModule{
public float amount;
public float capacity = 10f;
public float voltage = 0.0001f;
public PowerGraph graph = new PowerGraph();
public IntArray links = new IntArray();
public boolean acceptsPower(){
return amount + 0.001f <= capacity;
}
public float addPower(float add){
if(add < voltage){
return add;
}
float canAccept = Math.min(capacity - amount, add);
amount += canAccept;
return canAccept;
}
@Override
public void write(DataOutput stream) throws IOException{
stream.writeFloat(amount);