Merge branches 'master' and 'mech-rework' of https://github.com/Anuken/Mindustry into mech-rework
# Conflicts: # android/src/mindustry/android/AndroidLauncher.java # annotations/src/main/java/mindustry/annotations/SerializeAnnotationProcessor.java # annotations/src/main/java/mindustry/annotations/impl/AssetsAnnotationProcessor.java # build.gradle # core/assets-raw/fontgen/config.json # core/assets/bundles/bundle_cs.properties # core/assets/bundles/bundle_it.properties # core/assets/fonts/font.ttf # core/assets/fonts/icon.ttf # core/assets/icons/icons.properties # 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/UnitTypes.java # core/src/mindustry/core/NetClient.java # core/src/mindustry/core/NetServer.java # core/src/mindustry/entities/bullet/BulletType.java # core/src/mindustry/entities/type/TileEntity.java # core/src/mindustry/maps/filters/FilterOption.java # core/src/mindustry/mod/Scripts.java # core/src/mindustry/ui/Fonts.java # core/src/mindustry/ui/dialogs/DeployDialog.java # core/src/mindustry/ui/fragments/HudFragment.java # core/src/mindustry/ui/fragments/MenuFragment.java # core/src/mindustry/world/blocks/production/Cultivator.java # core/src/mindustry/world/blocks/units/CommandCenter.java # gradle.properties # tools/src/mindustry/tools/FontGenerator.java
This commit is contained in:
@@ -32,7 +32,6 @@ import java.util.*;
|
||||
|
||||
import static arc.Core.settings;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class Vars implements Loadable{
|
||||
/** Whether to load locales.*/
|
||||
public static boolean loadLocales = true;
|
||||
@@ -60,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();
|
||||
|
||||
@@ -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, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, massDriver,
|
||||
conveyor, titaniumConveyor, armoredConveyor, distributor, junction, itemBridge, phaseConveyor, sorter, invertedSorter, router, overflowGate, underflowGate, massDriver,
|
||||
|
||||
//liquids
|
||||
mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit,
|
||||
@@ -396,12 +396,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
|
||||
@@ -651,7 +676,6 @@ public class Blocks implements ContentList{
|
||||
int topRegion = reg("-top");
|
||||
|
||||
drawIcons = () -> new TextureRegion[]{Core.atlas.find(name), Core.atlas.find(name + "-top")};
|
||||
|
||||
drawer = tile -> {
|
||||
GenericCrafterEntity entity = tile.ent();
|
||||
|
||||
@@ -943,6 +967,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,16 +44,18 @@ public class TechTree implements ContentList{
|
||||
});
|
||||
});
|
||||
|
||||
node(titaniumConveyor, () -> {
|
||||
node(phaseConveyor, () -> {
|
||||
node(massDriver, () -> {
|
||||
node(itemBridge, () -> {
|
||||
node(titaniumConveyor, () -> {
|
||||
node(phaseConveyor, () -> {
|
||||
node(massDriver, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(armoredConveyor, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
node(armoredConveyor, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -100,23 +103,25 @@ public class TechTree implements ContentList{
|
||||
|
||||
|
||||
node(copperWall, () -> {
|
||||
node(copperWallLarge);
|
||||
node(titaniumWall, () -> {
|
||||
node(door, () -> {
|
||||
node(doorLarge);
|
||||
});
|
||||
node(plastaniumWall, () -> {
|
||||
node(plastaniumWallLarge, () -> {
|
||||
node(copperWallLarge, () -> {
|
||||
node(titaniumWall, () -> {
|
||||
node(titaniumWallLarge);
|
||||
|
||||
node(door, () -> {
|
||||
node(doorLarge);
|
||||
});
|
||||
});
|
||||
node(titaniumWallLarge);
|
||||
node(thoriumWall, () -> {
|
||||
node(thoriumWallLarge);
|
||||
node(surgeWall, () -> {
|
||||
node(surgeWallLarge);
|
||||
node(phaseWall, () -> {
|
||||
node(phaseWallLarge);
|
||||
node(plastaniumWall, () -> {
|
||||
node(plastaniumWallLarge, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
node(thoriumWall, () -> {
|
||||
node(thoriumWallLarge);
|
||||
node(surgeWall, () -> {
|
||||
node(surgeWallLarge);
|
||||
node(phaseWall, () -> {
|
||||
node(phaseWallLarge);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -196,6 +201,8 @@ public class TechTree implements ContentList{
|
||||
node(liquidRouter, () -> {
|
||||
node(liquidTank);
|
||||
|
||||
node(bridgeConduit);
|
||||
|
||||
node(pulseConduit, () -> {
|
||||
node(phaseConduit, () -> {
|
||||
|
||||
@@ -212,7 +219,6 @@ public class TechTree implements ContentList{
|
||||
});
|
||||
});
|
||||
});
|
||||
node(bridgeConduit);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -100,9 +100,10 @@ public class UnitTypes implements ContentList{
|
||||
shootSound = Sounds.explosion;
|
||||
bullet = new BombBulletType(2f, 3f, "clear"){{
|
||||
hitEffect = Fx.pulverize;
|
||||
lifetime = 2f;
|
||||
lifetime = 30f;
|
||||
speed = 1.1f;
|
||||
splashDamageRadius = 55f;
|
||||
instantDisappear = true;
|
||||
splashDamage = 30f;
|
||||
killShooter = true;
|
||||
}};
|
||||
@@ -123,7 +124,6 @@ public class UnitTypes implements ContentList{
|
||||
shootSound = Sounds.flame;
|
||||
length = 1f;
|
||||
reload = 14f;
|
||||
range = 30f;
|
||||
alternate = true;
|
||||
recoil = 1f;
|
||||
ejectEffect = Fx.none;
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
package mindustry.core;
|
||||
|
||||
import arc.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.util.CommandHandler.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.CommandHandler.*;
|
||||
import arc.util.io.*;
|
||||
import arc.util.serialization.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.Administration.*;
|
||||
import mindustry.net.Net.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.net.Packets.*;
|
||||
import mindustry.type.TypeID;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.modules.*;
|
||||
|
||||
@@ -172,8 +172,8 @@ public class NetClient implements ApplicationListener{
|
||||
}
|
||||
|
||||
//special case; graphical server needs to see its message
|
||||
if(!headless && player == Vars.player){
|
||||
Vars.ui.chatfrag.addMessage(message, colorizeName(player.id, player.name));
|
||||
if(!headless){
|
||||
sendMessage(message, colorizeName(player.id, player.name), player);
|
||||
}
|
||||
|
||||
//server console logging
|
||||
@@ -266,6 +266,34 @@ public class NetClient implements ApplicationListener{
|
||||
ui.showText("", message);
|
||||
}
|
||||
|
||||
//TODO these are commented out to enforce compatibility with 103! uncomment before 104 release
|
||||
/*
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onInfoPopup(String message, float duration, int align, int top, int left, int bottom, int right){
|
||||
ui.showInfoPopup(message, duration, align, top, left, bottom, right);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onLabel(String info, float duration, float worldx, float worldy){
|
||||
ui.showLabel(info, duration, worldx, worldy);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both, unreliable = true)
|
||||
public static void onEffect(Effect effect, float x, float y, float rotation, Color color){
|
||||
Effects.effect(effect, color, x, y, rotation);
|
||||
}
|
||||
|
||||
@Remote(variants = Variant.both)
|
||||
public static void onEffectReliable(Effect effect, float x, float y, float rotation, Color color){
|
||||
Effects.effect(effect, color, x, y, rotation);
|
||||
}*/
|
||||
|
||||
@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;
|
||||
@@ -387,7 +415,7 @@ public class NetClient implements ApplicationListener{
|
||||
netClient.byteStream.setBytes(net.decompressSnapshot(coreData, coreDataLen));
|
||||
DataInputStream input = netClient.dataStream;
|
||||
|
||||
int cores = input.readInt();
|
||||
byte cores = input.readByte();
|
||||
for(int i = 0; i < cores; i++){
|
||||
int pos = input.readInt();
|
||||
Tile tile = world.tile(pos);
|
||||
|
||||
@@ -234,6 +234,13 @@ public class NetServer implements ApplicationListener{
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -257,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;
|
||||
}
|
||||
@@ -277,7 +284,11 @@ public class NetServer implements ApplicationListener{
|
||||
});
|
||||
|
||||
//duration of a a kick in seconds
|
||||
int kickDuration = 15 * 60;
|
||||
int kickDuration = 60 * 60;
|
||||
//voting round duration in seconds
|
||||
float voteDuration = 0.5f * 60;
|
||||
//cooldown between votes
|
||||
int voteCooldown = 60 * 1;
|
||||
|
||||
class VoteSession{
|
||||
Player target;
|
||||
@@ -295,17 +306,15 @@ public class NetServer implements ApplicationListener{
|
||||
map[0] = null;
|
||||
task.cancel();
|
||||
}
|
||||
}, 60 * 1);
|
||||
}, voteDuration);
|
||||
}
|
||||
|
||||
void vote(Player player, int d){
|
||||
votes += d;
|
||||
voted.addAll(player.uuid, admins.getInfo(player.uuid).lastIP);
|
||||
|
||||
if(!checkPass()){
|
||||
Call.sendMessage(Strings.format("[orange]{0}[lightgray] has voted to kick[orange] {1}[].[accent] ({2}/{3})\n[lightgray]Type[orange] /vote <y/n>[] to agree.",
|
||||
player.name, target.name, votes, votesRequired()));
|
||||
}
|
||||
|
||||
Call.sendMessage(Strings.format("[orange]{0}[lightgray] has voted to kick[orange] {1}[].[accent] ({2}/{3})\n[lightgray]Type[orange] /vote <y/n>[] to agree.",
|
||||
player.name, target.name, votes, votesRequired()));
|
||||
}
|
||||
|
||||
boolean checkPass(){
|
||||
@@ -321,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};
|
||||
|
||||
@@ -370,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;
|
||||
}
|
||||
|
||||
@@ -465,7 +472,7 @@ public class NetServer implements ApplicationListener{
|
||||
Call.onPlayerDisconnect(player.id);
|
||||
}
|
||||
|
||||
Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason);
|
||||
if(Config.showConnectMessages.bool()) Log.info("&lm[{1}] &lc{0} has disconnected. &lg&fi({2})", player.name, player.uuid, reason);
|
||||
}
|
||||
|
||||
player.remove();
|
||||
@@ -613,8 +620,10 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
player.add();
|
||||
player.con.hasConnected = true;
|
||||
if(Config.showConnectMessages.bool()) Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
|
||||
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid);
|
||||
if(Config.showConnectMessages.bool()){
|
||||
Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
|
||||
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid);
|
||||
}
|
||||
|
||||
if(!Config.motd.string().equalsIgnoreCase("off")){
|
||||
player.sendMessage(Config.motd.string());
|
||||
@@ -706,7 +715,7 @@ public class NetServer implements ApplicationListener{
|
||||
syncStream.reset();
|
||||
Array<CoreEntity> cores = state.teams.cores(player.getTeam());
|
||||
|
||||
dataStream.writeInt(cores.size);
|
||||
dataStream.writeByte(cores.size);
|
||||
|
||||
for(CoreEntity entity : cores){
|
||||
dataStream.writeInt(entity.tile.pos());
|
||||
|
||||
@@ -9,6 +9,7 @@ import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.input.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.*;
|
||||
import arc.scene.actions.*;
|
||||
import arc.scene.event.*;
|
||||
@@ -289,6 +290,49 @@ public class UI implements ApplicationListener, Loadable{
|
||||
Core.scene.add(table);
|
||||
}
|
||||
|
||||
/** Shows a fading label at the top of the screen. */
|
||||
public void showInfoToast(String info, float duration){
|
||||
Table table = new Table();
|
||||
table.setFillParent(true);
|
||||
table.touchable(Touchable.disabled);
|
||||
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);
|
||||
}
|
||||
|
||||
/** Shows a label at some position on the screen. Does not fade. */
|
||||
public void showInfoPopup(String info, float duration, int align, int top, int left, int bottom, int right){
|
||||
Table table = new Table();
|
||||
table.setFillParent(true);
|
||||
table.touchable(Touchable.disabled);
|
||||
table.update(() -> {
|
||||
if(state.is(State.menu)) table.remove();
|
||||
});
|
||||
table.actions(Actions.delay(duration), Actions.remove());
|
||||
table.align(align).table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).pad(top, left, bottom, right);
|
||||
Core.scene.add(table);
|
||||
}
|
||||
|
||||
/** Shows a label in the world. This label is behind everything. Does not fade. */
|
||||
public void showLabel(String info, float duration, float worldx, float worldy){
|
||||
Table table = new Table();
|
||||
table.setFillParent(true);
|
||||
table.touchable(Touchable.disabled);
|
||||
table.update(() -> {
|
||||
if(state.is(State.menu)) table.remove();
|
||||
});
|
||||
table.actions(Actions.delay(duration), Actions.remove());
|
||||
table.align(Align.center).table(Styles.black3, t -> t.margin(4).add(info).style(Styles.outlineLabel)).update(t -> {
|
||||
Vec2 v = Core.camera.project(worldx, worldy);
|
||||
t.setPosition(v.x, v.y, Align.center);
|
||||
});
|
||||
//make sure it's at the back
|
||||
Core.scene.root.addChildAt(0, table);
|
||||
}
|
||||
|
||||
public void showInfo(String info){
|
||||
new Dialog(""){{
|
||||
getCell(cont).growX();
|
||||
@@ -426,7 +470,6 @@ public class UI implements ApplicationListener, Loadable{
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
|
||||
public void showCustomConfirm(String title, String text, String yes, String no, Runnable confirmed, Runnable denied){
|
||||
FloatingDialog dialog = new FloatingDialog(title);
|
||||
dialog.cont.add(text).width(mobile ? 400f : 500f).wrap().pad(4f).get().setAlignment(Align.center, Align.center);
|
||||
@@ -459,11 +502,11 @@ public class UI implements ApplicationListener, Loadable{
|
||||
|
||||
public String formatAmount(int number){
|
||||
if(number >= 1000000){
|
||||
return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.millions") + "[]";
|
||||
return Strings.fixed(number / 1000000f, 1) + "[gray]" + Core.bundle.get("unit.millions") + "[]";
|
||||
}else if(number >= 10000){
|
||||
return number / 1000 + "[gray]k[]";
|
||||
return number / 1000 + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
|
||||
}else if(number >= 1000){
|
||||
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.getOrNull("unit.thousands") + "[]";
|
||||
return Strings.fixed(number / 1000f, 1) + "[gray]" + Core.bundle.get("unit.thousands") + "[]";
|
||||
}else{
|
||||
return number + "";
|
||||
}
|
||||
|
||||
@@ -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 internal 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){
|
||||
|
||||
@@ -3,8 +3,7 @@ package mindustry.entities.bullet;
|
||||
import arc.audio.*;
|
||||
import arc.math.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.Content;
|
||||
import mindustry.ctype.ContentType;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.Effects.*;
|
||||
import mindustry.entities.effect.*;
|
||||
@@ -41,7 +40,9 @@ public abstract class BulletType extends Content{
|
||||
public float recoil;
|
||||
/** Whether to kill the shooter when this is shot. For suicide bombers. */
|
||||
public boolean killShooter;
|
||||
|
||||
/** Whether to instantly make the bullet disappear. */
|
||||
public boolean instantDisappear;
|
||||
/** Damage dealt in splash. 0 to disable.*/
|
||||
public float splashDamage = 0f;
|
||||
/** Knockback in velocity. */
|
||||
public float knockback;
|
||||
@@ -151,6 +152,10 @@ public abstract class BulletType extends Content{
|
||||
if(killShooter && b.getOwner() instanceof HealthTrait){
|
||||
((HealthTrait)b.getOwner()).kill();
|
||||
}
|
||||
|
||||
if(instantDisappear){
|
||||
b.time(lifetime);
|
||||
}
|
||||
}
|
||||
|
||||
public void update(Bullet b){
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,9 +367,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,12 +9,11 @@ import arc.math.geom.Point2;
|
||||
import arc.math.geom.Vec2;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.entities.EntityGroup;
|
||||
import mindustry.entities.traits.HealthTrait;
|
||||
import mindustry.entities.traits.TargetTrait;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.EventType.BlockDestroyEvent;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.consumers.*;
|
||||
@@ -24,8 +23,8 @@ import java.io.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait, TeamTrait{
|
||||
public static final float timeToSleep = 60f * 4; //4 seconds to fall asleep
|
||||
public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
public static final float timeToSleep = 60f * 1; //1 second to fall asleep
|
||||
private static final ObjectSet<Tile> tmpTiles = new ObjectSet<>();
|
||||
/** This value is only used for debugging. */
|
||||
public static int sleepingEntities = 0;
|
||||
@@ -85,11 +84,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait,
|
||||
return this;
|
||||
}
|
||||
|
||||
public void applyBoost(float intensity, float duration){
|
||||
timeScaleDuration = Math.max(timeScaleDuration, duration);
|
||||
timeScale = Math.max(timeScale, intensity);
|
||||
}
|
||||
|
||||
/** Scaled delta. */
|
||||
public float delta(){
|
||||
return Time.delta() * timeScale;
|
||||
|
||||
@@ -42,7 +42,6 @@ public class GroundUnit extends BaseUnit{
|
||||
moveToCore(PathTarget.enemyCores);
|
||||
}
|
||||
}else{
|
||||
|
||||
float dst = dst(core);
|
||||
|
||||
if(dst < getWeapon().bullet.range() / 1.1f){
|
||||
@@ -165,6 +164,7 @@ public class GroundUnit extends BaseUnit{
|
||||
|
||||
if(!Units.invalidateTarget(target, this)){
|
||||
if(dst(target) < getWeapon().bullet.range()){
|
||||
|
||||
rotate(angleTo(target));
|
||||
|
||||
if(Angles.near(angleTo(target), rotation, 13f)){
|
||||
|
||||
@@ -125,7 +125,7 @@ public class Teams{
|
||||
}
|
||||
|
||||
private void updateEnemies(){
|
||||
if(!active.contains(get(state.rules.waveTeam))){
|
||||
if(state.rules.waves && !active.contains(get(state.rules.waveTeam))){
|
||||
active.add(get(state.rules.waveTeam));
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -704,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");
|
||||
|
||||
@@ -258,7 +258,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
selectRequests.clear();
|
||||
mode = none;
|
||||
block = null;
|
||||
}).width(155f);
|
||||
}).width(155f).margin(12f);
|
||||
});
|
||||
|
||||
group.fill(t -> {
|
||||
|
||||
@@ -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.*;
|
||||
@@ -77,14 +78,14 @@ public abstract class FilterOption{
|
||||
@Override
|
||||
public void build(Table table){
|
||||
table.addButton(b -> b.addImage(supplier.get().icon(Cicon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable())
|
||||
.setRegion(supplier.get() == Blocks.air ? Core.atlas.find("Icon.none") : supplier.get().icon(Cicon.small))).size(8 * 3), () -> {
|
||||
.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-") : 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();
|
||||
|
||||
@@ -246,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);
|
||||
}
|
||||
@@ -258,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);
|
||||
}
|
||||
@@ -354,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ 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");
|
||||
"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;
|
||||
|
||||
@@ -420,7 +420,7 @@ public class Administration{
|
||||
crashReport("Whether to send crash reports.", false, "crashreport"),
|
||||
logging("Whether to log everything to files.", true),
|
||||
strict("Whether strict mode is on - corrects positions and prevents duplicate UUIDs.", true),
|
||||
antiSpam("Whether spammers are automatically kicked and rate-limited.", true),
|
||||
antiSpam("Whether spammers are automatically kicked and rate-limited.", headless),
|
||||
messageRateLimit("Message rate limit in seconds. 0 to disable.", 0),
|
||||
messageSpamKick("How many times a player must send a message before the cooldown to get kicked. 0 to disable.", 3),
|
||||
socketInput("Allows a local application to control this server through a local TCP socket.", false, "socket", () -> Events.fire(Trigger.socketConfigChanged)),
|
||||
|
||||
@@ -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();
|
||||
@@ -147,7 +147,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();
|
||||
@@ -194,7 +194,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();
|
||||
|
||||
@@ -54,8 +54,9 @@ public class Fonts{
|
||||
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 = (int)(Scl.scl(30f));
|
||||
size = 30;
|
||||
incremental = true;
|
||||
characters = "\0";
|
||||
}})).loaded = f -> Fonts.icon = (BitmapFont)f;
|
||||
}
|
||||
|
||||
@@ -104,12 +105,19 @@ public class Fonts{
|
||||
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;
|
||||
@@ -119,8 +127,8 @@ public class Fonts{
|
||||
|
||||
FreeTypeFontParameter param = new FreeTypeFontParameter(){{
|
||||
borderColor = Color.darkGray;
|
||||
size = (int)(Scl.scl(18f));
|
||||
incremental = true;
|
||||
size = 18;
|
||||
}};
|
||||
|
||||
Core.assets.load("outline", BitmapFont.class, new FreeTypeFontLoaderParameter("fonts/font.ttf", param)).loaded = t -> Fonts.outline = (BitmapFont)t;
|
||||
@@ -162,7 +170,6 @@ public class Fonts{
|
||||
if(g == null) throw new IllegalArgumentException("No glyph: " + glyph + " (" + (int)glyph + ")");
|
||||
|
||||
float size = Math.max(g.width, g.height);
|
||||
float aspect = (float)g.height / g.width;
|
||||
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){
|
||||
@@ -173,6 +180,19 @@ public class Fonts{
|
||||
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;
|
||||
@@ -186,7 +206,7 @@ public class Fonts{
|
||||
|
||||
static FreeTypeFontParameter fontParameter(){
|
||||
return new FreeTypeFontParameter(){{
|
||||
size = (int)(Scl.scl(18f));
|
||||
size = 18;
|
||||
shadowColor = Color.darkGray;
|
||||
shadowOffsetY = 2;
|
||||
incremental = true;
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -122,7 +122,7 @@ public class DeployDialog extends FloatingDialog{
|
||||
setFilter(TextureFilter.Linear);
|
||||
}}){{
|
||||
float[] time = {0};
|
||||
setColor(Color.gray(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.gray(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();
|
||||
@@ -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.gray(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);
|
||||
|
||||
@@ -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};
|
||||
@@ -266,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()){
|
||||
@@ -363,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")
|
||||
|
||||
@@ -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.*;
|
||||
@@ -240,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(){
|
||||
|
||||
@@ -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{
|
||||
@@ -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);
|
||||
@@ -358,7 +377,7 @@ public class TechTreeDialog extends FloatingDialog{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
}).name("pause").update(i -> {
|
||||
if(net.active()){
|
||||
i.getStyle().imageUp = Icon.user;
|
||||
i.getStyle().imageUp = Icon.players;
|
||||
}else{
|
||||
i.setDisabled(false);
|
||||
i.getStyle().imageUp = state.is(State.paused) ? Icon.play : Icon.pause;
|
||||
@@ -256,7 +256,7 @@ public class HudFragment extends Fragment{
|
||||
t.add(new Minimap());
|
||||
t.row();
|
||||
//position
|
||||
t.label(() -> world.toTile(player.x) + "," + world.toTile(player.y)).style(Styles.outlineLabel)
|
||||
t.label(() -> world.toTile(player.x) + "," + world.toTile(player.y))
|
||||
.visible(() -> Core.settings.getBool("position") && !state.rules.tutorial);
|
||||
t.top().right();
|
||||
});
|
||||
@@ -352,7 +352,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.server)
|
||||
public static void spawnUnitEditor(Player player, UnitDef type){
|
||||
public static void spawnUnitEditor(Player player, UnitType type){
|
||||
if(state.isEditor()){
|
||||
BaseUnit unit = type.create(player.getTeam());
|
||||
unit.set(player.x, player.y);
|
||||
|
||||
@@ -171,7 +171,7 @@ public class MenuFragment extends Fragment{
|
||||
new Buttoni("$loadgame", Icon.download, () -> checkPlay(ui.load::show)),
|
||||
new Buttoni("$tutorial", Icon.info, () -> checkPlay(control::playTutorial))
|
||||
),
|
||||
new Buttoni("$editor", Icon.terrain, () -> checkPlay(ui.maps::show)), steam ? new Buttoni("$workshop", Icon.save, platform::openWorkshop) : null,
|
||||
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.paste, ui.schematics::show),
|
||||
|
||||
@@ -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();
|
||||
@@ -240,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
|
||||
@@ -343,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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -274,8 +274,7 @@ public abstract class BlockStorage extends UnlockableContent{
|
||||
|
||||
/** Try offloading an item to a nearby container in its facing direction. Returns true if success. */
|
||||
public boolean offloadDir(Tile tile, Item item){
|
||||
Tile other = tile.getNearby(tile.rotation());
|
||||
if(other != null) other = other.link();
|
||||
Tile other = tile.front();
|
||||
if(other != null && other.getTeam() == tile.getTeam() && other.block().acceptItem(item, other, tile)){
|
||||
other.block().handleItem(item, other, tile);
|
||||
return true;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package mindustry.world.blocks.distribution;
|
||||
|
||||
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.ArcAnnotate.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.traits.BuilderTrait.*;
|
||||
@@ -24,10 +25,8 @@ import static mindustry.Vars.*;
|
||||
|
||||
public class Conveyor extends Block implements Autotiler{
|
||||
private static final float itemSpace = 0.4f;
|
||||
private static final float minmove = 1f / (Short.MAX_VALUE - 2);
|
||||
private static ItemPos drawpos = new ItemPos();
|
||||
private static ItemPos pos1 = new ItemPos();
|
||||
private static ItemPos pos2 = new ItemPos();
|
||||
private static final int capacity = 4;
|
||||
|
||||
private final Vec2 tr1 = new Vec2();
|
||||
private final Vec2 tr2 = new Vec2();
|
||||
private TextureRegion[][] regions = new TextureRegion[7][4];
|
||||
@@ -51,12 +50,6 @@ public class Conveyor extends Block implements Autotiler{
|
||||
unloadable = false;
|
||||
}
|
||||
|
||||
private static int compareItems(long a, long b){
|
||||
pos1.set(a, ItemPos.packShorts);
|
||||
pos2.set(b, ItemPos.packShorts);
|
||||
return Float.compare(pos1.y, pos2.y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStats(){
|
||||
super.setStats();
|
||||
@@ -100,6 +93,12 @@ public class Conveyor extends Block implements Autotiler{
|
||||
entity.blendbits = bits[0];
|
||||
entity.blendsclx = bits[1];
|
||||
entity.blendscly = bits[2];
|
||||
|
||||
if(tile.front() != null && tile.front().entity != null){
|
||||
entity.next = tile.front().entity;
|
||||
entity.nextc = entity.next instanceof ConveyorEntity && entity.next.getTeam() == tile.getTeam() ? (ConveyorEntity)entity.next : null;
|
||||
entity.aligned = entity.nextc != null && tile.rotation() == entity.next.tile.rotation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -124,27 +123,17 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
@Override
|
||||
public void drawLayer(Tile tile){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
|
||||
ConveyorEntity e = tile.ent();
|
||||
byte rotation = tile.rotation();
|
||||
|
||||
try{
|
||||
for(int i = 0; i < e.len; i++){
|
||||
Item item = e.ids[i];
|
||||
tr1.trns(rotation * 90, tilesize, 0);
|
||||
tr2.trns(rotation * 90, -tilesize / 2f, e.xs[i] * tilesize / 2f);
|
||||
|
||||
for(int i = 0; i < entity.convey.size; i++){
|
||||
ItemPos pos = drawpos.set(entity.convey.get(i), ItemPos.drawShorts);
|
||||
|
||||
if(pos.item == null) continue;
|
||||
|
||||
tr1.trns(rotation * 90, tilesize, 0);
|
||||
tr2.trns(rotation * 90, -tilesize / 2f, pos.x * tilesize / 2f);
|
||||
|
||||
Draw.rect(pos.item.icon(Cicon.medium),
|
||||
(tile.x * tilesize + tr1.x * pos.y + tr2.x),
|
||||
(tile.y * tilesize + tr1.y * pos.y + tr2.y), itemSize, itemSize);
|
||||
}
|
||||
|
||||
}catch(IndexOutOfBoundsException e){
|
||||
Log.err(e);
|
||||
Draw.rect(item.icon(Cicon.medium),
|
||||
(tile.x * tilesize + tr1.x * e.ys[i] + tr2.x),
|
||||
(tile.y * tilesize + tr1.y * e.ys[i] + tr2.y), itemSize, itemSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,79 +162,56 @@ public class Conveyor extends Block implements Autotiler{
|
||||
if(Math.abs(tile.worldx() - unit.x) < 1f) centerx = 0f;
|
||||
}
|
||||
|
||||
if(entity.convey.size * itemSpace < 0.9f){
|
||||
if(entity.len * itemSpace < 0.9f){
|
||||
unit.applyImpulse((tx * speed + centerx) * entity.delta(), (ty * speed + centery) * entity.delta());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Tile tile){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
entity.minitem = 1f;
|
||||
Tile next = tile.getNearby(tile.rotation());
|
||||
if(next != null) next = next.link();
|
||||
ConveyorEntity e = tile.ent();
|
||||
e.minitem = 1f;
|
||||
e.mid = 0;
|
||||
|
||||
float nextMax = next != null && next.block() instanceof Conveyor && next.block().acceptItem(null, next, tile) ? 1f - Math.max(itemSpace - next.<ConveyorEntity>ent().minitem, 0) : 1f;
|
||||
int minremove = Integer.MAX_VALUE;
|
||||
//skip updates if possible
|
||||
if(e.len == 0){
|
||||
e.clogHeat = 0f;
|
||||
e.sleep();
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = entity.convey.size - 1; i >= 0; i--){
|
||||
long value = entity.convey.get(i);
|
||||
ItemPos pos = pos1.set(value, ItemPos.updateShorts);
|
||||
float nextMax = e.nextc != null && tile.rotation() == e.nextc.tile.rotation() ? 1f - Math.max(itemSpace - e.nextc.minitem, 0) : 1f;
|
||||
|
||||
//..this should never happen, but in case it does, remove it and stop here
|
||||
if(pos.item == null){
|
||||
entity.convey.removeValue(value);
|
||||
break;
|
||||
}
|
||||
for(int i = e.len - 1; i >= 0; i--){
|
||||
float nextpos = (i == e.len - 1 ? 100f : e.ys[i + 1]) - itemSpace;
|
||||
float maxmove = Mathf.clamp(nextpos - e.ys[i], 0, speed * e.delta());
|
||||
|
||||
float nextpos = (i == entity.convey.size - 1 ? 100f : pos2.set(entity.convey.get(i + 1), ItemPos.updateShorts).y) - itemSpace;
|
||||
float maxmove = Math.min(nextpos - pos.y, speed * entity.delta());
|
||||
e.ys[i] += maxmove;
|
||||
|
||||
if(maxmove > minmove){
|
||||
pos.y += maxmove;
|
||||
if(Mathf.equal(pos.x, 0, 0.1f)){
|
||||
pos.x = 0f;
|
||||
if(e.ys[i] > nextMax) e.ys[i] = nextMax;
|
||||
if(e.ys[i] > 0.5 && i > 0) e.mid = i - 1;
|
||||
e.xs[i] = Mathf.approachDelta(e.xs[i], 0, 0.1f);
|
||||
|
||||
if(e.ys[i] >= 1f && offloadDir(tile, e.ids[i])){
|
||||
//align X position if passing forwards
|
||||
if(e.aligned){
|
||||
e.nextc.xs[e.nextc.lastInserted] = e.xs[i];
|
||||
}
|
||||
pos.x = Mathf.lerpDelta(pos.x, 0, 0.1f);
|
||||
}
|
||||
|
||||
pos.y = Mathf.clamp(pos.y, 0, nextMax);
|
||||
|
||||
if(pos.y >= 0.9999f && offloadDir(tile, pos.item)){
|
||||
if(next != null && next.block() instanceof Conveyor){
|
||||
ConveyorEntity othere = next.ent();
|
||||
|
||||
ItemPos ni = pos2.set(othere.convey.get(othere.lastInserted), ItemPos.updateShorts);
|
||||
|
||||
if(next.rotation() == tile.rotation()){
|
||||
ni.x = pos.x;
|
||||
}
|
||||
othere.convey.set(othere.lastInserted, ni.pack());
|
||||
}
|
||||
minremove = Math.min(i, minremove);
|
||||
tile.entity.items.remove(pos.item, 1);
|
||||
}else{
|
||||
value = pos.pack();
|
||||
|
||||
if(pos.y < entity.minitem)
|
||||
entity.minitem = pos.y;
|
||||
entity.convey.set(i, value);
|
||||
//remove last item
|
||||
e.items.remove(e.ids[i], e.len - i);
|
||||
e.len = Math.min(i, e.len);
|
||||
}else if(e.ys[i] < e.minitem){
|
||||
e.minitem = e.ys[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(entity.minitem < itemSpace){
|
||||
entity.clogHeat = Mathf.lerpDelta(entity.clogHeat, 1f, 0.02f);
|
||||
if(e.minitem < itemSpace + (e.blendbits == 1 ? 0.5f : 0f)){
|
||||
e.clogHeat = Mathf.lerpDelta(e.clogHeat, 1f, 0.02f);
|
||||
}else{
|
||||
entity.clogHeat = Mathf.lerpDelta(entity.clogHeat, 0f, 1f);
|
||||
e.clogHeat = 0f;
|
||||
}
|
||||
|
||||
if(entity.items.total() == 0){
|
||||
entity.sleep();
|
||||
}else{
|
||||
entity.noSleep();
|
||||
}
|
||||
|
||||
if(minremove != Integer.MAX_VALUE) entity.convey.truncate(minremove);
|
||||
e.noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -265,22 +231,22 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
@Override
|
||||
public int removeStack(Tile tile, Item item, int amount){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
entity.noSleep();
|
||||
ConveyorEntity e = tile.ent();
|
||||
e.noSleep();
|
||||
int removed = 0;
|
||||
|
||||
for(int j = 0; j < amount; j++){
|
||||
for(int i = 0; i < entity.convey.size; i++){
|
||||
long val = entity.convey.get(i);
|
||||
ItemPos pos = pos1.set(val, ItemPos.drawShorts);
|
||||
if(pos.item == item){
|
||||
entity.convey.removeValue(val);
|
||||
entity.items.remove(item, 1);
|
||||
removed++;
|
||||
for(int i = 0; i < e.len; i++){
|
||||
if(e.ids[i] == item){
|
||||
e.remove(i);
|
||||
removed ++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
e.items.remove(item, removed);
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
@@ -297,58 +263,66 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
@Override
|
||||
public void handleStack(Item item, int amount, Tile tile, Unit source){
|
||||
ConveyorEntity entity = tile.ent();
|
||||
ConveyorEntity e = tile.ent();
|
||||
|
||||
for(int i = amount - 1; i >= 0; i--){
|
||||
long result = ItemPos.packItem(item, 0f, i * itemSpace);
|
||||
entity.convey.insert(0, result);
|
||||
entity.items.add(item, 1);
|
||||
e.add(0);
|
||||
e.xs[0] = 0;
|
||||
e.ys[0] = i * itemSpace;
|
||||
e.ids[0] = item;
|
||||
e.items.add(item, 1);
|
||||
}
|
||||
|
||||
entity.noSleep();
|
||||
e.noSleep();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||
ConveyorEntity e = tile.ent();
|
||||
if(e.len >= capacity) return false;
|
||||
int direction = source == null ? 0 : Math.abs(source.relativeTo(tile.x, tile.y) - tile.rotation());
|
||||
float minitem = tile.<ConveyorEntity>ent().minitem;
|
||||
return (((direction == 0) && minitem > itemSpace) ||
|
||||
((direction % 2 == 1) && minitem > 0.52f)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation()));
|
||||
return (((direction == 0) && e.minitem >= itemSpace) || ((direction % 2 == 1) && e.minitem > 0.5f)) && (source == null || !(source.block().rotate && (source.rotation() + 2) % 4 == tile.rotation()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleItem(Item item, Tile tile, Tile source){
|
||||
byte rotation = tile.rotation();
|
||||
ConveyorEntity e = tile.ent();
|
||||
if(e.len >= capacity) return;
|
||||
|
||||
int ch = Math.abs(source.relativeTo(tile.x, tile.y) - rotation);
|
||||
int ang = ((source.relativeTo(tile.x, tile.y) - rotation));
|
||||
byte r = tile.rotation();
|
||||
int ang = ((source.relativeTo(tile.x, tile.y) - r));
|
||||
float x = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0;
|
||||
|
||||
float pos = ch == 0 ? 0 : ch % 2 == 1 ? 0.5f : 1f;
|
||||
float y = (ang == -1 || ang == 3) ? 1 : (ang == 1 || ang == -3) ? -1 : 0;
|
||||
e.noSleep();
|
||||
e.items.add(item, 1);
|
||||
|
||||
ConveyorEntity entity = tile.ent();
|
||||
entity.noSleep();
|
||||
long result = ItemPos.packItem(item, y * 0.9f, pos);
|
||||
|
||||
tile.entity.items.add(item, 1);
|
||||
|
||||
for(int i = 0; i < entity.convey.size; i++){
|
||||
if(compareItems(result, entity.convey.get(i)) < 0){
|
||||
entity.convey.insert(i, result);
|
||||
entity.lastInserted = (byte)i;
|
||||
return;
|
||||
}
|
||||
if(Math.abs(source.relativeTo(tile.x, tile.y) - r) == 0){ //idx = 0
|
||||
e.add(0);
|
||||
e.xs[0] = x;
|
||||
e.ys[0] = 0;
|
||||
e.ids[0] = item;
|
||||
}else{ //idx = mid
|
||||
e.add(e.mid);
|
||||
e.xs[e.mid] = x;
|
||||
e.ys[e.mid] = 0.5f;
|
||||
e.ids[e.mid] = item;
|
||||
}
|
||||
|
||||
//this item must be greater than anything there...
|
||||
entity.convey.add(result);
|
||||
entity.lastInserted = (byte)(entity.convey.size - 1);
|
||||
}
|
||||
|
||||
public static class ConveyorEntity extends TileEntity{
|
||||
//parallel array data
|
||||
Item[] ids = new Item[capacity];
|
||||
float[] xs = new float[capacity];
|
||||
float[] ys = new float[capacity];
|
||||
//amount of items, always < capacity
|
||||
int len = 0;
|
||||
//next entity
|
||||
@Nullable TileEntity next;
|
||||
@Nullable ConveyorEntity nextc;
|
||||
//whether the next conveyor's rotation == tile rotation
|
||||
boolean aligned;
|
||||
|
||||
LongArray convey = new LongArray();
|
||||
byte lastInserted;
|
||||
int lastInserted, mid;
|
||||
float minitem = 1;
|
||||
|
||||
int blendbits;
|
||||
@@ -356,96 +330,53 @@ public class Conveyor extends Block implements Autotiler{
|
||||
|
||||
float clogHeat = 0f;
|
||||
|
||||
final void add(int o){
|
||||
for(int i = Math.max(o + 1, len); i > o; i--){
|
||||
ids[i] = ids[i - 1];
|
||||
xs[i] = xs[i - 1];
|
||||
ys[i] = ys[i - 1];
|
||||
}
|
||||
|
||||
len++;
|
||||
}
|
||||
|
||||
final void remove(int o){
|
||||
for(int i = o; i < len - 1; i++){
|
||||
ids[i] = ids[i + 1];
|
||||
xs[i] = xs[i + 1];
|
||||
ys[i] = ys[i + 1];
|
||||
}
|
||||
|
||||
len--;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
super.write(stream);
|
||||
stream.writeInt(convey.size);
|
||||
stream.writeInt(len);
|
||||
|
||||
for(int i = 0; i < convey.size; i++){
|
||||
stream.writeInt(ItemPos.toInt(convey.get(i)));
|
||||
for(int i = 0; i < len; i++){
|
||||
stream.writeInt(Pack.intBytes((byte)ids[i].id, (byte)(xs[i] * 127), (byte)(ys[i] * 255 - 128), (byte)0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
super.read(stream, revision);
|
||||
convey.clear();
|
||||
int amount = stream.readInt();
|
||||
convey.ensureCapacity(Math.min(amount, 10));
|
||||
len = Math.min(amount, capacity);
|
||||
|
||||
for(int i = 0; i < amount; i++){
|
||||
convey.add(ItemPos.toLong(stream.readInt()));
|
||||
int val = stream.readInt();
|
||||
byte id = (byte)(val >> 24);
|
||||
float x = (float)((byte)(val >> 16)) / 127f;
|
||||
float y = ((float)((byte)(val >> 8)) + 128f) / 255f;
|
||||
if(i < capacity){
|
||||
ids[i] = content.item(id);
|
||||
xs[i] = x;
|
||||
ys[i] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Container class. Do not instantiate.
|
||||
static class ItemPos{
|
||||
private static short[] writeShort = new short[4];
|
||||
private static byte[] writeByte = new byte[4];
|
||||
|
||||
private static short[] packShorts = new short[4];
|
||||
private static short[] drawShorts = new short[4];
|
||||
private static short[] updateShorts = new short[4];
|
||||
|
||||
Item item;
|
||||
float x, y;
|
||||
|
||||
private ItemPos(){
|
||||
}
|
||||
|
||||
static long packItem(Item item, float x, float y){
|
||||
short[] shorts = packShorts;
|
||||
shorts[0] = (short)item.id;
|
||||
shorts[1] = (short)(x * Short.MAX_VALUE);
|
||||
shorts[2] = (short)((y - 1f) * Short.MAX_VALUE);
|
||||
return Pack.longShorts(shorts);
|
||||
}
|
||||
|
||||
static int toInt(long value){
|
||||
short[] values = Pack.shorts(value, writeShort);
|
||||
|
||||
short itemid = values[0];
|
||||
float x = values[1] / (float)Short.MAX_VALUE;
|
||||
float y = ((float)values[2]) / Short.MAX_VALUE + 1f;
|
||||
|
||||
byte[] bytes = writeByte;
|
||||
bytes[0] = (byte)itemid;
|
||||
bytes[1] = (byte)(x * 127);
|
||||
bytes[2] = (byte)(y * 255 - 128);
|
||||
|
||||
return Pack.intBytes(bytes);
|
||||
}
|
||||
|
||||
static long toLong(int value){
|
||||
byte[] values = Pack.bytes(value, writeByte);
|
||||
|
||||
short itemid = content.item(values[0]).id;
|
||||
float x = values[1] / 127f;
|
||||
float y = ((int)values[2] + 128) / 255f;
|
||||
|
||||
short[] shorts = writeShort;
|
||||
shorts[0] = itemid;
|
||||
shorts[1] = (short)(x * Short.MAX_VALUE);
|
||||
shorts[2] = (short)((y - 1f) * Short.MAX_VALUE);
|
||||
return Pack.longShorts(shorts);
|
||||
}
|
||||
|
||||
ItemPos set(long lvalue, short[] values){
|
||||
Pack.shorts(lvalue, values);
|
||||
|
||||
if(values[0] >= content.items().size || values[0] < 0)
|
||||
item = null;
|
||||
else
|
||||
item = content.items().get(values[0]);
|
||||
|
||||
x = values[1] / (float)Short.MAX_VALUE;
|
||||
y = ((float)values[2]) / Short.MAX_VALUE + 1f;
|
||||
return this;
|
||||
}
|
||||
|
||||
long pack(){
|
||||
return packItem(item, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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){
|
||||
|
||||
@@ -182,8 +182,11 @@ public class PowerNode extends PowerBlock{
|
||||
|
||||
if(tile == other){
|
||||
if(other.entity.power.links.size == 0){
|
||||
int[] total = {0};
|
||||
getPotentialLinks(tile, link -> {
|
||||
if(!insulated(tile, link)) tile.configure(link.pos());
|
||||
if(!insulated(tile, link) && total[0]++ < maxNodes){
|
||||
tile.configure(link.pos());
|
||||
}
|
||||
});
|
||||
}else{
|
||||
while(entity.power.links.size > 0){
|
||||
|
||||
@@ -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.Rand;
|
||||
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.*;
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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() + "-");
|
||||
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() + "-"), 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));
|
||||
|
||||
21
core/src/mindustry/world/meta/values/FloorValue.java
Normal file
21
core/src/mindustry/world/meta/values/FloorValue.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package mindustry.world.meta.values;
|
||||
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.blocks.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
public class FloorValue implements StatValue{
|
||||
private final Floor floor;
|
||||
|
||||
public FloorValue(Floor floor){
|
||||
this.floor = floor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void display(Table table){
|
||||
table.add(new Image(floor.icon(Cicon.small))).padRight(3);
|
||||
table.add(floor.localizedName).padRight(3);
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,7 @@ public class LiquidModule extends BlockModule{
|
||||
@Override
|
||||
public void read(DataInput stream) throws IOException{
|
||||
Arrays.fill(liquids, 0);
|
||||
total = 0f;
|
||||
byte count = stream.readByte();
|
||||
|
||||
for(int j = 0; j < count; j++){
|
||||
|
||||
Reference in New Issue
Block a user