Update to v103
# Conflicts: # core/assets/sprites/block_colors.png # core/assets/sprites/sprites.atlas # core/assets/sprites/sprites.png # core/assets/sprites/sprites3.png # core/assets/sprites/sprites5.png # core/src/mindustry/content/Blocks.java # core/src/mindustry/content/TechTree.java # core/src/mindustry/world/blocks/distribution/ItemConveyor.java
This commit is contained in:
@@ -11,13 +11,14 @@ import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import arc.util.async.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.ctype.Content;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.mod.*;
|
||||
import mindustry.net.Net;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import static arc.Core.*;
|
||||
import static mindustry.Vars.*;
|
||||
@@ -33,6 +34,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
|
||||
@Override
|
||||
public void setup(){
|
||||
Vars.loadLogger();
|
||||
Vars.loadFileLogger();
|
||||
Vars.platform = this;
|
||||
beginTime = Time.millis();
|
||||
|
||||
@@ -54,14 +56,15 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
|
||||
Vars.net = new Net(platform.getNet());
|
||||
mods = new Mods();
|
||||
|
||||
UI.loadSystemCursors();
|
||||
Fonts.loadSystemCursors();
|
||||
|
||||
assets.load(new Vars());
|
||||
|
||||
UI.loadDefaultFont();
|
||||
Fonts.loadDefaultFont();
|
||||
|
||||
assets.load(new AssetDescriptor<>("sprites/sprites.atlas", TextureAtlas.class)).loaded = t -> {
|
||||
atlas = (TextureAtlas)t;
|
||||
Fonts.mergeFontAtlas(atlas);
|
||||
};
|
||||
|
||||
assets.loadRun("maps", Map.class, () -> maps.loadPreviews());
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
package mindustry;
|
||||
|
||||
import arc.*;
|
||||
import arc.Application.*;
|
||||
import arc.*;
|
||||
import arc.assets.*;
|
||||
import arc.struct.*;
|
||||
import arc.files.*;
|
||||
import arc.graphics.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.Log.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.ai.*;
|
||||
import mindustry.core.*;
|
||||
@@ -21,21 +22,21 @@ import mindustry.gen.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.mod.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.net.Net;
|
||||
import mindustry.net.*;
|
||||
import mindustry.world.blocks.defense.ForceProjector.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.*;
|
||||
import java.util.*;
|
||||
|
||||
import static arc.Core.settings;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Vars implements Loadable{
|
||||
/** Whether to load locales.*/
|
||||
public static boolean loadLocales = true;
|
||||
/** Whether the logger is loaded. */
|
||||
public static boolean loadedLogger = false;
|
||||
public static boolean loadedLogger = false, loadedFileLogger = false;
|
||||
/** Maximum schematic size.*/
|
||||
public static final int maxSchematicSize = 32;
|
||||
/** All schematic base64 starts with this string.*/
|
||||
@@ -58,7 +59,7 @@ public class Vars implements Loadable{
|
||||
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json";
|
||||
/** URL to the JSON file containing all the BE servers. Only queried in BE. */
|
||||
public static final String serverJsonBeURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers_be.json";
|
||||
/** URL the links to the wiki's modding guide.*/
|
||||
/** URL of the github issue report template.*/
|
||||
public static final String reportIssueURL = "https://github.com/Anuken/Mindustry/issues/new?template=bug_report.md";
|
||||
/** list of built-in servers.*/
|
||||
public static final Array<String> defaultServers = Array.with();
|
||||
@@ -86,7 +87,7 @@ public class Vars implements Loadable{
|
||||
public static final Color[] playerColors = {
|
||||
Color.valueOf("82759a"),
|
||||
Color.valueOf("c0c1c5"),
|
||||
Color.valueOf("fff0e7"),
|
||||
Color.valueOf("ffffff"),
|
||||
Color.valueOf("7d2953"),
|
||||
Color.valueOf("ff074e"),
|
||||
Color.valueOf("ff072a"),
|
||||
@@ -282,9 +283,10 @@ public class Vars implements Loadable{
|
||||
String[] stags = {"&lc&fb[D]", "&lg&fb[I]", "&ly&fb[W]", "&lr&fb[E]", ""};
|
||||
|
||||
Array<String> logBuffer = new Array<>();
|
||||
Log.setLogger((level, text, args) -> {
|
||||
String result = Log.format(text, args);
|
||||
System.out.println(Log.format(stags[level.ordinal()] + "&fr " + text, args));
|
||||
Log.setLogger((level, text) -> {
|
||||
String result = text;
|
||||
String rawText = Log.format(stags[level.ordinal()] + "&fr " + text);
|
||||
System.out.println(rawText);
|
||||
|
||||
result = tags[level.ordinal()] + " " + result;
|
||||
|
||||
@@ -300,6 +302,28 @@ public class Vars implements Loadable{
|
||||
loadedLogger = true;
|
||||
}
|
||||
|
||||
public static void loadFileLogger(){
|
||||
if(loadedFileLogger) return;
|
||||
|
||||
Core.settings.setAppName(appName);
|
||||
|
||||
Writer writer = settings.getDataDirectory().child("last_log.txt").writer(false);
|
||||
LogHandler log = Log.getLogger();
|
||||
Log.setLogger(((level, text) -> {
|
||||
log.log(level, text);
|
||||
|
||||
try{
|
||||
writer.write("[" + Character.toUpperCase(level.name().charAt(0)) +"] " + Log.removeCodes(text) + "\n");
|
||||
writer.flush();
|
||||
}catch(IOException e){
|
||||
e.printStackTrace();
|
||||
//ignore it
|
||||
}
|
||||
}));
|
||||
|
||||
loadedFileLogger = true;
|
||||
}
|
||||
|
||||
public static void loadSettings(){
|
||||
Core.settings.setAppName(appName);
|
||||
|
||||
|
||||
@@ -207,6 +207,7 @@ public class BlockIndexer{
|
||||
public TileEntity findTile(Team team, float x, float y, float range, Boolf<Tile> pred, boolean usePriority){
|
||||
TileEntity closest = null;
|
||||
float dst = 0;
|
||||
float range2 = range*range;
|
||||
|
||||
for(int rx = Math.max((int)((x - range) / tilesize / quadrantSize), 0); rx <= (int)((x + range) / tilesize / quadrantSize) && rx < quadWidth(); rx++){
|
||||
for(int ry = Math.max((int)((y - range) / tilesize / quadrantSize), 0); ry <= (int)((y + range) / tilesize / quadrantSize) && ry < quadHeight(); ry++){
|
||||
@@ -224,8 +225,12 @@ public class BlockIndexer{
|
||||
|
||||
TileEntity e = other.entity;
|
||||
|
||||
float ndst = Mathf.dst(x, y, e.x, e.y);
|
||||
if(ndst < range && (closest == null || ndst < dst || (usePriority && closest.block.priority.ordinal() <= e.block.priority.ordinal()))){
|
||||
float ndst = Mathf.dst2(x, y, e.x, e.y);
|
||||
if(ndst < range2 && (closest == null ||
|
||||
//this one is closer, and it is at least of equal priority
|
||||
(ndst < dst && (!usePriority || closest.block.priority.ordinal() <= e.block.priority.ordinal())) ||
|
||||
//priority is used, and new block has higher priority regardless of range
|
||||
(usePriority && closest.block.priority.ordinal() < e.block.priority.ordinal()))){
|
||||
dst = ndst;
|
||||
closest = e;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class Blocks implements ContentList{
|
||||
scrapWall, scrapWallLarge, scrapWallHuge, scrapWallGigantic, thruster, //ok, these names are getting ridiculous, but at least I don't have humongous walls yet
|
||||
|
||||
//transport
|
||||
conveyor, titaniumConveyor, plastaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, massDriver,
|
||||
conveyor, titaniumConveyor, plastaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, underflowGate, massDriver,
|
||||
|
||||
//liquids
|
||||
mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit,
|
||||
@@ -398,12 +398,37 @@ public class Blocks implements ContentList{
|
||||
//endregion
|
||||
//region ore
|
||||
|
||||
oreCopper = new OreBlock(Items.copper);
|
||||
oreLead = new OreBlock(Items.lead);
|
||||
oreCopper = new OreBlock(Items.copper){{
|
||||
oreDefault = true;
|
||||
oreThreshold = 0.81f;
|
||||
oreScale = 23.47619f;
|
||||
}};
|
||||
|
||||
oreLead = new OreBlock(Items.lead){{
|
||||
oreDefault = true;
|
||||
oreThreshold = 0.828f;
|
||||
oreScale = 23.952381f;
|
||||
}};
|
||||
|
||||
oreScrap = new OreBlock(Items.scrap);
|
||||
oreCoal = new OreBlock(Items.coal);
|
||||
oreTitanium = new OreBlock(Items.titanium);
|
||||
oreThorium = new OreBlock(Items.thorium);
|
||||
|
||||
oreCoal = new OreBlock(Items.coal){{
|
||||
oreDefault = true;
|
||||
oreThreshold = 0.846f;
|
||||
oreScale = 24.428572f;
|
||||
}};
|
||||
|
||||
oreTitanium = new OreBlock(Items.titanium){{
|
||||
oreDefault = true;
|
||||
oreThreshold = 0.864f;
|
||||
oreScale = 24.904762f;
|
||||
}};
|
||||
|
||||
oreThorium = new OreBlock(Items.thorium){{
|
||||
oreDefault = true;
|
||||
oreThreshold = 0.882f;
|
||||
oreScale = 25.380953f;
|
||||
}};
|
||||
|
||||
//endregion
|
||||
//region crafting
|
||||
@@ -624,10 +649,6 @@ public class Blocks implements ContentList{
|
||||
);
|
||||
hasPower = true;
|
||||
craftTime = 35f;
|
||||
spinnerLength = 1.5f;
|
||||
spinnerRadius = 3.5f;
|
||||
spinnerThickness = 1.5f;
|
||||
spinnerSpeed = 3f;
|
||||
size = 2;
|
||||
|
||||
consumes.power(1f);
|
||||
@@ -883,12 +904,14 @@ public class Blocks implements ContentList{
|
||||
requirements(Category.distribution, ItemStack.with(Items.copper, 1), true);
|
||||
health = 45;
|
||||
speed = 0.03f;
|
||||
displayedSpeed = 4.2f;
|
||||
}};
|
||||
|
||||
titaniumConveyor = new ItemConveyor("titanium-conveyor"){{
|
||||
requirements(Category.distribution, ItemStack.with(Items.copper, 1, Items.lead, 1, Items.titanium, 1));
|
||||
health = 65;
|
||||
speed = 0.08f;
|
||||
displayedSpeed = 10f;
|
||||
}};
|
||||
|
||||
plastaniumConveyor = new CraterConveyor("plastanium-conveyor"){{
|
||||
@@ -902,6 +925,7 @@ public class Blocks implements ContentList{
|
||||
requirements(Category.distribution, ItemStack.with(Items.plastanium, 1, Items.thorium, 1, Items.metaglass, 1));
|
||||
health = 180;
|
||||
speed = 0.08f;
|
||||
displayedSpeed = 10f;
|
||||
}};
|
||||
|
||||
junction = new Junction("junction"){{
|
||||
@@ -953,6 +977,12 @@ public class Blocks implements ContentList{
|
||||
buildCostMultiplier = 3f;
|
||||
}};
|
||||
|
||||
underflowGate = new OverflowGate("underflow-gate"){{
|
||||
requirements(Category.distribution, ItemStack.with(Items.lead, 2, Items.copper, 4));
|
||||
buildCostMultiplier = 3f;
|
||||
invert = true;
|
||||
}};
|
||||
|
||||
massDriver = new MassDriver("mass-driver"){{
|
||||
requirements(Category.distribution, ItemStack.with(Items.titanium, 125, Items.silicon, 75, Items.lead, 125, Items.thorium, 50));
|
||||
size = 3;
|
||||
|
||||
@@ -22,7 +22,6 @@ public class TechTree implements ContentList{
|
||||
node(conveyor, () -> {
|
||||
|
||||
node(junction, () -> {
|
||||
node(itemBridge);
|
||||
node(router, () -> {
|
||||
node(launchPad, () -> {
|
||||
node(launchPadLarge, () -> {
|
||||
@@ -34,7 +33,9 @@ public class TechTree implements ContentList{
|
||||
node(sorter, () -> {
|
||||
node(invertedSorter);
|
||||
node(message);
|
||||
node(overflowGate);
|
||||
node(overflowGate, () -> {
|
||||
node(underflowGate);
|
||||
});
|
||||
});
|
||||
node(container, () -> {
|
||||
node(unloader);
|
||||
@@ -43,223 +44,260 @@ public class TechTree implements ContentList{
|
||||
});
|
||||
});
|
||||
|
||||
node(titaniumConveyor, () -> {
|
||||
node(phaseConveyor, () -> {
|
||||
node(massDriver, () -> {
|
||||
node(itemBridge, () -> {
|
||||
node(titaniumConveyor, () -> {
|
||||
node(phaseConveyor, () -> {
|
||||
node(massDriver, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(plastaniumConveyor, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(plastaniumConveyor, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(armoredConveyor, () -> {
|
||||
node(armoredConveyor, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(duo, () -> {
|
||||
node(scatter, () -> {
|
||||
node(hail, () -> {
|
||||
node(duo, () -> {
|
||||
node(scatter, () -> {
|
||||
node(hail, () -> {
|
||||
|
||||
node(salvo, () -> {
|
||||
node(swarmer, () -> {
|
||||
node(cyclone, () -> {
|
||||
node(spectre, () -> {
|
||||
node(salvo, () -> {
|
||||
node(swarmer, () -> {
|
||||
node(cyclone, () -> {
|
||||
node(spectre, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(ripple, () -> {
|
||||
node(fuse, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(scorch, () -> {
|
||||
node(arc, () -> {
|
||||
node(wave, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(lancer, () -> {
|
||||
node(meltdown, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(shockMine, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
node(copperWall, () -> {
|
||||
node(copperWallLarge, () -> {
|
||||
node(titaniumWall, () -> {
|
||||
node(titaniumWallLarge);
|
||||
|
||||
node(door, () -> {
|
||||
node(doorLarge);
|
||||
});
|
||||
node(plastaniumWall, () -> {
|
||||
node(plastaniumWallLarge, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
node(thoriumWall, () -> {
|
||||
node(thoriumWallLarge);
|
||||
node(surgeWall, () -> {
|
||||
node(surgeWallLarge);
|
||||
node(phaseWall, () -> {
|
||||
node(phaseWallLarge);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(mechanicalDrill, () -> {
|
||||
node(graphitePress, () -> {
|
||||
node(pneumaticDrill, () -> {
|
||||
node(cultivator, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(laserDrill, () -> {
|
||||
node(blastDrill, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(waterExtractor, () -> {
|
||||
node(oilExtractor, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(pyratiteMixer, () -> {
|
||||
node(blastMixer, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(siliconSmelter, () -> {
|
||||
|
||||
node(sporePress, () -> {
|
||||
node(coalCentrifuge, () -> {
|
||||
|
||||
});
|
||||
node(multiPress, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(plastaniumCompressor, () -> {
|
||||
node(phaseWeaver, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(ripple, () -> {
|
||||
node(fuse, () -> {
|
||||
node(kiln, () -> {
|
||||
node(incinerator, () -> {
|
||||
node(melter, () -> {
|
||||
node(surgeSmelter, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(scorch, () -> {
|
||||
node(arc, () -> {
|
||||
node(wave, () -> {
|
||||
node(separator, () -> {
|
||||
node(pulverizer, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(lancer, () -> {
|
||||
node(meltdown, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(shockMine, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
node(copperWall, () -> {
|
||||
node(copperWallLarge);
|
||||
node(titaniumWall, () -> {
|
||||
node(door, () -> {
|
||||
node(doorLarge);
|
||||
});
|
||||
node(plastaniumWall, () -> {
|
||||
node(plastaniumWallLarge, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
node(titaniumWallLarge);
|
||||
node(thoriumWall, () -> {
|
||||
node(thoriumWallLarge);
|
||||
node(surgeWall, () -> {
|
||||
node(surgeWallLarge);
|
||||
node(phaseWall, () -> {
|
||||
node(phaseWallLarge);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(mechanicalDrill, () -> {
|
||||
node(graphitePress, () -> {
|
||||
node(pneumaticDrill, () -> {
|
||||
node(cultivator, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(laserDrill, () -> {
|
||||
node(blastDrill, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(waterExtractor, () -> {
|
||||
node(oilExtractor, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(pyratiteMixer, () -> {
|
||||
node(blastMixer, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(siliconSmelter, () -> {
|
||||
|
||||
node(sporePress, () -> {
|
||||
node(coalCentrifuge, () -> {
|
||||
|
||||
});
|
||||
node(multiPress, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(plastaniumCompressor, () -> {
|
||||
node(phaseWeaver, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(kiln, () -> {
|
||||
node(incinerator, () -> {
|
||||
node(melter, () -> {
|
||||
node(surgeSmelter, () -> {
|
||||
node(cryofluidMixer, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(separator, () -> {
|
||||
node(pulverizer, () -> {
|
||||
|
||||
node(mechanicalPump, () -> {
|
||||
node(conduit, () -> {
|
||||
node(liquidJunction, () -> {
|
||||
node(liquidRouter, () -> {
|
||||
node(liquidTank);
|
||||
|
||||
node(bridgeConduit);
|
||||
|
||||
node(pulseConduit, () -> {
|
||||
node(phaseConduit, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(platedConduit, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(cryofluidMixer, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
node(mechanicalPump, () -> {
|
||||
node(conduit, () -> {
|
||||
node(liquidJunction, () -> {
|
||||
node(liquidRouter, () -> {
|
||||
node(liquidTank);
|
||||
|
||||
node(pulseConduit, () -> {
|
||||
node(phaseConduit, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(platedConduit, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(rotaryPump, () -> {
|
||||
node(thermalPump, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
node(bridgeConduit);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(combustionGenerator, () -> {
|
||||
node(powerNode, () -> {
|
||||
node(powerNodeLarge, () -> {
|
||||
node(diode, () -> {
|
||||
node(surgeTower, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(battery, () -> {
|
||||
node(batteryLarge, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(mender, () -> {
|
||||
node(mendProjector, () -> {
|
||||
node(forceProjector, () -> {
|
||||
node(overdriveProjector, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(repairPoint, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(turbineGenerator, () -> {
|
||||
node(thermalGenerator, () -> {
|
||||
node(differentialGenerator, () -> {
|
||||
node(thoriumReactor, () -> {
|
||||
node(impactReactor, () -> {
|
||||
node(rotaryPump, () -> {
|
||||
node(thermalPump, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(rtgGenerator, () -> {
|
||||
node(combustionGenerator, () -> {
|
||||
node(powerNode, () -> {
|
||||
node(powerNodeLarge, () -> {
|
||||
node(diode, () -> {
|
||||
node(surgeTower, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(battery, () -> {
|
||||
node(batteryLarge, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(mender, () -> {
|
||||
node(mendProjector, () -> {
|
||||
node(forceProjector, () -> {
|
||||
node(overdriveProjector, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(repairPoint, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(turbineGenerator, () -> {
|
||||
node(thermalGenerator, () -> {
|
||||
node(differentialGenerator, () -> {
|
||||
node(thoriumReactor, () -> {
|
||||
node(impactReactor, () -> {
|
||||
|
||||
});
|
||||
|
||||
node(rtgGenerator, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(solarPanel, () -> {
|
||||
node(largeSolarPanel, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(draugFactory, () -> {
|
||||
node(spiritFactory, () -> {
|
||||
node(phantomFactory);
|
||||
});
|
||||
|
||||
node(daggerFactory, () -> {
|
||||
node(commandCenter, () -> {
|
||||
});
|
||||
node(crawlerFactory, () -> {
|
||||
node(titanFactory, () -> {
|
||||
node(fortressFactory, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(wraithFactory, () -> {
|
||||
node(ghoulFactory, () -> {
|
||||
node(revenantFactory, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
@@ -267,58 +305,27 @@ public class TechTree implements ContentList{
|
||||
});
|
||||
});
|
||||
|
||||
node(solarPanel, () -> {
|
||||
node(largeSolarPanel, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(draugFactory, () -> {
|
||||
node(spiritFactory, () -> {
|
||||
node(phantomFactory);
|
||||
});
|
||||
|
||||
node(daggerFactory, () -> {
|
||||
node(commandCenter, () -> {});
|
||||
node(crawlerFactory, () -> {
|
||||
node(titanFactory, () -> {
|
||||
node(fortressFactory, () -> {
|
||||
node(dartPad, () -> {
|
||||
node(deltaPad, () -> {
|
||||
|
||||
node(javelinPad, () -> {
|
||||
node(tridentPad, () -> {
|
||||
node(glaivePad);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(wraithFactory, () -> {
|
||||
node(ghoulFactory, () -> {
|
||||
node(revenantFactory, () -> {
|
||||
node(tauPad, () -> {
|
||||
node(omegaPad, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
node(dartPad, () -> {
|
||||
node(deltaPad, () -> {
|
||||
|
||||
node(javelinPad, () -> {
|
||||
node(tridentPad, () -> {
|
||||
node(glaivePad);
|
||||
});
|
||||
});
|
||||
|
||||
node(tauPad, () -> {
|
||||
node(omegaPad, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private static TechNode node(Block block, Runnable children){
|
||||
ItemStack[] requirements = new ItemStack[block.requirements.length];
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package mindustry.content;
|
||||
|
||||
import arc.struct.*;
|
||||
import mindustry.ctype.ContentList;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.bullet.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.entities.type.Bullet;
|
||||
import mindustry.entities.type.base.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
@@ -103,23 +101,14 @@ public class UnitTypes implements ContentList{
|
||||
reload = 12f;
|
||||
ejectEffect = Fx.none;
|
||||
shootSound = Sounds.explosion;
|
||||
bullet = new BombBulletType(2f, 3f, "clear"){
|
||||
{
|
||||
hitEffect = Fx.pulverize;
|
||||
lifetime = 30f;
|
||||
speed = 1.1f;
|
||||
splashDamageRadius = 55f;
|
||||
splashDamage = 30f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Bullet b){
|
||||
if(b.getOwner() instanceof Unit){
|
||||
((Unit)b.getOwner()).kill();
|
||||
}
|
||||
b.time(b.lifetime());
|
||||
}
|
||||
};
|
||||
bullet = new BombBulletType(2f, 3f, "clear"){{
|
||||
hitEffect = Fx.pulverize;
|
||||
lifetime = 2f;
|
||||
speed = 1.1f;
|
||||
splashDamageRadius = 55f;
|
||||
splashDamage = 30f;
|
||||
killShooter = true;
|
||||
}};
|
||||
}};
|
||||
}};
|
||||
|
||||
|
||||
@@ -133,9 +133,9 @@ public class NetClient implements ApplicationListener{
|
||||
}
|
||||
|
||||
//called on all clients
|
||||
@Remote(called = Loc.server, targets = Loc.server, variants = Variant.both)
|
||||
@Remote(targets = Loc.server, variants = Variant.both)
|
||||
public static void sendMessage(String message, String sender, Player playersender){
|
||||
if(Vars.ui != null && !(playersender != null && net.server() && sender.startsWith("[#" + player.getTeam().color.toString() + "]<T>"))){
|
||||
if(Vars.ui != null){
|
||||
Vars.ui.chatfrag.addMessage(message, sender);
|
||||
}
|
||||
|
||||
@@ -171,6 +171,11 @@ public class NetClient implements ApplicationListener{
|
||||
return;
|
||||
}
|
||||
|
||||
//special case; graphical server needs to see its message
|
||||
if(!headless && player == Vars.player){
|
||||
Vars.ui.chatfrag.addMessage(message, colorizeName(player.id, player.name));
|
||||
}
|
||||
|
||||
//server console logging
|
||||
Log.info("&y{0}: &lb{1}", player.name, message);
|
||||
|
||||
@@ -261,6 +266,11 @@ public class NetClient implements ApplicationListener{
|
||||
ui.showText("", message);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onInfoToast(String message, float duration){
|
||||
ui.showInfoToast(message, duration);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onSetRules(Rules rules){
|
||||
state.rules = rules;
|
||||
@@ -272,7 +282,6 @@ public class NetClient implements ApplicationListener{
|
||||
netClient.removed.clear();
|
||||
logic.reset();
|
||||
|
||||
ui.chatfrag.clearMessages();
|
||||
net.setClientLoaded(false);
|
||||
|
||||
ui.loadfrag.show("$connecting.data");
|
||||
@@ -513,7 +522,7 @@ public class NetClient implements ApplicationListener{
|
||||
return Core.settings.getString("usid-" + ip, null);
|
||||
}else{
|
||||
byte[] bytes = new byte[8];
|
||||
new RandomXS128().nextBytes(bytes);
|
||||
new Rand().nextBytes(bytes);
|
||||
String result = new String(Base64Coder.encode(bytes));
|
||||
Core.settings.put("usid-" + ip, result);
|
||||
Core.settings.save();
|
||||
|
||||
@@ -230,7 +230,18 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
net.handleServer(InvokePacket.class, (con, packet) -> {
|
||||
if(con.player == null) return;
|
||||
RemoteReadServer.readPacket(packet.writeBuffer, packet.type, con.player);
|
||||
try{
|
||||
RemoteReadServer.readPacket(packet.writeBuffer, packet.type, con.player);
|
||||
}catch(ValidateException e){
|
||||
Log.debug("Validation failed for '{0}': {1}", e.player, e.getMessage());
|
||||
}catch(RuntimeException e){
|
||||
if(e.getCause() instanceof ValidateException){
|
||||
ValidateException v = (ValidateException)e.getCause();
|
||||
Log.debug("Validation failed for '{0}': {1}", v.player, v.getMessage());
|
||||
}else{
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerCommands();
|
||||
@@ -253,7 +264,7 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
page --;
|
||||
|
||||
if(page > pages || page < 0){
|
||||
if(page >= pages || page < 0){
|
||||
player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet].");
|
||||
return;
|
||||
}
|
||||
@@ -273,7 +284,11 @@ public class NetServer implements ApplicationListener{
|
||||
});
|
||||
|
||||
//duration of a a kick in seconds
|
||||
int kickDuration = 15 * 60;
|
||||
int kickDuration = 20 * 60;
|
||||
//voting round duration in seconds
|
||||
float voteDuration = 0.5f * 60;
|
||||
//cooldown between votes
|
||||
int voteCooldown = 60 * 2;
|
||||
|
||||
class VoteSession{
|
||||
Player target;
|
||||
@@ -291,7 +306,7 @@ public class NetServer implements ApplicationListener{
|
||||
map[0] = null;
|
||||
task.cancel();
|
||||
}
|
||||
}, 60 * 1);
|
||||
}, voteDuration);
|
||||
}
|
||||
|
||||
void vote(Player player, int d){
|
||||
@@ -315,9 +330,7 @@ public class NetServer implements ApplicationListener{
|
||||
}
|
||||
}
|
||||
|
||||
//cooldown between votes
|
||||
int voteTime = 60 * 3;
|
||||
Timekeeper vtime = new Timekeeper(voteTime);
|
||||
Timekeeper vtime = new Timekeeper(voteCooldown);
|
||||
//current kick sessions
|
||||
VoteSession[] currentlyKicking = {null};
|
||||
|
||||
@@ -364,7 +377,7 @@ public class NetServer implements ApplicationListener{
|
||||
player.sendMessage("[scarlet]Only players on your team can be kicked.");
|
||||
}else{
|
||||
if(!vtime.get()){
|
||||
player.sendMessage("[scarlet]You must wait " + voteTime/60 + " minutes between votekicks.");
|
||||
player.sendMessage("[scarlet]You must wait " + voteCooldown/60 + " minutes between votekicks.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -504,6 +517,7 @@ public class NetServer implements ApplicationListener{
|
||||
player.isShooting = shooting;
|
||||
player.isBuilding = building;
|
||||
player.buildQueue().clear();
|
||||
|
||||
for(BuildRequest req : requests){
|
||||
if(req == null) continue;
|
||||
Tile tile = world.tile(req.x, req.y);
|
||||
@@ -513,10 +527,23 @@ public class NetServer implements ApplicationListener{
|
||||
continue;
|
||||
}else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || tile.rotation() == req.rotation)){
|
||||
continue;
|
||||
}else if(connection.rejectedRequests.contains(r -> r.breaking == req.breaking && r.x == req.x && r.y == req.y)){ //check if request was recently rejected, and skip it if so
|
||||
continue;
|
||||
}else if(!netServer.admins.allowAction(player, req.breaking ? ActionType.breakBlock : ActionType.placeBlock, tile, action -> { //make sure request is allowed by the server
|
||||
action.block = req.block;
|
||||
action.rotation = req.rotation;
|
||||
action.config = req.config;
|
||||
})){
|
||||
//force the player to remove this request if that's not the case
|
||||
Call.removeQueueBlock(player.con, req.x, req.y, req.breaking);
|
||||
connection.rejectedRequests.add(req);
|
||||
continue;
|
||||
}
|
||||
player.buildQueue().addLast(req);
|
||||
}
|
||||
|
||||
connection.rejectedRequests.clear();
|
||||
|
||||
vector.set(x - player.getInterpolator().target.x, y - player.getInterpolator().target.y);
|
||||
vector.limit(maxMove);
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public interface Platform{
|
||||
String uuid = Core.settings.getString("uuid", "");
|
||||
if(uuid.isEmpty()){
|
||||
byte[] result = new byte[8];
|
||||
new RandomXS128().nextBytes(result);
|
||||
new Rand().nextBytes(result);
|
||||
uuid = new String(Base64Coder.encode(result));
|
||||
Core.settings.put("uuid", uuid);
|
||||
Core.settings.save();
|
||||
|
||||
@@ -2,29 +2,22 @@ package mindustry.core;
|
||||
|
||||
import arc.*;
|
||||
import arc.Graphics.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.Input.*;
|
||||
import arc.assets.*;
|
||||
import arc.assets.loaders.*;
|
||||
import arc.assets.loaders.resolvers.*;
|
||||
import arc.struct.*;
|
||||
import arc.files.*;
|
||||
import arc.freetype.*;
|
||||
import arc.freetype.FreeTypeFontGenerator.*;
|
||||
import arc.freetype.FreetypeFontLoader.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.actions.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.TextField.*;
|
||||
import arc.scene.ui.Tooltip.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.editor.*;
|
||||
@@ -39,6 +32,8 @@ import static arc.scene.actions.Actions.*;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class UI implements ApplicationListener, Loadable{
|
||||
public static PixmapPacker packer;
|
||||
|
||||
public MenuFragment menufrag;
|
||||
public HudFragment hudfrag;
|
||||
public ChatFragment chatfrag;
|
||||
@@ -77,7 +72,7 @@ public class UI implements ApplicationListener, Loadable{
|
||||
public Cursor drillCursor, unloadCursor;
|
||||
|
||||
public UI(){
|
||||
setupFonts();
|
||||
Fonts.loadFonts();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,6 +94,7 @@ public class UI implements ApplicationListener, Loadable{
|
||||
Icon.load();
|
||||
Styles.load();
|
||||
Tex.loadStyles();
|
||||
Fonts.loadContentIcons();
|
||||
|
||||
Dialog.setShowAction(() -> sequence(alpha(0f), fadeIn(0.1f)));
|
||||
Dialog.setHideAction(() -> sequence(fadeOut(0.1f)));
|
||||
@@ -116,7 +112,9 @@ public class UI implements ApplicationListener, Loadable{
|
||||
Colors.put("unlaunched", Color.valueOf("8982ed"));
|
||||
Colors.put("highlight", Pal.accent.cpy().lerp(Color.white, 0.3f));
|
||||
Colors.put("stat", Pal.stat);
|
||||
loadExtraCursors();
|
||||
|
||||
drillCursor = Core.graphics.newCursor("drill");
|
||||
unloadCursor = Core.graphics.newCursor("unload");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,64 +122,6 @@ public class UI implements ApplicationListener, Loadable{
|
||||
return Array.with(new AssetDescriptor<>(Control.class), new AssetDescriptor<>("outline", BitmapFont.class), new AssetDescriptor<>("default", BitmapFont.class), new AssetDescriptor<>("chat", BitmapFont.class));
|
||||
}
|
||||
|
||||
/** Called from a static context to make the cursor appear immediately upon startup.*/
|
||||
public static void loadSystemCursors(){
|
||||
SystemCursor.arrow.set(Core.graphics.newCursor("cursor"));
|
||||
SystemCursor.hand.set(Core.graphics.newCursor("hand"));
|
||||
SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam"));
|
||||
|
||||
Core.graphics.restoreCursor();
|
||||
}
|
||||
|
||||
/** Called from a static context for use in the loading screen.*/
|
||||
public static void loadDefaultFont(){
|
||||
FileHandleResolver resolver = new InternalFileHandleResolver();
|
||||
Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
|
||||
Core.assets.setLoader(BitmapFont.class, null, new FreetypeFontLoader(resolver){
|
||||
@Override
|
||||
public BitmapFont loadSync(AssetManager manager, String fileName, Fi file, FreeTypeFontLoaderParameter parameter){
|
||||
if(fileName.equals("outline")){
|
||||
parameter.fontParameters.borderWidth = Scl.scl(2f);
|
||||
parameter.fontParameters.spaceX -= parameter.fontParameters.borderWidth;
|
||||
}
|
||||
parameter.fontParameters.magFilter = TextureFilter.Linear;
|
||||
parameter.fontParameters.minFilter = TextureFilter.Linear;
|
||||
parameter.fontParameters.size = fontParameter().size;
|
||||
return super.loadSync(manager, fileName, file, parameter);
|
||||
}
|
||||
});
|
||||
|
||||
FreeTypeFontParameter param = new FreeTypeFontParameter(){{
|
||||
borderColor = Color.darkGray;
|
||||
incremental = true;
|
||||
}};
|
||||
|
||||
Core.assets.load("outline", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/font.ttf", param)).loaded = t -> Fonts.outline = (BitmapFont)t;
|
||||
}
|
||||
|
||||
void loadExtraCursors(){
|
||||
drillCursor = Core.graphics.newCursor("drill");
|
||||
unloadCursor = Core.graphics.newCursor("unload");
|
||||
}
|
||||
|
||||
public void setupFonts(){
|
||||
String fontName = "fonts/font.ttf";
|
||||
|
||||
FreeTypeFontParameter param = fontParameter();
|
||||
|
||||
Core.assets.load("default", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.def = (BitmapFont)f;
|
||||
Core.assets.load("chat", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.chat = (BitmapFont)f;
|
||||
}
|
||||
|
||||
static FreeTypeFontParameter fontParameter(){
|
||||
return new FreeTypeFontParameter(){{
|
||||
size = (int)(Scl.scl(18f));
|
||||
shadowColor = Color.darkGray;
|
||||
shadowOffsetY = 2;
|
||||
incremental = true;
|
||||
}};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
if(disableUI || Core.scene == null) return;
|
||||
@@ -271,7 +211,17 @@ public class UI implements ApplicationListener, Loadable{
|
||||
|
||||
@Override
|
||||
public void dispose(){
|
||||
//generator.dispose();
|
||||
if(packer != null){
|
||||
packer.dispose();
|
||||
packer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public TextureRegionDrawable getIcon(String name){
|
||||
if(Icon.icons.containsKey(name)){
|
||||
return Icon.icons.get(name);
|
||||
}
|
||||
return Core.atlas.getDrawable("error");
|
||||
}
|
||||
|
||||
public void loadAnd(Runnable call){
|
||||
@@ -339,6 +289,19 @@ public class UI implements ApplicationListener, Loadable{
|
||||
Core.scene.add(table);
|
||||
}
|
||||
|
||||
public void showInfoToast(String info, float duration){
|
||||
Table table = new Table();
|
||||
table.setFillParent(true);
|
||||
table.update(() -> {
|
||||
if(state.is(State.menu)){
|
||||
table.remove();
|
||||
}
|
||||
});
|
||||
table.actions(Actions.delay(duration * 0.9f), Actions.fadeOut(duration * 0.1f, Interpolation.fade), Actions.remove());
|
||||
table.top().table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).padTop(10);
|
||||
Core.scene.add(table);
|
||||
}
|
||||
|
||||
public void showInfo(String info){
|
||||
new Dialog(""){{
|
||||
getCell(cont).growX();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.ctype;
|
||||
|
||||
import arc.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
@@ -13,7 +14,7 @@ public abstract class UnlockableContent extends MappableContent{
|
||||
/** Localized, formal name. Never null. Set to block name if not found in bundle. */
|
||||
public String localizedName;
|
||||
/** Localized description. May be null. */
|
||||
public String description;
|
||||
public @Nullable String description;
|
||||
/** Icons by Cicon ID.*/
|
||||
protected TextureRegion[] cicons = new TextureRegion[mindustry.ui.Cicon.all.length];
|
||||
|
||||
@@ -24,6 +25,10 @@ public abstract class UnlockableContent extends MappableContent{
|
||||
this.description = Core.bundle.getOrNull(getContentType() + "." + this.name + ".description");
|
||||
}
|
||||
|
||||
public String displayDescription(){
|
||||
return minfo.mod == null ? description : description + "\n" + Core.bundle.format("mod.display", minfo.mod.meta.displayName());
|
||||
}
|
||||
|
||||
/** Generate any special icons for this content. Called asynchronously.*/
|
||||
@CallSuper
|
||||
public void createIcons(MultiPacker packer){
|
||||
|
||||
@@ -66,30 +66,30 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
menu.cont.table(t -> {
|
||||
t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5);
|
||||
|
||||
t.addImageTextButton("$editor.savemap", Icon.floppy16Small, this::save);
|
||||
t.addImageTextButton("$editor.savemap", Icon.save, this::save);
|
||||
|
||||
t.addImageTextButton("$editor.mapinfo", Icon.pencilSmall, () -> {
|
||||
t.addImageTextButton("$editor.mapinfo", Icon.pencil, () -> {
|
||||
infoDialog.show();
|
||||
menu.hide();
|
||||
});
|
||||
|
||||
t.row();
|
||||
|
||||
t.addImageTextButton("$editor.generate", Icon.editorSmall, () -> {
|
||||
t.addImageTextButton("$editor.generate", Icon.terrain, () -> {
|
||||
generateDialog.show(generateDialog::applyToEditor);
|
||||
menu.hide();
|
||||
});
|
||||
|
||||
t.addImageTextButton("$editor.resize", Icon.resizeSmall, () -> {
|
||||
t.addImageTextButton("$editor.resize", Icon.resize, () -> {
|
||||
resizeDialog.show();
|
||||
menu.hide();
|
||||
});
|
||||
|
||||
t.row();
|
||||
|
||||
t.addImageTextButton("$editor.import", Icon.loadMapSmall, () ->
|
||||
t.addImageTextButton("$editor.import", Icon.download, () ->
|
||||
createDialog("$editor.import",
|
||||
"$editor.importmap", "$editor.importmap.description", Icon.loadMap, (Runnable)loadDialog::show,
|
||||
"$editor.importmap", "$editor.importmap.description", Icon.download, (Runnable)loadDialog::show,
|
||||
"$editor.importfile", "$editor.importfile.description", Icon.file, (Runnable)() ->
|
||||
platform.showFileChooser(true, mapExtension, file -> ui.loadAnd(() -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
@@ -115,7 +115,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
})))
|
||||
);
|
||||
|
||||
t.addImageTextButton("$editor.export", Icon.saveMapSmall, () -> {
|
||||
t.addImageTextButton("$editor.export", Icon.upload, () -> {
|
||||
if(!ios){
|
||||
platform.showFileChooser(false, mapExtension, file -> {
|
||||
ui.loadAnd(() -> {
|
||||
@@ -148,7 +148,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
menu.cont.row();
|
||||
|
||||
if(steam){
|
||||
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.linkSmall, () -> {
|
||||
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.link, () -> {
|
||||
Map builtin = maps.all().find(m -> m.name().equals(editor.getTags().get("name", "").trim()));
|
||||
|
||||
if(editor.getTags().containsKey("steamid") && builtin != null && !builtin.custom){
|
||||
@@ -181,11 +181,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
menu.cont.row();
|
||||
}
|
||||
|
||||
menu.cont.addImageTextButton("$editor.ingame", Icon.arrowSmall, this::playtest).padTop(!steam ? -3 : 1).size(swidth * 2f + 10, 60f);
|
||||
menu.cont.addImageTextButton("$editor.ingame", Icon.right, this::playtest).padTop(!steam ? -3 : 1).size(swidth * 2f + 10, 60f);
|
||||
|
||||
menu.cont.row();
|
||||
|
||||
menu.cont.addImageTextButton("$quit", Icon.backSmall, () -> {
|
||||
menu.cont.addImageTextButton("$quit", Icon.exit, () -> {
|
||||
tryExit();
|
||||
menu.hide();
|
||||
}).size(swidth * 2f + 10, 60f);
|
||||
@@ -427,7 +427,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
|
||||
Cons<EditorTool> addTool = tool -> {
|
||||
|
||||
ImageButton button = new ImageButton(Core.atlas.drawable("icon-" + tool.name() + "-small"), Styles.clearTogglei);
|
||||
ImageButton button = new ImageButton(ui.getIcon(tool.name()), Styles.clearTogglei);
|
||||
button.clicked(() -> {
|
||||
view.setTool(tool);
|
||||
if(lastTable[0] != null){
|
||||
@@ -503,16 +503,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
|
||||
tools.defaults().size(size, size);
|
||||
|
||||
tools.addImageButton(Icon.menuLargeSmall, Styles.cleari, menu::show);
|
||||
tools.addImageButton(Icon.menu, Styles.cleari, menu::show);
|
||||
|
||||
ImageButton grid = tools.addImageButton(Icon.gridSmall, Styles.clearTogglei, () -> view.setGrid(!view.isGrid())).get();
|
||||
ImageButton grid = tools.addImageButton(Icon.grid, Styles.clearTogglei, () -> view.setGrid(!view.isGrid())).get();
|
||||
|
||||
addTool.get(EditorTool.zoom);
|
||||
|
||||
tools.row();
|
||||
|
||||
ImageButton undo = tools.addImageButton(Icon.undoSmall, Styles.cleari, editor::undo).get();
|
||||
ImageButton redo = tools.addImageButton(Icon.redoSmall, Styles.cleari, editor::redo).get();
|
||||
ImageButton undo = tools.addImageButton(Icon.undo, Styles.cleari, editor::undo).get();
|
||||
ImageButton redo = tools.addImageButton(Icon.redo, Styles.cleari, editor::redo).get();
|
||||
|
||||
addTool.get(EditorTool.pick);
|
||||
|
||||
@@ -534,7 +534,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
addTool.get(EditorTool.fill);
|
||||
addTool.get(EditorTool.spray);
|
||||
|
||||
ImageButton rotate = tools.addImageButton(Icon.arrow16Small, Styles.cleari, () -> editor.rotation = (editor.rotation + 1) % 4).get();
|
||||
ImageButton rotate = tools.addImageButton(Icon.right, Styles.cleari, () -> editor.rotation = (editor.rotation + 1) % 4).get();
|
||||
rotate.getImage().update(() -> {
|
||||
rotate.getImage().setRotation(editor.rotation * 90);
|
||||
rotate.getImage().setOrigin(Align.center);
|
||||
|
||||
@@ -235,24 +235,24 @@ public class MapGenerateDialog extends FloatingDialog{
|
||||
t.table(b -> {
|
||||
ImageButtonStyle style = Styles.cleari;
|
||||
b.defaults().size(50f);
|
||||
b.addImageButton(Icon.refreshSmall, style, () -> {
|
||||
b.addImageButton(Icon.refresh, style, () -> {
|
||||
filter.randomize();
|
||||
update();
|
||||
});
|
||||
|
||||
b.addImageButton(Icon.arrowUpSmall, style, () -> {
|
||||
b.addImageButton(Icon.upOpen, style, () -> {
|
||||
int idx = filters.indexOf(filter);
|
||||
filters.swap(idx, Math.max(0, idx - 1));
|
||||
rebuildFilters();
|
||||
update();
|
||||
});
|
||||
b.addImageButton(Icon.arrowDownSmall, style, () -> {
|
||||
b.addImageButton(Icon.downOpen, style, () -> {
|
||||
int idx = filters.indexOf(filter);
|
||||
filters.swap(idx, Math.min(filters.size - 1, idx + 1));
|
||||
rebuildFilters();
|
||||
update();
|
||||
});
|
||||
b.addImageButton(Icon.trashSmall, style, () -> {
|
||||
b.addImageButton(Icon.trash, style, () -> {
|
||||
filters.remove(filter);
|
||||
rebuildFilters();
|
||||
update();
|
||||
|
||||
@@ -189,7 +189,7 @@ public class MapView extends Element implements GestureListener{
|
||||
lastTool = null;
|
||||
}
|
||||
|
||||
if(ui.editor.hasPane()) return;
|
||||
if(Core.scene.getScrollFocus() != this) return;
|
||||
|
||||
zoom += Core.input.axis(KeyCode.SCROLL) / 10f * zoom;
|
||||
clampZoom();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package mindustry.entities;
|
||||
|
||||
/** A higher ordinal means a higher priority. Higher priority blocks will always get targeted over those of lower priority, regardless of distance. */
|
||||
public enum TargetPriority{
|
||||
base,
|
||||
turret
|
||||
|
||||
@@ -39,6 +39,8 @@ public abstract class BulletType extends Content{
|
||||
public float reloadMultiplier = 1f;
|
||||
/** Recoil from shooter entities. */
|
||||
public float recoil;
|
||||
/** Whether to kill the shooter when this is shot. For suicide bombers. */
|
||||
public boolean killShooter;
|
||||
|
||||
public float splashDamage = 0f;
|
||||
/** Knockback in velocity. */
|
||||
@@ -146,6 +148,9 @@ public abstract class BulletType extends Content{
|
||||
}
|
||||
|
||||
public void init(Bullet b){
|
||||
if(killShooter && b.getOwner() instanceof HealthTrait){
|
||||
((HealthTrait)b.getOwner()).kill();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Bullet b){
|
||||
|
||||
@@ -27,7 +27,7 @@ import static mindustry.Vars.*;
|
||||
public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{
|
||||
public static final float lifetime = 10f;
|
||||
|
||||
private static final RandomXS128 random = new RandomXS128();
|
||||
private static final Rand random = new Rand();
|
||||
private static final Rect rect = new Rect();
|
||||
private static final Array<Unit> entities = new Array<>();
|
||||
private static final IntSet hit = new IntSet();
|
||||
|
||||
@@ -38,4 +38,9 @@ public class RubbleDecal extends Decal{
|
||||
}
|
||||
Draw.rect(region, x, y, Mathf.randomSeed(id, 0, 4) * 90);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float drawSize(){
|
||||
return region.getWidth() * 3f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,14 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
||||
return request.stuck && !core.items.has(request.block.requirements);
|
||||
}
|
||||
|
||||
default void removeRequest(int x, int y, boolean breaking){
|
||||
//remove matching request
|
||||
int idx = player.buildQueue().indexOf(req -> req.breaking == breaking && req.x == x && req.y == y);
|
||||
if(idx != -1){
|
||||
player.buildQueue().removeIndex(idx);
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns the queue for storing build requests. */
|
||||
Queue<BuildRequest> buildQueue();
|
||||
|
||||
|
||||
@@ -14,6 +14,11 @@ public interface HealthTrait{
|
||||
|
||||
void setDead(boolean dead);
|
||||
|
||||
default void kill(){
|
||||
health(-1);
|
||||
damage(1);
|
||||
}
|
||||
|
||||
default void onHit(SolidTrait entity){
|
||||
}
|
||||
|
||||
|
||||
@@ -407,9 +407,9 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
if(isAdmin){
|
||||
float s = 3f;
|
||||
Draw.color(color.r * 0.5f, color.g * 0.5f, color.b * 0.5f, 1f);
|
||||
Draw.rect(Core.atlas.find("icon-admin-badge"), x + layout.width / 2f + 2 + 1, y + nameHeight - 1.5f, s, s);
|
||||
Draw.rect(Icon.adminSmall.getRegion(), x + layout.width / 2f + 2 + 1, y + nameHeight - 1.5f, s, s);
|
||||
Draw.color(color);
|
||||
Draw.rect(Core.atlas.find("icon-admin-badge"), x + layout.width / 2f + 2 + 1, y + nameHeight - 1f, s, s);
|
||||
Draw.rect(Icon.adminSmall.getRegion(), x + layout.width / 2f + 2 + 1, y + nameHeight - 1f, s, s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -762,7 +762,6 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
||||
public void sendMessage(String text){
|
||||
if(isLocal){
|
||||
if(Vars.ui != null){
|
||||
Log.info("add " + text);
|
||||
Vars.ui.chatfrag.addMessage(text, null);
|
||||
}
|
||||
}else{
|
||||
|
||||
@@ -185,11 +185,6 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
y = Mathf.clamp(y, 0, world.height() * tilesize - tilesize);
|
||||
}
|
||||
|
||||
public void kill(){
|
||||
health = -1;
|
||||
damage(1);
|
||||
}
|
||||
|
||||
public boolean isImmune(StatusEffect effect){
|
||||
return false;
|
||||
}
|
||||
@@ -242,6 +237,10 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
return tile == null ? (Floor)Blocks.air : tile.floor();
|
||||
}
|
||||
|
||||
public @Nullable Tile tileOn(){
|
||||
return world.tileWorld(x, y);
|
||||
}
|
||||
|
||||
public void onRespawn(Tile tile){
|
||||
}
|
||||
|
||||
|
||||
@@ -85,9 +85,15 @@ public class GlobalData{
|
||||
if(amount > 0){
|
||||
unlockContent(item);
|
||||
}
|
||||
amount = Math.max(amount, 0);
|
||||
|
||||
modified = true;
|
||||
items.getAndIncrement(item, 0, amount);
|
||||
state.stats.itemsDelivered.getAndIncrement(item, 0, amount);
|
||||
|
||||
//clamp overflow
|
||||
if(items.get(item, 0) < 0) items.put(item, Integer.MAX_VALUE);
|
||||
if(state.stats.itemsDelivered.get(item, 0) < 0) state.stats.itemsDelivered.put(item, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
public boolean hasItems(Array<ItemStack> stacks){
|
||||
|
||||
@@ -35,7 +35,7 @@ public class Team implements Comparable<Team>{
|
||||
for(int i = 6; i < all.length; i++){
|
||||
new Team(i, "team#" + i, Color.HSVtoRGB(360f * Mathf.random(), 100f * Mathf.random(0.6f, 1f), 100f * Mathf.random(0.8f, 1f), 1f));
|
||||
}
|
||||
Mathf.random.setSeed(new RandomXS128().nextLong());
|
||||
Mathf.random.setSeed(new Rand().nextLong());
|
||||
}
|
||||
|
||||
public static Team get(int id){
|
||||
|
||||
@@ -43,6 +43,10 @@ public class Drawf{
|
||||
}
|
||||
|
||||
public static void arrow(float x, float y, float x2, float y2, float length, float radius){
|
||||
arrow(x, y, x2, y2, length, radius, Pal.accent);
|
||||
}
|
||||
|
||||
public static void arrow(float x, float y, float x2, float y2, float length, float radius, Color color){
|
||||
float angle = Angles.angle(x, y, x2, y2);
|
||||
float space = 2f;
|
||||
Tmp.v1.set(x2, y2).sub(x, y).limit(length);
|
||||
@@ -50,7 +54,7 @@ public class Drawf{
|
||||
|
||||
Draw.color(Pal.gray);
|
||||
Fill.poly(vx, vy, 3, radius + space, angle);
|
||||
Draw.color(Pal.accent);
|
||||
Draw.color(color);
|
||||
Fill.poly(vx, vy, 3, radius, angle);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ public class FloorRenderer implements Disposable{
|
||||
int chunksx = Mathf.ceil((float)(world.width()) / chunksize),
|
||||
chunksy = Mathf.ceil((float)(world.height()) / chunksize);
|
||||
cache = new Chunk[chunksx][chunksy];
|
||||
cbatch = new MultiCacheBatch(chunksize * chunksize * 4);
|
||||
cbatch = new MultiCacheBatch(chunksize * chunksize * 5);
|
||||
|
||||
Time.mark();
|
||||
|
||||
|
||||
@@ -46,9 +46,9 @@ public class IndexedRenderer implements Disposable{
|
||||
private float[] tmpVerts = new float[vsize * 6];
|
||||
private float[] vertices;
|
||||
|
||||
private Matrix3 projMatrix = new Matrix3();
|
||||
private Matrix3 transMatrix = new Matrix3();
|
||||
private Matrix3 combined = new Matrix3();
|
||||
private Mat projMatrix = new Mat();
|
||||
private Mat transMatrix = new Mat();
|
||||
private Mat combined = new Mat();
|
||||
private float color = Color.white.toFloatBits();
|
||||
|
||||
public IndexedRenderer(int sprites){
|
||||
@@ -210,11 +210,11 @@ public class IndexedRenderer implements Disposable{
|
||||
mesh.updateVertices(index * vsize * 6, vertices);
|
||||
}
|
||||
|
||||
public Matrix3 getTransformMatrix(){
|
||||
public Mat getTransformMatrix(){
|
||||
return transMatrix;
|
||||
}
|
||||
|
||||
public void setProjectionMatrix(Matrix3 matrix){
|
||||
public void setProjectionMatrix(Mat matrix){
|
||||
projMatrix = matrix;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ public class MenuRenderer implements Disposable{
|
||||
|
||||
private int cacheFloor, cacheWall;
|
||||
private Camera camera = new Camera();
|
||||
private Matrix3 mat = new Matrix3();
|
||||
private Mat mat = new Mat();
|
||||
private FrameBuffer shadows;
|
||||
private CacheBatch batch;
|
||||
private float time = 0f;
|
||||
|
||||
@@ -64,7 +64,7 @@ public class OverlayRenderer{
|
||||
for(Tile mechpad : indexer.getAllied(player.getTeam(), BlockFlag.mechPad)){
|
||||
if(!(mechpad.block() instanceof MechPad)) continue;
|
||||
if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f)
|
||||
.setCenter(Core.camera.position.x, Core.camera.position.y).contains(mechpad.x, mechpad.y)){
|
||||
.setCenter(Core.camera.position.x, Core.camera.position.y).contains(mechpad.drawx(), mechpad.drawy())){
|
||||
|
||||
Tmp.v1.set(mechpad.drawx(), mechpad.drawy()).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public class DesktopInput extends InputHandler{
|
||||
Core.keybinds.get(Binding.schematic_flip_y).key.toString())).style(Styles.outlineLabel);
|
||||
b.row();
|
||||
b.table(a -> {
|
||||
a.addImageTextButton("$schematic.add", Icon.saveSmall, this::showSchematicSave).colspan(2).size(250f, 50f).disabled(f -> lastSchematic == null || lastSchematic.file != null);
|
||||
a.addImageTextButton("$schematic.add", Icon.save, this::showSchematicSave).colspan(2).size(250f, 50f).disabled(f -> lastSchematic == null || lastSchematic.file != null);
|
||||
});
|
||||
}).margin(6f);
|
||||
});
|
||||
@@ -256,7 +256,7 @@ public class DesktopInput extends InputHandler{
|
||||
table.row();
|
||||
table.left().margin(0f).defaults().size(48f).left();
|
||||
|
||||
table.addImageButton(Icon.pasteSmall, Styles.clearPartiali, () -> {
|
||||
table.addImageButton(Icon.paste, Styles.clearPartiali, () -> {
|
||||
ui.schematics.show();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package mindustry.input;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -13,8 +11,10 @@ import arc.math.geom.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.effect.*;
|
||||
@@ -27,12 +27,13 @@ import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.input.Placement.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.net.Administration.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.fragments.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.BuildBlock.*;
|
||||
import mindustry.world.blocks.power.PowerNode;
|
||||
import mindustry.world.blocks.power.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -66,6 +67,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
//methods to override
|
||||
|
||||
@Remote(variants = Variant.one)
|
||||
public static void removeQueueBlock(int x, int y, boolean breaking){
|
||||
player.removeRequest(x, y, breaking);
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.client, called = Loc.server)
|
||||
public static void dropItem(Player player, float angle){
|
||||
if(net.server() && player.item().amount <= 0){
|
||||
@@ -78,8 +84,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true, unreliable = true)
|
||||
public static void rotateBlock(Player player, Tile tile, boolean direction){
|
||||
if(net.server() && !Units.canInteract(player, tile)){
|
||||
throw new ValidateException(player, "Player cannot drop an item.");
|
||||
if(net.server() && (!Units.canInteract(player, tile) ||
|
||||
!netServer.admins.allowAction(player, ActionType.rotate, tile, action -> action.rotation = Mathf.mod(tile.rotation() + Mathf.sign(direction), 4)))){
|
||||
throw new ValidateException(player, "Player cannot rotate a block.");
|
||||
}
|
||||
|
||||
tile.rotation(Mathf.mod(tile.rotation() + Mathf.sign(direction), 4));
|
||||
@@ -93,7 +100,11 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
@Remote(targets = Loc.both, forward = true, called = Loc.server)
|
||||
public static void transferInventory(Player player, Tile tile){
|
||||
if(player == null || player.timer == null) return;
|
||||
if(net.server() && (player.item().amount <= 0 || player.isTransferring|| !Units.canInteract(player, tile))){
|
||||
if(net.server() && (player.item().amount <= 0 || player.isTransferring|| !Units.canInteract(player, tile) ||
|
||||
!netServer.admins.allowAction(player, ActionType.depositItem, tile, action -> {
|
||||
action.itemAmount = player.item().amount;
|
||||
action.item = player.item().item;
|
||||
}))){
|
||||
throw new ValidateException(player, "Player cannot transfer an item.");
|
||||
}
|
||||
|
||||
@@ -143,14 +154,18 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
@Remote(targets = Loc.both, called = Loc.server, forward = true)
|
||||
public static void onTileTapped(Player player, Tile tile){
|
||||
if(tile == null || player == null) return;
|
||||
if(!Units.canInteract(player, tile)) return;
|
||||
if(net.server() && (!Units.canInteract(player, tile) ||
|
||||
!netServer.admins.allowAction(player, ActionType.tapTile, tile, action -> {}))) throw new ValidateException(player, "Player cannot tap a tile.");
|
||||
tile.block().tapped(tile, player);
|
||||
Core.app.post(() -> Events.fire(new TapEvent(tile, player)));
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
public static void onTileConfig(Player player, Tile tile, int value){
|
||||
if(tile == null || !Units.canInteract(player, tile)) return;
|
||||
if(tile == null) return;
|
||||
|
||||
if(net.server() && (!Units.canInteract(player, tile) ||
|
||||
!netServer.admins.allowAction(player, ActionType.configure, tile, action -> action.config = value))) throw new ValidateException(player, "Player cannot configure a tile.");
|
||||
tile.block().configured(tile, player, value);
|
||||
Core.app.post(() -> Events.fire(new TapConfigEvent(tile, player, value)));
|
||||
}
|
||||
@@ -689,7 +704,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
}
|
||||
|
||||
public void add(){
|
||||
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
|
||||
Core.input.getInputProcessors().remove(i -> i instanceof InputHandler || (i instanceof GestureDetector && ((GestureDetector)i).getListener() instanceof InputHandler));
|
||||
Core.input.addProcessor(detector = new GestureDetector(20, 0.5f, 0.3f, 0.15f, this));
|
||||
Core.input.addProcessor(this);
|
||||
if(Core.scene != null){
|
||||
Table table = (Table)Core.scene.find("inputTable");
|
||||
|
||||
@@ -179,19 +179,19 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
table.row();
|
||||
table.left().margin(0f).defaults().size(48f);
|
||||
|
||||
table.addImageButton(Icon.breakSmall, Styles.clearTogglePartiali, () -> {
|
||||
table.addImageButton(Icon.hammer, Styles.clearTogglePartiali, () -> {
|
||||
mode = mode == breaking ? block == null ? none : placing : breaking;
|
||||
lastBlock = block;
|
||||
}).update(l -> l.setChecked(mode == breaking)).name("breakmode");
|
||||
|
||||
//diagonal swap button
|
||||
table.addImageButton(Icon.diagonalSmall, Styles.clearTogglePartiali, () -> {
|
||||
table.addImageButton(Icon.diagonal, Styles.clearTogglePartiali, () -> {
|
||||
Core.settings.put("swapdiagonal", !Core.settings.getBool("swapdiagonal"));
|
||||
Core.settings.save();
|
||||
}).update(l -> l.setChecked(Core.settings.getBool("swapdiagonal")));
|
||||
|
||||
//rotate button
|
||||
table.addImageButton(Icon.arrowSmall, Styles.clearTogglePartiali, () -> {
|
||||
table.addImageButton(Icon.right, Styles.clearTogglePartiali, () -> {
|
||||
if(block != null && block.rotate){
|
||||
rotation = Mathf.mod(rotation + 1, 4);
|
||||
}else{
|
||||
@@ -205,12 +205,12 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
boolean arrow = block != null && block.rotate;
|
||||
|
||||
i.getImage().setRotationOrigin(!arrow ? 0 : rotation * 90, Align.center);
|
||||
i.getStyle().imageUp = arrow ? Icon.arrowSmall : Icon.pasteSmall;
|
||||
i.getStyle().imageUp = arrow ? Icon.right : Icon.paste;
|
||||
i.setChecked(!arrow && schematicMode);
|
||||
});
|
||||
|
||||
//confirm button
|
||||
table.addImageButton(Icon.checkSmall, Styles.clearPartiali, () -> {
|
||||
table.addImageButton(Icon.ok, Styles.clearPartiali, () -> {
|
||||
for(BuildRequest request : selectRequests){
|
||||
Tile tile = request.tile();
|
||||
|
||||
@@ -253,12 +253,12 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
group.fill(t -> {
|
||||
t.bottom().left().visible(() -> (player.isBuilding() || block != null || mode == breaking || !selectRequests.isEmpty()) && !schem.get());
|
||||
t.addImageTextButton("$cancel", Icon.cancelSmall, () -> {
|
||||
t.addImageTextButton("$cancel", Icon.cancel, () -> {
|
||||
player.clearBuilding();
|
||||
selectRequests.clear();
|
||||
mode = none;
|
||||
block = null;
|
||||
}).width(155f);
|
||||
}).width(155f).margin(12f);
|
||||
});
|
||||
|
||||
group.fill(t -> {
|
||||
@@ -269,15 +269,15 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
ImageButtonStyle style = Styles.clearPartiali;
|
||||
|
||||
b.addImageButton(Icon.floppySmall, style, this::showSchematicSave).disabled(f -> lastSchematic == null || lastSchematic.file != null);
|
||||
b.addImageButton(Icon.cancelSmall, style, () -> {
|
||||
b.addImageButton(Icon.save, style, this::showSchematicSave).disabled(f -> lastSchematic == null || lastSchematic.file != null);
|
||||
b.addImageButton(Icon.cancel, style, () -> {
|
||||
selectRequests.clear();
|
||||
});
|
||||
b.row();
|
||||
b.addImageButton(Icon.flipSmall, style, () -> flipRequests(selectRequests, true));
|
||||
b.addImageButton(Icon.flipSmall, style, () -> flipRequests(selectRequests, false)).update(i -> i.getImage().setRotationOrigin(90f, Align.center));
|
||||
b.addImageButton(Icon.flipX, style, () -> flipRequests(selectRequests, true));
|
||||
b.addImageButton(Icon.flipY, style, () -> flipRequests(selectRequests, false));
|
||||
b.row();
|
||||
b.addImageButton(Icon.rotateSmall, style, () -> rotateRequests(selectRequests, 1));
|
||||
b.addImageButton(Icon.rotate, style, () -> rotateRequests(selectRequests, 1));
|
||||
|
||||
}).margin(4f);
|
||||
});
|
||||
|
||||
@@ -338,11 +338,11 @@ public class Maps{
|
||||
}
|
||||
|
||||
public void addDefaultOres(Array<GenerateFilter> filters){
|
||||
int index = 0;
|
||||
for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){
|
||||
Array<Block> ores = content.blocks().select(b -> b.isOverlay() && b.asFloor().oreDefault);
|
||||
for(Block block : ores){
|
||||
OreFilter filter = new OreFilter();
|
||||
filter.threshold += index ++ * 0.018f;
|
||||
filter.scl += index/2.1f;
|
||||
filter.threshold = block.asFloor().oreThreshold;
|
||||
filter.scl = block.asFloor().oreScale;
|
||||
filter.ore = block;
|
||||
filters.add(filter);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.dialogs.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
@@ -76,15 +77,15 @@ public abstract class FilterOption{
|
||||
|
||||
@Override
|
||||
public void build(Table table){
|
||||
table.addButton(b -> b.addImage(supplier.get().icon(mindustry.ui.Cicon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable())
|
||||
.setRegion(supplier.get() == Blocks.air ? Core.atlas.find("icon-none") : supplier.get().icon(mindustry.ui.Cicon.small))).size(8 * 3), () -> {
|
||||
table.addButton(b -> b.addImage(supplier.get().icon(Cicon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable())
|
||||
.setRegion(supplier.get() == Blocks.air ? Icon.block.getRegion() : supplier.get().icon(Cicon.small))).size(8 * 3), () -> {
|
||||
FloatingDialog dialog = new FloatingDialog("");
|
||||
dialog.setFillParent(false);
|
||||
int i = 0;
|
||||
for(Block block : Vars.content.blocks()){
|
||||
if(!filter.get(block)) continue;
|
||||
|
||||
dialog.cont.addImage(block == Blocks.air ? Core.atlas.find("icon-none-small") : block.icon(Cicon.medium)).size(8 * 4).pad(3).get().clicked(() -> {
|
||||
dialog.cont.addImage(block == Blocks.air ? Icon.block.getRegion() : block.icon(Cicon.medium)).size(8 * 4).pad(3).get().clicked(() -> {
|
||||
consumer.get(block);
|
||||
dialog.hide();
|
||||
changed.run();
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -42,7 +42,7 @@ public class Mods implements Loadable{
|
||||
|
||||
private Array<LoadedMod> mods = new Array<>();
|
||||
private ObjectMap<Class<?>, ModMeta> metas = new ObjectMap<>();
|
||||
private boolean requiresReload;
|
||||
private boolean requiresReload, createdAtlas;
|
||||
|
||||
public Mods(){
|
||||
Events.on(ClientLoadEvent.class, e -> Core.app.post(this::checkWarnings));
|
||||
@@ -112,13 +112,6 @@ public class Mods implements Loadable{
|
||||
totalSprites += sprites.size + overrides.size;
|
||||
});
|
||||
|
||||
for(AtlasRegion region : Core.atlas.getRegions()){
|
||||
PageType type = getPage(region);
|
||||
if(!packer.has(type, region.name)){
|
||||
packer.add(type, region.name, Core.atlas.getPixmap(region));
|
||||
}
|
||||
}
|
||||
|
||||
Log.debug("Time to pack textures: {0}", Time.elapsed());
|
||||
}
|
||||
|
||||
@@ -159,6 +152,16 @@ public class Mods implements Loadable{
|
||||
|
||||
//get textures packed
|
||||
if(totalSprites > 0){
|
||||
if(!createdAtlas) Core.atlas = new TextureAtlas(Core.files.internal("sprites/sprites.atlas"));
|
||||
createdAtlas = true;
|
||||
|
||||
for(AtlasRegion region : Core.atlas.getRegions()){
|
||||
PageType type = getPage(region);
|
||||
if(!packer.has(type, region.name)){
|
||||
packer.add(type, region.name, Core.atlas.getPixmap(region));
|
||||
}
|
||||
}
|
||||
|
||||
TextureFilter filter = Core.settings.getBool("linear") ? TextureFilter.Linear : TextureFilter.Nearest;
|
||||
|
||||
//flush so generators can use these sprites
|
||||
@@ -243,7 +246,7 @@ public class Mods implements Loadable{
|
||||
try{
|
||||
LoadedMod mod = loadMod(file);
|
||||
mods.add(mod);
|
||||
}catch(Exception e){
|
||||
}catch(Throwable e){
|
||||
Log.err("Failed to load mod file {0}. Skipping.", file);
|
||||
Log.err(e);
|
||||
}
|
||||
@@ -255,7 +258,7 @@ public class Mods implements Loadable{
|
||||
LoadedMod mod = loadMod(file);
|
||||
mods.add(mod);
|
||||
mod.addSteamID(file.name());
|
||||
}catch(Exception e){
|
||||
}catch(Throwable e){
|
||||
Log.err("Failed to load mod workshop file {0}. Skipping.", file);
|
||||
Log.err(e);
|
||||
}
|
||||
@@ -351,7 +354,7 @@ public class Mods implements Loadable{
|
||||
for(Fi file : bundles.getOr(locale, Array::new)){
|
||||
try{
|
||||
PropertiesUtils.load(bundle.getProperties(), file.reader());
|
||||
}catch(Exception e){
|
||||
}catch(Throwable e){
|
||||
Log.err("Error loading bundle: " + file + "/" + locale, e);
|
||||
}
|
||||
}
|
||||
@@ -389,12 +392,12 @@ public class Mods implements Loadable{
|
||||
d.left().marginLeft(15f);
|
||||
for(Content c : m.erroredContent){
|
||||
d.add(c.minfo.sourceFile.nameWithoutExtension()).left().padRight(10);
|
||||
d.addImageTextButton("$details", Icon.arrowDownSmall, Styles.transt, () -> {
|
||||
d.addImageTextButton("$details", Icon.downOpen, Styles.transt, () -> {
|
||||
new Dialog(""){{
|
||||
setFillParent(true);
|
||||
cont.pane(e -> e.add(c.minfo.error)).grow();
|
||||
cont.row();
|
||||
cont.addImageTextButton("$ok", Icon.backSmall, this::hide).size(240f, 60f);
|
||||
cont.addImageTextButton("$ok", Icon.left, this::hide).size(240f, 60f);
|
||||
}}.show();
|
||||
}).size(190f, 50f).left().marginLeft(6);
|
||||
d.row();
|
||||
@@ -419,6 +422,7 @@ public class Mods implements Loadable{
|
||||
//epic memory leak
|
||||
//TODO make it less epic
|
||||
Core.atlas = new TextureAtlas(Core.files.internal("sprites/sprites.atlas"));
|
||||
createdAtlas = true;
|
||||
|
||||
mods.each(LoadedMod::dispose);
|
||||
mods.clear();
|
||||
|
||||
@@ -2,6 +2,7 @@ package mindustry.mod;
|
||||
|
||||
import arc.*;
|
||||
import arc.files.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.Log.*;
|
||||
import mindustry.*;
|
||||
@@ -9,6 +10,10 @@ import mindustry.mod.Mods.*;
|
||||
import org.mozilla.javascript.*;
|
||||
|
||||
public class Scripts implements Disposable{
|
||||
private final Array<String> blacklist = Array.with("net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
|
||||
"runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system",
|
||||
".awt", "socket", "classloader", "oracle");
|
||||
private final Array<String> whitelist = Array.with("mindustry.net");
|
||||
private final Context context;
|
||||
private final String wrapper;
|
||||
private Scriptable scope;
|
||||
@@ -18,9 +23,7 @@ public class Scripts implements Disposable{
|
||||
Time.mark();
|
||||
|
||||
context = Vars.platform.getScriptContext();
|
||||
context.setClassShutter(type -> (ClassAccess.allowedClassNames.contains(type) || type.startsWith("$Proxy") ||
|
||||
type.startsWith("adapter") || type.contains("PrintStream") ||
|
||||
type.startsWith("mindustry")) && !type.equals("mindustry.mod.ClassAccess"));
|
||||
context.setClassShutter(type -> !blacklist.contains(type.toLowerCase()::contains) || whitelist.contains(type.toLowerCase()::contains));
|
||||
context.getWrapFactory().setJavaPrimitiveWrap(false);
|
||||
|
||||
scope = new ImporterTopLevel(context);
|
||||
|
||||
@@ -325,7 +325,8 @@ public class Administration{
|
||||
ObjectSet<PlayerInfo> result = new ObjectSet<>();
|
||||
|
||||
for(PlayerInfo info : playerInfo.values()){
|
||||
if(info.lastName.toLowerCase().equals(name.toLowerCase()) || (info.names.contains(name, false))
|
||||
if(info.lastName.equalsIgnoreCase(name) || (info.names.contains(name, false))
|
||||
|| Strings.stripColors(Strings.stripColors(info.lastName)).equals(name)
|
||||
|| info.ips.contains(name, false) || info.id.equals(name)){
|
||||
result.add(info);
|
||||
}
|
||||
@@ -334,6 +335,19 @@ public class Administration{
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Finds by name, using contains(). */
|
||||
public ObjectSet<PlayerInfo> searchNames(String name){
|
||||
ObjectSet<PlayerInfo> result = new ObjectSet<>();
|
||||
|
||||
for(PlayerInfo info : playerInfo.values()){
|
||||
if(info.names.contains(n -> n.toLowerCase().contains(name.toLowerCase()) || Strings.stripColors(n).trim().toLowerCase().contains(name))){
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public Array<PlayerInfo> findByIPs(String ip){
|
||||
Array<PlayerInfo> result = new Array<>();
|
||||
|
||||
@@ -397,6 +411,7 @@ public class Administration{
|
||||
/** Server configuration definition. Each config value can be a string, boolean or number. */
|
||||
public enum Config{
|
||||
name("The server name as displayed on clients.", "Server", "servername"),
|
||||
desc("The server description, displayed under the name. Max 100 characters.", "off"),
|
||||
port("The port to host on.", Vars.port),
|
||||
autoUpdate("Whether to auto-update and exit when a new bleeding-edge update arrives.", false),
|
||||
showConnectMessages("Whether to display connect/disconnect messages.", true),
|
||||
@@ -529,6 +544,10 @@ public class Administration{
|
||||
public @NonNull ActionType type;
|
||||
public @NonNull Tile tile;
|
||||
|
||||
/** valid for block placement events only */
|
||||
public @Nullable Block block;
|
||||
public int rotation;
|
||||
|
||||
/** valid for configure and rotation-type events only. */
|
||||
public int config;
|
||||
|
||||
@@ -554,7 +573,7 @@ public class Administration{
|
||||
}
|
||||
|
||||
public enum ActionType{
|
||||
breakBlock, placeBlock, rotate, configure, withdrawItem, depositItem
|
||||
breakBlock, placeBlock, rotate, configure, tapTile, withdrawItem, depositItem
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class ArcNetProvider implements NetProvider{
|
||||
final Client client;
|
||||
final Prov<DatagramPacket> packetSupplier = () -> new DatagramPacket(new byte[256], 256);
|
||||
final Prov<DatagramPacket> packetSupplier = () -> new DatagramPacket(new byte[512], 512);
|
||||
|
||||
final Server server;
|
||||
final CopyOnWriteArrayList<ArcConnection> connections = new CopyOnWriteArrayList<>();
|
||||
@@ -114,12 +114,7 @@ public class ArcNetProvider implements NetProvider{
|
||||
try{
|
||||
net.handleServerReceived(k, object);
|
||||
}catch(RuntimeException e){
|
||||
if(e.getCause() instanceof ValidateException){
|
||||
ValidateException v = (ValidateException)e.getCause();
|
||||
Log.err("Validation failed: {0} ({1})", v.player.name, v.getMessage());
|
||||
}else{
|
||||
e.printStackTrace();
|
||||
}
|
||||
e.printStackTrace();
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public class BeControl{
|
||||
});
|
||||
|
||||
dialog.cont.add(new Bar(() -> length[0] == 0 ? Core.bundle.get("be.updating") : (int)(progress[0] * length[0]) / 1024/ 1024 + "/" + length[0]/1024/1024 + " MB", () -> Pal.accent, () -> progress[0])).width(400f).height(70f);
|
||||
dialog.buttons.addImageTextButton("$cancel", Icon.cancelSmall, () -> {
|
||||
dialog.buttons.addImageTextButton("$cancel", Icon.cancel, () -> {
|
||||
cancel[0] = true;
|
||||
dialog.hide();
|
||||
}).size(210f, 64f);
|
||||
|
||||
@@ -21,6 +21,18 @@ import static mindustry.Vars.net;
|
||||
|
||||
public class CrashSender{
|
||||
|
||||
public static void log(Throwable exception){
|
||||
try{
|
||||
Core.settings.getDataDirectory().child("crashes").child("crash_" + System.currentTimeMillis() + ".txt").writeString(Strings.parseException(exception, true));
|
||||
}catch(Throwable ignored){
|
||||
}
|
||||
|
||||
if(exception instanceof RuntimeException){
|
||||
throw (RuntimeException)exception;
|
||||
}
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
public static void send(Throwable exception, Cons<File> writeListener){
|
||||
|
||||
try{
|
||||
|
||||
@@ -6,7 +6,7 @@ import mindustry.game.*;
|
||||
public class Host{
|
||||
public final String name;
|
||||
public final String address;
|
||||
public final String mapname;
|
||||
public final String mapname, description;
|
||||
public final int wave;
|
||||
public final int players, playerLimit;
|
||||
public final int version;
|
||||
@@ -14,7 +14,7 @@ public class Host{
|
||||
public final Gamemode mode;
|
||||
public int ping, port = Vars.port;
|
||||
|
||||
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType, Gamemode mode, int playerLimit){
|
||||
public Host(String name, String address, String mapname, int wave, int players, int version, String versionType, Gamemode mode, int playerLimit, String description){
|
||||
this.name = name;
|
||||
this.address = address;
|
||||
this.players = players;
|
||||
@@ -24,5 +24,6 @@ public class Host{
|
||||
this.versionType = versionType;
|
||||
this.playerLimit = playerLimit;
|
||||
this.mode = mode;
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package mindustry.net;
|
||||
|
||||
import arc.util.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.Administration.*;
|
||||
@@ -21,6 +23,8 @@ public abstract class NetConnection{
|
||||
public int lastRecievedClientSnapshot = -1;
|
||||
/** Timestamp of last recieved snapshot. */
|
||||
public long lastRecievedClientTime;
|
||||
/** Build requests that have been recently rejected. This is cleared every snapshot. */
|
||||
public Array<BuildRequest> rejectedRequests = new Array<>();
|
||||
|
||||
public boolean hasConnected, hasBegunConnecting, hasDisconnected;
|
||||
public float viewWidth, viewHeight, viewX, viewY;
|
||||
|
||||
@@ -63,9 +63,10 @@ public class NetworkIO{
|
||||
|
||||
public static ByteBuffer writeServerData(){
|
||||
String name = (headless ? Config.name.string() : player.name);
|
||||
String description = headless && !Config.desc.string().equals("off") ? Config.desc.string() : "";
|
||||
String map = world.getMap() == null ? "None" : world.getMap().name();
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(256);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(512);
|
||||
|
||||
writeString(buffer, name, 100);
|
||||
writeString(buffer, map);
|
||||
@@ -77,6 +78,8 @@ public class NetworkIO{
|
||||
|
||||
buffer.put((byte)Gamemode.bestFit(state.rules).ordinal());
|
||||
buffer.putInt(netServer.admins.getPlayerLimit());
|
||||
|
||||
writeString(buffer, description, 100);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -89,8 +92,9 @@ public class NetworkIO{
|
||||
String vertype = readString(buffer);
|
||||
Gamemode gamemode = Gamemode.all[buffer.get()];
|
||||
int limit = buffer.getInt();
|
||||
String description = readString(buffer);
|
||||
|
||||
return new Host(host, hostAddress, map, wave, players, version, vertype, gamemode, limit);
|
||||
return new Host(host, hostAddress, map, wave, players, version, vertype, gamemode, limit, description);
|
||||
}
|
||||
|
||||
private static void writeString(ByteBuffer buffer, String string, int maxlen){
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ContentDisplay{
|
||||
table.row();
|
||||
|
||||
if(block.description != null){
|
||||
table.add(block.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.add(block.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.row();
|
||||
|
||||
table.addImage().height(3).color(Color.lightGray).pad(8).padLeft(0).padRight(0).fillX();
|
||||
@@ -76,7 +76,7 @@ public class ContentDisplay{
|
||||
table.row();
|
||||
|
||||
if(item.description != null){
|
||||
table.add(item.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.add(item.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.row();
|
||||
|
||||
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
|
||||
@@ -110,7 +110,7 @@ public class ContentDisplay{
|
||||
table.row();
|
||||
|
||||
if(liquid.description != null){
|
||||
table.add(liquid.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.add(liquid.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.row();
|
||||
|
||||
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
|
||||
@@ -145,7 +145,7 @@ public class ContentDisplay{
|
||||
table.row();
|
||||
|
||||
if(mech.description != null){
|
||||
table.add(mech.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.add(mech.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.row();
|
||||
|
||||
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
|
||||
@@ -192,7 +192,7 @@ public class ContentDisplay{
|
||||
table.row();
|
||||
|
||||
if(unit.description != null){
|
||||
table.add(unit.description).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.add(unit.displayDescription()).padLeft(5).padRight(5).width(400f).wrap().fillX();
|
||||
table.row();
|
||||
|
||||
table.addImage().height(3).color(Color.lightGray).pad(15).padLeft(0).padRight(0).fillX();
|
||||
|
||||
@@ -1,9 +1,215 @@
|
||||
package mindustry.ui;
|
||||
|
||||
import arc.*;
|
||||
import arc.Graphics.Cursor.*;
|
||||
import arc.assets.*;
|
||||
import arc.assets.loaders.*;
|
||||
import arc.assets.loaders.resolvers.*;
|
||||
import arc.files.*;
|
||||
import arc.freetype.*;
|
||||
import arc.freetype.FreeTypeFontGenerator.*;
|
||||
import arc.freetype.FreetypeFontLoader.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Pixmap.*;
|
||||
import arc.graphics.Texture.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.graphics.g2d.BitmapFont.*;
|
||||
import arc.graphics.g2d.PixmapPacker.*;
|
||||
import arc.graphics.g2d.TextureAtlas.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class Fonts{
|
||||
private static ObjectIntMap<String> unicodeIcons = new ObjectIntMap<>();
|
||||
|
||||
public static BitmapFont def;
|
||||
public static BitmapFont outline;
|
||||
public static BitmapFont chat;
|
||||
public static BitmapFont icon;
|
||||
|
||||
public static int getUnicode(String content){
|
||||
return unicodeIcons.get(content, 0);
|
||||
}
|
||||
|
||||
/** Called from a static context to make the cursor appear immediately upon startup.*/
|
||||
public static void loadSystemCursors(){
|
||||
SystemCursor.arrow.set(Core.graphics.newCursor("cursor"));
|
||||
SystemCursor.hand.set(Core.graphics.newCursor("hand"));
|
||||
SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam"));
|
||||
|
||||
Core.graphics.restoreCursor();
|
||||
}
|
||||
|
||||
public static void loadFonts(){
|
||||
String fontName = "fonts/font.ttf";
|
||||
|
||||
FreeTypeFontParameter param = fontParameter();
|
||||
|
||||
Core.assets.load("default", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.def = (BitmapFont)f;
|
||||
Core.assets.load("chat", BitmapFont.class, new FreeTypeFontLoaderParameter(fontName, param)).loaded = f -> Fonts.chat = (BitmapFont)f;
|
||||
Core.assets.load("icon", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{
|
||||
size = 30;
|
||||
incremental = true;
|
||||
characters = "\0";
|
||||
}})).loaded = f -> Fonts.icon = (BitmapFont)f;
|
||||
}
|
||||
|
||||
public static void loadContentIcons(){
|
||||
Array<BitmapFont> fonts = Array.with(Fonts.chat, Fonts.def, Fonts.outline);
|
||||
Texture uitex = Core.atlas.find("logo").getTexture();
|
||||
int size = (int)(Fonts.def.getData().lineHeight/Fonts.def.getData().scaleY);
|
||||
|
||||
try(Scanner scan = new Scanner(Core.files.internal("icons/icons.properties").read(512))){
|
||||
while(scan.hasNextLine()){
|
||||
String line = scan.nextLine();
|
||||
String[] split = line.split("=");
|
||||
String[] nametex = split[1].split("\\|");
|
||||
String character = split[0], texture = nametex[1];
|
||||
int ch = Integer.parseInt(character);
|
||||
TextureRegion region = Core.atlas.find(texture);
|
||||
|
||||
if(region.getTexture() != uitex) throw new IllegalArgumentException("Font icon '" + texture + "' is not in the UI texture.");
|
||||
|
||||
unicodeIcons.put(nametex[0], ch);
|
||||
|
||||
Glyph glyph = new Glyph();
|
||||
glyph.id = ch;
|
||||
glyph.srcX = 0;
|
||||
glyph.srcY = 0;
|
||||
glyph.width = size;
|
||||
glyph.height = size;
|
||||
glyph.u = region.getU();
|
||||
glyph.v = region.getV2();
|
||||
glyph.u2 = region.getU2();
|
||||
glyph.v2 = region.getV();
|
||||
glyph.xoffset = 0;
|
||||
glyph.yoffset = -size;
|
||||
glyph.xadvance = size;
|
||||
glyph.kerning = null;
|
||||
glyph.fixedWidth = true;
|
||||
glyph.page = 0;
|
||||
fonts.each(f -> f.getData().setGlyph(ch, glyph));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Called from a static context for use in the loading screen.*/
|
||||
public static void loadDefaultFont(){
|
||||
UI.packer = new PixmapPacker(2048, 2048, Format.RGBA8888, 2, true);
|
||||
FileHandleResolver resolver = new InternalFileHandleResolver();
|
||||
Core.assets.setLoader(FreeTypeFontGenerator.class, new FreeTypeFontGeneratorLoader(resolver));
|
||||
Core.assets.setLoader(BitmapFont.class, null, new FreetypeFontLoader(resolver){
|
||||
ObjectSet<FreeTypeFontParameter> scaled = new ObjectSet<>();
|
||||
|
||||
@Override
|
||||
public BitmapFont loadSync(AssetManager manager, String fileName, Fi file, FreeTypeFontLoaderParameter parameter){
|
||||
if(fileName.equals("outline")){
|
||||
parameter.fontParameters.borderWidth = Scl.scl(2f);
|
||||
parameter.fontParameters.spaceX -= parameter.fontParameters.borderWidth;
|
||||
}
|
||||
if(!scaled.contains(parameter.fontParameters)){
|
||||
parameter.fontParameters.size = (int)(Scl.scl(parameter.fontParameters.size));
|
||||
scaled.add(parameter.fontParameters);
|
||||
}
|
||||
|
||||
parameter.fontParameters.magFilter = TextureFilter.Linear;
|
||||
parameter.fontParameters.minFilter = TextureFilter.Linear;
|
||||
parameter.fontParameters.packer = UI.packer;
|
||||
return super.loadSync(manager, fileName, file, parameter);
|
||||
}
|
||||
});
|
||||
|
||||
FreeTypeFontParameter param = new FreeTypeFontParameter(){{
|
||||
borderColor = Color.darkGray;
|
||||
incremental = true;
|
||||
size = 18;
|
||||
}};
|
||||
|
||||
Core.assets.load("outline", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/font.ttf", param)).loaded = t -> Fonts.outline = (BitmapFont)t;
|
||||
}
|
||||
|
||||
/** Merges the UI and font atlas together for better performance. */
|
||||
public static void mergeFontAtlas(TextureAtlas atlas){
|
||||
//grab all textures from the ui page, remove all the regions assigned to it, then copy them over to Fonts.packer and replace the texture in this atlas.
|
||||
|
||||
//grab old UI texture and regions...
|
||||
Texture texture = atlas.find("logo").getTexture();
|
||||
|
||||
Page page = UI.packer.getPages().first();
|
||||
|
||||
Array<AtlasRegion> regions = atlas.getRegions().select(t -> t.getTexture() == texture);
|
||||
for(AtlasRegion region : regions){
|
||||
//get new pack rect
|
||||
page.setDirty(false);
|
||||
Rect rect = UI.packer.pack(region.name + (region.splits != null ? ".9" : ""), atlas.getPixmap(region));
|
||||
//set new texture
|
||||
region.setTexture(UI.packer.getPages().first().getTexture());
|
||||
//set its new position
|
||||
region.set((int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);
|
||||
//add old texture
|
||||
atlas.getTextures().add(region.getTexture());
|
||||
}
|
||||
|
||||
//remove old texture, it will no longer be used
|
||||
atlas.getTextures().remove(texture);
|
||||
texture.dispose();
|
||||
atlas.disposePixmap(texture);
|
||||
|
||||
page.setDirty(true);
|
||||
page.updateTexture(TextureFilter.Linear, TextureFilter.Linear, false);
|
||||
}
|
||||
|
||||
public static TextureRegionDrawable getGlyph(BitmapFont font, char glyph){
|
||||
Glyph g = font.getData().getGlyph(glyph);
|
||||
if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")");
|
||||
|
||||
float size = Math.max(g.width, g.height);
|
||||
TextureRegionDrawable draw = new TextureRegionDrawable(new TextureRegion(font.getRegion().getTexture(), g.u, g.v2, g.u2, g.v)){
|
||||
@Override
|
||||
public void draw(float x, float y, float width, float height){
|
||||
Draw.color(Tmp.c1.set(tint).mul(Draw.getColor()).toFloatBits());
|
||||
float cx = x + width/2f - g.width/2f, cy = y + height/2f - g.height/2f;
|
||||
cx = (int)cx;
|
||||
cy = (int)cy;
|
||||
Draw.rect(region, cx + g.width/2f, cy + g.height/2f, g.width, g.height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(float x, float y, float originX, float originY, float width, float height, float scaleX, float scaleY, float rotation){
|
||||
width *= scaleX;
|
||||
height *= scaleY;
|
||||
Draw.color(Tmp.c1.set(tint).mul(Draw.getColor()).toFloatBits());
|
||||
float cx = x + width/2f - g.width/2f, cy = y + height/2f - g.height/2f;
|
||||
cx = (int)cx;
|
||||
cy = (int)cy;
|
||||
originX = g.width/2f;
|
||||
originY = g.height/2f;
|
||||
Draw.rect(region, cx + g.width/2f, cy + g.height/2f, g.width, g.height, originX, originY, rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float imageSize(){
|
||||
return size;
|
||||
}
|
||||
};
|
||||
|
||||
draw.setMinWidth(size);
|
||||
draw.setMinHeight(size);
|
||||
return draw;
|
||||
}
|
||||
|
||||
static FreeTypeFontParameter fontParameter(){
|
||||
return new FreeTypeFontParameter(){{
|
||||
size = 18;
|
||||
shadowColor = Color.darkGray;
|
||||
shadowOffsetY = 2;
|
||||
incremental = true;
|
||||
}};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public class ItemImage extends Stack{
|
||||
|
||||
if(stack.amount != 0){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(stack.amount + "").name("item-label");
|
||||
t.add(stack.amount + "").name("item-label").style(Styles.outlineLabel);
|
||||
add(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.ui;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.gen.*;
|
||||
@@ -21,18 +22,31 @@ public class ItemsDisplay extends Table{
|
||||
top().left();
|
||||
margin(0);
|
||||
|
||||
table(Tex.button,t -> {
|
||||
t.margin(10).marginLeft(15).marginTop(15f);
|
||||
t.label(() -> state.is(State.menu) ? "$launcheditems" : "$launchinfo").colspan(3).padBottom(4).left().colspan(3).width(210f).wrap();
|
||||
t.row();
|
||||
for(Item item : content.items()){
|
||||
if(item.type == ItemType.material && data.isUnlocked(item)){
|
||||
t.label(() -> format(item)).left();
|
||||
t.addImage(item.icon(Cicon.small)).size(8 * 3).padLeft(4).padRight(4);
|
||||
t.add(item.localizedName).color(Color.lightGray).left();
|
||||
t.row();
|
||||
table(Tex.button, c -> {
|
||||
c.margin(10).marginLeft(12).marginTop(15f);
|
||||
c.marginRight(12f);
|
||||
c.left();
|
||||
|
||||
Collapser col = new Collapser(base -> base.pane(t -> {
|
||||
t.marginRight(30f);
|
||||
t.left();
|
||||
for(Item item : content.items()){
|
||||
if(item.type == ItemType.material && data.isUnlocked(item)){
|
||||
t.label(() -> format(item)).left();
|
||||
t.addImage(item.icon(Cicon.small)).size(8 * 3).padLeft(4).padRight(4);
|
||||
t.add(item.localizedName).color(Color.lightGray).left();
|
||||
t.row();
|
||||
}
|
||||
}
|
||||
}
|
||||
}).get().setScrollingDisabled(true, false), false).setDuration(0.3f);
|
||||
|
||||
c.addImageTextButton("$launcheditems", Icon.downOpen, Styles.clearTogglet, col::toggle).update(t -> {
|
||||
t.setText(state.is(State.menu) ? "$launcheditems" : "$launchinfo");
|
||||
t.setChecked(col.isCollapsed());
|
||||
((Image)t.getChildren().get(1)).setDrawable(col.isCollapsed() ? Icon.upOpen : Icon.downOpen);
|
||||
}).padBottom(4).left().fillX().margin(12f);
|
||||
c.row();
|
||||
c.add(col);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package mindustry.ui;
|
||||
|
||||
import arc.Core;
|
||||
import arc.scene.style.*;
|
||||
import arc.util.Strings;
|
||||
import arc.graphics.Color;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.Pal;
|
||||
|
||||
public class Links{
|
||||
@@ -10,17 +12,17 @@ public class Links{
|
||||
|
||||
private static void createLinks(){
|
||||
links = new LinkEntry[]{
|
||||
new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")),
|
||||
new LinkEntry("changelog", "https://github.com/Anuken/Mindustry/releases", Pal.accent.cpy()),
|
||||
new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")),
|
||||
new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Color.valueOf("0f142f")),
|
||||
new LinkEntry("feathub", "https://feathub.com/Anuken/Mindustry/", Color.valueOf("ebebeb")),
|
||||
new LinkEntry("reddit", "https://www.reddit.com/r/Mindustry/", Color.valueOf("ee593b")),
|
||||
new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")),
|
||||
new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Color.valueOf("689f38")),
|
||||
new LinkEntry("f-droid", "https://f-droid.org/packages/io.anuke.mindustry/", Color.valueOf("026aa7")),
|
||||
new LinkEntry("github", "https://github.com/Anuken/Mindustry/", Color.valueOf("24292e")),
|
||||
new LinkEntry("dev-builds", "https://github.com/Anuken/MindustryBuilds", Color.valueOf("fafbfc"))
|
||||
new LinkEntry("discord", "https://discord.gg/mindustry", Icon.discord, Color.valueOf("7289da")),
|
||||
new LinkEntry("changelog", "https://github.com/Anuken/Mindustry/releases", Icon.list, Pal.accent.cpy()),
|
||||
new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Icon.trello, Color.valueOf("026aa7")),
|
||||
new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Icon.book, Color.valueOf("0f142f")),
|
||||
new LinkEntry("feathub", "https://feathub.com/Anuken/Mindustry/", Icon.add, Color.valueOf("ebebeb")),
|
||||
new LinkEntry("reddit", "https://www.reddit.com/r/Mindustry/", Icon.redditAlien, Color.valueOf("ee593b")),
|
||||
new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Icon.itchio, Color.valueOf("fa5c5c")),
|
||||
new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Icon.googleplay, Color.valueOf("689f38")),
|
||||
new LinkEntry("f-droid", "https://f-droid.org/packages/io.anuke.mindustry/", Icon.android, Color.valueOf("026aa7")),
|
||||
new LinkEntry("github", "https://github.com/Anuken/Mindustry/", Icon.github, Color.valueOf("24292e")),
|
||||
new LinkEntry("dev-builds", "https://github.com/Anuken/MindustryBuilds", Icon.githubSquare, Color.valueOf("fafbfc"))
|
||||
};
|
||||
}
|
||||
|
||||
@@ -35,12 +37,14 @@ public class Links{
|
||||
public static class LinkEntry{
|
||||
public final String name, title, description, link;
|
||||
public final Color color;
|
||||
public final Drawable icon;
|
||||
|
||||
public LinkEntry(String name, String link, Color color){
|
||||
public LinkEntry(String name, String link, Drawable icon, Color color){
|
||||
this.name = name;
|
||||
this.color = color;
|
||||
this.description = Core.bundle.getNotNull("link." + name + ".description");
|
||||
this.link = link;
|
||||
this.icon = icon;
|
||||
|
||||
String title = Core.bundle.getOrNull("link." + name + ".title");
|
||||
this.title = title != null ? title : Strings.capitalize(name.replace("-", " "));
|
||||
|
||||
@@ -24,13 +24,13 @@ public class LiquidDisplay extends Table{
|
||||
|
||||
if(amount != 0){
|
||||
Table t = new Table().left().bottom();
|
||||
t.add(Strings.autoFixed(amount, 1));
|
||||
t.add(Strings.autoFixed(amount, 1)).style(Styles.outlineLabel);
|
||||
add(t);
|
||||
}
|
||||
}}).size(8 * 4).padRight(3 + (amount != 0 && Strings.autoFixed(amount, 1).length() > 2 ? 8 : 0));
|
||||
|
||||
if(perSecond){
|
||||
add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray);
|
||||
add(StatUnit.perSecond.localized()).padLeft(2).padRight(5).color(Color.lightGray).style(Styles.outlineLabel);
|
||||
}
|
||||
|
||||
add(liquid.localizedName);
|
||||
|
||||
@@ -55,7 +55,7 @@ public class AboutDialog extends FloatingDialog{
|
||||
|
||||
table.table(i -> {
|
||||
i.background(Tex.buttonEdge3);
|
||||
i.addImage(Core.atlas.drawable("icon-" + link.name));
|
||||
i.addImage(link.icon);
|
||||
}).size(h - 5, h);
|
||||
|
||||
table.table(inset -> {
|
||||
|
||||
@@ -55,7 +55,7 @@ public class ColorPicker extends FloatingDialog{
|
||||
|
||||
buttons.clear();
|
||||
addCloseButton();
|
||||
buttons.addImageTextButton("$ok", Icon.checkSmall, () -> {
|
||||
buttons.addImageTextButton("$ok", Icon.ok, () -> {
|
||||
cons.get(current);
|
||||
hide();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@ public class ControlsDialog extends KeybindDialog{
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeftSmall, this::hide).size(230f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(230f, 64f);
|
||||
|
||||
keyDown(key -> {
|
||||
if(key == KeyCode.ESCAPE || key == KeyCode.BACK)
|
||||
|
||||
@@ -3,6 +3,7 @@ package mindustry.ui.dialogs;
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
@@ -59,8 +60,9 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
image.table(t -> {
|
||||
t.left();
|
||||
for(Gamemode mode : Gamemode.all){
|
||||
if(mode.valid(map) && Core.atlas.has("icon-mode-" + mode.name())){
|
||||
t.addImage(Core.atlas.drawable("icon-mode-" + mode.name())).size(16f).pad(4f);
|
||||
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()) + "Small");
|
||||
if(mode.valid(map) && Core.atlas.isFound(icon.getRegion())){
|
||||
t.addImage(icon).size(16f).pad(4f);
|
||||
}
|
||||
}
|
||||
}).left();
|
||||
|
||||
@@ -35,12 +35,12 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
banDialog.addCloseButton();
|
||||
|
||||
banDialog.shown(this::rebuildBanned);
|
||||
banDialog.buttons.addImageTextButton("$addall", Icon.arrow16Small, () -> {
|
||||
banDialog.buttons.addImageTextButton("$addall", Icon.add, () -> {
|
||||
rules.bannedBlocks.addAll(content.blocks().select(Block::isBuildable));
|
||||
rebuildBanned();
|
||||
}).size(180, 64f);
|
||||
|
||||
banDialog.buttons.addImageTextButton("$clear", Icon.trash16Small, () -> {
|
||||
banDialog.buttons.addImageTextButton("$clear", Icon.trash, () -> {
|
||||
rules.bannedBlocks.clear();
|
||||
rebuildBanned();
|
||||
}).size(180, 64f);
|
||||
@@ -72,7 +72,7 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
b.addImage(block.icon(Cicon.medium)).size(Cicon.medium.size).padRight(3);
|
||||
b.add(block.localizedName).color(Color.lightGray).padLeft(3).growX().left().wrap();
|
||||
|
||||
b.addImageButton(Icon.cancelSmall, Styles.clearPartiali, () -> {
|
||||
b.addImageButton(Icon.cancel, Styles.clearPartiali, () -> {
|
||||
rules.bannedBlocks.remove(block);
|
||||
rebuildBanned();
|
||||
}).size(70f).pad(-4f).padLeft(0f);
|
||||
@@ -84,7 +84,7 @@ public class CustomRulesDialog extends FloatingDialog{
|
||||
}
|
||||
}).get().setScrollYForce(previousScroll);
|
||||
banDialog.cont.row();
|
||||
banDialog.cont.addImageTextButton("$add", Icon.addSmall, () -> {
|
||||
banDialog.cont.addImageTextButton("$add", Icon.add, () -> {
|
||||
FloatingDialog dialog = new FloatingDialog("$add");
|
||||
dialog.cont.pane(t -> {
|
||||
t.left().margin(14f);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.input.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.scene.event.*;
|
||||
@@ -15,6 +16,8 @@ import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
|
||||
import static mindustry.Vars.ui;
|
||||
|
||||
public class DatabaseDialog extends FloatingDialog{
|
||||
|
||||
public DatabaseDialog(){
|
||||
@@ -55,7 +58,7 @@ public class DatabaseDialog extends FloatingDialog{
|
||||
for(int i = 0; i < array.size; i++){
|
||||
UnlockableContent unlock = (UnlockableContent)array.get(i);
|
||||
|
||||
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)) : new Image(Icon.lockedSmall, Pal.gray);
|
||||
Image image = unlocked(unlock) ? new Image(unlock.icon(Cicon.medium)) : new Image(Icon.lockOpen, Pal.gray);
|
||||
list.add(image).size(8*4).pad(3);
|
||||
ClickListener listener = new ClickListener();
|
||||
image.addListener(listener);
|
||||
@@ -65,7 +68,14 @@ public class DatabaseDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
if(unlocked(unlock)){
|
||||
image.clicked(() -> Vars.ui.content.show(unlock));
|
||||
image.clicked(() -> {
|
||||
if(Core.input.keyDown(KeyCode.SHIFT_LEFT) && Fonts.getUnicode(unlock.name) != 0){
|
||||
Core.app.setClipboardText((char)Fonts.getUnicode(unlock.name) + "");
|
||||
ui.showInfoFade("$copied");
|
||||
}else{
|
||||
Vars.ui.content.show(unlock);
|
||||
}
|
||||
});
|
||||
image.addListener(new Tooltip(t -> t.background(Tex.button).add(unlock.localizedName)));
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
setFilter(TextureFilter.Linear);
|
||||
}}){{
|
||||
float[] time = {0};
|
||||
setColor(Color.fromGray(0.3f));
|
||||
setColor(Color.grays(0.3f));
|
||||
setScale(1.5f);
|
||||
update(() -> {
|
||||
setOrigin(Align.center);
|
||||
@@ -140,7 +140,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
Stack sub = new Stack();
|
||||
|
||||
if(slot.getZone() != null){
|
||||
sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.fromGray(0.1f)).grow()));
|
||||
sub.add(new Table(f -> f.margin(4f).add(new Image()).color(Color.grays(0.1f)).grow()));
|
||||
|
||||
sub.add(new Table(f -> f.margin(4f).add(new Image(slot.getZone().preview).setScaling(Scaling.fit)).update(img -> {
|
||||
TextureRegionDrawable draw = (TextureRegionDrawable)img.getDrawable();
|
||||
@@ -235,7 +235,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
button.labelWrap(zone.localizedName).style(Styles.outlineLabel).width(140).growX().get().setAlignment(Align.center);
|
||||
}else{
|
||||
Cons<Element> flasher = zone.canUnlock() && !hidden(zone) ? e -> e.update(() -> e.getColor().set(Color.white).lerp(Pal.accent, Mathf.absin(3f, 1f))) : e -> {};
|
||||
flasher.get(button.addImage(Icon.locked).get());
|
||||
flasher.get(button.addImage(Icon.lock).get());
|
||||
button.row();
|
||||
flasher.get(button.add("$locked").get());
|
||||
}
|
||||
@@ -254,7 +254,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
stack.setSize(Tmp.v1.x, Tmp.v1.y);
|
||||
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.fromGray(0.2f)).grow()));
|
||||
stack.add(new Table(t -> t.margin(4f).add(new Image(node.zone.preview).setScaling(Scaling.stretch)).color(node.zone.unlocked() ? Color.darkGray : Color.grays(0.2f)).grow()));
|
||||
stack.update(() -> stack.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f, Align.center));
|
||||
|
||||
Button button = new Button(Styles.squaret);
|
||||
|
||||
@@ -92,15 +92,15 @@ public class FileChooser extends FloatingDialog{
|
||||
|
||||
Table icontable = new Table();
|
||||
|
||||
ImageButton up = new ImageButton(Icon.folderParent);
|
||||
ImageButton up = new ImageButton(Icon.upOpen);
|
||||
up.clicked(() -> {
|
||||
directory = directory.parent();
|
||||
updateFiles(true);
|
||||
});
|
||||
|
||||
|
||||
ImageButton back = new ImageButton(Icon.arrowLeft);
|
||||
ImageButton forward = new ImageButton(Icon.arrowRight);
|
||||
ImageButton back = new ImageButton(Icon.left);
|
||||
ImageButton forward = new ImageButton(Icon.right);
|
||||
|
||||
forward.clicked(() -> stack.forward());
|
||||
back.clicked(() -> stack.back());
|
||||
@@ -185,7 +185,7 @@ public class FileChooser extends FloatingDialog{
|
||||
files.top().left();
|
||||
Fi[] names = getFileNames();
|
||||
|
||||
Image upimage = new Image(Icon.folderParentSmall);
|
||||
Image upimage = new Image(Icon.upOpen);
|
||||
TextButton upbutton = new TextButton(".." + directory.toString(), Styles.clearTogglet);
|
||||
upbutton.clicked(() -> {
|
||||
directory = directory.parent();
|
||||
@@ -229,7 +229,7 @@ public class FileChooser extends FloatingDialog{
|
||||
button.setChecked(filename.equals(filefield.getText()));
|
||||
});
|
||||
|
||||
Image image = new Image(file.isDirectory() ? Icon.folderSmall : Icon.fileTextSmall);
|
||||
Image image = new Image(file.isDirectory() ? Icon.folder : Icon.fileText);
|
||||
|
||||
button.add(image).padRight(4f).padLeft(4);
|
||||
button.getCells().reverse();
|
||||
|
||||
@@ -56,7 +56,7 @@ public class FloatingDialog extends Dialog{
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.defaults().size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
keyDown(key -> {
|
||||
if(key == KeyCode.ESCAPE || key == KeyCode.BACK){
|
||||
|
||||
@@ -95,11 +95,16 @@ public class JoinDialog extends FloatingDialog{
|
||||
}
|
||||
});
|
||||
|
||||
onResize(this::setup);
|
||||
onResize(() -> {
|
||||
setup();
|
||||
refreshLocal();
|
||||
refreshRemote();
|
||||
});
|
||||
}
|
||||
|
||||
void setupRemote(){
|
||||
remote.clear();
|
||||
|
||||
for(Server server : servers){
|
||||
//why are java lambdas this bad
|
||||
TextButton[] buttons = {null};
|
||||
@@ -122,7 +127,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
|
||||
inner.add(button.getLabel()).growX();
|
||||
|
||||
inner.addImageButton(Icon.arrowUpSmall, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.upOpen, Styles.emptyi, () -> {
|
||||
int index = servers.indexOf(server);
|
||||
if(index > 0){
|
||||
servers.remove(index);
|
||||
@@ -141,16 +146,16 @@ public class JoinDialog extends FloatingDialog{
|
||||
|
||||
}).margin(3f).padTop(6f).top().right();
|
||||
|
||||
inner.addImageButton(Icon.loadingSmall, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.refresh, Styles.emptyi, () -> {
|
||||
refreshServer(server);
|
||||
}).margin(3f).padTop(6f).top().right();
|
||||
|
||||
inner.addImageButton(Icon.pencilSmall, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.pencil, Styles.emptyi, () -> {
|
||||
renaming = server;
|
||||
add.show();
|
||||
}).margin(3f).padTop(6f).top().right();
|
||||
|
||||
inner.addImageButton(Icon.trash16Small, Styles.emptyi, () -> {
|
||||
inner.addImageButton(Icon.trash, Styles.emptyi, () -> {
|
||||
ui.showConfirm("$confirm", "$server.delete", () -> {
|
||||
servers.removeValue(server, true);
|
||||
saveServers();
|
||||
@@ -179,7 +184,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
|
||||
net.pingHost(server.ip, server.port, host -> setupServer(server, host), e -> {
|
||||
server.content.clear();
|
||||
server.content.add("$host.invalid");
|
||||
server.content.add("$host.invalid").padBottom(4);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -212,6 +217,10 @@ public class JoinDialog extends FloatingDialog{
|
||||
content.table(t -> {
|
||||
t.add("[lightgray]" + host.name + " " + versionString).width(targetWidth() - 10f).left().get().setEllipsis(true);
|
||||
t.row();
|
||||
if(!host.description.isEmpty()){
|
||||
t.add("[gray]" + host.description).width(targetWidth() - 10f).left().wrap();
|
||||
t.row();
|
||||
}
|
||||
t.add("[lightgray]" + (Core.bundle.format("players" + (host.players == 1 && host.playerLimit <= 0 ? ".single" : ""), (host.players == 0 ? "[lightgray]" : "[accent]") + host.players + (host.playerLimit > 0 ? "[lightgray]/[accent]" + host.playerLimit : "")+ "[lightgray]"))).left();
|
||||
t.row();
|
||||
t.add("[lightgray]" + Core.bundle.format("save.map", host.mapname) + "[lightgray] / " + host.mode.toString()).width(targetWidth() - 10f).left().get().setEllipsis(true);
|
||||
@@ -262,7 +271,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
cont.addCenteredImageTextButton("$server.add", Icon.add, () -> {
|
||||
renaming = null;
|
||||
add.show();
|
||||
}).marginLeft(6).width(w).height(80f).update(button -> {
|
||||
}).marginLeft(10).width(w).height(80f).update(button -> {
|
||||
float pw = w;
|
||||
float pad = 0f;
|
||||
if(pane.getChildren().first().getPrefHeight() > pane.getHeight()){
|
||||
@@ -303,7 +312,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
local.background(Tex.button);
|
||||
local.add("$hosts.none").pad(10f);
|
||||
local.add().growX();
|
||||
local.addImageButton(Icon.loading, this::refreshLocal).pad(-12f).padLeft(0).size(70f);
|
||||
local.addImageButton(Icon.refresh, this::refreshLocal).pad(-12f).padLeft(0).size(70f);
|
||||
}else{
|
||||
local.background(null);
|
||||
}
|
||||
@@ -359,7 +368,7 @@ public class JoinDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
float targetWidth(){
|
||||
return Core.graphics.isPortrait() ? 350f : 500f;
|
||||
return Math.min(Core.graphics.getWidth() / Scl.scl() * 0.9f, 500f);//Core.graphics.isPortrait() ? 350f : 500f;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -71,7 +71,7 @@ public class LoadDialog extends FloatingDialog{
|
||||
title.table(t -> {
|
||||
t.right();
|
||||
|
||||
t.addImageButton(Icon.floppy, Styles.emptytogglei, () -> {
|
||||
t.addImageButton(Icon.save, Styles.emptytogglei, () -> {
|
||||
slot.setAutosave(!slot.isAutosave());
|
||||
}).checked(slot.isAutosave()).right();
|
||||
|
||||
|
||||
@@ -42,9 +42,9 @@ public class LoadoutDialog extends FloatingDialog{
|
||||
}
|
||||
});
|
||||
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f, 64f);
|
||||
|
||||
buttons.addImageTextButton("$settings.reset", Icon.refreshSmall, () -> {
|
||||
buttons.addImageTextButton("$settings.reset", Icon.refresh, () -> {
|
||||
resetter.run();
|
||||
reseed();
|
||||
updater.run();
|
||||
@@ -83,7 +83,7 @@ public class LoadoutDialog extends FloatingDialog{
|
||||
updater.run();
|
||||
}).size(bsize);
|
||||
|
||||
t.addImageButton(Icon.pencilSmaller, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
|
||||
t.addImageButton(Icon.pencil, Styles.cleari, () -> ui.showTextInput("$configure", stack.item.localizedName, 10, stack.amount + "", true, str -> {
|
||||
if(Strings.canParsePostiveInt(str)){
|
||||
int amount = Strings.parseInt(str);
|
||||
if(amount >= 0 && amount <= capacity){
|
||||
|
||||
@@ -68,7 +68,7 @@ public class MapPlayDialog extends FloatingDialog{
|
||||
|
||||
cont.add(selmode);
|
||||
cont.row();
|
||||
cont.addImageTextButton("$customize", Icon.toolsSmall, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
|
||||
cont.addImageTextButton("$customize", Icon.settings, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
|
||||
cont.row();
|
||||
cont.add(new BorderImage(map.safeTexture(), 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
|
||||
//only maps with survival are valid for high scores
|
||||
|
||||
@@ -44,10 +44,10 @@ public class MapsDialog extends FloatingDialog{
|
||||
buttons.clearChildren();
|
||||
|
||||
if(Core.graphics.isPortrait()){
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f*2f, 64f).colspan(2);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f*2f, 64f).colspan(2);
|
||||
buttons.row();
|
||||
}else{
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeft, this::hide).size(210f, 64f);
|
||||
buttons.addImageTextButton("$back", Icon.left, this::hide).size(210f, 64f);
|
||||
}
|
||||
|
||||
buttons.addImageTextButton("$editor.newmap", Icon.add, () -> {
|
||||
@@ -67,7 +67,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
|
||||
buttons.addImageTextButton("$editor.importmap", Icon.load, () -> {
|
||||
buttons.addImageTextButton("$editor.importmap", Icon.upload, () -> {
|
||||
platform.showFileChooser(true, mapExtension, file -> {
|
||||
ui.loadAnd(() -> {
|
||||
maps.tryCatchMapError(() -> {
|
||||
@@ -192,7 +192,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
|
||||
table.row();
|
||||
|
||||
table.addImageTextButton("$editor.openin", Icon.loadMapSmall, () -> {
|
||||
table.addImageTextButton("$editor.openin", Icon.export, () -> {
|
||||
try{
|
||||
Vars.ui.editor.beginEditMap(map.file);
|
||||
dialog.hide();
|
||||
@@ -203,7 +203,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10);
|
||||
|
||||
table.addImageTextButton(map.workshop && steam ? "$view.workshop" : "$delete", map.workshop && steam ? Icon.linkSmall : Icon.trash16Small, () -> {
|
||||
table.addImageTextButton(map.workshop && steam ? "$view.workshop" : "$delete", map.workshop && steam ? Icon.link : Icon.trash, () -> {
|
||||
if(map.workshop && steam){
|
||||
platform.viewListing(map);
|
||||
}else{
|
||||
|
||||
@@ -20,15 +20,8 @@ public class ModsDialog extends FloatingDialog{
|
||||
super("$mods");
|
||||
addCloseButton();
|
||||
|
||||
buttons.addImageTextButton(mobile ? "$mods.report" : "$mods.openfolder", Icon.link,
|
||||
() -> {
|
||||
if(mobile){
|
||||
Core.net.openURI(reportIssueURL);
|
||||
}else{
|
||||
Core.net.openFolder(modDirectory.absolutePath());
|
||||
}
|
||||
})
|
||||
.size(250f, 64f);
|
||||
buttons.addImageTextButton("$mods.openfolder", Icon.link,
|
||||
() -> Core.app.openFolder(modDirectory.absolutePath())).size(250f, 64f);
|
||||
|
||||
buttons.row();
|
||||
|
||||
@@ -127,18 +120,18 @@ public class ModsDialog extends FloatingDialog{
|
||||
title.add("[accent]" + mod.meta.displayName() + "[lightgray] v" + mod.meta.version + (mod.enabled() ? "" : "\n" + Core.bundle.get("mod.disabled") + "")).width(200f).wrap();
|
||||
title.add().growX();
|
||||
|
||||
title.addImageTextButton(mod.enabled() ? "$mod.disable" : "$mod.enable", mod.enabled() ? Icon.arrowDownSmall : Icon.arrowUpSmall, Styles.cleart, () -> {
|
||||
title.addImageTextButton(mod.enabled() ? "$mod.disable" : "$mod.enable", mod.enabled() ? Icon.downOpen : Icon.upOpen, Styles.cleart, () -> {
|
||||
mods.setEnabled(mod, !mod.enabled());
|
||||
setup();
|
||||
}).height(50f).margin(8f).width(130f).disabled(!mod.isSupported());
|
||||
|
||||
if(steam && !mod.hasSteamID()){
|
||||
title.addImageButton(Icon.loadMapSmall, Styles.cleari, () -> {
|
||||
title.addImageButton(Icon.download, Styles.cleari, () -> {
|
||||
platform.publish(mod);
|
||||
}).size(50f);
|
||||
}
|
||||
|
||||
title.addImageButton(mod.hasSteamID() ? Icon.linkSmall : Icon.trash16Small, Styles.cleari, () -> {
|
||||
title.addImageButton(mod.hasSteamID() ? Icon.link : Icon.trash, Styles.cleari, () -> {
|
||||
if(!mod.hasSteamID()){
|
||||
ui.showConfirm("$confirm", "$mod.remove.confirm", () -> {
|
||||
mods.removeMod(mod);
|
||||
|
||||
@@ -35,29 +35,29 @@ public class PausedDialog extends FloatingDialog{
|
||||
});
|
||||
|
||||
if(!mobile){
|
||||
float dw = 210f;
|
||||
cont.defaults().width(dw).height(50).pad(5f);
|
||||
float dw = 220f;
|
||||
cont.defaults().width(dw).height(55).pad(5f);
|
||||
|
||||
cont.addButton("$back", this::hide).colspan(2).width(dw * 2 + 20f);
|
||||
cont.addImageTextButton("$back", Icon.left, this::hide).colspan(2).width(dw * 2 + 20f);
|
||||
|
||||
cont.row();
|
||||
if(world.isZone()){
|
||||
cont.addButton("$techtree", ui.tech::show);
|
||||
cont.addImageTextButton("$techtree", Icon.tree, ui.tech::show);
|
||||
}else{
|
||||
cont.addButton("$database", ui.database::show);
|
||||
cont.addImageTextButton("$database", Icon.book, ui.database::show);
|
||||
}
|
||||
cont.addButton("$settings", ui.settings::show);
|
||||
cont.addImageTextButton("$settings", Icon.settings, ui.settings::show);
|
||||
|
||||
if(!state.rules.tutorial){
|
||||
if(!world.isZone() && !state.isEditor()){
|
||||
cont.row();
|
||||
cont.addButton("$savegame", save::show);
|
||||
cont.addButton("$loadgame", load::show).disabled(b -> net.active());
|
||||
cont.addImageTextButton("$savegame", Icon.save, save::show);
|
||||
cont.addImageTextButton("$loadgame", Icon.upload, load::show).disabled(b -> net.active());
|
||||
}
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.addButton("$hostserver", () -> {
|
||||
cont.addImageTextButton("$hostserver", Icon.host, () -> {
|
||||
if(net.server() && steam){
|
||||
platform.inviteFriends();
|
||||
}else{
|
||||
@@ -72,26 +72,29 @@ public class PausedDialog extends FloatingDialog{
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.addButton("$quit", this::showQuitConfirm).colspan(2).width(dw + 10f).update(s -> s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit"));
|
||||
cont.addImageTextButton("$quit", Icon.exit, this::showQuitConfirm).colspan(2).width(dw + 20f).update(s -> s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit"));
|
||||
|
||||
}else{
|
||||
cont.defaults().size(130f).pad(5);
|
||||
cont.addRowImageTextButton("$back", Icon.play2, this::hide);
|
||||
cont.addRowImageTextButton("$settings", Icon.tools, ui.settings::show);
|
||||
cont.addRowImageTextButton("$back", Icon.play, this::hide);
|
||||
cont.addRowImageTextButton("$settings", Icon.settings, ui.settings::show);
|
||||
|
||||
if(!world.isZone() && !state.isEditor()){
|
||||
cont.addRowImageTextButton("$save", Icon.save, save::show);
|
||||
|
||||
cont.row();
|
||||
|
||||
cont.addRowImageTextButton("$load", Icon.load, load::show).disabled(b -> net.active());
|
||||
cont.addRowImageTextButton("$load", Icon.download, load::show).disabled(b -> net.active());
|
||||
}else{
|
||||
cont.row();
|
||||
}
|
||||
|
||||
cont.addRowImageTextButton("$hostserver.mobile", Icon.host, ui.host::show).disabled(b -> net.active());
|
||||
|
||||
cont.addRowImageTextButton("$quit", Icon.quit, this::showQuitConfirm).update(s -> s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit"));
|
||||
cont.addRowImageTextButton("$quit", Icon.exit, this::showQuitConfirm).update(s -> {
|
||||
s.setText(control.saves.getCurrent() != null && control.saves.getCurrent().isAutosave() ? "$save.quit" : "$quit");
|
||||
s.getLabelCell().growX().wrap();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
|
||||
shouldPause = true;
|
||||
addCloseButton();
|
||||
buttons.addImageTextButton("$schematic.import", Icon.loadMapSmall, this::showImport);
|
||||
buttons.addImageTextButton("$schematic.import", Icon.download, this::showImport);
|
||||
shown(this::setup);
|
||||
onResize(this::setup);
|
||||
}
|
||||
@@ -79,15 +79,15 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
|
||||
ImageButtonStyle style = Styles.clearPartiali;
|
||||
|
||||
buttons.addImageButton(Icon.infoSmall, style, () -> {
|
||||
buttons.addImageButton(Icon.info, style, () -> {
|
||||
showInfo(s);
|
||||
});
|
||||
|
||||
buttons.addImageButton(Icon.loadMapSmall, style, () -> {
|
||||
buttons.addImageButton(Icon.download, style, () -> {
|
||||
showExport(s);
|
||||
});
|
||||
|
||||
buttons.addImageButton(Icon.pencilSmall, style, () -> {
|
||||
buttons.addImageButton(Icon.pencil, style, () -> {
|
||||
ui.showTextInput("$schematic.rename", "$name", s.name(), res -> {
|
||||
s.tags.put("name", res);
|
||||
s.save();
|
||||
@@ -96,9 +96,9 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
});
|
||||
|
||||
if(s.hasSteamID()){
|
||||
buttons.addImageButton(Icon.linkSmall, style, () -> platform.viewListing(s));
|
||||
buttons.addImageButton(Icon.link, style, () -> platform.viewListing(s));
|
||||
}else{
|
||||
buttons.addImageButton(Icon.trash16Small, style, () -> {
|
||||
buttons.addImageButton(Icon.trash, style, () -> {
|
||||
if(s.mod != null){
|
||||
ui.showInfo(Core.bundle.format("mod.item.remove", s.mod.meta.displayName()));
|
||||
}else{
|
||||
@@ -154,7 +154,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
TextButtonStyle style = Styles.cleart;
|
||||
t.defaults().size(280f, 60f).left();
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.copy.import", Icon.copySmall, style, () -> {
|
||||
t.addImageTextButton("$schematic.copy.import", Icon.copy, style, () -> {
|
||||
dialog.hide();
|
||||
try{
|
||||
Schematic s = Schematics.readBase64(Core.app.getClipboardText());
|
||||
@@ -168,7 +168,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
}
|
||||
}).marginLeft(12f).disabled(b -> Core.app.getClipboardText() == null || !Core.app.getClipboardText().startsWith(schematicBaseStart));
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.importfile", Icon.saveMapSmall, style, () -> platform.showFileChooser(true, schematicExtension, file -> {
|
||||
t.addImageTextButton("$schematic.importfile", Icon.download, style, () -> platform.showFileChooser(true, schematicExtension, file -> {
|
||||
dialog.hide();
|
||||
|
||||
try{
|
||||
@@ -183,7 +183,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
})).marginLeft(12f);
|
||||
t.row();
|
||||
if(steam){
|
||||
t.addImageTextButton("$schematic.browseworkshop", Icon.wikiSmall, style, () -> {
|
||||
t.addImageTextButton("$schematic.browseworkshop", Icon.book, style, () -> {
|
||||
dialog.hide();
|
||||
platform.openWorkshop();
|
||||
}).marginLeft(12f);
|
||||
@@ -203,18 +203,18 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
TextButtonStyle style = Styles.cleart;
|
||||
t.defaults().size(280f, 60f).left();
|
||||
if(steam && !s.hasSteamID()){
|
||||
t.addImageTextButton("$schematic.shareworkshop", Icon.wikiSmall, style,
|
||||
t.addImageTextButton("$schematic.shareworkshop", Icon.book, style,
|
||||
() -> platform.publish(s)).marginLeft(12f);
|
||||
t.row();
|
||||
dialog.hide();
|
||||
}
|
||||
t.addImageTextButton("$schematic.copy", Icon.copySmall, style, () -> {
|
||||
t.addImageTextButton("$schematic.copy", Icon.copy, style, () -> {
|
||||
dialog.hide();
|
||||
ui.showInfoFade("$copied");
|
||||
Core.app.setClipboardText(schematics.writeBase64(s));
|
||||
}).marginLeft(12f);
|
||||
t.row();
|
||||
t.addImageTextButton("$schematic.exportfile", Icon.saveMapSmall, style, () -> platform.showFileChooser(false, schematicExtension, file -> {
|
||||
t.addImageTextButton("$schematic.exportfile", Icon.export, style, () -> platform.showFileChooser(false, schematicExtension, file -> {
|
||||
dialog.hide();
|
||||
try{
|
||||
Schematics.write(s, file);
|
||||
@@ -272,7 +272,7 @@ public class SchematicsDialog extends FloatingDialog{
|
||||
if(wasSet){
|
||||
super.draw();
|
||||
}else{
|
||||
Draw.rect(Icon.loading.getRegion(), x + width/2f, y + height/2f, width/4f, height/4f);
|
||||
Draw.rect(Icon.refresh.getRegion(), x + width/2f, y + height/2f, width/4f, height/4f);
|
||||
}
|
||||
|
||||
Draw.color(checked ? Pal.accent : borderColor);
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.files.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.Texture.*;
|
||||
@@ -12,6 +11,7 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.SettingsDialog.SettingsTable.*;
|
||||
import arc.scene.ui.TextButton.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.core.*;
|
||||
@@ -81,10 +81,10 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
dataDialog.addCloseButton();
|
||||
|
||||
dataDialog.cont.table(Tex.button, t -> {
|
||||
t.defaults().size(240f, 60f).left();
|
||||
t.defaults().size(270f, 60f).left();
|
||||
TextButtonStyle style = Styles.cleart;
|
||||
|
||||
t.addButton("$settings.cleardata", style, () -> ui.showConfirm("$confirm", "$settings.clearall.confirm", () -> {
|
||||
t.addImageTextButton("$settings.cleardata", Icon.trash, style, () -> ui.showConfirm("$confirm", "$settings.clearall.confirm", () -> {
|
||||
ObjectMap<String, Object> map = new ObjectMap<>();
|
||||
for(String value : Core.settings.keys()){
|
||||
if(value.contains("usid") || value.contains("uuid")){
|
||||
@@ -104,7 +104,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
|
||||
t.row();
|
||||
|
||||
t.addButton("$data.export", style, () -> {
|
||||
t.addImageTextButton("$data.export", Icon.download, style, () -> {
|
||||
if(ios){
|
||||
Fi file = Core.files.local("mindustry-data-export.zip");
|
||||
try{
|
||||
@@ -128,7 +128,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
|
||||
t.row();
|
||||
|
||||
t.addButton("$data.import", style, () -> ui.showConfirm("$confirm", "$data.import.confirm", () -> platform.showFileChooser(true, "zip", file -> {
|
||||
t.addImageTextButton("$data.import", Icon.download, style, () -> ui.showConfirm("$confirm", "$data.import.confirm", () -> platform.showFileChooser(true, "zip", file -> {
|
||||
try{
|
||||
data.importData(file);
|
||||
Core.app.exit();
|
||||
@@ -143,6 +143,11 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
}
|
||||
}
|
||||
})));
|
||||
|
||||
if(!ios){
|
||||
t.row();
|
||||
t.addImageTextButton("$data.openfolder", Icon.folder, style, () -> Core.app.openFolder(Core.settings.getDataDirectory().absolutePath()));
|
||||
}
|
||||
});
|
||||
|
||||
ScrollPane pane = new ScrollPane(prefs);
|
||||
@@ -235,10 +240,17 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
game.checkPref("buildautopause", false);
|
||||
}
|
||||
|
||||
if(steam && !Version.modifier.contains("beta")){
|
||||
game.checkPref("publichost", false, i -> {
|
||||
if(steam){
|
||||
game.sliderPref("playerlimit", 16, 2, 32, i -> {
|
||||
platform.updateLobby();
|
||||
return i + "";
|
||||
});
|
||||
|
||||
if(!Version.modifier.contains("beta")){
|
||||
game.checkPref("publichost", false, i -> {
|
||||
platform.updateLobby();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
game.pref(new Setting(){
|
||||
@@ -290,7 +302,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
if(Core.settings.getBool("borderlesswindow")){
|
||||
Core.app.post(() -> Core.graphics.setUndecorated(true));
|
||||
}
|
||||
}else{
|
||||
}else if(!ios){
|
||||
graphics.checkPref("landscape", false, b -> {
|
||||
if(b){
|
||||
platform.beginForceLandscape();
|
||||
@@ -357,7 +369,7 @@ public class SettingsMenuDialog extends SettingsDialog{
|
||||
|
||||
@Override
|
||||
public void addCloseButton(){
|
||||
buttons.addImageTextButton("$back", Icon.arrowLeftSmaller, () -> {
|
||||
buttons.addImageTextButton("$back", Icon.leftOpen, () -> {
|
||||
if(prefs.getChildren().first() != menu){
|
||||
back();
|
||||
}else{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package mindustry.ui.dialogs;
|
||||
|
||||
import arc.*;
|
||||
import arc.scene.ui.layout.Stack;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
@@ -25,6 +26,8 @@ import mindustry.ui.Cicon;
|
||||
import mindustry.ui.layout.*;
|
||||
import mindustry.ui.layout.TreeLayout.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class TechTreeDialog extends FloatingDialog{
|
||||
@@ -60,7 +63,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
|
||||
addCloseButton();
|
||||
|
||||
buttons.addImageTextButton("$database", Icon.database, () -> {
|
||||
buttons.addImageTextButton("$database", Icon.book, () -> {
|
||||
hide();
|
||||
ui.database.show();
|
||||
}).size(210f, 64f);
|
||||
@@ -110,9 +113,25 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
}
|
||||
|
||||
void treeLayout(){
|
||||
RadialTreeLayout layout = new RadialTreeLayout();
|
||||
float spacing = 20f;
|
||||
LayoutNode node = new LayoutNode(root, null);
|
||||
layout.layout(node);
|
||||
LayoutNode[] children = node.children;
|
||||
LayoutNode[] leftHalf = Arrays.copyOfRange(node.children, 0, Mathf.ceil(node.children.length/2f));
|
||||
LayoutNode[] rightHalf = Arrays.copyOfRange(node.children, Mathf.ceil(node.children.length/2f), node.children.length);
|
||||
node.children = leftHalf;
|
||||
new BranchTreeLayout(){{
|
||||
gapBetweenLevels = gapBetweenNodes = spacing;
|
||||
rootLocation = TreeLocation.top;
|
||||
}}.layout(node);
|
||||
node.children = rightHalf;
|
||||
|
||||
new BranchTreeLayout(){{
|
||||
gapBetweenLevels = gapBetweenNodes = spacing;
|
||||
rootLocation = TreeLocation.bottom;
|
||||
}}.layout(node);
|
||||
|
||||
node.children = children;
|
||||
|
||||
float minx = 0f, miny = 0f, maxx = 0f, maxy = 0f;
|
||||
copyInfo(node);
|
||||
|
||||
@@ -252,7 +271,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f + offset, Align.center);
|
||||
button.getStyle().up = !locked(node.node) ? Tex.buttonOver : !data.hasItems(node.node.requirements) ? Tex.buttonRed : Tex.button;
|
||||
((TextureRegionDrawable)button.getStyle().imageUp)
|
||||
.setRegion(node.visible ? node.node.block.icon(Cicon.medium) : Core.atlas.find("icon-locked"));
|
||||
.setRegion(node.visible ? node.node.block.icon(Cicon.medium) : Icon.lock.getRegion());
|
||||
button.getImage().setColor(!locked(node.node) ? Color.white : Color.gray);
|
||||
});
|
||||
addChild(button);
|
||||
@@ -324,7 +343,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
infoTable.table(b -> {
|
||||
b.margin(0).left().defaults().left();
|
||||
|
||||
b.addImageButton(Icon.infoSmall, Styles.cleari, () -> ui.content.show(node.block)).growY().width(50f);
|
||||
b.addImageButton(Icon.info, Styles.cleari, () -> ui.content.show(node.block)).growY().width(50f);
|
||||
b.add().grow();
|
||||
b.table(desc -> {
|
||||
desc.left().defaults().left();
|
||||
@@ -351,14 +370,14 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
|
||||
if(mobile && locked(node)){
|
||||
b.row();
|
||||
b.addImageTextButton("$research", Icon.checkSmall, Styles.nodet, () -> unlock(node))
|
||||
b.addImageTextButton("$research", Icon.ok, Styles.nodet, () -> unlock(node))
|
||||
.disabled(i -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3);
|
||||
}
|
||||
});
|
||||
|
||||
infoTable.row();
|
||||
if(node.block.description != null){
|
||||
infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.description).color(Color.lightGray).growX()).fillX();
|
||||
infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.displayDescription()).color(Color.lightGray).growX()).fillX();
|
||||
}
|
||||
|
||||
addChild(infoTable);
|
||||
@@ -378,7 +397,12 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
|
||||
Lines.stroke(Scl.scl(4f), locked(node.node) || locked(child.node) ? Pal.gray : Pal.accent);
|
||||
Draw.alpha(parentAlpha);
|
||||
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
|
||||
if(Mathf.equal(Math.abs(node.y - child.y), Math.abs(node.x - child.x), 1f) && Mathf.dstm(node.x, node.y, child.x, child.y) <= node.width*3){
|
||||
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
|
||||
}else{
|
||||
Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, node.y + offsetY);
|
||||
Lines.line(child.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
if(i++ % 2 == 0){
|
||||
iteminfo.row();
|
||||
}
|
||||
iteminfo.addImage(stack.item.icon(mindustry.ui.Cicon.small)).size(8 * 3).padRight(1);
|
||||
iteminfo.addImage(stack.item.icon(Cicon.small)).size(8 * 3).padRight(1);
|
||||
iteminfo.add(stack.amount + "").color(Color.lightGray).padRight(5);
|
||||
}
|
||||
};
|
||||
@@ -54,7 +54,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
|
||||
cont.pane(cont -> {
|
||||
if(zone.locked()){
|
||||
cont.addImage(Icon.locked);
|
||||
cont.addImage(Icon.lock);
|
||||
cont.row();
|
||||
cont.add("$locked").padBottom(6);
|
||||
cont.row();
|
||||
@@ -71,7 +71,7 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
for(Objective o : zones){
|
||||
r.addImage(Icon.terrain).padRight(4);
|
||||
r.add(o.display()).color(Color.lightGray);
|
||||
r.addImage(o.complete() ? Icon.checkSmall : Icon.cancelSmall, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.addImage(o.complete() ? Icon.ok : Icon.cancel, o.complete() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.row();
|
||||
}
|
||||
});
|
||||
@@ -85,9 +85,9 @@ public class ZoneInfoDialog extends FloatingDialog{
|
||||
r.add("$research.list").colspan(2).left();
|
||||
r.row();
|
||||
for(Unlock blocko : blocks){
|
||||
r.addImage(blocko.block.icon(mindustry.ui.Cicon.small)).size(8 * 3).padRight(5);
|
||||
r.addImage(blocko.block.icon(Cicon.small)).size(8 * 3).padRight(5);
|
||||
r.add(blocko.block.localizedName).color(Color.lightGray).left();
|
||||
r.addImage(blocko.block.unlocked() ? Icon.checkSmall : Icon.cancelSmall, blocko.block.unlocked() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.addImage(blocko.block.unlocked() ? Icon.ok : Icon.cancel, blocko.block.unlocked() ? Color.lightGray : Color.scarlet).padLeft(3);
|
||||
r.row();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package mindustry.ui.fragments;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
@@ -13,14 +11,18 @@ import arc.scene.actions.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.Administration.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@@ -37,7 +39,14 @@ public class BlockInventoryFragment extends Fragment{
|
||||
@Remote(called = Loc.server, targets = Loc.both, forward = true)
|
||||
public static void requestItem(Player player, Tile tile, Item item, int amount){
|
||||
if(player == null || tile == null || !tile.interactable(player.getTeam())) return;
|
||||
if(!Units.canInteract(player, tile)) return;
|
||||
amount = Mathf.clamp(amount, 0, player.getItemCapacity());
|
||||
int fa = amount;
|
||||
|
||||
if(net.server() && (!Units.canInteract(player, tile) ||
|
||||
!netServer.admins.allowAction(player, ActionType.withdrawItem, tile, action -> {
|
||||
action.item = item;
|
||||
action.itemAmount = fa;
|
||||
}))) throw new ValidateException(player, "Player cannot request items.");
|
||||
|
||||
int removed = tile.block().removeStack(tile, item, amount);
|
||||
|
||||
|
||||
@@ -62,12 +62,12 @@ public class HudFragment extends Fragment{
|
||||
|
||||
ImageButtonStyle style = Styles.clearTransi;
|
||||
|
||||
select.addImageButton(Icon.menuLargeSmall, style, ui.paused::show);
|
||||
flip = select.addImageButton(Icon.arrowUpSmall, style, this::toggleMenus).get();
|
||||
select.addImageButton(Icon.menu, style, ui.paused::show);
|
||||
flip = select.addImageButton(Icon.upOpen, style, this::toggleMenus).get();
|
||||
|
||||
select.addImageButton(Icon.pasteSmall, style, ui.schematics::show);
|
||||
select.addImageButton(Icon.paste, style, ui.schematics::show);
|
||||
|
||||
select.addImageButton(Icon.pauseSmall, style, () -> {
|
||||
select.addImageButton(Icon.pause, style, () -> {
|
||||
if(net.active()){
|
||||
ui.listfrag.toggle();
|
||||
}else{
|
||||
@@ -75,14 +75,14 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
}).name("pause").update(i -> {
|
||||
if(net.active()){
|
||||
i.getStyle().imageUp = Icon.playersSmall;
|
||||
i.getStyle().imageUp = Icon.players;
|
||||
}else{
|
||||
i.setDisabled(false);
|
||||
i.getStyle().imageUp = state.is(State.paused) ? Icon.playSmall : Icon.pauseSmall;
|
||||
i.getStyle().imageUp = state.is(State.paused) ? Icon.play : Icon.pause;
|
||||
}
|
||||
});
|
||||
|
||||
select.addImageButton(Icon.chatSmall, style,() -> {
|
||||
select.addImageButton(Icon.chat, style,() -> {
|
||||
if(net.active() && mobile){
|
||||
if(ui.chatfrag.shown()){
|
||||
ui.chatfrag.hide();
|
||||
@@ -96,9 +96,9 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
}).update(i -> {
|
||||
if(net.active() && mobile){
|
||||
i.getStyle().imageUp = Icon.chatSmall;
|
||||
i.getStyle().imageUp = Icon.chat;
|
||||
}else{
|
||||
i.getStyle().imageUp = Icon.databaseSmall;
|
||||
i.getStyle().imageUp = Icon.book;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -203,7 +203,7 @@ public class HudFragment extends Fragment{
|
||||
float[] position = {0, 0};
|
||||
|
||||
t.row();
|
||||
t.addImageTextButton("$editor.removeunit", Icon.quit, Styles.togglet, () -> {}).fillX().update(b -> {
|
||||
t.addImageTextButton("$editor.removeunit", Icon.cancel, Styles.togglet, () -> {}).fillX().update(b -> {
|
||||
boolean[] found = {false};
|
||||
if(b.isChecked()){
|
||||
Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
|
||||
@@ -319,7 +319,7 @@ public class HudFragment extends Fragment{
|
||||
setDisabled(() -> !control.tutorial.canNext());
|
||||
}},
|
||||
new Table(f -> {
|
||||
f.left().addImageButton(Icon.arrowLeftSmall, Styles.emptyi, () -> {
|
||||
f.left().addImageButton(Icon.left, Styles.emptyi, () -> {
|
||||
control.tutorial.prevSentence();
|
||||
}).width(44f).growY().visible(() -> control.tutorial.canPrev());
|
||||
}));
|
||||
@@ -393,7 +393,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
});
|
||||
table.margin(12);
|
||||
table.addImage(Icon.check).pad(3);
|
||||
table.addImage(Icon.ok).pad(3);
|
||||
table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center);
|
||||
table.pack();
|
||||
|
||||
@@ -562,7 +562,7 @@ public class HudFragment extends Fragment{
|
||||
|
||||
private void toggleMenus(){
|
||||
if(flip != null){
|
||||
flip.getStyle().imageUp = shown ? Icon.arrowDownSmall : Icon.arrowUpSmall;
|
||||
flip.getStyle().imageUp = shown ? Icon.downOpen : Icon.upOpen;
|
||||
}
|
||||
|
||||
shown = !shown;
|
||||
@@ -650,7 +650,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
|
||||
private void addPlayButton(Table table){
|
||||
table.right().addImageButton(Icon.playSmaller, Styles.righti, 30f, () -> {
|
||||
table.right().addImageButton(Icon.play, Styles.righti, 30f, () -> {
|
||||
if(net.client() && player.isAdmin){
|
||||
Call.onAdminRequest(player, AdminAction.wave);
|
||||
}else if(inLaunchWave()){
|
||||
|
||||
@@ -60,7 +60,7 @@ public class MenuFragment extends Fragment{
|
||||
parent.fill(c -> c.bottom().left().addButton("", Styles.infot, ui.about::show).size(84, 45));
|
||||
parent.fill(c -> c.bottom().right().addButton("", Styles.discordt, ui.discord::show).size(84, 45));
|
||||
}else if(becontrol.active()){
|
||||
parent.fill(c -> c.bottom().right().addImageTextButton("$be.check", Icon.refreshSmall, () -> {
|
||||
parent.fill(c -> c.bottom().right().addImageTextButton("$be.check", Icon.refresh, () -> {
|
||||
ui.loadfrag.show();
|
||||
becontrol.checkUpdate(result -> {
|
||||
ui.loadfrag.hide();
|
||||
@@ -100,13 +100,13 @@ public class MenuFragment extends Fragment{
|
||||
container.defaults().size(size).pad(5).padTop(4f);
|
||||
|
||||
MobileButton
|
||||
play = new MobileButton(Icon.play2, "$campaign", () -> checkPlay(ui.deploy::show)),
|
||||
custom = new MobileButton(Icon.playCustom, "$customgame", () -> checkPlay(ui.custom::show)),
|
||||
maps = new MobileButton(Icon.load, "$loadgame", () -> checkPlay(ui.load::show)),
|
||||
play = new MobileButton(Icon.play, "$campaign", () -> checkPlay(ui.deploy::show)),
|
||||
custom = new MobileButton(Icon.rightOpenOut, "$customgame", () -> checkPlay(ui.custom::show)),
|
||||
maps = new MobileButton(Icon.download, "$loadgame", () -> checkPlay(ui.load::show)),
|
||||
join = new MobileButton(Icon.add, "$joingame", () -> checkPlay(ui.join::show)),
|
||||
editor = new MobileButton(Icon.editor, "$editor", () -> checkPlay(ui.maps::show)),
|
||||
tools = new MobileButton(Icon.tools, "$settings", ui.settings::show),
|
||||
mods = new MobileButton(Icon.wiki, "$mods", ui.mods::show),
|
||||
editor = new MobileButton(Icon.terrain, "$editor", () -> checkPlay(ui.maps::show)),
|
||||
tools = new MobileButton(Icon.settings, "$settings", ui.settings::show),
|
||||
mods = new MobileButton(Icon.book, "$mods", ui.mods::show),
|
||||
donate = new MobileButton(Icon.link, "$website", () -> Core.net.openURI("https://anuke.itch.io/mindustry")),
|
||||
exit = new MobileButton(Icon.exit, "$quit", () -> Core.app.exit());
|
||||
|
||||
@@ -164,20 +164,20 @@ public class MenuFragment extends Fragment{
|
||||
t.defaults().width(width).height(70f);
|
||||
|
||||
buttons(t,
|
||||
new Buttoni("$play", Icon.play2Small,
|
||||
new Buttoni("$campaign", Icon.play2Small, () -> checkPlay(ui.deploy::show)),
|
||||
new Buttoni("$joingame", Icon.addSmall, () -> checkPlay(ui.join::show)),
|
||||
new Buttoni("$customgame", Icon.editorSmall, () -> checkPlay(ui.custom::show)),
|
||||
new Buttoni("$loadgame", Icon.loadSmall, () -> checkPlay(ui.load::show)),
|
||||
new Buttoni("$tutorial", Icon.infoSmall, () -> checkPlay(control::playTutorial))
|
||||
new Buttoni("$play", Icon.play,
|
||||
new Buttoni("$campaign", Icon.play, () -> checkPlay(ui.deploy::show)),
|
||||
new Buttoni("$joingame", Icon.add, () -> checkPlay(ui.join::show)),
|
||||
new Buttoni("$customgame", Icon.terrain, () -> checkPlay(ui.custom::show)),
|
||||
new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)),
|
||||
new Buttoni("$tutorial", Icon.info, () -> checkPlay(control::playTutorial))
|
||||
),
|
||||
new Buttoni("$editor", Icon.editorSmall, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.saveSmall, platform::openWorkshop) : null,
|
||||
new Buttoni(Core.bundle.get("mods") + "\n" + Core.bundle.get("mods.alpha"), Icon.wikiSmall, ui.mods::show),
|
||||
new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.book, platform::openWorkshop) : null,
|
||||
new Buttoni(Core.bundle.get("mods"), Icon.bookOpen, ui.mods::show),
|
||||
//not enough space for this button
|
||||
//new Buttoni("$schematics", Icon.pasteSmall, ui.schematics::show),
|
||||
new Buttoni("$settings", Icon.toolsSmall, ui.settings::show),
|
||||
new Buttoni("$about.button", Icon.infoSmall, ui.about::show),
|
||||
new Buttoni("$quit", Icon.exitSmall, Core.app::exit)
|
||||
//new Buttoni("$schematics", Icon.paste, ui.schematics::show),
|
||||
new Buttoni("$settings", Icon.settings, ui.settings::show),
|
||||
new Buttoni("$about.button", Icon.info, ui.about::show),
|
||||
new Buttoni("$quit", Icon.exit, Core.app::exit)
|
||||
);
|
||||
|
||||
}).width(width).growY();
|
||||
|
||||
@@ -100,7 +100,7 @@ public class MinimapFragment extends Fragment{
|
||||
t.row();
|
||||
t.add().growY();
|
||||
t.row();
|
||||
t.addImageTextButton("$back", Icon.backSmall, () -> shown = false).size(220f, 60f).pad(10f);
|
||||
t.addImageTextButton("$back", Icon.leftOpen, () -> shown = false).size(220f, 60f).pad(10f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package mindustry.ui.fragments;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.input.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.event.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
@@ -19,7 +20,6 @@ import mindustry.graphics.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@@ -31,11 +31,13 @@ public class PlacementFragment extends Fragment{
|
||||
Array<Block> returnArray = new Array<>();
|
||||
Array<Category> returnCatArray = new Array<>();
|
||||
boolean[] categoryEmpty = new boolean[Category.all.length];
|
||||
ObjectMap<Category,Block> selectedBlocks = new ObjectMap<Category,Block>();
|
||||
ObjectMap<Category,Block> selectedBlocks = new ObjectMap<>();
|
||||
ObjectFloatMap<Category> scrollPositions = new ObjectFloatMap<>();
|
||||
Block hovered, lastDisplay;
|
||||
Tile lastHover;
|
||||
Tile hoverTile;
|
||||
Table blockTable, toggler, topTable;
|
||||
ScrollPane blockPane;
|
||||
boolean lastGround;
|
||||
boolean blockSelectEnd;
|
||||
int blockSelectSeq;
|
||||
@@ -86,6 +88,8 @@ public class PlacementFragment extends Fragment{
|
||||
}
|
||||
|
||||
boolean gridUpdate(InputHandler input){
|
||||
scrollPositions.put(currentCategory, blockPane.getScrollY());
|
||||
|
||||
if(Core.input.keyDown(Binding.pick)){ //mouse eyedropper select
|
||||
Tile tile = world.ltileWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
|
||||
Block tryRecipe = tile == null ? null : tile.block();
|
||||
@@ -202,14 +206,18 @@ public class PlacementFragment extends Fragment{
|
||||
blockTable.row();
|
||||
}
|
||||
|
||||
ImageButton button = blockTable.addImageButton(Icon.lockedSmall, Styles.selecti, () -> {
|
||||
ImageButton button = blockTable.addImageButton(new TextureRegionDrawable(block.icon(Cicon.medium)), Styles.selecti, () -> {
|
||||
if(unlocked(block)){
|
||||
control.input.block = control.input.block == block ? null : block;
|
||||
selectedBlocks.put(currentCategory, control.input.block);
|
||||
if(Core.input.keyDown(KeyCode.SHIFT_LEFT) && Fonts.getUnicode(block.name) != 0){
|
||||
Core.app.setClipboardText((char)Fonts.getUnicode(block.name) + "");
|
||||
ui.showInfoFade("$copied");
|
||||
}else{
|
||||
control.input.block = control.input.block == block ? null : block;
|
||||
selectedBlocks.put(currentCategory, control.input.block);
|
||||
}
|
||||
}
|
||||
}).size(46f).group(group).name("block-" + block.name).get();
|
||||
|
||||
button.getStyle().imageUp = new TextureRegionDrawable(block.icon(Cicon.medium));
|
||||
button.resizeImage(Cicon.medium.size);
|
||||
|
||||
button.update(() -> { //color unplacable things gray
|
||||
TileEntity core = player.getClosestCore();
|
||||
@@ -236,6 +244,12 @@ public class PlacementFragment extends Fragment{
|
||||
}
|
||||
}
|
||||
blockTable.act(0f);
|
||||
blockPane.setScrollYForce(scrollPositions.get(currentCategory, 0));
|
||||
Core.app.post(() -> {
|
||||
blockPane.setScrollYForce(scrollPositions.get(currentCategory, 0));
|
||||
blockPane.act(0f);
|
||||
blockPane.layout();
|
||||
});
|
||||
};
|
||||
|
||||
//top table with hover info
|
||||
@@ -311,7 +325,7 @@ public class PlacementFragment extends Fragment{
|
||||
if(state.rules.bannedBlocks.contains(lastDisplay)){
|
||||
topTable.row();
|
||||
topTable.table(b -> {
|
||||
b.addImage(Icon.cancelSmall).padRight(2).color(Color.scarlet);
|
||||
b.addImage(Icon.cancel).padRight(2).color(Color.scarlet);
|
||||
b.add("$banned");
|
||||
b.left();
|
||||
}).padTop(2).left();
|
||||
@@ -339,14 +353,15 @@ public class PlacementFragment extends Fragment{
|
||||
frame.row();
|
||||
frame.table(Tex.pane2, blocksSelect -> {
|
||||
blocksSelect.margin(4).marginTop(0);
|
||||
blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> {
|
||||
blockPane = blocksSelect.pane(blocks -> blockTable = blocks).height(194f).update(pane -> {
|
||||
if(pane.hasScroll()){
|
||||
Element result = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true);
|
||||
if(result == null || !result.isDescendantOf(pane)){
|
||||
Core.scene.setScrollFocus(null);
|
||||
}
|
||||
}
|
||||
}).grow().get().setStyle(Styles.smallPane);
|
||||
}).grow().get();
|
||||
blockPane.setStyle(Styles.smallPane);
|
||||
blocksSelect.row();
|
||||
blocksSelect.table(control.input::buildPlacementUI).name("inputTable").growX();
|
||||
}).fillY().bottom().touchable(Touchable.enabled);
|
||||
@@ -378,7 +393,7 @@ public class PlacementFragment extends Fragment{
|
||||
continue;
|
||||
}
|
||||
|
||||
categories.addImageButton(Core.atlas.drawable("icon-" + cat.name() + "-smaller"), Styles.clearToggleTransi, () -> {
|
||||
categories.addImageButton(ui.getIcon(cat.name()), Styles.clearToggleTransi, () -> {
|
||||
currentCategory = cat;
|
||||
if(control.input.block != null){
|
||||
control.input.block = getSelectedBlock(currentCategory);
|
||||
|
||||
@@ -104,14 +104,14 @@ public class PlayerListFragment extends Fragment{
|
||||
button.table(t -> {
|
||||
t.defaults().size(bs);
|
||||
|
||||
t.addImageButton(Icon.banSmall, Styles.clearPartiali,
|
||||
t.addImageButton(Icon.hammer, Styles.clearPartiali,
|
||||
() -> ui.showConfirm("$confirm", "$confirmban", () -> Call.onAdminRequest(user, AdminAction.ban)));
|
||||
t.addImageButton(Icon.cancelSmall, Styles.clearPartiali,
|
||||
t.addImageButton(Icon.cancel, Styles.clearPartiali,
|
||||
() -> ui.showConfirm("$confirm", "$confirmkick", () -> Call.onAdminRequest(user, AdminAction.kick)));
|
||||
|
||||
t.row();
|
||||
|
||||
t.addImageButton(Icon.adminSmall, Styles.clearTogglePartiali, () -> {
|
||||
t.addImageButton(Icon.admin, Styles.clearTogglePartiali, () -> {
|
||||
if(net.client()) return;
|
||||
|
||||
String id = user.uuid;
|
||||
@@ -127,13 +127,13 @@ public class PlayerListFragment extends Fragment{
|
||||
.touchable(() -> net.client() ? Touchable.disabled : Touchable.enabled)
|
||||
.checked(user.isAdmin);
|
||||
|
||||
t.addImageButton(Icon.zoomSmall, Styles.clearPartiali, () -> Call.onAdminRequest(user, AdminAction.trace));
|
||||
t.addImageButton(Icon.zoom, Styles.clearPartiali, () -> Call.onAdminRequest(user, AdminAction.trace));
|
||||
|
||||
}).padRight(12).size(bs + 10f, bs);
|
||||
}else if((!user.isLocal && !user.isAdmin) && net.client() && playerGroup.size() >= 3 && player.getTeam() != user.getTeam()){ //votekick
|
||||
}else if(!user.isLocal && !user.isAdmin && net.client() && playerGroup.size() >= 3 && player.getTeam() == user.getTeam()){ //votekick
|
||||
button.add().growY();
|
||||
|
||||
button.addImageButton(Icon.banSmall, Styles.clearPartiali,
|
||||
button.addImageButton(Icon.hammer, Styles.clearPartiali,
|
||||
() -> ui.showConfirm("$confirm", "$confirmvotekick", () -> Call.sendChatMessage("/votekick " + user.name))).size(h);
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ public class ScriptConsoleFragment extends Table{
|
||||
clearChatInput();
|
||||
}
|
||||
|
||||
return shown && Vars.net.active();
|
||||
return shown && !Vars.net.active();
|
||||
});
|
||||
|
||||
update(() -> {
|
||||
|
||||
@@ -148,8 +148,7 @@ public class BranchTreeLayout implements TreeLayout{
|
||||
wPlus.mode = wPlus.mode + shift;
|
||||
}
|
||||
|
||||
private TreeNode apportion(TreeNode v, TreeNode defaultAncestor,
|
||||
TreeNode leftSibling, TreeNode parentOfV){
|
||||
private TreeNode apportion(TreeNode v, TreeNode defaultAncestor, TreeNode leftSibling, TreeNode parentOfV){
|
||||
if(leftSibling == null){
|
||||
return defaultAncestor;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public class RadialTreeLayout implements TreeLayout{
|
||||
@Override
|
||||
public void layout(TreeNode root){
|
||||
startRadius = root.height * 2.4f;
|
||||
delta = root.height * 2.4f;
|
||||
delta = root.height * 20.4f;
|
||||
|
||||
bfs(root, true);
|
||||
|
||||
|
||||
36
core/src/mindustry/ui/layout/RowTreeLayout.java
Normal file
36
core/src/mindustry/ui/layout/RowTreeLayout.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package mindustry.ui.layout;
|
||||
|
||||
import arc.struct.*;
|
||||
|
||||
public class RowTreeLayout implements TreeLayout{
|
||||
|
||||
@Override
|
||||
public void layout(TreeNode root){
|
||||
layout(root, 0, new IntArray());
|
||||
|
||||
/*
|
||||
def minimum_ws(tree, depth=0):
|
||||
tree.x = nexts[depth]
|
||||
tree.y = depth
|
||||
nexts[depth] += 1
|
||||
for c in tree.children:
|
||||
minimum_ws(tree, c)
|
||||
*/
|
||||
}
|
||||
|
||||
void layout(TreeNode node, int depth, IntArray nexts){
|
||||
float size = node.height * 5f;
|
||||
|
||||
if(nexts.size < depth + 1){
|
||||
nexts.ensureCapacity(depth + 1);
|
||||
nexts.size = depth + 1;
|
||||
}
|
||||
|
||||
node.x = size * nexts.get(depth);
|
||||
node.y = size * depth;
|
||||
nexts.incr(depth, 1);
|
||||
for(TreeNode child : node.children){
|
||||
layout(child, depth + 1, nexts);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,15 @@
|
||||
package mindustry.world;
|
||||
|
||||
import mindustry.annotations.Annotations.Loc;
|
||||
import mindustry.annotations.Annotations.Remote;
|
||||
import arc.Core;
|
||||
import arc.Events;
|
||||
import arc.math.Mathf;
|
||||
import arc.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import mindustry.content.Blocks;
|
||||
import mindustry.entities.Units;
|
||||
import mindustry.game.EventType.BlockBuildBeginEvent;
|
||||
import mindustry.game.Team;
|
||||
import mindustry.world.blocks.BuildBlock;
|
||||
import mindustry.world.blocks.BuildBlock.BuildEntity;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.blocks.BuildBlock.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package mindustry.world;
|
||||
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
@@ -215,6 +216,16 @@ public class Tile implements Position, TargetTrait{
|
||||
}
|
||||
}
|
||||
|
||||
/** remove()-s this tile, except it's synced across the network */
|
||||
public void removeNet(){
|
||||
Call.removeTile(this);
|
||||
}
|
||||
|
||||
/** set()-s this tile, except it's synced across the network */
|
||||
public void setNet(Block block, Team team, int rotation){
|
||||
Call.setTile(this, block, team, rotation);
|
||||
}
|
||||
|
||||
public byte rotation(){
|
||||
return rotation;
|
||||
}
|
||||
@@ -506,4 +517,16 @@ public class Tile implements Position, TargetTrait{
|
||||
public String toString(){
|
||||
return floor.name + ":" + block.name + ":" + overlay + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())) + ":" + getTeam();
|
||||
}
|
||||
|
||||
//remote utility methods
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void removeTile(Tile tile){
|
||||
tile.remove();
|
||||
}
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void setTile(Tile tile, Block block, Team team, int rotation){
|
||||
tile.set(block, team, rotation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,8 +57,8 @@ public class BuildBlock extends Block{
|
||||
public static void onDeconstructFinish(Tile tile, Block block, int builderID){
|
||||
Team team = tile.getTeam();
|
||||
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
|
||||
tile.remove();
|
||||
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true));
|
||||
tile.remove();
|
||||
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ public class Floor extends Block{
|
||||
public Effect updateEffect = Fx.none;
|
||||
/** Array of affinities to certain things. */
|
||||
public Attributes attributes = new Attributes();
|
||||
/** Whether this ore generates in maps by default. */
|
||||
public boolean oreDefault = false;
|
||||
/** Ore generation params. */
|
||||
public float oreScale = 24f, oreThreshold = 0.828f;
|
||||
|
||||
protected TextureRegion[][] edges;
|
||||
protected byte eq = 0;
|
||||
|
||||
@@ -28,6 +28,10 @@ public class ItemConveyor extends BaseConveyor implements Autotiler{
|
||||
private static ItemPos pos2 = new ItemPos();
|
||||
private final Vec2 tr1 = new Vec2();
|
||||
private final Vec2 tr2 = new Vec2();
|
||||
private TextureRegion[][] regions = new TextureRegion[7][4];
|
||||
|
||||
public float speed = 0f;
|
||||
public float displayedSpeed = 0f;
|
||||
|
||||
protected ItemConveyor(String name){
|
||||
super(name);
|
||||
@@ -44,7 +48,8 @@ public class ItemConveyor extends BaseConveyor implements Autotiler{
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.itemsMoved, speed * 60 / itemSpace, StatUnit.itemsSecond);
|
||||
//have to add a custom calculated speed, since the actual movement speed is apparently not linear
|
||||
stats.add(BlockStat.itemsMoved, displayedSpeed, StatUnit.itemsSecond);
|
||||
stats.add(BlockStat.boostEffect, "$blocks.itemsmoved");
|
||||
}
|
||||
|
||||
|
||||
@@ -192,6 +192,11 @@ public class MassDriver extends Block{
|
||||
|
||||
MassDriverEntity entity = tile.ent();
|
||||
|
||||
for(Tile shooter : entity.waitingShooters){
|
||||
Drawf.circles(shooter.drawx(), shooter.drawy(), (tile.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
|
||||
Drawf.arrow(shooter.drawx(), shooter.drawy(), tile.drawx(), tile.drawy(), size * tilesize + sin, 4f + sin, Pal.place);
|
||||
}
|
||||
|
||||
if(linkValid(tile)){
|
||||
Tile target = world.tile(entity.link);
|
||||
Drawf.circles(target.drawx(), target.drawy(), (target.block().size / 2f + 1) * tilesize + sin - 2f, Pal.place);
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.io.*;
|
||||
|
||||
public class OverflowGate extends Block{
|
||||
public float speed = 1f;
|
||||
public boolean invert = false;
|
||||
|
||||
public OverflowGate(String name){
|
||||
super(name);
|
||||
@@ -72,23 +73,26 @@ public class OverflowGate extends Block{
|
||||
entity.lastItem = item;
|
||||
entity.time = 0f;
|
||||
entity.lastInput = source;
|
||||
|
||||
update(tile);
|
||||
}
|
||||
|
||||
Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){
|
||||
public Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){
|
||||
int from = tile.relativeTo(src.x, src.y);
|
||||
if(from == -1) return null;
|
||||
Tile to = tile.getNearby((from + 2) % 4);
|
||||
if(to == null) return null;
|
||||
Tile edge = Edges.getFacingEdge(tile, to);
|
||||
boolean canForward = to.block().acceptItem(item, to, edge) && to.getTeam() == tile.getTeam() && !(to.block() instanceof OverflowGate);
|
||||
|
||||
if(!to.block().acceptItem(item, to, edge) || to.getTeam() != tile.getTeam() || (to.block() instanceof OverflowGate)){
|
||||
if(!canForward || invert){
|
||||
Tile a = tile.getNearby(Mathf.mod(from - 1, 4));
|
||||
Tile b = tile.getNearby(Mathf.mod(from + 1, 4));
|
||||
boolean ac = a != null && a.block().acceptItem(item, a, edge) && !(a.block() instanceof OverflowGate) && a.getTeam() == tile.getTeam();
|
||||
boolean bc = b != null && b.block().acceptItem(item, b, edge) && !(b.block() instanceof OverflowGate) && b.getTeam() == tile.getTeam();
|
||||
|
||||
if(!ac && !bc){
|
||||
return null;
|
||||
return invert && canForward ? to : null;
|
||||
}
|
||||
|
||||
if(ac && !bc){
|
||||
|
||||
@@ -3,8 +3,8 @@ package mindustry.world.blocks.distribution;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.type.*;
|
||||
@@ -85,7 +85,8 @@ public class Sorter extends Block{
|
||||
}
|
||||
|
||||
boolean isSame(Tile tile, Tile other){
|
||||
return other != null && other.block() instanceof Sorter;
|
||||
//uncomment comment below to prevent sorter/gate chaining (hacky)
|
||||
return other != null && (other.block() instanceof Sorter/* || other.block() instanceof OverflowGate */);
|
||||
}
|
||||
|
||||
Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package mindustry.world.blocks.liquid;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
@@ -13,7 +13,6 @@ import mindustry.entities.type.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
public class Conduit extends LiquidBlock implements Autotiler{
|
||||
public final int timerFlow = timers++;
|
||||
@@ -92,13 +91,12 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
@Override
|
||||
public void draw(Tile tile){
|
||||
ConduitEntity entity = tile.ent();
|
||||
LiquidModule mod = tile.entity.liquids;
|
||||
int rotation = tile.rotation() * 90;
|
||||
|
||||
Draw.colorl(0.34f);
|
||||
Draw.rect(botRegions[entity.blendbits], tile.drawx(), tile.drawy(), rotation);
|
||||
|
||||
Draw.color(mod.current().color);
|
||||
Draw.color(tile.entity.liquids.current().color);
|
||||
Draw.alpha(entity.smoothLiquid);
|
||||
Draw.rect(botRegions[entity.blendbits], tile.drawx(), tile.drawy(), rotation);
|
||||
Draw.color();
|
||||
@@ -109,7 +107,7 @@ public class Conduit extends LiquidBlock implements Autotiler{
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ConduitEntity entity = tile.ent();
|
||||
entity.smoothLiquid = Mathf.lerpDelta(entity.smoothLiquid, entity.liquids.total() / liquidCapacity, 0.05f);
|
||||
entity.smoothLiquid = Mathf.lerpDelta(entity.smoothLiquid, entity.liquids.currentAmount() / liquidCapacity, 0.05f);
|
||||
|
||||
if(tile.entity.liquids.total() > 0.001f && tile.entity.timer.get(timerFlow, 1)){
|
||||
tryMoveLiquid(tile, tile.getNearby(tile.rotation()), leakResistance, tile.entity.liquids.current());
|
||||
|
||||
@@ -98,7 +98,7 @@ public class MessageBlock extends Block{
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
MessageBlockEntity entity = tile.ent();
|
||||
|
||||
table.addImageButton(Icon.pencilSmall, () -> {
|
||||
table.addImageButton(Icon.pencil, () -> {
|
||||
if(mobile){
|
||||
Core.input.getTextInput(new TextInput(){{
|
||||
text = entity.message;
|
||||
|
||||
@@ -52,7 +52,7 @@ public class LightBlock extends Block{
|
||||
public void buildConfiguration(Tile tile, Table table){
|
||||
LightEntity entity = tile.ent();
|
||||
|
||||
table.addImageButton(Icon.pencilSmall, () -> {
|
||||
table.addImageButton(Icon.pencil, () -> {
|
||||
ui.picker.show(Tmp.c1.set(entity.color).a(0.5f), false, res -> {
|
||||
entity.color = res.rgba();
|
||||
lastColor = entity.color;
|
||||
|
||||
@@ -13,11 +13,19 @@ import static mindustry.Vars.renderer;
|
||||
|
||||
public class ThermalGenerator extends PowerGenerator{
|
||||
public Effect generateEffect = Fx.none;
|
||||
public Attribute attribute = Attribute.heat;
|
||||
|
||||
public ThermalGenerator(String name){
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.tiles, attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
GeneratorEntity entity = tile.ent();
|
||||
@@ -29,7 +37,7 @@ public class ThermalGenerator extends PowerGenerator{
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(Attribute.heat, x, y) * 100, 1), x, y, valid);
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", sumAttribute(attribute, x, y) * 100, 1), x, y, valid);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,7 +51,7 @@ public class ThermalGenerator extends PowerGenerator{
|
||||
super.onProximityAdded(tile);
|
||||
|
||||
GeneratorEntity entity = tile.ent();
|
||||
entity.productionEfficiency = sumAttribute(Attribute.heat, tile.x, tile.y);
|
||||
entity.productionEfficiency = sumAttribute(attribute, tile.x, tile.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,6 +64,6 @@ public class ThermalGenerator extends PowerGenerator{
|
||||
@Override
|
||||
public boolean canPlaceOn(Tile tile){
|
||||
//make sure there's heat at this location
|
||||
return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(Attribute.heat)) > 0.01f;
|
||||
return tile.getLinkedTilesAs(this, tempTiles).sumf(other -> other.floor().attributes.get(attribute)) > 0.01f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.Core;
|
||||
import arc.graphics.Color;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.RandomXS128;
|
||||
import arc.util.Time;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.graphics.Pal;
|
||||
import mindustry.ui.Bar;
|
||||
import mindustry.world.Tile;
|
||||
import mindustry.world.meta.Attribute;
|
||||
import arc.math.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
@@ -21,7 +20,7 @@ public class Cultivator extends GenericCrafter{
|
||||
public Color bottomColor = Color.valueOf("474747");
|
||||
|
||||
public TextureRegion middleRegion, topRegion;
|
||||
public RandomXS128 random = new RandomXS128(0);
|
||||
public Rand random = new Rand(0);
|
||||
public float recurrence = 6f;
|
||||
public Attribute attribute = Attribute.spores;
|
||||
|
||||
@@ -57,6 +56,13 @@ public class Cultivator extends GenericCrafter{
|
||||
() -> ((CultivatorEntity)entity).warmup));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
|
||||
stats.add(BlockStat.affinities, attribute);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawPlace(int x, int y, int rotation, boolean valid){
|
||||
drawPlaceText(Core.bundle.formatFloat("bar.efficiency", (1 + sumAttribute(attribute, x, y)) * 100, 1), x, y, valid);
|
||||
|
||||
@@ -134,8 +134,6 @@ public class GenericCrafter extends Block{
|
||||
return outputItem != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean shouldConsume(Tile tile){
|
||||
if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package mindustry.world.blocks.production;
|
||||
|
||||
import arc.graphics.*;
|
||||
import arc.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
@@ -15,15 +15,11 @@ import mindustry.world.meta.values.*;
|
||||
* Extracts a random list of items from an input item and an input liquid.
|
||||
*/
|
||||
public class Separator extends Block{
|
||||
protected @NonNull ItemStack[] results;
|
||||
protected float craftTime;
|
||||
protected float spinnerRadius = 2.5f;
|
||||
protected float spinnerLength = 1f;
|
||||
protected float spinnerThickness = 1f;
|
||||
protected float spinnerSpeed = 2f;
|
||||
public @NonNull ItemStack[] results;
|
||||
public float craftTime;
|
||||
|
||||
protected Color color = Color.valueOf("858585");
|
||||
protected int liquidRegion;
|
||||
public int liquidRegion, spinnerRegion;
|
||||
public float spinnerSpeed = 3f;
|
||||
|
||||
public Separator(String name){
|
||||
super(name);
|
||||
@@ -33,6 +29,7 @@ public class Separator extends Block{
|
||||
hasLiquids = true;
|
||||
|
||||
liquidRegion = reg("-liquid");
|
||||
spinnerRegion = reg("-spinner");
|
||||
entityType = GenericCrafterEntity::new;
|
||||
}
|
||||
|
||||
@@ -70,10 +67,10 @@ public class Separator extends Block{
|
||||
Draw.alpha(tile.entity.liquids.total() / liquidCapacity);
|
||||
Draw.rect(reg(liquidRegion), tile.drawx(), tile.drawy());
|
||||
|
||||
Draw.color(color);
|
||||
Lines.stroke(spinnerThickness);
|
||||
Lines.spikes(tile.drawx(), tile.drawy(), spinnerRadius, spinnerLength, 3, entity.totalProgress * spinnerSpeed);
|
||||
Draw.reset();
|
||||
if(Core.atlas.isFound(reg(spinnerRegion))){
|
||||
Draw.rect(reg(spinnerRegion), tile.drawx(), tile.drawy(), entity.totalProgress * spinnerSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import arc.graphics.g2d.Draw;
|
||||
import arc.graphics.g2d.TextureRegion;
|
||||
import arc.math.Mathf;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.Fx;
|
||||
import mindustry.content.Liquids;
|
||||
import mindustry.entities.Effects;
|
||||
@@ -26,7 +27,7 @@ public class SolidPump extends Pump{
|
||||
public float updateEffectChance = 0.02f;
|
||||
public float rotateSpeed = 1f;
|
||||
/** Attribute that is checked when calculating output. */
|
||||
public Attribute attribute;
|
||||
public @Nullable Attribute attribute;
|
||||
|
||||
public SolidPump(String name){
|
||||
super(name);
|
||||
@@ -64,6 +65,9 @@ public class SolidPump extends Pump{
|
||||
|
||||
stats.remove(BlockStat.output);
|
||||
stats.add(BlockStat.output, result, 60f * pumpAmount, true);
|
||||
if(attribute != null){
|
||||
stats.add(BlockStat.affinities, attribute);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -99,7 +99,7 @@ public class CoreBlock extends StorageBlock{
|
||||
|
||||
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||
if(other.tile == tile) continue;
|
||||
entity.storageCapacity += other.block.itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
entity.storageCapacity += other.block.itemCapacity + other.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
}
|
||||
|
||||
if(!world.isGenerating()){
|
||||
|
||||
@@ -3,6 +3,7 @@ package mindustry.world.blocks.units;
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
@@ -20,10 +21,10 @@ import mindustry.world.meta.*;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import static mindustry.Vars.indexer;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class CommandCenter extends Block{
|
||||
protected TextureRegion[] commandRegions = new TextureRegion[UnitCommand.all.length];
|
||||
protected TextureRegionDrawable[] commandRegions = new TextureRegionDrawable[UnitCommand.all.length];
|
||||
protected Color topColor = Pal.command;
|
||||
protected Color bottomColor = Color.valueOf("5e5e5e");
|
||||
protected Effect effect = Fx.commandSend;
|
||||
@@ -65,8 +66,10 @@ public class CommandCenter extends Block{
|
||||
public void load(){
|
||||
super.load();
|
||||
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
commandRegions[cmd.ordinal()] = Core.atlas.find("icon-command-" + cmd.name() + "-small");
|
||||
if(ui != null){
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
commandRegions[cmd.ordinal()] = ui.getIcon("command" + Strings.capitalize(cmd.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,12 +78,12 @@ public class CommandCenter extends Block{
|
||||
CommandCenterEntity entity = tile.ent();
|
||||
super.draw(tile);
|
||||
|
||||
float size = IconSize.small.size/4f;
|
||||
float size = 6f;
|
||||
|
||||
Draw.color(bottomColor);
|
||||
Draw.rect(commandRegions[entity.command.ordinal()], tile.drawx(), tile.drawy() - 1, size, size);
|
||||
Draw.rect(commandRegions[entity.command.ordinal()].getRegion(), tile.drawx(), tile.drawy() - 1, size, size);
|
||||
Draw.color(topColor);
|
||||
Draw.rect(commandRegions[entity.command.ordinal()], tile.drawx(), tile.drawy(), size, size);
|
||||
Draw.rect(commandRegions[entity.command.ordinal()].getRegion(), tile.drawx(), tile.drawy(), size, size);
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
@@ -91,7 +94,7 @@ public class CommandCenter extends Block{
|
||||
Table buttons = new Table();
|
||||
|
||||
for(UnitCommand cmd : UnitCommand.all){
|
||||
buttons.addImageButton(Core.atlas.drawable("icon-command-" + cmd.name() + "-small"), Styles.clearToggleTransi, () -> tile.configure(cmd.ordinal()))
|
||||
buttons.addImageButton(commandRegions[cmd.ordinal()], Styles.clearToggleTransi, () -> tile.configure(cmd.ordinal()))
|
||||
.size(44).group(group).update(b -> b.setChecked(entity.command == cmd));
|
||||
}
|
||||
table.add(buttons);
|
||||
|
||||
@@ -24,6 +24,7 @@ public enum BlockStat{
|
||||
powerConnections(StatCategory.power),
|
||||
basePowerGeneration(StatCategory.power),
|
||||
|
||||
tiles(StatCategory.crafting),
|
||||
input(StatCategory.crafting),
|
||||
output(StatCategory.crafting),
|
||||
productionTime(StatCategory.crafting),
|
||||
@@ -45,7 +46,8 @@ public enum BlockStat{
|
||||
ammo(StatCategory.shooting),
|
||||
|
||||
booster(StatCategory.optional),
|
||||
boostEffect(StatCategory.optional);
|
||||
boostEffect(StatCategory.optional),
|
||||
affinities(StatCategory.optional);
|
||||
|
||||
public final StatCategory category;
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
package mindustry.world.meta;
|
||||
|
||||
import arc.struct.Array;
|
||||
import arc.struct.ObjectMap.Entry;
|
||||
import arc.struct.OrderedMap;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.struct.ObjectMap.*;
|
||||
import mindustry.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.meta.values.*;
|
||||
|
||||
/** Hold and organizes a list of block stats. */
|
||||
@@ -36,6 +38,13 @@ public class BlockStats{
|
||||
add(stat, new LiquidValue(liquid, amount, perSecond));
|
||||
}
|
||||
|
||||
public void add(BlockStat stat, Attribute attr){
|
||||
for(Block block : Vars.content.blocks()){
|
||||
if(!block.isFloor() || Mathf.zero(block.asFloor().attributes.get(attr))) continue;
|
||||
add(stat, new FloorValue(block.asFloor()));
|
||||
}
|
||||
}
|
||||
|
||||
/** Adds a single string value with this stat. */
|
||||
public void add(BlockStat stat, String format, Object... args){
|
||||
add(stat, new StringValue(format, args));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user