Merged current Anuke master into branch
This commit is contained in:
@@ -33,6 +33,7 @@ public class Vars{
|
||||
public static final String appName = "Mindustry";
|
||||
public static final String discordURL = "https://discord.gg/mindustry";
|
||||
public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases";
|
||||
public static final String contributorsURL = "https://api.github.com/repos/Anuken/Mindustry/contributors";
|
||||
public static final String crashReportURL = "http://mindustry.us.to/report";
|
||||
//time between waves in frames (on normal mode)
|
||||
public static final float wavespace = 60 * 60 * 1.5f;
|
||||
@@ -49,8 +50,7 @@ public class Vars{
|
||||
public static final int maxNameLength = 40;
|
||||
public static final float itemSize = 5f;
|
||||
public static final int tilesize = 8;
|
||||
public static final int sectorSize = 250;
|
||||
public static final int mapPadding = 3;
|
||||
public static final int sectorSize = 256;
|
||||
public static final int invalidSector = Integer.MAX_VALUE;
|
||||
public static Locale[] locales;
|
||||
public static final Color[] playerColors = {
|
||||
@@ -73,6 +73,7 @@ public class Vars{
|
||||
};
|
||||
//server port
|
||||
public static final int port = 6567;
|
||||
public static boolean disableUI;
|
||||
public static boolean testMobile;
|
||||
//shorthand for whether or not this is running on android or ios
|
||||
public static boolean mobile;
|
||||
@@ -80,6 +81,8 @@ public class Vars{
|
||||
public static boolean android;
|
||||
//main data directory
|
||||
public static FileHandle dataDirectory;
|
||||
//subdirectory for screenshots
|
||||
public static FileHandle screenshotDirectory;
|
||||
//directory for user-created map data
|
||||
public static FileHandle customMapDirectory;
|
||||
//save file directory
|
||||
@@ -171,6 +174,7 @@ public class Vars{
|
||||
android = Gdx.app.getType() == ApplicationType.Android;
|
||||
|
||||
dataDirectory = Settings.getDataDirectory(appName);
|
||||
screenshotDirectory = dataDirectory.child("screenshots/");
|
||||
customMapDirectory = dataDirectory.child("maps/");
|
||||
saveDirectory = dataDirectory.child("saves/");
|
||||
baseCameraScale = Math.round(Unit.dp.scl(4));
|
||||
|
||||
@@ -21,7 +21,6 @@ import io.anuke.ucore.util.ThreadArray;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
//TODO consider using quadtrees for finding specific types of blocks within an area
|
||||
//TODO maybe use Arrays instead of ObjectSets?
|
||||
|
||||
/**Class used for indexing special target blocks for AI.*/
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -182,7 +182,7 @@ public class Pathfinder{
|
||||
}
|
||||
}
|
||||
|
||||
state.spawner.checkAllQuadrants();
|
||||
world.spawner.checkAllQuadrants();
|
||||
}
|
||||
|
||||
class PathData{
|
||||
|
||||
@@ -43,43 +43,46 @@ public class Recipes implements ContentList{
|
||||
new Recipe(defense, DefenseBlocks.surgeWallLarge, new ItemStack(Items.surgealloy, 12 * 4));
|
||||
|
||||
//projectors
|
||||
new Recipe(defense, DefenseBlocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180));
|
||||
new Recipe(defense, DefenseBlocks.overdriveProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
|
||||
new Recipe(defense, DefenseBlocks.forceProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
|
||||
new Recipe(effect, DefenseBlocks.mendProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 50), new ItemStack(Items.silicon, 180));
|
||||
new Recipe(effect, DefenseBlocks.overdriveProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
|
||||
new Recipe(effect, DefenseBlocks.forceProjector, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 150), new ItemStack(Items.titanium, 150), new ItemStack(Items.silicon, 250));
|
||||
|
||||
//extra blocks
|
||||
new Recipe(defense, DefenseBlocks.shockMine, new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 25))
|
||||
new Recipe(effect, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60));
|
||||
new Recipe(effect, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
|
||||
new Recipe(effect, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
|
||||
|
||||
new Recipe(effect, DefenseBlocks.shockMine, new ItemStack(Items.lead, 50), new ItemStack(Items.silicon, 25))
|
||||
.setDependencies(Items.blastCompound);
|
||||
|
||||
//TURRETS
|
||||
new Recipe(weapon, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true);
|
||||
new Recipe(weapon, TurretBlocks.arc, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 30), new ItemStack(Items.silicon, 20));
|
||||
new Recipe(weapon, TurretBlocks.hail, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 35));
|
||||
new Recipe(weapon, TurretBlocks.lancer, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 90));
|
||||
new Recipe(weapon, TurretBlocks.wave, new ItemStack(Items.densealloy, 60), new ItemStack(Items.titanium, 70), new ItemStack(Items.lead, 150));
|
||||
new Recipe(weapon, TurretBlocks.salvo, new ItemStack(Items.copper, 210), new ItemStack(Items.densealloy, 190), new ItemStack(Items.thorium, 130));
|
||||
new Recipe(weapon, TurretBlocks.swarmer, new ItemStack(Items.densealloy, 70), new ItemStack(Items.titanium, 70), new ItemStack(Items.plastanium, 90), new ItemStack(Items.silicon, 60));
|
||||
new Recipe(weapon, TurretBlocks.ripple, new ItemStack(Items.copper, 300), new ItemStack(Items.densealloy, 220), new ItemStack(Items.thorium, 120));
|
||||
new Recipe(weapon, TurretBlocks.cyclone, new ItemStack(Items.copper, 400), new ItemStack(Items.densealloy, 400), new ItemStack(Items.surgealloy, 200), new ItemStack(Items.plastanium, 150));
|
||||
new Recipe(weapon, TurretBlocks.fuse, new ItemStack(Items.copper, 450), new ItemStack(Items.densealloy, 450), new ItemStack(Items.surgealloy, 250));
|
||||
new Recipe(weapon, TurretBlocks.spectre, new ItemStack(Items.copper, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 500), new ItemStack(Items.plastanium, 350), new ItemStack(Items.thorium, 500));
|
||||
new Recipe(weapon, TurretBlocks.meltdown, new ItemStack(Items.copper, 500), new ItemStack(Items.lead, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 650), new ItemStack(Items.silicon, 650));
|
||||
new Recipe(turret, TurretBlocks.duo, new ItemStack(Items.copper, 40)).setAlwaysUnlocked(true);
|
||||
new Recipe(turret, TurretBlocks.arc, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 30), new ItemStack(Items.silicon, 20));
|
||||
new Recipe(turret, TurretBlocks.hail, new ItemStack(Items.copper, 60), new ItemStack(Items.densealloy, 35));
|
||||
new Recipe(turret, TurretBlocks.lancer, new ItemStack(Items.copper, 50), new ItemStack(Items.lead, 100), new ItemStack(Items.silicon, 90));
|
||||
new Recipe(turret, TurretBlocks.wave, new ItemStack(Items.densealloy, 60), new ItemStack(Items.titanium, 70), new ItemStack(Items.lead, 150));
|
||||
new Recipe(turret, TurretBlocks.salvo, new ItemStack(Items.copper, 210), new ItemStack(Items.densealloy, 190), new ItemStack(Items.thorium, 130));
|
||||
new Recipe(turret, TurretBlocks.swarmer, new ItemStack(Items.densealloy, 70), new ItemStack(Items.titanium, 70), new ItemStack(Items.plastanium, 90), new ItemStack(Items.silicon, 60));
|
||||
new Recipe(turret, TurretBlocks.ripple, new ItemStack(Items.copper, 300), new ItemStack(Items.densealloy, 220), new ItemStack(Items.thorium, 120));
|
||||
new Recipe(turret, TurretBlocks.cyclone, new ItemStack(Items.copper, 400), new ItemStack(Items.densealloy, 400), new ItemStack(Items.surgealloy, 200), new ItemStack(Items.plastanium, 150));
|
||||
new Recipe(turret, TurretBlocks.fuse, new ItemStack(Items.copper, 450), new ItemStack(Items.densealloy, 450), new ItemStack(Items.surgealloy, 250));
|
||||
new Recipe(turret, TurretBlocks.spectre, new ItemStack(Items.copper, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 500), new ItemStack(Items.plastanium, 350), new ItemStack(Items.thorium, 500));
|
||||
new Recipe(turret, TurretBlocks.meltdown, new ItemStack(Items.copper, 500), new ItemStack(Items.lead, 700), new ItemStack(Items.densealloy, 600), new ItemStack(Items.surgealloy, 650), new ItemStack(Items.silicon, 650));
|
||||
|
||||
//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.phasefabric, 10), new ItemStack(Items.silicon, 15), new ItemStack(Items.lead, 20), new ItemStack(Items.densealloy, 20));
|
||||
|
||||
//starter lead transportation
|
||||
//starter transport
|
||||
new Recipe(distribution, DistributionBlocks.junction, new ItemStack(Items.copper, 2)).setAlwaysUnlocked(true);
|
||||
new Recipe(distribution, DistributionBlocks.router, new ItemStack(Items.copper, 6)).setAlwaysUnlocked(true);
|
||||
|
||||
//advanced densealloy transporation
|
||||
//advanced densealloy transporat
|
||||
new Recipe(distribution, DistributionBlocks.distributor, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8));
|
||||
new Recipe(distribution, DistributionBlocks.sorter, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 4));
|
||||
new Recipe(distribution, DistributionBlocks.overflowGate, new ItemStack(Items.densealloy, 4), new ItemStack(Items.copper, 8));
|
||||
new Recipe(distribution, DistributionBlocks.itemBridge, new ItemStack(Items.densealloy, 8), new ItemStack(Items.copper, 8));
|
||||
new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.densealloy, 400), new ItemStack(Items.silicon, 300), new ItemStack(Items.lead, 400), new ItemStack(Items.thorium, 250));
|
||||
new Recipe(distribution, DistributionBlocks.massDriver, new ItemStack(Items.densealloy, 250), new ItemStack(Items.silicon, 150), new ItemStack(Items.lead, 250), new ItemStack(Items.thorium, 100));
|
||||
|
||||
//CRAFTING
|
||||
|
||||
@@ -131,9 +134,6 @@ public class Recipes implements ContentList{
|
||||
new Recipe(power, PowerBlocks.thoriumReactor, new ItemStack(Items.lead, 600), new ItemStack(Items.silicon, 400), new ItemStack(Items.densealloy, 300), new ItemStack(Items.thorium, 300));
|
||||
new Recipe(power, PowerBlocks.rtgGenerator, new ItemStack(Items.lead, 200), new ItemStack(Items.silicon, 150), new ItemStack(Items.phasefabric, 50), new ItemStack(Items.plastanium, 150), new ItemStack(Items.thorium, 100));
|
||||
|
||||
new Recipe(distribution, StorageBlocks.unloader, new ItemStack(Items.densealloy, 50), new ItemStack(Items.silicon, 60));
|
||||
new Recipe(distribution, StorageBlocks.container, new ItemStack(Items.densealloy, 200));
|
||||
new Recipe(distribution, StorageBlocks.vault, new ItemStack(Items.densealloy, 500), new ItemStack(Items.thorium, 250));
|
||||
//core disabled due to being broken
|
||||
/*new Recipe(distribution, StorageBlocks.core,
|
||||
new ItemStack(Items.copper, 2000), new ItemStack(Items.densealloy, 1500),
|
||||
@@ -153,16 +153,16 @@ public class Recipes implements ContentList{
|
||||
|
||||
//UNITS
|
||||
|
||||
//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.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));
|
||||
//upgrades
|
||||
new Recipe(upgrade, 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(upgrade, 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(upgrade, 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(upgrade, 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);
|
||||
new Recipe(units, UpgradeBlocks.tauPad, new ItemStack(Items.lead, 250), new ItemStack(Items.densealloy, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250));
|
||||
new Recipe(units, UpgradeBlocks.deltaPad, new ItemStack(Items.lead, 350), new ItemStack(Items.densealloy, 350), new ItemStack(Items.copper, 400), new ItemStack(Items.silicon, 450), new ItemStack(Items.thorium, 300));
|
||||
new Recipe(units, UpgradeBlocks.omegaPad, new ItemStack(Items.lead, 450), new ItemStack(Items.densealloy, 550), new ItemStack(Items.silicon, 650), new ItemStack(Items.thorium, 600), new ItemStack(Items.surgealloy, 240));
|
||||
new Recipe(upgrade, UpgradeBlocks.alphaPad, new ItemStack(Items.lead, 200), new ItemStack(Items.densealloy, 100), new ItemStack(Items.copper, 150)).setVisible(RecipeVisibility.mobileOnly);
|
||||
new Recipe(upgrade, UpgradeBlocks.tauPad, new ItemStack(Items.lead, 250), new ItemStack(Items.densealloy, 250), new ItemStack(Items.copper, 250), new ItemStack(Items.silicon, 250));
|
||||
new Recipe(upgrade, UpgradeBlocks.deltaPad, new ItemStack(Items.lead, 350), new ItemStack(Items.densealloy, 350), new ItemStack(Items.copper, 400), new ItemStack(Items.silicon, 450), new ItemStack(Items.thorium, 300));
|
||||
new Recipe(upgrade, UpgradeBlocks.omegaPad, new ItemStack(Items.lead, 450), new ItemStack(Items.densealloy, 550), new ItemStack(Items.silicon, 650), new ItemStack(Items.thorium, 600), new ItemStack(Items.surgealloy, 240));
|
||||
|
||||
//actual unit related stuff
|
||||
new Recipe(units, UnitBlocks.spiritFactory, new ItemStack(Items.copper, 70), new ItemStack(Items.lead, 110), new ItemStack(Items.silicon, 130));
|
||||
|
||||
@@ -37,6 +37,7 @@ public class UnitTypes implements ContentList{
|
||||
};
|
||||
|
||||
spirit = new UnitType("spirit", Spirit.class, Spirit::new){{
|
||||
weapon = Weapons.healBlasterDrone;
|
||||
isFlying = true;
|
||||
drag = 0.01f;
|
||||
speed = 0.2f;
|
||||
|
||||
@@ -7,7 +7,7 @@ import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.type.Weapon;
|
||||
|
||||
public class Weapons implements ContentList{
|
||||
public static Weapon blaster, blasterSmall, glaiveBlaster, droneBlaster, healBlaster, chainBlaster, shockgun,
|
||||
public static Weapon blaster, blasterSmall, glaiveBlaster, droneBlaster, healBlaster, healBlasterDrone, chainBlaster, shockgun,
|
||||
sapper, swarmer, bomber, bomberTrident, flakgun, flamethrower, missiles, artillery, laserBurster;
|
||||
|
||||
@Override
|
||||
@@ -169,6 +169,16 @@ public class Weapons implements ContentList{
|
||||
ejectEffect = Fx.none;
|
||||
ammo = AmmoTypes.lancerLaser;
|
||||
}};
|
||||
|
||||
healBlasterDrone = new Weapon("heal-blaster"){{
|
||||
length = 1.5f;
|
||||
reload = 40f;
|
||||
width = 0.5f;
|
||||
roundrobin = true;
|
||||
ejectEffect = Fx.none;
|
||||
recoil = 2f;
|
||||
ammo = AmmoTypes.healBlaster;
|
||||
}};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,9 +33,9 @@ public class DistributionBlocks extends BlockList implements ContentList{
|
||||
}};
|
||||
|
||||
phaseConveyor = new ItemBridge("phase-conveyor"){{
|
||||
range = 11;
|
||||
range = 12;
|
||||
hasPower = true;
|
||||
consumes.powerDirect(0.05f);
|
||||
consumes.powerDirect(0.03f);
|
||||
}};
|
||||
|
||||
sorter = new Sorter("sorter");
|
||||
@@ -50,8 +50,8 @@ public class DistributionBlocks extends BlockList implements ContentList{
|
||||
|
||||
massDriver = new MassDriver("mass-driver"){{
|
||||
size = 3;
|
||||
itemCapacity = 80;
|
||||
range = 340f;
|
||||
itemCapacity = 60;
|
||||
range = 440f;
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ public class LiquidBlocks extends BlockList implements ContentList{
|
||||
}};
|
||||
|
||||
phaseConduit = new LiquidBridge("phase-conduit"){{
|
||||
range = 11;
|
||||
range = 12;
|
||||
hasPower = true;
|
||||
consumes.powerDirect(0.05f);
|
||||
consumes.powerDirect(0.03f);
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,24 +32,13 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
|
||||
hail = new ArtilleryTurret("hail"){{
|
||||
ammoTypes = new AmmoType[]{AmmoTypes.artilleryDense, AmmoTypes.artilleryHoming, AmmoTypes.artilleryIncindiary};
|
||||
reload = 70f;
|
||||
reload = 60f;
|
||||
recoil = 2f;
|
||||
range = 230f;
|
||||
inaccuracy = 1f;
|
||||
shootCone = 10f;
|
||||
health = 120;
|
||||
}};
|
||||
/*
|
||||
scatter = new BurstTurret("scatter"){{
|
||||
ammoTypes = new AmmoType[]{AmmoTypes.flakCopper};
|
||||
reload = 70f;
|
||||
recoil = 2f;
|
||||
shots = 3;
|
||||
range = 220f;
|
||||
inaccuracy = 2f;
|
||||
shootCone = 40f;
|
||||
health = 120;
|
||||
}};*/
|
||||
|
||||
scorch = new LiquidTurret("scorch"){
|
||||
protected TextureRegion shootRegion;
|
||||
@@ -117,11 +106,11 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
|
||||
arc = new PowerTurret("arc"){{
|
||||
shootType = AmmoTypes.arc;
|
||||
reload = 55f;
|
||||
reload = 85f;
|
||||
shootShake = 1f;
|
||||
shootCone = 40f;
|
||||
rotatespeed = 8f;
|
||||
powerUsed = 7 / 30f;
|
||||
powerUsed = 10f;
|
||||
consumes.powerBuffered(30f);
|
||||
range = 150f;
|
||||
shootEffect = ShootFx.lightningShoot;
|
||||
@@ -132,7 +121,7 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
|
||||
swarmer = new BurstTurret("swarmer"){{
|
||||
ammoTypes = new AmmoType[]{AmmoTypes.missileExplosive, AmmoTypes.missileIncindiary, AmmoTypes.missileSurge};
|
||||
reload = 60f;
|
||||
reload = 50f;
|
||||
shots = 4;
|
||||
burstSpacing = 5;
|
||||
inaccuracy = 10f;
|
||||
@@ -156,7 +145,7 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
size = 2;
|
||||
range = 120f;
|
||||
ammoTypes = new AmmoType[]{AmmoTypes.bulletCopper, AmmoTypes.bulletDense, AmmoTypes.bulletPyratite, AmmoTypes.bulletThorium, AmmoTypes.bulletSilicon};
|
||||
reload = 40f;
|
||||
reload = 35f;
|
||||
restitution = 0.03f;
|
||||
ammoEjectBack = 3f;
|
||||
cooldown = 0.03f;
|
||||
@@ -216,7 +205,6 @@ public class TurretBlocks extends BlockList implements ContentList{
|
||||
}};
|
||||
|
||||
fuse = new ItemTurret("fuse"){{
|
||||
//TODO make it use power
|
||||
ammoTypes = new AmmoType[]{AmmoTypes.fuseShotgun};
|
||||
reload = 50f;
|
||||
shootShake = 4f;
|
||||
|
||||
@@ -21,7 +21,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
produceTime = 5700;
|
||||
size = 2;
|
||||
consumes.powerDirect(0.08f);
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30)});
|
||||
consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30));
|
||||
}};
|
||||
|
||||
phantomFactory = new UnitFactory("phantom-factory"){{
|
||||
@@ -29,7 +29,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
produceTime = 7300;
|
||||
size = 2;
|
||||
consumes.powerDirect(0.2f);
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80)});
|
||||
consumes.items(new ItemStack(Items.silicon, 70), new ItemStack(Items.lead, 80), new ItemStack(Items.titanium, 80));
|
||||
}};
|
||||
|
||||
wraithFactory = new UnitFactory("wraith-factory"){{
|
||||
@@ -37,7 +37,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
produceTime = 1800;
|
||||
size = 2;
|
||||
consumes.powerDirect(0.1f);
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 10), new ItemStack(Items.titanium, 10)});
|
||||
consumes.items(new ItemStack(Items.silicon, 10), new ItemStack(Items.titanium, 10));
|
||||
}};
|
||||
|
||||
ghoulFactory = new UnitFactory("ghoul-factory"){{
|
||||
@@ -46,7 +46,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
size = 3;
|
||||
consumes.powerDirect(0.2f);
|
||||
shadow = "shadow-round-3";
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20)});
|
||||
consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20));
|
||||
}};
|
||||
|
||||
revenantFactory = new UnitFactory("revenant-factory"){{
|
||||
@@ -55,7 +55,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
size = 4;
|
||||
consumes.powerDirect(0.3f);
|
||||
shadow = "shadow-round-4";
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80), new ItemStack(Items.plastanium, 50)});
|
||||
consumes.items(new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80), new ItemStack(Items.plastanium, 50));
|
||||
}};
|
||||
|
||||
daggerFactory = new UnitFactory("dagger-factory"){{
|
||||
@@ -63,7 +63,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
produceTime = 1700;
|
||||
size = 2;
|
||||
consumes.powerDirect(0.05f);
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 10)});
|
||||
consumes.items(new ItemStack(Items.silicon, 10));
|
||||
}};
|
||||
|
||||
titanFactory = new UnitFactory("titan-factory"){{
|
||||
@@ -72,7 +72,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
size = 3;
|
||||
consumes.powerDirect(0.15f);
|
||||
shadow = "shadow-round-3";
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 20), new ItemStack(Items.thorium, 30)});
|
||||
consumes.items(new ItemStack(Items.silicon, 20), new ItemStack(Items.thorium, 30));
|
||||
}};
|
||||
|
||||
fortressFactory = new UnitFactory("fortress-factory"){{
|
||||
@@ -81,7 +81,7 @@ public class UnitBlocks extends BlockList implements ContentList{
|
||||
size = 3;
|
||||
consumes.powerDirect(0.2f);
|
||||
shadow = "shadow-round-3";
|
||||
consumes.items(new ItemStack[]{new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50)});
|
||||
consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50));
|
||||
}};
|
||||
|
||||
repairPoint = new RepairPoint("repair-point"){{
|
||||
|
||||
@@ -43,7 +43,7 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
};
|
||||
|
||||
healBullet = new BulletType(5.2f, 13){
|
||||
float healAmount = 21f;
|
||||
float healPercent = 3f;
|
||||
|
||||
{
|
||||
hiteffect = BulletFx.hitLaser;
|
||||
@@ -51,6 +51,11 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
collidesTeam = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean collides(Bullet b, Tile tile){
|
||||
return tile.getTeam() != b.getTeam() || tile.entity.healthf() < 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Bullet b){
|
||||
Draw.color(Palette.heal);
|
||||
@@ -67,8 +72,8 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
tile = tile.target();
|
||||
|
||||
if(tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){
|
||||
Effects.effect(BlockFx.healBlock, tile.drawx(), tile.drawy(), tile.block().size);
|
||||
tile.entity.healBy(healAmount);
|
||||
Effects.effect(BlockFx.healBlockFull, Palette.heal, tile.drawx(), tile.drawy(), tile.block().size);
|
||||
tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth());
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -304,7 +309,7 @@ public class TurretBullets extends BulletList implements ContentList{
|
||||
}
|
||||
};
|
||||
|
||||
arc = new BulletType(0.001f, 30){
|
||||
arc = new BulletType(0.001f, 26){
|
||||
{
|
||||
lifetime = 1;
|
||||
despawneffect = Fx.none;
|
||||
|
||||
@@ -89,7 +89,7 @@ public class Control extends Module{
|
||||
"color-1", Color.rgba8888(playerColors[11]),
|
||||
"color-2", Color.rgba8888(playerColors[13]),
|
||||
"color-3", Color.rgba8888(playerColors[9]),
|
||||
"name", "player",
|
||||
"name", "",
|
||||
"lastBuild", 0
|
||||
);
|
||||
|
||||
@@ -111,15 +111,6 @@ public class Control extends Module{
|
||||
}
|
||||
|
||||
state.set(State.playing);
|
||||
|
||||
if(world.getSector() == null && !Settings.getBool("custom-warning-for-real-1", false)){
|
||||
threads.runGraphics(() -> ui.showInfo("$mode.custom.warning", () ->
|
||||
ui.showInfo("$mode.custom.warning.read", () -> {
|
||||
Settings.putBool("custom-warning-for-real-1", true);
|
||||
Settings.save();
|
||||
})));
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Events.on(WorldLoadGraphicsEvent.class, event -> {
|
||||
@@ -382,6 +373,10 @@ public class Control extends Module{
|
||||
}
|
||||
}
|
||||
|
||||
if(Inputs.keyTap("screenshot")){
|
||||
renderer.takeMapScreenshot();
|
||||
}
|
||||
|
||||
}else{
|
||||
if(!state.isPaused()){
|
||||
Timers.update();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import io.anuke.mindustry.ai.WaveSpawner;
|
||||
import io.anuke.mindustry.game.Difficulty;
|
||||
import io.anuke.mindustry.game.EventType.StateChangeEvent;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
@@ -12,14 +11,21 @@ import static io.anuke.mindustry.Vars.unitGroups;
|
||||
import static io.anuke.mindustry.Vars.waveTeam;
|
||||
|
||||
public class GameState{
|
||||
/**Current wave number, can be anything in non-wave modes.*/
|
||||
public int wave = 1;
|
||||
/**Wave countdown in ticks.*/
|
||||
public float wavetime;
|
||||
/**Whether the game is in game over state.*/
|
||||
public boolean gameOver = false;
|
||||
/**The current game mode.*/
|
||||
public GameMode mode = GameMode.waves;
|
||||
/**The current difficulty for wave modes.*/
|
||||
public Difficulty difficulty = Difficulty.normal;
|
||||
public WaveSpawner spawner = new WaveSpawner();
|
||||
/**Team data. Gets reset every new game.*/
|
||||
public Teams teams = new Teams();
|
||||
/**Number of enemies in the game; only used clientside in servers.*/
|
||||
public int enemies;
|
||||
/**Current game state.*/
|
||||
private State state = State.menu;
|
||||
|
||||
public int enemies(){
|
||||
|
||||
@@ -93,7 +93,7 @@ public class Logic extends Module{
|
||||
}
|
||||
|
||||
public void runWave(){
|
||||
state.spawner.spawnEnemies();
|
||||
world.spawner.spawnEnemies();
|
||||
state.wave++;
|
||||
state.wavetime = wavespace * state.difficulty.timeScaling;
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.entities.traits.TypeTrait;
|
||||
import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.gen.RemoteReadClient;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
@@ -95,6 +96,7 @@ public class NetClient extends Module{
|
||||
ConnectPacket c = new ConnectPacket();
|
||||
c.name = player.name;
|
||||
c.mobile = mobile;
|
||||
c.versionType = Version.type;
|
||||
c.color = Color.rgba8888(player.color);
|
||||
c.usid = getUsid(packet.addressTCP);
|
||||
c.uuid = Platform.instance.getUUID();
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest;
|
||||
import io.anuke.mindustry.entities.traits.SyncTrait;
|
||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
@@ -24,6 +25,7 @@ import io.anuke.mindustry.net.*;
|
||||
import io.anuke.mindustry.net.Administration.PlayerInfo;
|
||||
import io.anuke.mindustry.net.Packets.*;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
@@ -76,6 +78,9 @@ public class NetServer extends Module{
|
||||
private DataOutputStream dataStream = new DataOutputStream(syncStream);
|
||||
|
||||
public NetServer(){
|
||||
Events.on(WorldLoadEvent.class, event -> {
|
||||
connections.clear();
|
||||
});
|
||||
|
||||
Net.handleServer(Connect.class, (id, connect) -> {
|
||||
if(admins.isIPBanned(connect.addressTCP)){
|
||||
@@ -120,7 +125,7 @@ public class NetServer extends Module{
|
||||
return;
|
||||
}
|
||||
|
||||
if(packet.version == -1 && Version.build != -1 && !admins.allowsCustomClients()){
|
||||
if(packet.versionType == null || ((packet.version == -1 || !packet.versionType.equals("official")) && Version.build != -1 && !admins.allowsCustomClients())){
|
||||
kick(id, KickReason.customClient);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
import io.anuke.ucore.scene.ui.Dialog;
|
||||
import io.anuke.ucore.scene.ui.TextField;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@@ -29,7 +28,6 @@ public abstract class Platform {
|
||||
if(!mobile) return; //this is mobile only, desktop doesn't need dialogs
|
||||
|
||||
field.tapped(() -> {
|
||||
Log.info("yappd");
|
||||
Dialog dialog = new Dialog("", "dialog");
|
||||
dialog.setFillParent(true);
|
||||
dialog.content().top();
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.PixmapIO;
|
||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import com.badlogic.gdx.utils.BufferUtils;
|
||||
import com.badlogic.gdx.utils.ScreenUtils;
|
||||
import com.badlogic.gdx.utils.TimeUtils;
|
||||
import io.anuke.mindustry.content.fx.Fx;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
@@ -33,6 +39,7 @@ import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.graphics.Surface;
|
||||
import io.anuke.ucore.modules.RendererModule;
|
||||
import io.anuke.ucore.scene.utils.Cursors;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Pooling;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
@@ -378,4 +385,44 @@ public class Renderer extends RendererModule{
|
||||
targetscale = Mathf.clamp(targetscale, Math.round(s * 2), Math.round(s * 5));
|
||||
}
|
||||
|
||||
public void takeMapScreenshot(){
|
||||
float vpW = Core.camera.viewportWidth, vpH = Core.camera.viewportHeight;
|
||||
int w = world.width()*tilesize, h = world.height()*tilesize;
|
||||
int pw = pixelSurface.width(), ph = pixelSurface.height();
|
||||
showFog = false;
|
||||
disableUI = true;
|
||||
pixelSurface.setSize(w, h, true);
|
||||
Graphics.getEffectSurface().setSize(w, h, true);
|
||||
Core.camera.viewportWidth = w;
|
||||
Core.camera.viewportHeight = h;
|
||||
Core.camera.position.x = w/2f;
|
||||
Core.camera.position.y = h/2f;
|
||||
|
||||
draw();
|
||||
|
||||
showFog = true;
|
||||
disableUI = false;
|
||||
Core.camera.viewportWidth = vpW;
|
||||
Core.camera.viewportHeight = vpH;
|
||||
|
||||
pixelSurface.getBuffer().begin();
|
||||
byte[] lines = ScreenUtils.getFrameBufferPixels(0, 0, w, h, true);
|
||||
for(int i = 0; i < lines.length; i+= 4){
|
||||
lines[i + 3] = (byte)255;
|
||||
}
|
||||
pixelSurface.getBuffer().end();
|
||||
|
||||
Pixmap fullPixmap = new Pixmap(w, h, Pixmap.Format.RGBA8888);
|
||||
|
||||
BufferUtils.copy(lines, 0, fullPixmap.getPixels(), lines.length);
|
||||
FileHandle file = screenshotDirectory.child("screenshot-" + TimeUtils.millis() + ".png");
|
||||
PixmapIO.writePNG(file, fullPixmap);
|
||||
fullPixmap.dispose();
|
||||
|
||||
pixelSurface.setSize(pw, ph, false);
|
||||
Graphics.getEffectSurface().setSize(pw, ph, false);
|
||||
|
||||
ui.showInfoFade(Bundles.format("text.screenshot", file.toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ 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.Strings;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.ucore.scene.actions.Actions.*;
|
||||
@@ -122,6 +123,8 @@ public class UI extends SceneModule{
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(disableUI) return;
|
||||
|
||||
if(Graphics.drawing()) Graphics.end();
|
||||
|
||||
act();
|
||||
@@ -293,4 +296,16 @@ public class UI extends SceneModule{
|
||||
dialog.keyDown(Keys.BACK, dialog::hide);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public String formatAmount(int number){
|
||||
if(number >= 1000000){
|
||||
return Strings.toFixed(number / 1000000f, 1) + "[gray]mil[]";
|
||||
}else if(number >= 10000){
|
||||
return number / 1000 + "[gray]k[]";
|
||||
}else if(number >= 1000){
|
||||
return Strings.toFixed(number / 1000f, 1) + "[gray]k[]";
|
||||
}else{
|
||||
return number + "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import io.anuke.mindustry.ai.BlockIndexer;
|
||||
import io.anuke.mindustry.ai.Pathfinder;
|
||||
import io.anuke.mindustry.ai.WaveSpawner;
|
||||
import io.anuke.mindustry.content.blocks.Blocks;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
||||
@@ -30,6 +31,7 @@ public class World extends Module{
|
||||
public final WorldGenerator generator = new WorldGenerator();
|
||||
public final BlockIndexer indexer = new BlockIndexer();
|
||||
public final Pathfinder pathfinder = new Pathfinder();
|
||||
public final WaveSpawner spawner = new WaveSpawner();
|
||||
|
||||
private Map currentMap;
|
||||
private Sector currentSector;
|
||||
|
||||
@@ -17,6 +17,8 @@ import static io.anuke.mindustry.Vars.ui;
|
||||
public enum EditorTool{
|
||||
pick{
|
||||
public void touched(MapEditor editor, int x, int y){
|
||||
if(!Structs.inBounds(x, y, editor.getMap().width(), editor.getMap().height())) return;
|
||||
|
||||
byte bf = editor.getMap().read(x, y, DataPosition.floor);
|
||||
byte bw = editor.getMap().read(x, y, DataPosition.wall);
|
||||
byte link = editor.getMap().read(x, y, DataPosition.link);
|
||||
|
||||
@@ -175,7 +175,6 @@ public class MapView extends Element implements GestureListener{
|
||||
|
||||
public void clearStack(){
|
||||
stack.clear();
|
||||
//TODO clear und obuffer
|
||||
}
|
||||
|
||||
public OperationStack getStack(){
|
||||
@@ -292,7 +291,6 @@ public class MapView extends Element implements GestureListener{
|
||||
}
|
||||
}
|
||||
|
||||
//todo is it really math.max?
|
||||
float scaling = zoom * Math.min(width, height) / editor.getMap().width();
|
||||
|
||||
Draw.color(Palette.accent);
|
||||
|
||||
@@ -19,10 +19,7 @@ import io.anuke.mindustry.graphics.Trail;
|
||||
import io.anuke.mindustry.io.TypeIO;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.net.NetConnection;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Mech;
|
||||
import io.anuke.mindustry.type.Weapon;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.Floor;
|
||||
@@ -192,6 +189,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
this.mining = tile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMine(Item item){
|
||||
return item.hardness <= mech.drillPower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getArmor(){
|
||||
return mech.armor + mech.getExtraArmor(this);
|
||||
|
||||
@@ -209,7 +209,7 @@ public class Bullet extends BulletEntity<BulletType> implements TeamTrait, SyncT
|
||||
if(tile == null) return false;
|
||||
tile = tile.target();
|
||||
|
||||
if(tile.entity != null && tile.entity.collide(this) && !tile.entity.isDead() && (type.collidesTeam || tile.getTeam() != team)){
|
||||
if(tile.entity != null && tile.entity.collide(this) && type.collides(this, tile) && !tile.entity.isDead() && (type.collidesTeam || tile.getTeam() != team)){
|
||||
if(tile.getTeam() != team){
|
||||
tile.entity.collision(this);
|
||||
}
|
||||
|
||||
@@ -55,6 +55,10 @@ public abstract class BulletType extends Content implements BaseBulletType<Bulle
|
||||
despawneffect = BulletFx.hitBulletSmall;
|
||||
}
|
||||
|
||||
public boolean collides(Bullet bullet, Tile tile){
|
||||
return true;
|
||||
}
|
||||
|
||||
public void hitTile(Bullet b, Tile tile){
|
||||
hit(b);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,9 @@ public interface BuilderTrait extends Entity{
|
||||
/**Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all.*/
|
||||
float getBuildPower(Tile tile);
|
||||
|
||||
/**Returns whether or not this builder can mine a specific item type.*/
|
||||
boolean canMine(Item item);
|
||||
|
||||
/**Whether this type of builder can begin creating new blocks.*/
|
||||
default boolean canCreateBlocks(){
|
||||
return true;
|
||||
@@ -236,7 +239,8 @@ public interface BuilderTrait extends Entity{
|
||||
Tile tile = getMineTile();
|
||||
TileEntity core = unit.getClosestCore();
|
||||
|
||||
if(core == null || tile.block() != Blocks.air || unit.distanceTo(tile.worldx(), tile.worldy()) > mineDistance || !unit.inventory.canAcceptItem(tile.floor().drops.item)){
|
||||
if(core == null || tile.block() != Blocks.air || unit.distanceTo(tile.worldx(), tile.worldy()) > mineDistance
|
||||
|| tile.floor().drops == null || !unit.inventory.canAcceptItem(tile.floor().drops.item) || !canMine(tile.floor().drops.item)){
|
||||
setMineTile(null);
|
||||
}else{
|
||||
Item item = tile.floor().drops.item;
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
import io.anuke.ucore.entities.trait.HealthTrait;
|
||||
|
||||
//TODO implement
|
||||
public interface RepairTrait extends TeamTrait{
|
||||
|
||||
HealthTrait getRepairing();
|
||||
|
||||
void setRepairing(HealthTrait trait);
|
||||
|
||||
default void drawRepair(){
|
||||
if(getRepairing() == null) return;
|
||||
}
|
||||
|
||||
default void updateRepair(){
|
||||
if(getRepairing() == null) return;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import io.anuke.ucore.util.Bundles;
|
||||
import io.anuke.ucore.util.Log;
|
||||
import io.anuke.ucore.util.Strings;
|
||||
|
||||
//TODO merge unit type with mech
|
||||
public class UnitType extends UnlockableContent{
|
||||
protected final Supplier<? extends BaseUnit> constructor;
|
||||
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
package io.anuke.mindustry.entities.units.types;
|
||||
|
||||
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;
|
||||
import io.anuke.mindustry.entities.traits.TargetTrait;
|
||||
import io.anuke.mindustry.entities.units.BaseUnit;
|
||||
import io.anuke.mindustry.entities.units.FlyingUnit;
|
||||
import io.anuke.mindustry.entities.units.UnitCommand;
|
||||
@@ -16,7 +13,6 @@ import io.anuke.mindustry.entities.units.UnitState;
|
||||
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;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.ItemType;
|
||||
@@ -24,13 +20,11 @@ import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock;
|
||||
import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Shapes;
|
||||
import io.anuke.ucore.util.*;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Structs;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -117,12 +111,7 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
if(target.distanceTo(Drone.this) > type.range){
|
||||
circle(type.range*0.9f);
|
||||
}else{
|
||||
TileEntity entity = (TileEntity) target;
|
||||
entity.healBy(type.healSpeed * entity.tile.block().health / 100f * Timers.delta());
|
||||
|
||||
if(timer.get(timerRepairEffect, 30)){
|
||||
Effects.effect(BlockFx.healBlockFull, Palette.heal, entity.x, entity.y, entity.tile.block().size);
|
||||
}
|
||||
getWeapon().update(Drone.this, target.getX(), target.getY());
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -279,6 +268,11 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
//no
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canMine(Item item){
|
||||
return type.toMine.contains(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getBuildPower(Tile tile){
|
||||
return type.buildPower;
|
||||
@@ -312,16 +306,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
target = null;
|
||||
}
|
||||
|
||||
if(Net.client() && state.is(repair) && target instanceof TileEntity && target.distanceTo(this) < type.range){
|
||||
TileEntity entity = (TileEntity) target;
|
||||
entity.health += type.healSpeed * Timers.delta();
|
||||
entity.health = Mathf.clamp(entity.health, 0, entity.tile.block().health);
|
||||
|
||||
if(timer.get(timerRepairEffect, 30)){
|
||||
Effects.effect(BlockFx.healBlockFull, Palette.heal, entity.x, entity.y, entity.tile.block().size);
|
||||
}
|
||||
}
|
||||
|
||||
updateBuilding(this);
|
||||
}
|
||||
|
||||
@@ -350,19 +334,6 @@ public class Drone extends FlyingUnit implements BuilderTrait{
|
||||
@Override
|
||||
public void drawOver(){
|
||||
trail.draw(Palette.lightTrail, 3f);
|
||||
|
||||
TargetTrait entity = target;
|
||||
|
||||
if(entity instanceof TileEntity && state.is(repair) && target.distanceTo(this) < type.range){
|
||||
float len = 5f;
|
||||
Draw.color(Color.BLACK, Color.WHITE, 0.95f + Mathf.absin(Timers.time(), 0.8f, 0.05f));
|
||||
Shapes.laser("beam", "beam-end",
|
||||
x + Angles.trnsx(rotation, len),
|
||||
y + Angles.trnsy(rotation, len),
|
||||
entity.getX(), entity.getY());
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
drawBuilding(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package io.anuke.mindustry.game;
|
||||
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import io.anuke.mindustry.game.EventType.UnlockEvent;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.ucore.core.Events;
|
||||
|
||||
public class ContentUnlockSet {
|
||||
private ObjectMap<ContentType, ObjectSet<String>> unlocked = new ObjectMap<>();
|
||||
private boolean dirty;
|
||||
|
||||
public boolean isUnlocked(UnlockableContent content){
|
||||
if(content.alwaysUnlocked()) return true;
|
||||
|
||||
if(!unlocked.containsKey(content.getContentType())){
|
||||
unlocked.put(content.getContentType(), new ObjectSet<>());
|
||||
}
|
||||
|
||||
ObjectSet<String> set = unlocked.get(content.getContentType());
|
||||
|
||||
return set.contains(content.getContentName());
|
||||
}
|
||||
|
||||
public boolean unlockContent(UnlockableContent content){
|
||||
if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false;
|
||||
|
||||
if(!unlocked.containsKey(content.getContentType())){
|
||||
unlocked.put(content.getContentType(), new ObjectSet<>());
|
||||
}
|
||||
|
||||
boolean ret = unlocked.get(content.getContentType()).add(content.getContentName());
|
||||
|
||||
//fire unlock event so other classes can use it
|
||||
if(ret){
|
||||
content.onUnlock();
|
||||
Events.fire(new UnlockEvent(content));
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public boolean isDirty() {
|
||||
return dirty;
|
||||
}
|
||||
|
||||
public ObjectMap<ContentType, ObjectSet<String>> getUnlocked() {
|
||||
return unlocked;
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,15 @@ import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectMap;
|
||||
import com.badlogic.gdx.utils.ObjectMap.Entry;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.game.EventType.UnlockEvent;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
/**Stores player unlocks. Clientside only.*/
|
||||
public class Unlocks{
|
||||
private ObjectMap<String, ContentUnlockSet> sets = new ObjectMap<>();
|
||||
private ObjectMap<ContentType, ObjectSet<String>> unlocked = new ObjectMap<>();
|
||||
private boolean dirty;
|
||||
|
||||
static{
|
||||
Settings.setSerializer(ContentType.class, (stream, t) -> stream.writeInt(t.ordinal()), stream -> ContentType.values()[stream.readInt()]);
|
||||
@@ -21,7 +20,15 @@ public class Unlocks{
|
||||
|
||||
/** Returns whether or not this piece of content is unlocked yet.*/
|
||||
public boolean isUnlocked(UnlockableContent content){
|
||||
return rootSet().isUnlocked(content) || currentSet().isUnlocked(content);
|
||||
if(content.alwaysUnlocked()) return true;
|
||||
|
||||
if(!unlocked.containsKey(content.getContentType())){
|
||||
unlocked.put(content.getContentType(), new ObjectSet<>());
|
||||
}
|
||||
|
||||
ObjectSet<String> set = unlocked.get(content.getContentType());
|
||||
|
||||
return set.contains(content.getContentName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -32,77 +39,59 @@ public class Unlocks{
|
||||
* @return whether or not this content was newly unlocked.
|
||||
*/
|
||||
public boolean unlockContent(UnlockableContent content){
|
||||
return !rootSet().isUnlocked(content) && currentSet().unlockContent(content);
|
||||
}
|
||||
if(!content.canBeUnlocked() || content.alwaysUnlocked()) return false;
|
||||
|
||||
private ContentUnlockSet currentSet(){
|
||||
//client connected to server: always return the IP-specific set
|
||||
if(Net.client()){
|
||||
return getSet(Net.getLastIP());
|
||||
}else if((world.getSector() != null || state.mode.infiniteResources) || state.is(State.menu)){ //sector-sandbox have shared set
|
||||
return rootSet();
|
||||
}else{ //per-mode set
|
||||
return getSet(state.mode.name());
|
||||
if(!unlocked.containsKey(content.getContentType())){
|
||||
unlocked.put(content.getContentType(), new ObjectSet<>());
|
||||
}
|
||||
}
|
||||
|
||||
private ContentUnlockSet rootSet(){
|
||||
return getSet("root");
|
||||
}
|
||||
boolean ret = unlocked.get(content.getContentType()).add(content.getContentName());
|
||||
|
||||
private ContentUnlockSet getSet(String name){
|
||||
if(!sets.containsKey(name)){
|
||||
sets.put(name, new ContentUnlockSet());
|
||||
//fire unlock event so other classes can use it
|
||||
if(ret){
|
||||
content.onUnlock();
|
||||
Events.fire(new UnlockEvent(content));
|
||||
dirty = true;
|
||||
}
|
||||
return sets.get(name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Returns whether unlockables have changed since the last save.*/
|
||||
public boolean isDirty(){
|
||||
for(ContentUnlockSet set : sets.values()){
|
||||
if(set.isDirty()){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return dirty;
|
||||
}
|
||||
|
||||
/** Clears all unlocked content. Automatically saves.*/
|
||||
public void reset(){
|
||||
sets.clear();
|
||||
save();
|
||||
}
|
||||
|
||||
public void load(){
|
||||
sets.clear();
|
||||
|
||||
ObjectMap<String, ObjectMap<ContentType, Array<String>>> result = Settings.getObject("content-sets", ObjectMap.class, ObjectMap::new);
|
||||
|
||||
for(Entry<String, ObjectMap<ContentType, Array<String>>> outer : result.entries()){
|
||||
ContentUnlockSet cset = new ContentUnlockSet();
|
||||
for (Entry<ContentType, Array<String>> entry : outer.value.entries()){
|
||||
ObjectSet<String> set = new ObjectSet<>();
|
||||
set.addAll(entry.value);
|
||||
cset.getUnlocked().put(entry.key, set);
|
||||
/**Loads 'legacy' unlocks. Will be removed in final release.*/
|
||||
public void tryLoadLegacy(){
|
||||
try{
|
||||
ObjectMap<String, ObjectMap<ContentType, Array<String>>> sets = Settings.getObject("content-sets", ObjectMap.class, ObjectMap::new);
|
||||
for(Entry<ContentType, Array<String>> entry : sets.get("root").entries()){
|
||||
unlocked.put(entry.key, new ObjectSet<>());
|
||||
unlocked.get(entry.key).addAll(entry.value);
|
||||
}
|
||||
sets.put(outer.key, cset);
|
||||
}catch(Throwable t){
|
||||
t.printStackTrace();
|
||||
}
|
||||
Settings.prefs().remove("content-sets");
|
||||
Settings.save();
|
||||
}
|
||||
|
||||
public void load(){
|
||||
unlocked = Settings.getObject("unlockset", ObjectMap.class, ObjectMap::new);
|
||||
|
||||
if(Settings.has("content-sets")){
|
||||
tryLoadLegacy();
|
||||
}
|
||||
}
|
||||
|
||||
public void save(){
|
||||
ObjectMap<String, ObjectMap<ContentType, Array<String>>> output = new ObjectMap<>();
|
||||
|
||||
for(Entry<String, ContentUnlockSet> centry : sets.entries()){
|
||||
ObjectMap<ContentType, Array<String>> write = new ObjectMap<>();
|
||||
|
||||
for(Entry<ContentType, ObjectSet<String>> entry : centry.value.getUnlocked().entries()){
|
||||
write.put(entry.key, entry.value.iterator().toArray());
|
||||
}
|
||||
|
||||
output.put(centry.key, write);
|
||||
}
|
||||
|
||||
Settings.putObject("content-sets", output);
|
||||
Settings.putObject("unlockset", unlocked);
|
||||
Settings.save();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,10 @@ import java.io.IOException;
|
||||
public class Version{
|
||||
/**Build type. 'official' for official releases; 'custom' or 'bleeding edge' are also used.*/
|
||||
public static String type;
|
||||
/**Number specifying the major version, e.g. '4.0'*/
|
||||
public static String number;
|
||||
/**Build modifier, e.g. 'alpha' or 'release'*/
|
||||
public static String modifier;
|
||||
/**Number specifying the major version, e.g. '4'*/
|
||||
public static int number;
|
||||
/**Build number, e.g. '43'. set to '-1' for custom builds.*/
|
||||
public static int build = 0;
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Version{
|
||||
PropertiesUtils.load(map, file.reader());
|
||||
|
||||
type = map.get("type");
|
||||
number = map.get("number");
|
||||
number = Integer.parseInt(map.get("number"));
|
||||
modifier = map.get("modifier");
|
||||
build = Strings.canParseInt(map.get("build")) ? Integer.parseInt(map.get("build")) : -1;
|
||||
}catch(IOException e){
|
||||
|
||||
@@ -21,7 +21,7 @@ import static io.anuke.ucore.core.Core.camera;
|
||||
|
||||
public class BlockRenderer{
|
||||
private final static int initialRequests = 32 * 32;
|
||||
private final static int expandr = 4;
|
||||
private final static int expandr = 6;
|
||||
|
||||
private FloorRenderer floorRenderer;
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public enum CacheLayer{
|
||||
|
||||
protected void beginShader(){
|
||||
//renderer.getBlocks().endFloor();
|
||||
renderer.effectSurface.getBuffer().bind();
|
||||
renderer.effectSurface.getBuffer().begin();
|
||||
Graphics.clear(Color.CLEAR);
|
||||
//renderer.getBlocks().beginFloor();
|
||||
}
|
||||
@@ -73,7 +73,9 @@ public enum CacheLayer{
|
||||
public void endShader(Shader shader){
|
||||
renderer.blocks.endFloor();
|
||||
|
||||
renderer.pixelSurface.getBuffer().bind();
|
||||
//renderer.effectSurface.getBuffer().end();
|
||||
|
||||
renderer.pixelSurface.getBuffer().begin();
|
||||
|
||||
Graphics.shader(shader);
|
||||
Graphics.begin();
|
||||
|
||||
@@ -29,6 +29,7 @@ public class Palette{
|
||||
|
||||
lightishGray = Color.valueOf("a2a2a2"),
|
||||
darkishGray = new Color(0.3f, 0.3f, 0.3f, 1f),
|
||||
darkerGray = new Color(0.2f, 0.2f, 0.2f, 1f),
|
||||
|
||||
boostTo = Color.valueOf("ffad4d"),
|
||||
boostFrom = Color.valueOf("ff7f57"),
|
||||
|
||||
@@ -157,17 +157,14 @@ public class Shaders{
|
||||
|
||||
@Override
|
||||
public void apply(){
|
||||
// shader.setUniformf("u_progress", progress);
|
||||
shader.setUniformf("u_color", color);
|
||||
shader.setUniformf("u_uv", region.getU(), region.getV());
|
||||
shader.setUniformf("u_uv2", region.getU2(), region.getV2());
|
||||
//shader.setUniformf("u_time", Timers.time());
|
||||
shader.setUniformf("u_texsize", region.getTexture().getWidth(), region.getTexture().getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
public static class Shield extends Shader{
|
||||
//public Color color = new Color();
|
||||
|
||||
public Shield(){
|
||||
super("shield", "default");
|
||||
@@ -175,17 +172,13 @@ public class Shaders{
|
||||
|
||||
@Override
|
||||
public void apply(){
|
||||
float scaling = Core.cameraScale / 4f / Core.camera.zoom;
|
||||
|
||||
shader.setUniformf("u_dp", Unit.dp.scl(1f));
|
||||
//shader.setUniformf("u_color", color);
|
||||
shader.setUniformf("u_time", Timers.time() / Unit.dp.scl(1f));
|
||||
shader.setUniformf("u_scaling", scaling);
|
||||
shader.setUniformf("u_offset",
|
||||
Core.camera.position.x - Core.camera.viewportWidth / 2 * Core.camera.zoom,
|
||||
Core.camera.position.y - Core.camera.viewportHeight / 2 * Core.camera.zoom);
|
||||
shader.setUniformf("u_texsize", Gdx.graphics.getWidth() / Core.cameraScale * Core.camera.zoom,
|
||||
Gdx.graphics.getHeight() / Core.cameraScale * Core.camera.zoom);
|
||||
shader.setUniformf("u_texsize", Core.camera.viewportWidth * Core.camera.zoom,
|
||||
Core.camera.viewportHeight * Core.camera.zoom);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,8 +193,8 @@ public class Shaders{
|
||||
shader.setUniformf("camerapos",
|
||||
Core.camera.position.x - Core.camera.viewportWidth / 2 * Core.camera.zoom,
|
||||
Core.camera.position.y - Core.camera.viewportHeight / 2 * Core.camera.zoom);
|
||||
shader.setUniformf("screensize", Gdx.graphics.getWidth() / Core.cameraScale * Core.camera.zoom,
|
||||
Gdx.graphics.getHeight() / Core.cameraScale * Core.camera.zoom);
|
||||
shader.setUniformf("screensize", Core.camera.viewportWidth* Core.camera.zoom,
|
||||
Core.camera.viewportHeight * Core.camera.zoom);
|
||||
shader.setUniformf("time", Timers.time());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public class DefaultKeybinds{
|
||||
"menu", Gdx.app.getType() == ApplicationType.Android ? Input.BACK : Input.ESCAPE,
|
||||
"pause", Input.SPACE,
|
||||
"toggle_menus", Input.C,
|
||||
"screenshot", Input.P,
|
||||
new Category("multiplayer"),
|
||||
"player_list", Input.TAB,
|
||||
"chat", Input.ENTER,
|
||||
|
||||
@@ -25,7 +25,7 @@ import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Angles;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
@@ -145,7 +145,7 @@ public abstract class InputHandler extends InputAdapter{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void buildUI(Group group){
|
||||
public void buildUI(Table table){
|
||||
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public abstract class InputHandler extends InputAdapter{
|
||||
}
|
||||
|
||||
//call tapped event
|
||||
if(tile.getTeam() == player.getTeam()){
|
||||
if(!consumed && tile.getTeam() == player.getTeam()){
|
||||
Call.onTileTapped(player, tile);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,7 @@ import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.graphics.Lines;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.event.Touchable;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@@ -208,78 +207,53 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
//region UI and drawing
|
||||
|
||||
@Override
|
||||
public void buildUI(Group group){
|
||||
public void buildUI(Table table){
|
||||
table.addImage("blank").color(Palette.accent).height(3f).colspan(4).growX();
|
||||
table.row();
|
||||
table.left().margin(0f).defaults().size(48f);
|
||||
|
||||
//Create confirm/cancel table
|
||||
group.fill(c -> {
|
||||
c.bottom().left().visible(() -> !state.is(State.menu));
|
||||
table.addImageButton("icon-break", "clear-toggle-partial", 16 * 2f, () -> {
|
||||
mode = mode == breaking ? recipe == null ? none : placing : breaking;
|
||||
lastRecipe = recipe;
|
||||
if(mode == breaking){
|
||||
showGuide("deconstruction");
|
||||
}
|
||||
}).update(l -> l.setChecked(mode == breaking));
|
||||
|
||||
c.table("pane", act -> {
|
||||
act.margin(5);
|
||||
act.defaults().size(60f);
|
||||
//rotate button
|
||||
table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4))
|
||||
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center))
|
||||
.visible(() -> recipe != null && recipe.result.rotate);
|
||||
|
||||
//Add a cancel button
|
||||
act.addImageButton("icon-cancel", 16*2f, () -> {
|
||||
mode = none;
|
||||
recipe = null;
|
||||
});
|
||||
//cancel button
|
||||
table.addImageButton("icon-cancel", "clear-partial", 16 * 2f, () -> {
|
||||
player.clearBuilding();
|
||||
mode = none;
|
||||
recipe = null;
|
||||
}).visible(() -> player.isBuilding() || recipe != null || mode == breaking);
|
||||
|
||||
act.row();
|
||||
//confirm button
|
||||
table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> {
|
||||
for(PlaceRequest request : selection){
|
||||
Tile tile = request.tile();
|
||||
|
||||
//Add an accept button, which places everything.
|
||||
act.addImageButton("icon-check", 16 * 2f, () -> {
|
||||
for(PlaceRequest request : selection){
|
||||
Tile tile = request.tile();
|
||||
|
||||
//actually place/break all selected blocks
|
||||
if(tile != null){
|
||||
if(!request.remove){
|
||||
rotation = request.rotation;
|
||||
recipe = request.recipe;
|
||||
tryPlaceBlock(tile.x, tile.y);
|
||||
}else{
|
||||
tryBreakBlock(tile.x, tile.y);
|
||||
}
|
||||
}
|
||||
//actually place/break all selected blocks
|
||||
if(tile != null){
|
||||
if(!request.remove){
|
||||
rotation = request.rotation;
|
||||
recipe = request.recipe;
|
||||
tryPlaceBlock(tile.x, tile.y);
|
||||
}else{
|
||||
tryBreakBlock(tile.x, tile.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//move all current requests to removal array so they fade out
|
||||
removals.addAll(selection);
|
||||
selection.clear();
|
||||
selecting = false;
|
||||
}).disabled(i -> selection.size == 0);
|
||||
|
||||
act.row();
|
||||
|
||||
//Add a rotate button
|
||||
act.addImageButton("icon-arrow", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4))
|
||||
.update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center))
|
||||
.disabled(i -> recipe == null || !recipe.result.rotate);
|
||||
}).visible(() -> mode != none).touchable(Touchable.enabled);
|
||||
|
||||
c.row();
|
||||
|
||||
c.table("pane", remove -> {
|
||||
remove.defaults().size(60f);
|
||||
|
||||
//Add a break button.
|
||||
remove.addImageButton("icon-break", "toggle", 16 * 2f, () -> {
|
||||
mode = mode == breaking ? recipe == null ? none : placing : breaking;
|
||||
lastRecipe = recipe;
|
||||
if(mode == breaking){
|
||||
showGuide("deconstruction");
|
||||
}
|
||||
}).update(l -> l.setChecked(mode == breaking));
|
||||
}).margin(5).touchable(Touchable.enabled);
|
||||
|
||||
c.table("pane", cancel -> {
|
||||
cancel.defaults().size(60f);
|
||||
|
||||
//Add a 'cancel building' button.
|
||||
cancel.addImageButton("icon-cancel", 16 * 2f, player::clearBuilding);
|
||||
|
||||
}).left().colspan(2).margin(5).touchable(Touchable.enabled).visible(() -> player.getPlaceQueue().size > 0);
|
||||
});
|
||||
//move all current requests to removal array so they fade out
|
||||
removals.addAll(selection);
|
||||
selection.clear();
|
||||
selecting = false;
|
||||
}).visible(() -> !selection.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -554,7 +528,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
//ignore off-screen taps
|
||||
if(cursor == null || ui.hasMouse(x, y)) return false;
|
||||
|
||||
threads.run(() -> checkTargets(worldx, worldy));
|
||||
checkTargets(worldx, worldy);
|
||||
|
||||
//remove if request present
|
||||
if(hasRequest(cursor)){
|
||||
@@ -574,14 +548,13 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
consumed = true;
|
||||
player.dropCarry(); //drop off unit
|
||||
}else{
|
||||
threads.run(() -> {
|
||||
Unit unit = Units.getClosest(player.getTeam(), Graphics.world(x, y).x, Graphics.world(x, y).y, 4f, u -> !u.isFlying() && u.getMass() <= player.mech.carryWeight);
|
||||
Unit unit = Units.getClosest(player.getTeam(), Graphics.world(x, y).x, Graphics.world(x, y).y, 4f, u -> !u.isFlying() && u.getMass() <= player.mech.carryWeight);
|
||||
|
||||
if(unit != null){
|
||||
player.moveTarget = unit;
|
||||
Effects.effect(Fx.select, unit.getX(), unit.getY());
|
||||
}
|
||||
});
|
||||
if(unit != null){
|
||||
consumed = true;
|
||||
player.moveTarget = unit;
|
||||
Effects.effect(Fx.select, unit.getX(), unit.getY());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
core/src/io/anuke/mindustry/io/Contributors.java
Normal file
43
core/src/io/anuke/mindustry/io/Contributors.java
Normal file
@@ -0,0 +1,43 @@
|
||||
package io.anuke.mindustry.io;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.JsonReader;
|
||||
import com.badlogic.gdx.utils.JsonValue;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
|
||||
import static io.anuke.mindustry.Vars.contributorsURL;
|
||||
|
||||
public class Contributors{
|
||||
|
||||
public static void getContributors(Consumer<Array<Contributor>> success, Consumer<Throwable> fail){
|
||||
Net.http(contributorsURL, "GET", result -> {
|
||||
JsonReader reader = new JsonReader();
|
||||
JsonValue value = reader.parse(result).child;
|
||||
Array<Contributor> out = new Array<>();
|
||||
|
||||
while(value != null){
|
||||
String login = value.getString("login");
|
||||
out.add(new Contributor(login));
|
||||
value = value.next;
|
||||
}
|
||||
|
||||
success.accept(out);
|
||||
}, fail);
|
||||
}
|
||||
|
||||
public static class Contributor{
|
||||
public final String login;
|
||||
|
||||
public Contributor(String login){
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Contributor{" +
|
||||
"login='" + login + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,6 @@ import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@@ -332,31 +331,21 @@ public class TypeIO{
|
||||
@WriteClass(String.class)
|
||||
public static void writeString(ByteBuffer buffer, String string){
|
||||
if(string != null){
|
||||
Charset charset = Charset.defaultCharset();
|
||||
byte[] nameBytes = charset.name().getBytes(StandardCharsets.UTF_8);
|
||||
buffer.put((byte)nameBytes.length);
|
||||
buffer.put(nameBytes);
|
||||
|
||||
byte[] bytes = string.getBytes(charset);
|
||||
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
|
||||
buffer.putShort((short) bytes.length);
|
||||
buffer.put(bytes);
|
||||
}else{
|
||||
buffer.put((byte) -1);
|
||||
buffer.putShort((short) -1);
|
||||
}
|
||||
}
|
||||
|
||||
@ReadClass(String.class)
|
||||
public static String readString(ByteBuffer buffer){
|
||||
byte length = buffer.get();
|
||||
if(length != -1){
|
||||
byte[] cbytes = new byte[length];
|
||||
buffer.get(cbytes);
|
||||
Charset charset = Charset.forName(new String(cbytes, StandardCharsets.UTF_8));
|
||||
|
||||
short slength = buffer.getShort();
|
||||
short slength = buffer.getShort();
|
||||
if(slength != -1){
|
||||
byte[] bytes = new byte[slength];
|
||||
buffer.get(bytes);
|
||||
return new String(bytes, charset);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
@@ -378,30 +367,20 @@ public class TypeIO{
|
||||
|
||||
public static void writeStringData(DataOutput buffer, String string) throws IOException{
|
||||
if(string != null){
|
||||
Charset charset = Charset.defaultCharset();
|
||||
byte[] nameBytes = charset.name().getBytes(StandardCharsets.UTF_8);
|
||||
buffer.writeByte((byte)nameBytes.length);
|
||||
buffer.write(nameBytes);
|
||||
|
||||
byte[] bytes = string.getBytes(charset);
|
||||
byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
|
||||
buffer.writeShort((short) bytes.length);
|
||||
buffer.write(bytes);
|
||||
}else{
|
||||
buffer.writeByte((byte) -1);
|
||||
buffer.writeShort((short) -1);
|
||||
}
|
||||
}
|
||||
|
||||
public static String readStringData(DataInput buffer) throws IOException{
|
||||
byte length = buffer.readByte();
|
||||
if(length != -1){
|
||||
byte[] cbytes = new byte[length];
|
||||
buffer.readFully(cbytes);
|
||||
Charset charset = Charset.forName(new String(cbytes, StandardCharsets.UTF_8));
|
||||
|
||||
short slength = buffer.readShort();
|
||||
short slength = buffer.readShort();
|
||||
if(slength != -1){
|
||||
byte[] bytes = new byte[slength];
|
||||
buffer.readFully(bytes);
|
||||
return new String(bytes, charset);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class Save16 extends SaveFileVersion{
|
||||
|
||||
content.setTemporaryMapper(readContentHeader(stream));
|
||||
|
||||
state.spawner.read(stream);
|
||||
world.spawner.read(stream);
|
||||
|
||||
readEntities(stream);
|
||||
|
||||
@@ -71,7 +71,7 @@ public class Save16 extends SaveFileVersion{
|
||||
|
||||
writeContentHeader(stream);
|
||||
|
||||
state.spawner.write(stream); //spawnes
|
||||
world.spawner.write(stream); //spawnes
|
||||
|
||||
//--ENTITIES--
|
||||
|
||||
|
||||
@@ -32,4 +32,13 @@ public class Map{
|
||||
public String getDisplayName(){
|
||||
return meta.tags.get("name", name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Map{" +
|
||||
"name='" + name + '\'' +
|
||||
", custom=" + custom +
|
||||
", meta=" + meta +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +37,13 @@ public class MapMeta{
|
||||
public boolean hasOreGen(){
|
||||
return !tags.get("oregen", "0").equals("0");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "MapMeta{" +
|
||||
"tags=" + tags +
|
||||
", width=" + width +
|
||||
", height=" + height +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ public class TutorialSector{
|
||||
new ItemMission(Items.copper, 100).setMessage("$tutorial.morecopper"),
|
||||
|
||||
new BlockMission(TurretBlocks.duo).setMessage("$tutorial.turret"),
|
||||
//TODO fill turret with items mission
|
||||
/
|
||||
//new BlockMission(ProductionBlocks.mechanicalDrill).setMessage("$tutorial.drillturret"),
|
||||
|
||||
// Create a wave mission which spawns the core at 60, 60 rather than in the center of the map
|
||||
|
||||
@@ -30,7 +30,6 @@ public class Generation{
|
||||
return tiles[x][y];
|
||||
}
|
||||
|
||||
//TODO implement
|
||||
Item drillItem(int x, int y, Drill block){
|
||||
if(block.isMultiblock()){
|
||||
Item result = null;
|
||||
|
||||
@@ -172,6 +172,25 @@ public class WorldGenerator{
|
||||
|
||||
prepareTiles(tiles);
|
||||
|
||||
for(int x = 0; x < width; x++){
|
||||
for(int y = 0; y < height; y++){
|
||||
Tile tile = tiles[x][y];
|
||||
|
||||
byte elevation = tile.getElevation();
|
||||
|
||||
for(GridPoint2 point : Geometry.d4){
|
||||
if(!Structs.inBounds(x + point.x, y + point.y, width, height)) continue;
|
||||
if(tiles[x + point.x][y + point.y].getElevation() < elevation){
|
||||
|
||||
if(sim2.octaveNoise2D(1, 1, 1.0 / 8, x, y) > 0.8){
|
||||
tile.setElevation(-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
world.setBlock(tiles[spawns.get(0).x][spawns.get(0).y], StorageBlocks.core, Team.blue);
|
||||
|
||||
if(state.mode.isPvp){
|
||||
|
||||
@@ -66,7 +66,7 @@ public class Net{
|
||||
}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");
|
||||
error = Bundles.get("text.error.timedout");
|
||||
}else if(error.equals("alreadyconnected")){
|
||||
error = Bundles.get("text.error.alreadyconnected");
|
||||
}else if(!error.isEmpty()){
|
||||
@@ -356,12 +356,13 @@ public class Net{
|
||||
Gdx.net.sendHttpRequest(req, new HttpResponseListener(){
|
||||
@Override
|
||||
public void handleHttpResponse(HttpResponse httpResponse){
|
||||
listener.accept(httpResponse.getResultAsString());
|
||||
String result = httpResponse.getResultAsString();
|
||||
Gdx.app.postRunnable(() -> listener.accept(result));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable t){
|
||||
failure.accept(t);
|
||||
Gdx.app.postRunnable(() -> failure.accept(t));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -2,7 +2,7 @@ package io.anuke.mindustry.net;
|
||||
|
||||
import com.badlogic.gdx.utils.Base64Coder;
|
||||
import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.ucore.io.IOUtils;
|
||||
import io.anuke.mindustry.io.TypeIO;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -65,6 +65,7 @@ public class Packets{
|
||||
|
||||
public static class ConnectPacket implements Packet{
|
||||
public int version;
|
||||
public String versionType;
|
||||
public String name, uuid, usid;
|
||||
public boolean mobile;
|
||||
public int color;
|
||||
@@ -72,8 +73,9 @@ public class Packets{
|
||||
@Override
|
||||
public void write(ByteBuffer buffer){
|
||||
buffer.putInt(Version.build);
|
||||
IOUtils.writeString(buffer, name);
|
||||
IOUtils.writeString(buffer, usid);
|
||||
TypeIO.writeString(buffer, versionType);
|
||||
TypeIO.writeString(buffer, name);
|
||||
TypeIO.writeString(buffer, usid);
|
||||
buffer.put(mobile ? (byte) 1 : 0);
|
||||
buffer.putInt(color);
|
||||
buffer.put(Base64Coder.decode(uuid));
|
||||
@@ -82,8 +84,9 @@ public class Packets{
|
||||
@Override
|
||||
public void read(ByteBuffer buffer){
|
||||
version = buffer.getInt();
|
||||
name = IOUtils.readString(buffer);
|
||||
usid = IOUtils.readString(buffer);
|
||||
versionType = TypeIO.readString(buffer);
|
||||
name = TypeIO.readString(buffer);
|
||||
usid = TypeIO.readString(buffer);
|
||||
mobile = buffer.get() == 1;
|
||||
color = buffer.getInt();
|
||||
byte[] idbytes = new byte[8];
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package io.anuke.mindustry.type;
|
||||
|
||||
/**
|
||||
* Used to store ammo amounts in units and turrets.
|
||||
*/
|
||||
/**Used to store ammo amounts in turrets.*/
|
||||
public class AmmoEntry{
|
||||
public AmmoType type;
|
||||
public int amount;
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
package io.anuke.mindustry.type;
|
||||
|
||||
public enum Category{
|
||||
weapon, production, distribution, liquid, power, defense, crafting, units
|
||||
/**Offensive turrets.*/
|
||||
turret,
|
||||
/**Blocks that produce raw resources, such as drills.*/
|
||||
production,
|
||||
/**Blocks that move items around.*/
|
||||
distribution,
|
||||
/**Blocks that move liquids around.*/
|
||||
liquid,
|
||||
/**Blocks that generate or transport power.*/
|
||||
power,
|
||||
/**Walls and other defensive structures.*/
|
||||
defense,
|
||||
/**Blocks that craft things.*/
|
||||
crafting,
|
||||
/**Blocks that create units.*/
|
||||
units,
|
||||
/**Things that upgrade the player such as mech pads.*/
|
||||
upgrade,
|
||||
/**Things for storage or passive effects.*/
|
||||
effect
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
//TODO merge unit type with mech
|
||||
public class Mech extends UnlockableContent{
|
||||
public final String name;
|
||||
public final String description;
|
||||
|
||||
@@ -23,6 +23,7 @@ import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class Recipe extends UnlockableContent{
|
||||
private static ObjectMap<Block, Recipe> recipeMap = new ObjectMap<>();
|
||||
private static Array<Recipe> returnArray = new Array<>();
|
||||
|
||||
public final Block result;
|
||||
public final ItemStack[] requirements;
|
||||
@@ -55,34 +56,15 @@ public class Recipe extends UnlockableContent{
|
||||
recipeMap.put(result, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unlocked recipes in a category.
|
||||
* Do not call on the server backend, as unlocking does not exist!
|
||||
*/
|
||||
public static void getUnlockedByCategory(Category category, Array<Recipe> arr){
|
||||
if(headless){
|
||||
throw new RuntimeException("Not implemented on the headless backend!");
|
||||
}
|
||||
|
||||
arr.clear();
|
||||
for(Recipe r : content.recipes()){
|
||||
if(r.category == category && (control.unlocks.isUnlocked(r)) &&
|
||||
!((r.mode != null && r.mode != state.mode) || !r.visibility.shown())){
|
||||
arr.add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all recipes in a category.
|
||||
*/
|
||||
public static void getByCategory(Category category, Array<Recipe> r){
|
||||
r.clear();
|
||||
/**Returns all non-hidden recipes in a category.*/
|
||||
public static Array<Recipe> getByCategory(Category category){
|
||||
returnArray.clear();
|
||||
for(Recipe recipe : content.recipes()){
|
||||
if(recipe.category == category){
|
||||
r.add(recipe);
|
||||
if(recipe.category == category && recipe.visibility.shown() && (recipe.mode == state.mode || recipe.mode == null)){
|
||||
returnArray.add(recipe);
|
||||
}
|
||||
}
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public static Recipe getByResult(Block block){
|
||||
@@ -109,7 +91,6 @@ public class Recipe extends UnlockableContent{
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean alwaysUnlocked(){
|
||||
return alwaysUnlocked;
|
||||
|
||||
14
core/src/io/anuke/mindustry/ui/ImageStack.java
Normal file
14
core/src/io/anuke/mindustry/ui/ImageStack.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Stack;
|
||||
|
||||
public class ImageStack extends Stack{
|
||||
|
||||
public ImageStack(TextureRegion... regions){
|
||||
for(TextureRegion region : regions){
|
||||
add(new Image(region));
|
||||
}
|
||||
}
|
||||
}
|
||||
18
core/src/io/anuke/mindustry/ui/ItemDisplay.java
Normal file
18
core/src/io/anuke/mindustry/ui/ItemDisplay.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
/**An item image with text.*/
|
||||
public class ItemDisplay extends Table{
|
||||
|
||||
public ItemDisplay(Item item){
|
||||
this(item, 0);
|
||||
}
|
||||
|
||||
public ItemDisplay(Item item, int amount){
|
||||
add(new ItemImage(new ItemStack(item, amount))).size(8*3);
|
||||
add(item.localizedName()).padLeft(4);
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,12 @@ public class ItemImage extends Stack{
|
||||
}
|
||||
|
||||
public ItemImage(ItemStack stack){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(stack.amount + "");
|
||||
|
||||
add(new Image(stack.item.region));
|
||||
add(t);
|
||||
|
||||
if(stack.amount != 0){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(stack.amount + "");
|
||||
add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
core/src/io/anuke/mindustry/ui/LiquidDisplay.java
Normal file
14
core/src/io/anuke/mindustry/ui/LiquidDisplay.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
/**An ItemDisplay, but for liquids.*/
|
||||
public class LiquidDisplay extends Table{
|
||||
|
||||
public LiquidDisplay(Liquid liquid){
|
||||
add(new Image(liquid.getContentIcon())).size(8*3);
|
||||
add(liquid.localizedName()).padLeft(3);
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
package io.anuke.mindustry.ui;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.style.TextureRegionDrawable;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.world;
|
||||
|
||||
public class SelectionTable extends Table{
|
||||
Tile lastTile;
|
||||
|
||||
public SelectionTable(){
|
||||
super("clear");
|
||||
|
||||
margin(5f);
|
||||
|
||||
update(() -> {
|
||||
Block result;
|
||||
Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y);
|
||||
if(tile != null){
|
||||
tile = tile.target();
|
||||
result = tile.block().synthetic() ? tile.block() : tile.floor() instanceof OreBlock ? tile.floor() : null;
|
||||
}else{
|
||||
result = null;
|
||||
}
|
||||
|
||||
if(result != null){
|
||||
lastTile = tile;
|
||||
}
|
||||
|
||||
getTranslation().y = Mathf.lerp(getTranslation().y, result == null ? -getHeight() : 0f, 0.2f);
|
||||
});
|
||||
|
||||
Image image = new Image(new TextureRegionDrawable(new TextureRegion(Draw.region("clear"))));
|
||||
image.update(() ->
|
||||
((TextureRegionDrawable)image.getDrawable()).setRegion(lastTile == null ? Draw.getBlankRegion() :
|
||||
(lastTile.block().synthetic() ? lastTile.block() : lastTile.floor()).getDisplayIcon(lastTile)));
|
||||
|
||||
add(image).size(8*5).padRight(4);
|
||||
label(() -> lastTile == null ? "" : (lastTile.block().synthetic() ? lastTile.block() : lastTile.floor()).getDisplayName(lastTile));
|
||||
|
||||
pack();
|
||||
getTranslation().y = - getHeight();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,11 @@ package io.anuke.mindustry.ui.dialogs;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.io.Contributors;
|
||||
import io.anuke.mindustry.io.Contributors.Contributor;
|
||||
import io.anuke.mindustry.ui.Links;
|
||||
import io.anuke.mindustry.ui.Links.LinkEntry;
|
||||
import io.anuke.ucore.core.Core;
|
||||
@@ -18,11 +22,14 @@ import static io.anuke.mindustry.Vars.ios;
|
||||
import static io.anuke.mindustry.Vars.ui;
|
||||
|
||||
public class AboutDialog extends FloatingDialog{
|
||||
private Array<Contributor> contributors = new Array<>();
|
||||
private static ObjectSet<String> bannedItems = ObjectSet.with("google-play", "itch.io", "dev-builds", "trello");
|
||||
|
||||
public AboutDialog(){
|
||||
super("$text.about.button");
|
||||
|
||||
Contributors.getContributors(out -> contributors = out, Throwable::printStackTrace);
|
||||
|
||||
shown(this::setup);
|
||||
onResize(this::setup);
|
||||
}
|
||||
@@ -94,7 +101,24 @@ public class AboutDialog extends FloatingDialog{
|
||||
public void showCredits(){
|
||||
FloatingDialog dialog = new FloatingDialog("$text.credits");
|
||||
dialog.addCloseButton();
|
||||
dialog.content().labelWrap("$text.credits.text").width(400f);
|
||||
dialog.content().add("$text.credits.text");
|
||||
dialog.content().row();
|
||||
if(!contributors.isEmpty()){
|
||||
dialog.content().addImage("blank").color(Palette.accent).fillX().height(3f).pad(3f);
|
||||
dialog.content().row();
|
||||
dialog.content().add("$text.contributors");
|
||||
dialog.content().row();
|
||||
dialog.content().pane("clear", new Table(){{
|
||||
int i = 0;
|
||||
left();
|
||||
for(Contributor c : contributors){
|
||||
add("[lightgray]" + c.login).left().pad(3).padLeft(6).padRight(6);
|
||||
if(++i % 3 == 0){
|
||||
row();
|
||||
}
|
||||
}
|
||||
}});
|
||||
}
|
||||
dialog.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ public class HostDialog extends FloatingDialog{
|
||||
content().table(t -> {
|
||||
t.add("$text.name").padRight(10);
|
||||
t.addField(Settings.getString("name"), text -> {
|
||||
if(text.isEmpty()) return;
|
||||
player.name = text;
|
||||
Settings.put("name", text);
|
||||
Settings.save();
|
||||
@@ -50,6 +49,11 @@ public class HostDialog extends FloatingDialog{
|
||||
content().add().width(65f);
|
||||
|
||||
content().addButton("$text.host", () -> {
|
||||
if(Settings.getString("name").trim().isEmpty()){
|
||||
ui.showInfo("$text.noname");
|
||||
return;
|
||||
}
|
||||
|
||||
ui.loadfrag.show("$text.hosting");
|
||||
Timers.runTask(5f, () -> {
|
||||
try{
|
||||
|
||||
@@ -205,7 +205,6 @@ public class JoinDialog extends FloatingDialog{
|
||||
content().table(t -> {
|
||||
t.add("$text.name").padRight(10);
|
||||
t.addField(Settings.getString("name"), text -> {
|
||||
if(text.isEmpty()) return;
|
||||
player.name = text;
|
||||
Settings.put("name", text);
|
||||
Settings.save();
|
||||
@@ -285,6 +284,11 @@ public class JoinDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
void connect(String ip, int port){
|
||||
if(Settings.getString("name").trim().isEmpty()){
|
||||
ui.showInfo("$text.noname");
|
||||
return;
|
||||
}
|
||||
|
||||
ui.loadfrag.show("$text.connecting");
|
||||
|
||||
ui.loadfrag.setButton(() -> {
|
||||
|
||||
@@ -6,10 +6,10 @@ import io.anuke.mindustry.game.Content;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.type.ContentType;
|
||||
import io.anuke.mindustry.world.meta.StatValue;
|
||||
import io.anuke.ucore.scene.event.HandCursorListener;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.ScrollPane;
|
||||
import io.anuke.ucore.scene.ui.Tooltip;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.scene.utils.UIUtils;
|
||||
|
||||
@@ -65,7 +65,10 @@ public class UnlocksDialog extends FloatingDialog{
|
||||
|
||||
if(control.unlocks.isUnlocked(unlock)){
|
||||
image.clicked(() -> Vars.ui.content.show(unlock));
|
||||
StatValue.addToolTip(image, unlock);
|
||||
image.addListener(new Tooltip<>(new Table("clear"){{
|
||||
add(unlock.localizedName());
|
||||
margin(4);
|
||||
}}));
|
||||
}
|
||||
|
||||
if((++count) % maxWidth == 0){
|
||||
|
||||
@@ -180,7 +180,9 @@ public class BlockInventoryFragment extends Fragment{
|
||||
|
||||
private String round(float f){
|
||||
f = (int) f;
|
||||
if(f >= 1000){
|
||||
if(f >= 1000000){
|
||||
return Strings.toFixed(f / 1000000f, 1) + "[gray]mil[]";
|
||||
}else if(f >= 1000){
|
||||
return Strings.toFixed(f / 1000, 1) + "k";
|
||||
}else{
|
||||
return (int) f + "";
|
||||
|
||||
@@ -1,349 +0,0 @@
|
||||
package io.anuke.mindustry.ui.fragments;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||
import io.anuke.mindustry.input.InputHandler;
|
||||
import io.anuke.mindustry.type.Category;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.actions.Actions;
|
||||
import io.anuke.ucore.scene.event.ClickListener;
|
||||
import io.anuke.ucore.scene.event.InputEvent;
|
||||
import io.anuke.ucore.scene.event.Touchable;
|
||||
import io.anuke.ucore.scene.ui.*;
|
||||
import io.anuke.ucore.scene.ui.layout.Stack;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.ucore.util.Strings;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class BlocksFragment extends Fragment{
|
||||
//number of block icon rows
|
||||
private static final int rows = 4;
|
||||
//number of category button rows
|
||||
private static final int secrows = 4;
|
||||
//size of each block icon
|
||||
private static final float size = 48;
|
||||
//maximum recipe rows
|
||||
private static final int maxrow = 3;
|
||||
/** Table containing description that is shown on top.*/
|
||||
private Table descTable;
|
||||
/** Main table containing the whole menu.*/
|
||||
private Table mainTable;
|
||||
/** Table for all section buttons and blocks.*/
|
||||
private Table selectTable;
|
||||
/** Whether the whole thing is shown or hidden by the popup button.*/
|
||||
private boolean shown = true;
|
||||
/** Recipe currently hovering over.*/
|
||||
private Recipe hoverRecipe;
|
||||
/** Last category selected.*/
|
||||
private Category lastCategory;
|
||||
/** Last block pane scroll Y position.*/
|
||||
private float lastScroll;
|
||||
/** Temporary recipe array for storage*/
|
||||
private Array<Recipe> recipes = new Array<>();
|
||||
|
||||
public void build(Group parent){
|
||||
InputHandler input = control.input(0);
|
||||
|
||||
parent.fill(container -> {
|
||||
container.bottom().right().visible(() -> !state.is(State.menu));
|
||||
|
||||
mainTable = container.table(main -> {
|
||||
|
||||
//add top description table
|
||||
descTable = new Table("button");
|
||||
descTable.visible(() -> (hoverRecipe != null || input.recipe != null) && shown); //make sure it's visible when necessary
|
||||
descTable.update(() -> {
|
||||
if(state.is(State.menu)){
|
||||
descTable.clear();
|
||||
control.input(0).recipe = null;
|
||||
}
|
||||
// note: This is required because there is no direct connection between input.recipe and the description ui.
|
||||
// If input.recipe gets set to null, a proper cleanup of the ui elements is required.
|
||||
boolean anyRecipeShown = input.recipe != null || hoverRecipe != null;
|
||||
boolean descriptionTableClean = descTable.getChildren().size == 0;
|
||||
boolean cleanupRequired = (!anyRecipeShown && !descriptionTableClean);
|
||||
if(cleanupRequired){
|
||||
descTable.clear();
|
||||
}
|
||||
});
|
||||
|
||||
float w = 246f;
|
||||
|
||||
main.add(descTable).width(w);
|
||||
|
||||
main.row();
|
||||
|
||||
//now add the block selection menu
|
||||
selectTable = main.table("pane", select -> {})
|
||||
.margin(10f).marginLeft(0f).marginRight(0f).marginTop(-5)
|
||||
.touchable(Touchable.enabled).right().bottom().width(w).get();
|
||||
|
||||
}).bottom().right().get();
|
||||
});
|
||||
|
||||
Events.on(WorldLoadEvent.class, event -> rebuild());
|
||||
|
||||
rebuild();
|
||||
}
|
||||
|
||||
/**Rebuilds the whole placement menu, attempting to preserve previous state.*/
|
||||
void rebuild(){
|
||||
selectTable.clear();
|
||||
|
||||
InputHandler input = control.input(0);
|
||||
Stack stack = new Stack();
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
Table catTable = selectTable;
|
||||
|
||||
int cati = 0;
|
||||
int checkedi = 0;
|
||||
int rowsUsed = 0;
|
||||
|
||||
//add categories
|
||||
for(Category cat : Category.values()){
|
||||
//get recipes out by category
|
||||
Recipe.getUnlockedByCategory(cat, recipes);
|
||||
|
||||
//empty section, nothing to see here
|
||||
if(recipes.size == 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
//table where actual recipes go
|
||||
Table recipeTable = new Table();
|
||||
recipeTable.margin(4).top().left().marginRight(15);
|
||||
|
||||
//add a new row here when needed
|
||||
if(cati % secrows == 0){
|
||||
catTable = new Table();
|
||||
selectTable.row();
|
||||
selectTable.add(catTable).colspan(secrows).padTop(-5).growX();
|
||||
}
|
||||
|
||||
//add category button
|
||||
ImageButton catb = catTable.addImageButton("icon-" + cat.name(), "toggle", 40, () -> {
|
||||
if(!recipeTable.isVisible() && input.recipe != null){
|
||||
input.recipe = null;
|
||||
}
|
||||
lastCategory = cat;
|
||||
stack.act(Gdx.graphics.getDeltaTime());
|
||||
stack.act(Gdx.graphics.getDeltaTime());
|
||||
}).growX().height(54).group(group)
|
||||
.name("sectionbutton" + cat.name()).get();
|
||||
|
||||
if(lastCategory == cat || lastCategory == null){
|
||||
checkedi = cati;
|
||||
lastCategory = cat;
|
||||
}
|
||||
|
||||
//scrollpane for recipes
|
||||
ScrollPane pane = new ScrollPane(recipeTable, "clear-black");
|
||||
pane.setOverscroll(false, false);
|
||||
pane.visible(catb::isChecked);
|
||||
pane.setScrollYForce(lastScroll);
|
||||
pane.update(() -> {
|
||||
Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true);
|
||||
if(e != null && e.isDescendantOf(pane)){
|
||||
Core.scene.setScrollFocus(pane);
|
||||
}else if(Core.scene.getScrollFocus() == pane){
|
||||
Core.scene.setScrollFocus(null);
|
||||
}
|
||||
|
||||
if(lastCategory == cat){
|
||||
lastScroll = pane.getVisualScrollY();
|
||||
}
|
||||
});
|
||||
stack.add(pane);
|
||||
|
||||
int i = 0;
|
||||
|
||||
//add actual recipes
|
||||
for(Recipe r : recipes){
|
||||
if((r.mode != null && r.mode != state.mode) || !r.visibility.shown()) continue;
|
||||
|
||||
ImageButton image = new ImageButton(new TextureRegion(), "select");
|
||||
|
||||
TextureRegion[] regions = r.result.getCompactIcon();
|
||||
Stack istack = new Stack();
|
||||
for(TextureRegion region : regions){
|
||||
Image u = new Image(region);
|
||||
u.update(() -> u.setColor(istack.getColor()));
|
||||
istack.add(u);
|
||||
}
|
||||
|
||||
image.getImageCell().setActor(istack).size(size);
|
||||
image.addChild(istack);
|
||||
image.setTouchable(Touchable.enabled);
|
||||
image.getImage().remove();
|
||||
|
||||
image.addListener(new ClickListener(){
|
||||
@Override
|
||||
public void enter(InputEvent event, float x, float y, int pointer, Element fromActor){
|
||||
super.enter(event, x, y, pointer, fromActor);
|
||||
if(hoverRecipe != r){
|
||||
hoverRecipe = r;
|
||||
updateRecipe(r);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exit(InputEvent event, float x, float y, int pointer, Element toActor){
|
||||
super.exit(event, x, y, pointer, toActor);
|
||||
hoverRecipe = null;
|
||||
updateRecipe(input.recipe);
|
||||
}
|
||||
});
|
||||
|
||||
image.clicked(() -> {
|
||||
// note: input.recipe only gets set here during a click.
|
||||
// during a hover only the visual description will be updated.
|
||||
InputHandler handler = mobile ? input : control.input(0);
|
||||
|
||||
boolean nothingSelectedYet = handler.recipe == null;
|
||||
boolean selectedSomethingElse = !nothingSelectedYet && handler.recipe != r;
|
||||
boolean shouldMakeSelection = nothingSelectedYet || selectedSomethingElse;
|
||||
if(shouldMakeSelection){
|
||||
handler.recipe = r;
|
||||
hoverRecipe = r;
|
||||
updateRecipe(r);
|
||||
}else{
|
||||
handler.recipe = null;
|
||||
hoverRecipe = null;
|
||||
updateRecipe(null);
|
||||
}
|
||||
});
|
||||
|
||||
recipeTable.add(image).size(size + 8);
|
||||
|
||||
image.update(() -> {
|
||||
image.setChecked(r == control.input(0).recipe);
|
||||
TileEntity entity = players[0].getClosestCore();
|
||||
|
||||
if(entity == null) return;
|
||||
|
||||
if(!state.mode.infiniteResources){
|
||||
for(ItemStack s : r.requirements){
|
||||
if(!entity.items.has(s.item, Mathf.ceil(s.amount))){
|
||||
istack.setColor(Color.GRAY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
istack.setColor(Color.WHITE);
|
||||
});
|
||||
|
||||
if(i % rows == rows - 1){
|
||||
rowsUsed = Math.max((i + 1) / rows, rowsUsed);
|
||||
recipeTable.row();
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
cati++;
|
||||
}
|
||||
|
||||
if(group.getButtons().size > 0){
|
||||
group.getButtons().get(checkedi).setChecked(true);
|
||||
}
|
||||
|
||||
selectTable.row();
|
||||
selectTable.add(stack).growX().left().top().colspan(Category.values().length).padBottom(-5).height((size + 12) * Math.min(rowsUsed, 3));
|
||||
}
|
||||
|
||||
void toggle(float t, Interpolation ip){
|
||||
if(shown){
|
||||
shown = false;
|
||||
mainTable.actions(Actions.translateBy(0, mainTable.getTranslation().y + (-mainTable.getHeight() - descTable.getHeight()), t, ip));
|
||||
}else{
|
||||
shown = true;
|
||||
mainTable.actions(Actions.translateBy(0, -mainTable.getTranslation().y, t, ip));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateRecipe(Recipe recipe){
|
||||
if(recipe == null){
|
||||
descTable.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
descTable.clear();
|
||||
descTable.setTouchable(Touchable.enabled);
|
||||
|
||||
descTable.defaults().left();
|
||||
descTable.left();
|
||||
descTable.margin(12);
|
||||
|
||||
Table header = new Table();
|
||||
|
||||
descTable.add(header).left();
|
||||
|
||||
descTable.row();
|
||||
|
||||
TextureRegion[] regions = recipe.result.getCompactIcon();
|
||||
|
||||
Stack istack = new Stack();
|
||||
|
||||
for(TextureRegion region : regions) istack.add(new Image(region));
|
||||
|
||||
header.add(istack).size(8 * 5).padTop(4);
|
||||
Label nameLabel = new Label(recipe.result.formalName);
|
||||
nameLabel.setWrap(true);
|
||||
header.add(nameLabel).padLeft(2).width(120f);
|
||||
|
||||
header.addButton("?", () -> ui.content.show(recipe)).expandX().padLeft(3).top().right().size(40f, 44f).padTop(-2);
|
||||
|
||||
descTable.add().pad(2);
|
||||
|
||||
Table requirements = new Table();
|
||||
|
||||
descTable.row();
|
||||
|
||||
descTable.left();
|
||||
descTable.add(requirements);
|
||||
|
||||
for(ItemStack stack : recipe.requirements){
|
||||
requirements.addImage(stack.item.region).size(8 * 3);
|
||||
Label reqlabel = new Label(() -> {
|
||||
TileEntity core = players[0].getClosestCore();
|
||||
if(core == null || state.mode.infiniteResources) return "*/*";
|
||||
|
||||
int amount = core.items.get(stack.item);
|
||||
String color = (amount < stack.amount / 2f ? "[red]" : amount < stack.amount ? "[accent]" : "[white]");
|
||||
|
||||
return color + format(amount) + "[white]/" + stack.amount;
|
||||
});
|
||||
|
||||
requirements.add(reqlabel).left();
|
||||
requirements.row();
|
||||
}
|
||||
|
||||
descTable.row();
|
||||
}
|
||||
|
||||
String format(int number){
|
||||
if(number >= 1000000){
|
||||
return Strings.toFixed(number / 1000000f, 1) + "[gray]mil[]";
|
||||
}else if(number >= 10000){
|
||||
return number / 1000 + "[gray]k[]";
|
||||
}else if(number >= 1000){
|
||||
return Strings.toFixed(number / 1000f, 1) + "[gray]k[]";
|
||||
}else{
|
||||
return number + "";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package io.anuke.mindustry.ui.fragments;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.g2d.BitmapFont;
|
||||
@@ -8,13 +10,13 @@ import com.badlogic.gdx.utils.Align;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.core.Platform;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Inputs;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.ui.Dialog;
|
||||
import io.anuke.ucore.scene.ui.Label;
|
||||
import io.anuke.ucore.scene.ui.Label.LabelStyle;
|
||||
import io.anuke.ucore.scene.ui.TextField;
|
||||
@@ -22,8 +24,7 @@ import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.players;
|
||||
import static io.anuke.mindustry.Vars.state;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.ucore.core.Core.scene;
|
||||
import static io.anuke.ucore.core.Core.skin;
|
||||
|
||||
@@ -113,9 +114,35 @@ public class ChatFragment extends Table{
|
||||
chatfield.getStyle().font = skin.getFont("default-font-chat");
|
||||
chatfield.getStyle().fontColor = Color.WHITE;
|
||||
chatfield.setStyle(chatfield.getStyle());
|
||||
Platform.instance.addDialog(chatfield, Vars.maxTextLength);
|
||||
|
||||
bottom().left().marginBottom(offsety).marginLeft(offsetx * 2).add(fieldlabel).padBottom(4f);
|
||||
if(mobile){
|
||||
chatfield.tapped(() -> {
|
||||
Dialog dialog = new Dialog("", "dialog");
|
||||
dialog.setFillParent(true);
|
||||
dialog.content().top();
|
||||
dialog.content().defaults().height(65f);
|
||||
TextField to = dialog.content().addField("", t-> {}).pad(15).width(250f).get();
|
||||
to.setMaxLength(maxTextLength);
|
||||
to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick());
|
||||
dialog.content().addButton("$text.ok", () -> {
|
||||
chatfield.clearText();
|
||||
chatfield.appendText(to.getText());
|
||||
chatfield.change();
|
||||
dialog.hide();
|
||||
Gdx.input.setOnscreenKeyboardVisible(false);
|
||||
toggle();
|
||||
}).width(90f).name("okb");
|
||||
|
||||
dialog.show();
|
||||
Timers.runTask(1f, () -> {
|
||||
to.setCursorPosition(to.getText().length());
|
||||
Core.scene.setKeyboardFocus(to);
|
||||
Gdx.input.setOnscreenKeyboardVisible(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bottom().left().marginBottom(offsety).marginLeft(offsetx * 2).add(fieldlabel).padBottom(6f);
|
||||
|
||||
add(chatfield).padBottom(offsety).padLeft(offsetx).growX().padRight(offsetx).height(28);
|
||||
|
||||
@@ -123,10 +150,6 @@ public class ChatFragment extends Table{
|
||||
marginBottom(105f);
|
||||
marginRight(240f);
|
||||
}
|
||||
|
||||
if(Vars.mobile){
|
||||
addImageButton("icon-arrow-right", 14 * 2, this::toggle).size(46f, 51f).visible(() -> chatOpen).pad(2f);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,7 +16,6 @@ import io.anuke.mindustry.net.Packets.AdminAction;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.ui.IntFormat;
|
||||
import io.anuke.mindustry.ui.Minimap;
|
||||
import io.anuke.mindustry.ui.SelectionTable;
|
||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.ucore.core.*;
|
||||
import io.anuke.ucore.graphics.Hue;
|
||||
@@ -33,7 +32,7 @@ import io.anuke.ucore.util.Mathf;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class HudFragment extends Fragment{
|
||||
public final BlocksFragment blockfrag = new BlocksFragment();
|
||||
public final PlacementFragment blockfrag = new PlacementFragment();
|
||||
|
||||
private ImageButton menu, flip;
|
||||
private Stack wavetable;
|
||||
@@ -199,12 +198,6 @@ public class HudFragment extends Fragment{
|
||||
t.add("$text.saveload");
|
||||
});
|
||||
|
||||
//tapped block indicator
|
||||
parent.fill(t -> {
|
||||
t.bottom().visible(() -> !state.is(State.menu));
|
||||
t.add(new SelectionTable());
|
||||
});
|
||||
|
||||
blockfrag.build(Core.scene.getRoot());
|
||||
}
|
||||
|
||||
@@ -231,7 +224,6 @@ public class HudFragment extends Fragment{
|
||||
|
||||
/**Show unlock notification for a new recipe.*/
|
||||
public void showUnlock(Recipe recipe){
|
||||
blockfrag.rebuild();
|
||||
|
||||
//if there's currently no unlock notification...
|
||||
if(lastUnlockTable == null){
|
||||
|
||||
@@ -11,6 +11,7 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Strings;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
@@ -42,7 +43,7 @@ public class MenuFragment extends Fragment{
|
||||
}
|
||||
|
||||
//version info
|
||||
parent.fill(c -> c.bottom().left().add("Mindustry " + Version.number + "-" + Version.modifier + " " + Version.type + " / " + (Version.build == -1 ? "custom build" : "build " + Version.build))
|
||||
parent.fill(c -> c.bottom().left().add(Strings.formatArgs("Mindustry v{0} {1}-{2} {3}", Version.number, Version.modifier, Version.type, (Version.build == -1 ? "custom build" : "build " + Version.build)))
|
||||
.visible(() -> state.is(State.menu)));
|
||||
}
|
||||
|
||||
@@ -55,14 +56,14 @@ public class MenuFragment extends Fragment{
|
||||
container.defaults().size(size).pad(5).padTop(4f);
|
||||
|
||||
MobileButton
|
||||
play = new MobileButton("icon-play-2", isize, "$text.play", this::showPlaySelect),
|
||||
maps = new MobileButton("icon-map", isize, "$text.maps", ui.maps::show),
|
||||
load = new MobileButton("icon-load", isize, "$text.load", ui.load::show),
|
||||
join = new MobileButton("icon-add", isize, "$text.joingame", ui.join::show),
|
||||
editor = new MobileButton("icon-editor", isize, "$text.editor", () -> ui.loadGraphics(ui.editor::show)),
|
||||
tools = new MobileButton("icon-tools", isize, "$text.settings", ui.settings::show),
|
||||
unlocks = new MobileButton("icon-unlocks", isize, "$text.unlocks", ui.unlocks::show),
|
||||
donate = new MobileButton("icon-donate", isize, "$text.donate", Platform.instance::openDonations);
|
||||
play = new MobileButton("icon-play-2", isize, "$text.play", this::showPlaySelect),
|
||||
maps = new MobileButton("icon-map", isize, "$text.maps", ui.maps::show),
|
||||
load = new MobileButton("icon-load", isize, "$text.load", ui.load::show),
|
||||
join = new MobileButton("icon-add", isize, "$text.joingame", ui.join::show),
|
||||
editor = new MobileButton("icon-editor", isize, "$text.editor", () -> ui.loadGraphics(ui.editor::show)),
|
||||
tools = new MobileButton("icon-tools", isize, "$text.settings", ui.settings::show),
|
||||
unlocks = new MobileButton("icon-unlocks", isize, "$text.unlocks", ui.unlocks::show),
|
||||
donate = new MobileButton("icon-donate", isize, "$text.donate", Platform.instance::openDonations);
|
||||
|
||||
if(Gdx.graphics.getWidth() > Gdx.graphics.getHeight()){
|
||||
container.add(play);
|
||||
|
||||
@@ -31,7 +31,7 @@ public class OverlayFragment extends Fragment{
|
||||
config.build(group);
|
||||
consume.build(group);
|
||||
|
||||
input.buildUI(group);
|
||||
//input.buildUI(group);
|
||||
}
|
||||
|
||||
public void remove(){
|
||||
|
||||
242
core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java
Normal file
242
core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java
Normal file
@@ -0,0 +1,242 @@
|
||||
package io.anuke.mindustry.ui.fragments;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.math.Interpolation;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
import io.anuke.mindustry.core.GameState.State;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.game.EventType.WorldLoadGraphicsEvent;
|
||||
import io.anuke.mindustry.graphics.Palette;
|
||||
import io.anuke.mindustry.input.InputHandler;
|
||||
import io.anuke.mindustry.type.Category;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.type.Recipe;
|
||||
import io.anuke.mindustry.ui.ImageStack;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.OreBlock;
|
||||
import io.anuke.ucore.core.Events;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.scene.Group;
|
||||
import io.anuke.ucore.scene.actions.Actions;
|
||||
import io.anuke.ucore.scene.event.Touchable;
|
||||
import io.anuke.ucore.scene.ui.ButtonGroup;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.ImageButton;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
public class PlacementFragment extends Fragment{
|
||||
final int rowWidth = 4;
|
||||
|
||||
Category currentCategory = Category.turret;
|
||||
Block hovered, lastDisplay;
|
||||
Tile hoverTile;
|
||||
Table blockTable, toggler, topTable;
|
||||
boolean shown = true;
|
||||
|
||||
public PlacementFragment(){
|
||||
Events.on(WorldLoadGraphicsEvent.class, event -> {
|
||||
Group group = toggler.getParent();
|
||||
toggler.remove();
|
||||
build(group);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(Group parent){
|
||||
parent.fill(full -> {
|
||||
toggler = full;
|
||||
full.bottom().right().visible(() -> !state.is(State.menu));
|
||||
|
||||
full.table(frame -> {
|
||||
InputHandler input = control.input(0);
|
||||
|
||||
//rebuilds the category table with the correct recipes
|
||||
Runnable rebuildCategory = () -> {
|
||||
blockTable.clear();
|
||||
blockTable.top().margin(5);
|
||||
|
||||
int index = 0;
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
group.setMinCheckCount(0);
|
||||
|
||||
for(Recipe recipe : Recipe.getByCategory(currentCategory)){
|
||||
|
||||
if(index++ % rowWidth == 0){
|
||||
blockTable.row();
|
||||
}
|
||||
|
||||
boolean[] unlocked = {false};
|
||||
|
||||
ImageButton button = blockTable.addImageButton("icon-locked", "select", 8*4, () -> {
|
||||
if(control.unlocks.isUnlocked(recipe)){
|
||||
input.recipe = input.recipe == recipe ? null : recipe;
|
||||
}
|
||||
}).size(46f).group(group).get();
|
||||
|
||||
button.update(() -> { //color unplacable things gray
|
||||
boolean ulock = control.unlocks.isUnlocked(recipe);
|
||||
TileEntity core = players[0].getClosestCore();
|
||||
Color color = core != null && (core.items.has(recipe.requirements) || state.mode.infiniteResources) ? Color.WHITE : ulock ? Color.GRAY : Color.WHITE;
|
||||
button.forEach(elem -> elem.setColor(color));
|
||||
button.setChecked(input.recipe == recipe);
|
||||
|
||||
if(ulock == unlocked[0]) return;
|
||||
unlocked[0] = ulock;
|
||||
|
||||
if(!ulock){
|
||||
button.replaceImage(new Image("icon-locked"));
|
||||
}else{
|
||||
button.replaceImage(new ImageStack(recipe.result.getCompactIcon()));
|
||||
}
|
||||
});
|
||||
|
||||
button.hovered(() -> hovered = recipe.result);
|
||||
button.exited(() -> {
|
||||
if(hovered == recipe.result){
|
||||
hovered = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
blockTable.act(0f);
|
||||
};
|
||||
|
||||
//top table with hover info
|
||||
frame.table("clear", top -> {
|
||||
topTable = top;
|
||||
top.add(new Table()).growX().update(topTable -> {
|
||||
if((tileDisplayBlock() == null && lastDisplay == getSelected()) ||
|
||||
(tileDisplayBlock() != null && lastDisplay == tileDisplayBlock())) return;
|
||||
|
||||
topTable.clear();
|
||||
topTable.top().left().margin(5);
|
||||
|
||||
lastDisplay = getSelected();
|
||||
|
||||
if(lastDisplay != null){ //show selected recipe
|
||||
topTable.table(header -> {
|
||||
header.left();
|
||||
header.add(new ImageStack(lastDisplay.getCompactIcon())).size(8*4);
|
||||
header.labelWrap(() ->
|
||||
!control.unlocks.isUnlocked(Recipe.getByResult(lastDisplay)) ? Bundles.get("text.blocks.unknown") : lastDisplay.formalName)
|
||||
.left().width(190f).padLeft(5);
|
||||
header.add().growX();
|
||||
if(control.unlocks.isUnlocked(Recipe.getByResult(lastDisplay))){
|
||||
header.addButton("?", "clear-partial", () -> ui.content.show(Recipe.getByResult(lastDisplay)))
|
||||
.size(8 * 5).padTop(-5).padRight(-5).right().grow();
|
||||
}
|
||||
}).growX().left();
|
||||
topTable.row();
|
||||
//add requirement table
|
||||
topTable.table(req -> {
|
||||
req.top().left();
|
||||
|
||||
for(ItemStack stack : Recipe.getByResult(lastDisplay).requirements){
|
||||
req.table(line -> {
|
||||
line.left();
|
||||
line.addImage(stack.item.region).size(8*2);
|
||||
line.add(stack.item.localizedName()).color(Color.LIGHT_GRAY).padLeft(2).left();
|
||||
line.labelWrap(() -> {
|
||||
TileEntity core = players[0].getClosestCore();
|
||||
if(core == null || state.mode.infiniteResources) return "*/*";
|
||||
|
||||
int amount = core.items.get(stack.item);
|
||||
String color = (amount < stack.amount / 2f ? "[red]" : amount < stack.amount ? "[accent]" : "[white]");
|
||||
|
||||
return color + ui.formatAmount(amount) + "[white]/" + stack.amount;
|
||||
}).padLeft(5);
|
||||
}).left();
|
||||
req.row();
|
||||
}
|
||||
}).growX().left().margin(3);
|
||||
|
||||
}else if(tileDisplayBlock() != null){ //show selected tile
|
||||
lastDisplay = tileDisplayBlock();
|
||||
topTable.add(new ImageStack(lastDisplay.getDisplayIcon(hoverTile))).size(8*4);
|
||||
topTable.labelWrap(lastDisplay.getDisplayName(hoverTile)).left().width(190f).padLeft(5);
|
||||
}
|
||||
});
|
||||
top.row();
|
||||
top.addImage("blank").growX().color(Palette.accent).height(3f);
|
||||
}).colspan(3).fillX().visible(() -> getSelected() != null || tileDisplayBlock() != null).touchable(Touchable.enabled);
|
||||
frame.row();
|
||||
frame.table("clear", blocksSelect -> {
|
||||
blocksSelect.table(blocks -> blockTable = blocks).grow();
|
||||
blocksSelect.row();
|
||||
blocksSelect.table(input::buildUI).growX();
|
||||
}).fillY().bottom().touchable(Touchable.enabled);
|
||||
frame.addImage("blank").width(3f).fillY().color(Palette.accent);
|
||||
frame.table(categories -> {
|
||||
categories.defaults().size(50f);
|
||||
|
||||
ButtonGroup<ImageButton> group = new ButtonGroup<>();
|
||||
|
||||
for(Category cat : Category.values()){
|
||||
if(Recipe.getByCategory(cat).isEmpty()) continue;
|
||||
|
||||
categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16*2, () -> {
|
||||
currentCategory = cat;
|
||||
rebuildCategory.run();
|
||||
}).group(group);
|
||||
|
||||
if(cat.ordinal() %2 == 1) categories.row();
|
||||
}
|
||||
}).touchable(Touchable.enabled);
|
||||
|
||||
rebuildCategory.run();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**Returns the currently displayed block in the top box.*/
|
||||
Block getSelected(){
|
||||
Block toDisplay = null;
|
||||
|
||||
Vector2 v = topTable.stageToLocalCoordinates(Graphics.mouse());
|
||||
|
||||
//setup hovering tile
|
||||
if(!ui.hasMouse() && topTable.hit(v.x, v.y, false) == null){
|
||||
Tile tile = world.tileWorld(Graphics.mouseWorld().x, Graphics.mouseWorld().y);
|
||||
if(tile != null){
|
||||
hoverTile = tile.target();
|
||||
}else{
|
||||
hoverTile = null;
|
||||
}
|
||||
}else{
|
||||
hoverTile = null;
|
||||
}
|
||||
|
||||
//block currently selected
|
||||
if(control.input(0).recipe != null){
|
||||
toDisplay = control.input(0).recipe.result;
|
||||
}
|
||||
|
||||
//block hovered on in build menu
|
||||
if(hovered != null){
|
||||
toDisplay = hovered;
|
||||
}
|
||||
|
||||
return toDisplay;
|
||||
}
|
||||
|
||||
/**Returns the block currently being hovered over in the world.*/
|
||||
Block tileDisplayBlock(){
|
||||
return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.floor() instanceof OreBlock ? hoverTile.floor() : null;
|
||||
}
|
||||
|
||||
/**Show or hide the placement menu.*/
|
||||
void toggle(float t, Interpolation ip){
|
||||
toggler.clearActions();
|
||||
if(shown){
|
||||
shown = false;
|
||||
toggler.actions(Actions.translateBy(toggler.getTranslation().x + toggler.getWidth(), 0, t, ip));
|
||||
}else{
|
||||
shown = true;
|
||||
toggler.actions(Actions.translateBy(-toggler.getTranslation().x, 0, t, ip));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ public abstract class BaseBlock extends MappableContent{
|
||||
/**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);
|
||||
return Math.min(getMaximumAccepted(tile, item) - tile.entity.items.get(item), amount);
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ public class Block extends BaseBlock {
|
||||
TileEntity entity = tile.entity();
|
||||
|
||||
for(Tile other : getPowerConnections(tile, tempTiles)){
|
||||
if(other.entity.power != null){
|
||||
if(other.entity.power != null && other.entity.power.graph != null){
|
||||
other.entity.power.graph.add(entity.power.graph);
|
||||
}
|
||||
}
|
||||
@@ -336,7 +336,6 @@ public class Block extends BaseBlock {
|
||||
if(hasItems) stats.add(BlockStat.itemCapacity, itemCapacity, StatUnit.items);
|
||||
}
|
||||
|
||||
//TODO make this easier to config.
|
||||
public void setBars(){
|
||||
if(consumes.has(ConsumePower.class)){
|
||||
bars.add(new BlockBar(BarType.power, true, tile -> tile.entity.power.satisfaction));
|
||||
|
||||
@@ -241,7 +241,7 @@ public class Tile implements PosTrait, TargetTrait{
|
||||
if(link == 0){
|
||||
return (block.destructible || block.breakable || block.update);
|
||||
}else{
|
||||
return getLinked() != this && getLinked().breakable();
|
||||
return getLinked() != this && getLinked().getLinked() == null && getLinked().breakable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public class BuildBlock extends Block{
|
||||
super(name);
|
||||
update = true;
|
||||
size = Integer.parseInt(name.charAt(name.length() - 1) + "");
|
||||
health = 1;
|
||||
health = 10;
|
||||
layer = Layer.placement;
|
||||
consumesTap = true;
|
||||
solidifes = true;
|
||||
@@ -118,15 +118,6 @@ public class BuildBlock extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterDestroyed(Tile tile, TileEntity e){
|
||||
BuildEntity entity = (BuildEntity) e;
|
||||
|
||||
if(entity.previous != null && entity.previous.synthetic()){
|
||||
tile.setBlock(entity.previous);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
BuildEntity entity = tile.entity();
|
||||
|
||||
@@ -181,7 +181,7 @@ public class Floor extends Block{
|
||||
|
||||
Floor floor = other.floor();
|
||||
|
||||
if((floor.id <= this.id && !(tile.getElevation() != -1 && other.getElevation() > tile.getElevation())) || (!blends.test(floor) && !tileBlends.test(tile, other)) || (floor.cacheLayer.ordinal() > this.cacheLayer.ordinal() && !sameLayer) ||
|
||||
if(floor.edgeRegions == null || (floor.id <= this.id && !(tile.getElevation() != -1 && other.getElevation() > tile.getElevation())) || (!blends.test(floor) && !tileBlends.test(tile, other)) || (floor.cacheLayer.ordinal() > this.cacheLayer.ordinal() && !sameLayer) ||
|
||||
(sameLayer && floor.cacheLayer == this.cacheLayer)) continue;
|
||||
|
||||
TextureRegion region = floor.edgeRegions[i];
|
||||
|
||||
@@ -95,8 +95,11 @@ public class MendProjector extends Block{
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
MendEntity entity = tile.entity();
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
|
||||
Draw.color(color);
|
||||
Lines.dashCircle(tile.drawx(), tile.drawy() - 1f, range);
|
||||
Lines.dashCircle(tile.drawx(), tile.drawy(), realRange);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package io.anuke.mindustry.world.blocks.defense;
|
||||
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.entities.bullet.Bullet;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.defense.DeflectorWall.DeflectorEntity;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.tilesize;
|
||||
|
||||
public class MendingWall extends Wall{
|
||||
protected float regenSpeed = 0.25f;
|
||||
|
||||
public MendingWall(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleBulletHit(TileEntity entity, Bullet bullet){
|
||||
super.handleBulletHit(entity, bullet);
|
||||
((DeflectorEntity) entity).hit = 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
DeflectorEntity entity = tile.entity();
|
||||
|
||||
if(entity.hit < 0.0001f) return;
|
||||
|
||||
Graphics.setAdditiveBlending();
|
||||
|
||||
Draw.color(Color.WHITE);
|
||||
Draw.alpha(entity.hit * 0.5f);
|
||||
Draw.rect("blank", tile.drawx(), tile.drawy(), tilesize * size, tilesize * size);
|
||||
Draw.reset();
|
||||
|
||||
entity.hit = Mathf.clamp(entity.hit - Timers.delta() / DeflectorWall.hitTime);
|
||||
|
||||
Graphics.setNormalBlending();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
tile.entity.health = Mathf.clamp(tile.entity.health + regenSpeed * Timers.delta(), 0f, health);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TileEntity newEntity(){
|
||||
return new DeflectorEntity();
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,7 @@ public class OverdriveProjector extends Block{
|
||||
protected float speedBoost = 1.5f;
|
||||
protected float speedBoostPhase = 0.75f;
|
||||
protected float useTime = 400f;
|
||||
protected float phaseRangeBoost = 20f;
|
||||
|
||||
public OverdriveProjector(String name){
|
||||
super(name);
|
||||
@@ -66,7 +67,7 @@ public class OverdriveProjector extends Block{
|
||||
}
|
||||
|
||||
if(entity.charge >= reload){
|
||||
float realRange = range + entity.phaseHeat * 20f;
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
float realBoost = speedBoost + entity.phaseHeat*speedBoostPhase;
|
||||
|
||||
Effects.effect(BlockFx.overdriveWave, Hue.mix(color, phase, entity.phaseHeat), tile.drawx(), tile.drawy(), realRange);
|
||||
@@ -97,8 +98,11 @@ public class OverdriveProjector extends Block{
|
||||
|
||||
@Override
|
||||
public void drawSelect(Tile tile){
|
||||
OverdriveEntity entity = tile.entity();
|
||||
float realRange = range + entity.phaseHeat * phaseRangeBoost;
|
||||
|
||||
Draw.color(color);
|
||||
Lines.dashCircle(tile.drawx(), tile.drawy() - 1f, range);
|
||||
Lines.dashCircle(tile.drawx(), tile.drawy(), realRange);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.anuke.mindustry.world.blocks.distribution;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.NumberUtils;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
@@ -8,10 +7,9 @@ import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
import io.anuke.ucore.util.Bits;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
|
||||
public class Junction extends Block{
|
||||
protected float speed = 26; //frames taken to go through this junction
|
||||
@@ -34,8 +32,8 @@ public class Junction extends Block{
|
||||
public void update(Tile tile){
|
||||
JunctionEntity entity = tile.entity();
|
||||
|
||||
for(int i = 0; i < 2; i++){
|
||||
Buffer buffer = (i == 0 ? entity.bx : entity.by);
|
||||
for(int i = 0; i < 4; i++){
|
||||
Buffer buffer = entity.buffers[i];
|
||||
|
||||
if(buffer.index > 0){
|
||||
if(buffer.index > buffer.items.length) buffer.index = buffer.items.length;
|
||||
@@ -44,17 +42,11 @@ public class Junction extends Block{
|
||||
|
||||
if(Timers.time() >= time + speed || Timers.time() < time){
|
||||
|
||||
int val = Bits.getRightInt(l);
|
||||
|
||||
Item item = content.item(Bits.getLeftShort(val));
|
||||
int direction = Bits.getRightShort(val);
|
||||
Tile dest = tile.getNearby(direction);
|
||||
Item item = content.item(Bits.getRightInt(l));
|
||||
Tile dest = tile.getNearby(i);
|
||||
|
||||
//skip blocks that don't want the item, keep waiting until they do
|
||||
if(dest == null || !dest.block().acceptItem(item, dest, tile)){
|
||||
if(buffer.index > 1 && Bits.getRightShort(Bits.getRightInt(buffer.items[1])) != direction){
|
||||
System.arraycopy(buffer.items, 1, buffer.items, 0, buffer.index - 1);
|
||||
buffer.index--;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -69,25 +61,19 @@ public class Junction extends Block{
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
JunctionEntity entity = tile.entity();
|
||||
boolean x = tile.x == source.x;
|
||||
long value = Bits.packLong(NumberUtils.floatToIntBits(Timers.time()), Bits.packInt((short) item.id, source.relativeTo(tile.x, tile.y)));
|
||||
if(x){
|
||||
entity.bx.add(value);
|
||||
}else{
|
||||
entity.by.add(value);
|
||||
}
|
||||
long value = Bits.packLong(NumberUtils.floatToIntBits(Timers.time()), item.id);
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
entity.buffers[relative].add(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
JunctionEntity entity = tile.entity();
|
||||
boolean x = tile.x == source.x;
|
||||
int relative = source.relativeTo(tile.x, tile.y);
|
||||
|
||||
if(entity == null || entity.bx == null || entity.by == null || (x && entity.bx.full()) || (!x && entity.by.full()))
|
||||
if(entity == null || relative == -1 || entity.buffers[relative].full())
|
||||
return false;
|
||||
int dir = source.relativeTo(tile.x, tile.y);
|
||||
if(dir == -1) return false;
|
||||
Tile to = tile.getNearby(dir);
|
||||
Tile to = tile.getNearby(relative);
|
||||
return to != null && to.block().acceptItem(item, to, tile);
|
||||
}
|
||||
|
||||
@@ -96,41 +82,8 @@ public class Junction extends Block{
|
||||
return new JunctionEntity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array<Object> getDebugInfo(Tile tile){
|
||||
JunctionEntity entity = tile.entity();
|
||||
Array<Object> arr = super.getDebugInfo(tile);
|
||||
for(int i = 0; i < 4; i++){
|
||||
arr.add("nearby." + i);
|
||||
arr.add(tile.getNearby(i));
|
||||
}
|
||||
|
||||
Consumer<Buffer> write = b -> {
|
||||
for(int i = 0; i < b.index; i++){
|
||||
long l = b.items[i];
|
||||
float time = NumberUtils.intBitsToFloat(Bits.getLeftInt(l));
|
||||
int val = Bits.getRightInt(l);
|
||||
Item item = content.item(Bits.getLeftShort(val));
|
||||
int direction = Bits.getRightShort(val);
|
||||
Tile dest = tile.getNearby(direction);
|
||||
arr.add(" bufferx.item");
|
||||
arr.add(time + " | " + item.name + " | " + dest.block() + ":" + dest.floor());
|
||||
}
|
||||
};
|
||||
|
||||
arr.add("buffer.bx");
|
||||
arr.add(entity.bx.index);
|
||||
write.accept(entity.bx);
|
||||
arr.add("buffer.by");
|
||||
arr.add(entity.bx.index);
|
||||
write.accept(entity.by);
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
class JunctionEntity extends TileEntity{
|
||||
Buffer bx = new Buffer();
|
||||
Buffer by = new Buffer();
|
||||
Buffer[] buffers = {new Buffer(), new Buffer(), new Buffer(), new Buffer()};
|
||||
}
|
||||
|
||||
class Buffer{
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.anuke.annotations.Annotations.Loc;
|
||||
import io.anuke.annotations.Annotations.Remote;
|
||||
import io.anuke.mindustry.entities.Player;
|
||||
import io.anuke.mindustry.entities.TileEntity;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.Block;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
@@ -13,13 +12,17 @@ import io.anuke.mindustry.world.meta.BlockGroup;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
import io.anuke.mindustry.gen.Call;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
import static io.anuke.mindustry.Vars.threads;
|
||||
|
||||
public class Sorter extends Block implements SelectionTrait{
|
||||
private static Item lastItem;
|
||||
|
||||
public Sorter(String name){
|
||||
super(name);
|
||||
@@ -35,6 +38,13 @@ public class Sorter extends Block implements SelectionTrait{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerPlaced(Tile tile){
|
||||
if(lastItem != null){
|
||||
threads.runDelay(() -> Call.setSorterItem(null, tile, lastItem));
|
||||
}
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
public static void setSorterItem(Player player, Tile tile, Item item){
|
||||
SorterEntity entity = tile.entity();
|
||||
@@ -45,8 +55,6 @@ public class Sorter extends Block implements SelectionTrait{
|
||||
public void draw(Tile tile){
|
||||
super.draw(tile);
|
||||
|
||||
//TODO call event for change
|
||||
|
||||
SorterEntity entity = tile.entity();
|
||||
|
||||
Draw.color(entity.sortItem.color);
|
||||
@@ -110,7 +118,10 @@ public class Sorter extends Block implements SelectionTrait{
|
||||
@Override
|
||||
public void buildTable(Tile tile, Table table){
|
||||
SorterEntity entity = tile.entity();
|
||||
buildItemTable(table, () -> entity.sortItem, item -> Call.setSorterItem(null, tile, item));
|
||||
buildItemTable(table, () -> entity.sortItem, item -> {
|
||||
lastItem = item;
|
||||
Call.setSorterItem(null, tile, item);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,7 +5,6 @@ import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
@@ -30,7 +29,6 @@ public abstract class ItemLiquidGenerator extends ItemGenerator{
|
||||
@Override
|
||||
public void init(){
|
||||
super.init();
|
||||
stats.remove(BlockStat.liquidFuelUse);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.anuke.mindustry.type.Liquid;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.consumers.ConsumeLiquid;
|
||||
|
||||
//TODO
|
||||
public class TurbineGenerator extends BurnerGenerator{
|
||||
|
||||
public TurbineGenerator(String name){
|
||||
|
||||
@@ -42,7 +42,7 @@ public class Cultivator extends Drill{
|
||||
stats.remove(BlockStat.drillTier);
|
||||
stats.add(BlockStat.drillTier, table -> {
|
||||
table.addImage("grass1").size(8 * 3).padBottom(3).padTop(3);
|
||||
// TODO: find out localized name and add tool tip
|
||||
table.add(Blocks.grass.formalName).padLeft(3);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -16,14 +16,11 @@ import io.anuke.mindustry.world.consumers.ConsumeLiquid;
|
||||
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||
import io.anuke.mindustry.world.meta.BlockStat;
|
||||
import io.anuke.mindustry.world.meta.StatUnit;
|
||||
import io.anuke.mindustry.world.meta.StatValue;
|
||||
import io.anuke.ucore.core.Effects;
|
||||
import io.anuke.ucore.core.Effects.Effect;
|
||||
import io.anuke.ucore.core.Graphics;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Cell;
|
||||
import io.anuke.ucore.util.Mathf;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
@@ -135,8 +132,9 @@ public class Drill extends Block{
|
||||
|
||||
for(int i = 0; i < list.size; i++){
|
||||
Item item = list.get(i);
|
||||
Cell<Image> imageCell = table.addImage(item.name + "1").size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3);
|
||||
StatValue.addToolTip(imageCell.getElement(), item);
|
||||
|
||||
table.addImage(item.name + "1").size(8 * 3).padRight(2).padLeft(2).padTop(3).padBottom(3);
|
||||
table.add(item.localizedName());
|
||||
if(i != list.size - 1){
|
||||
table.add("/");
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class LiquidMixer extends LiquidBlock{
|
||||
hasItems = true;
|
||||
rotate = false;
|
||||
solid = true;
|
||||
singleLiquid = false;
|
||||
outputsLiquid = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,11 +152,6 @@ public class Smelter extends Block{
|
||||
Effects.effect(craftEffect, flameColor, tile.drawx(), tile.drawy());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAccepted(Tile tile, Item item){
|
||||
return itemCapacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
boolean isInput = false;
|
||||
|
||||
@@ -11,8 +11,8 @@ import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import static io.anuke.mindustry.Vars.mobile;
|
||||
|
||||
public abstract class Consume{
|
||||
private boolean optional;
|
||||
private boolean update = true;
|
||||
protected boolean optional;
|
||||
protected boolean update = true;
|
||||
|
||||
public Consume optional(boolean optional){
|
||||
this.optional = optional;
|
||||
|
||||
@@ -53,6 +53,6 @@ public class ConsumeItem extends Consume{
|
||||
|
||||
@Override
|
||||
public void display(BlockStats stats){
|
||||
stats.add(BlockStat.inputItem, item);
|
||||
stats.add(optional ? BlockStat.boostItem : BlockStat.inputItem, item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,6 @@ public class ConsumeItemFilter extends Consume{
|
||||
|
||||
@Override
|
||||
public void display(BlockStats stats){
|
||||
stats.add(BlockStat.inputItems, new ItemFilterValue(filter));
|
||||
stats.add(optional ? BlockStat.boostItem : BlockStat.inputItem, new ItemFilterValue(filter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,6 @@ public class ConsumeItems extends Consume{
|
||||
|
||||
@Override
|
||||
public void display(BlockStats stats){
|
||||
stats.add(BlockStat.inputItems, new ItemListValue(items));
|
||||
stats.add(optional ? BlockStat.boostItem : BlockStat.inputItems, new ItemListValue(items));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class ConsumeLiquid extends Consume{
|
||||
|
||||
@Override
|
||||
public String getIcon(){
|
||||
return "icon-liquid";
|
||||
return "icon-liquid-small";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -47,8 +47,12 @@ public class ConsumeLiquid extends Consume{
|
||||
|
||||
@Override
|
||||
public void display(BlockStats stats){
|
||||
stats.add(BlockStat.liquidUse, use * 60f, StatUnit.liquidSecond);
|
||||
stats.add(BlockStat.inputLiquid, liquid);
|
||||
if(!optional){
|
||||
stats.add(BlockStat.liquidUse, use * 60f, StatUnit.liquidSecond);
|
||||
stats.add(BlockStat.inputLiquid, liquid);
|
||||
}else{
|
||||
stats.add(BlockStat.boostLiquid, liquid);
|
||||
}
|
||||
}
|
||||
|
||||
float use(Block block, TileEntity entity){
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ConsumeLiquidFilter extends Consume{
|
||||
|
||||
@Override
|
||||
public String getIcon(){
|
||||
return "icon-liquid";
|
||||
return "icon-liquid-small";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -62,10 +62,12 @@ public class ConsumeLiquidFilter extends Consume{
|
||||
|
||||
@Override
|
||||
public void display(BlockStats stats){
|
||||
if(isFuel){
|
||||
if(optional){
|
||||
stats.add(BlockStat.boostLiquid, new LiquidFilterValue(filter));
|
||||
}else if(isFuel){
|
||||
stats.add(BlockStat.inputLiquidFuel, new LiquidFilterValue(filter));
|
||||
stats.add(BlockStat.liquidFuelUse, 60f * use, StatUnit.liquidSecond);
|
||||
}else{
|
||||
}else {
|
||||
stats.add(BlockStat.inputLiquid, new LiquidFilterValue(filter));
|
||||
stats.add(BlockStat.liquidUse, 60f * use, StatUnit.liquidSecond);
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class ConsumePower extends Consume{
|
||||
|
||||
@Override
|
||||
public String getIcon(){
|
||||
return "icon-power";
|
||||
return "icon-power-small";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -87,7 +87,7 @@ public class Consumers{
|
||||
return i;
|
||||
}
|
||||
|
||||
public ConsumeItems items(ItemStack[] items){
|
||||
public ConsumeItems items(ItemStack... items){
|
||||
ConsumeItems i = new ConsumeItems(items);
|
||||
add(i);
|
||||
return i;
|
||||
|
||||
@@ -45,8 +45,10 @@ public enum BlockStat{
|
||||
shots(StatCategory.shooting),
|
||||
reload(StatCategory.shooting),
|
||||
powerShot(StatCategory.shooting),
|
||||
targetsAir(StatCategory.shooting),;
|
||||
targetsAir(StatCategory.shooting),
|
||||
|
||||
boostItem(StatCategory.optional),
|
||||
boostLiquid(StatCategory.optional),;
|
||||
|
||||
public final StatCategory category;
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@ import io.anuke.ucore.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Hold and organizes a list of block stats.
|
||||
*/
|
||||
/**Hold and organizes a list of block stats.*/
|
||||
public class BlockStats{
|
||||
private static final boolean errorWhenMissing = false;
|
||||
|
||||
@@ -26,52 +24,37 @@ public class BlockStats{
|
||||
this.block = block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single float value with this stat, formatted to 2 decimal places.
|
||||
*/
|
||||
/**Adds a single float value with this stat, formatted to 2 decimal places.*/
|
||||
public void add(BlockStat stat, float value, StatUnit unit){
|
||||
add(stat, new NumberValue(value, unit));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single y/n boolean value.
|
||||
*/
|
||||
/**Adds a single y/n boolean value.*/
|
||||
public void add(BlockStat stat, boolean value){
|
||||
add(stat, new BooleanValue(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item value.
|
||||
*/
|
||||
/**Adds an item value.*/
|
||||
public void add(BlockStat stat, Item item){
|
||||
add(stat, new ItemValue(new ItemStack(item, 1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a liquid value.
|
||||
*/
|
||||
/**Adds a liquid value.*/
|
||||
public void add(BlockStat stat, Liquid liquid){
|
||||
add(stat, new LiquidValue(liquid));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds an item value.
|
||||
*/
|
||||
/**Adds an item value.*/
|
||||
public void add(BlockStat stat, ItemStack item){
|
||||
add(stat, new ItemValue(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single string value with this stat.
|
||||
*/
|
||||
/**Adds a single string value with this stat.*/
|
||||
public void add(BlockStat stat, String format, Object... args){
|
||||
add(stat, new StringValue(format, args));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a stat value.
|
||||
*/
|
||||
/**Adds a stat value.*/
|
||||
public void add(BlockStat stat, StatValue value){
|
||||
if(!Bundles.has("text.blocks." + stat.name().toLowerCase(Locale.ROOT))){
|
||||
if(!errorWhenMissing){
|
||||
@@ -102,6 +85,7 @@ public class BlockStats{
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
/**Removes a stat, if it exists.*/
|
||||
public void remove(BlockStat stat){
|
||||
if(!map.containsKey(stat.category) || !map.get(stat.category).containsKey(stat)){
|
||||
throw new RuntimeException("No stat entry found: \"" + stat + "\" in block '" + block.name + "'!");
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
package io.anuke.mindustry.world.meta;
|
||||
|
||||
/**
|
||||
* A specific category for a stat.
|
||||
*/
|
||||
/**A specific category for a stat.*/
|
||||
public enum StatCategory{
|
||||
general,
|
||||
power,
|
||||
liquids,
|
||||
items,
|
||||
crafting,
|
||||
shooting
|
||||
shooting,
|
||||
optional,
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
package io.anuke.mindustry.world.meta;
|
||||
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.ucore.scene.Element;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.Tooltip;
|
||||
import io.anuke.ucore.scene.ui.layout.Cell;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
/**
|
||||
@@ -13,37 +8,7 @@ import io.anuke.ucore.scene.ui.layout.Table;
|
||||
public interface StatValue{
|
||||
/**
|
||||
* This method should provide all elements necessary to display this stat to the specified table.
|
||||
* For example, a stat that is just text would add label to the table.
|
||||
* For example, a stat that is just text would add a label to the table.
|
||||
*/
|
||||
void display(Table table);
|
||||
|
||||
/**
|
||||
* This method adds an icon image together with a tool tip which contains the name of the item.
|
||||
* @param table the table to add the image cell to.
|
||||
* @param item The item which provides the tool tip content.
|
||||
* @return the image cell which was created. The cell is not yet sized or padded.
|
||||
*/
|
||||
static Cell<Image> addImageWithToolTip(Table table, UnlockableContent item){
|
||||
|
||||
// Create a table cell with a new image as provided by the item
|
||||
Cell<Image> imageCell = table.addImage(item.getContentIcon());
|
||||
|
||||
// Retrieve the image and add a tool tip with the item's name
|
||||
addToolTip(imageCell.getElement(), item);
|
||||
|
||||
// Return the table cell for further processing (sizing, padding, ...)
|
||||
return imageCell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tool tip containing the item's localized name to the given element.
|
||||
* @param element The element to assign the tool tip to.
|
||||
* @param item The item which provides the tool tip content.
|
||||
*/
|
||||
static void addToolTip(Element element, UnlockableContent item){
|
||||
element.addListener(new Tooltip<>(new Table("clear"){{
|
||||
add(item.localizedName());
|
||||
margin(4);
|
||||
}}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package io.anuke.mindustry.world.meta.values;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.ui.ItemDisplay;
|
||||
import io.anuke.mindustry.world.meta.StatValue;
|
||||
import io.anuke.ucore.function.Predicate;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Cell;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
|
||||
public class ItemFilterValue implements StatValue{
|
||||
private final Predicate<Item> filter;
|
||||
@@ -27,10 +27,7 @@ public class ItemFilterValue implements StatValue{
|
||||
for(int i = 0; i < list.size; i++){
|
||||
Item item = list.get(i);
|
||||
|
||||
Cell<Image> imageCell = table.addImage(item.region);
|
||||
imageCell.size(8 * 3).padRight(2).padLeft(2);
|
||||
|
||||
StatValue.addToolTip(imageCell.getElement(), item);
|
||||
table.add(new ItemDisplay(item)).padRight(5);
|
||||
|
||||
if(i != list.size - 1){
|
||||
table.add("/");
|
||||
|
||||
@@ -3,11 +3,8 @@ package io.anuke.mindustry.world.meta.values;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.ui.ItemImage;
|
||||
import io.anuke.mindustry.ui.ItemDisplay;
|
||||
import io.anuke.mindustry.world.meta.ContentStatValue;
|
||||
import io.anuke.mindustry.world.meta.StatValue;
|
||||
import io.anuke.ucore.scene.ui.Image;
|
||||
import io.anuke.ucore.scene.ui.layout.Cell;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
public class ItemListValue implements ContentStatValue{
|
||||
@@ -41,17 +38,11 @@ public class ItemListValue implements ContentStatValue{
|
||||
public void display(Table table){
|
||||
if(items != null){
|
||||
for(Item item : items){
|
||||
Cell<Image> imageCell = table.addImage(item.region);
|
||||
imageCell.size(8 * 3).padRight(5);
|
||||
|
||||
StatValue.addToolTip(imageCell.getElement(), item);
|
||||
table.add(new ItemDisplay(item)).padRight(5);
|
||||
}
|
||||
}else{
|
||||
for(ItemStack stack : stacks){
|
||||
ItemImage image = new ItemImage(stack);
|
||||
table.add(image).size(8 * 3).padRight(5);
|
||||
|
||||
StatValue.addToolTip(image, stack.item);
|
||||
table.add(new ItemDisplay(stack.item, stack.amount)).padRight(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ package io.anuke.mindustry.world.meta.values;
|
||||
import io.anuke.mindustry.game.UnlockableContent;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.type.ItemStack;
|
||||
import io.anuke.mindustry.ui.ItemImage;
|
||||
import io.anuke.mindustry.ui.ItemDisplay;
|
||||
import io.anuke.mindustry.world.meta.ContentStatValue;
|
||||
import io.anuke.mindustry.world.meta.StatValue;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
|
||||
public class ItemValue implements ContentStatValue{
|
||||
@@ -22,9 +21,6 @@ public class ItemValue implements ContentStatValue{
|
||||
|
||||
@Override
|
||||
public void display(Table table){
|
||||
//TODO better implementation, quantity support
|
||||
ItemImage image = new ItemImage(item);
|
||||
table.add(image).size(8 * 3);
|
||||
StatValue.addToolTip(image, item.item);
|
||||
table.add(new ItemDisplay(item.item, item.amount));
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user