This commit is contained in:
Anuken
2021-10-23 18:33:07 -04:00
38 changed files with 462 additions and 179 deletions

View File

@@ -288,6 +288,7 @@ save.corrupted = Save file corrupted or invalid!
empty = <empty> empty = <empty>
on = On on = On
off = Off off = Off
save.search = Search saved games...
save.autosave = Autosave: {0} save.autosave = Autosave: {0}
save.map = Map: {0} save.map = Map: {0}
save.wave = Wave {0} save.wave = Wave {0}
@@ -379,9 +380,13 @@ editor.ingame = Edit In-Game
editor.publish.workshop = Publish On Workshop editor.publish.workshop = Publish On Workshop
editor.newmap = New Map editor.newmap = New Map
editor.center = Center editor.center = Center
editor.search = Search Maps... editor.search = Search maps...
editor.filters = Filter Maps editor.filters = Filter Maps
editor.showAll = Show Default Maps editor.filters.mode = Gamemodes:
editor.filters.type = Map Type:
editor.filters.search = Search In:
editor.filters.author = Author
editor.filters.description = Description
workshop = Workshop workshop = Workshop
waves.title = Waves waves.title = Waves
waves.remove = Remove waves.remove = Remove

View File

@@ -128,3 +128,4 @@ SAMBUYYA
genNAowl genNAowl
TranquillyUnpleasant TranquillyUnpleasant
Darkness6030 Darkness6030
hortiSquash

View File

@@ -1095,7 +1095,7 @@ public class Blocks implements ContentList{
}}; }};
mendProjector = new MendProjector("mend-projector"){{ mendProjector = new MendProjector("mend-projector"){{
requirements(Category.effect, with(Items.lead, 100, Items.titanium, 25, Items.silicon, 40)); requirements(Category.effect, with(Items.lead, 100, Items.titanium, 25, Items.silicon, 40, Items.copper, 50));
consumes.power(1.5f); consumes.power(1.5f);
size = 2; size = 2;
reload = 250f; reload = 250f;
@@ -1541,7 +1541,7 @@ public class Blocks implements ContentList{
}}; }};
waterExtractor = new SolidPump("water-extractor"){{ waterExtractor = new SolidPump("water-extractor"){{
requirements(Category.production, with(Items.metaglass, 30, Items.graphite, 30, Items.lead, 30)); requirements(Category.production, with(Items.metaglass, 30, Items.graphite, 30, Items.lead, 30, Items.copper, 30));
result = Liquids.water; result = Liquids.water;
pumpAmount = 0.11f; pumpAmount = 0.11f;
size = 2; size = 2;
@@ -1858,7 +1858,7 @@ public class Blocks implements ContentList{
shots = 4; shots = 4;
burstSpacing = 5; burstSpacing = 5;
inaccuracy = 10f; inaccuracy = 10f;
range = 235f; range = 240f;
xRand = 6f; xRand = 6f;
size = 2; size = 2;
health = 300 * size * size; health = 300 * size * size;
@@ -2310,12 +2310,12 @@ public class Blocks implements ContentList{
//region payloads //region payloads
payloadConveyor = new PayloadConveyor("payload-conveyor"){{ payloadConveyor = new PayloadConveyor("payload-conveyor"){{
requirements(Category.units, with(Items.graphite, 10, Items.copper, 20)); requirements(Category.units, with(Items.graphite, 10, Items.lead, 10));
canOverdrive = false; canOverdrive = false;
}}; }};
payloadRouter = new PayloadRouter("payload-router"){{ payloadRouter = new PayloadRouter("payload-router"){{
requirements(Category.units, with(Items.graphite, 15, Items.copper, 20)); requirements(Category.units, with(Items.graphite, 15, Items.lead, 15));
canOverdrive = false; canOverdrive = false;
}}; }};
@@ -2411,14 +2411,12 @@ public class Blocks implements ContentList{
requirements(Category.units, BuildVisibility.sandboxOnly, with()); requirements(Category.units, BuildVisibility.sandboxOnly, with());
size = 5; size = 5;
alwaysUnlocked = true; alwaysUnlocked = true;
group = BlockGroup.units;
}}; }};
payloadVoid = new PayloadVoid("payload-void"){{ payloadVoid = new PayloadVoid("payload-void"){{
requirements(Category.units, BuildVisibility.sandboxOnly, with()); requirements(Category.units, BuildVisibility.sandboxOnly, with());
size = 5; size = 5;
alwaysUnlocked = true; alwaysUnlocked = true;
group = BlockGroup.units;
}}; }};
//TODO move //TODO move

View File

@@ -275,7 +275,7 @@ public class NetServer implements ApplicationListener{
int page = args.length > 0 ? Strings.parseInt(args[0]) : 1; int page = args.length > 0 ? Strings.parseInt(args[0]) : 1;
int pages = Mathf.ceil((float)clientCommands.getCommandList().size / commandsPerPage); int pages = Mathf.ceil((float)clientCommands.getCommandList().size / commandsPerPage);
page --; 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]."); player.sendMessage("[scarlet]'page' must be a number between[orange] 1[] and[orange] " + pages + "[scarlet].");
@@ -724,6 +724,8 @@ public class NetServer implements ApplicationListener{
return; return;
} }
Events.fire(new EventType.AdminRequestEvent(player, other, action));
if(action == AdminAction.wave){ if(action == AdminAction.wave){
//no verification is done, so admins can hypothetically spam waves //no verification is done, so admins can hypothetically spam waves
//not a real issue, because server owners may want to do just that //not a real issue, because server owners may want to do just that

View File

@@ -24,6 +24,38 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
Seq<Payload> payloads = new Seq<>(); Seq<Payload> payloads = new Seq<>();
//uncomment for insanity
/*
private transient @Nullable PowerGraph payloadPower;
@Override
public void update(){
if(payloadPower != null){
payloadPower.clear();
}
//update power graph first, resolve everything
for(Payload pay : payloads){
if(pay instanceof BuildPayload pb && pb.build.power != null){
if(payloadPower == null) payloadPower = new PowerGraph();
pb.build.power.graph = null;
payloadPower.add(pb.build);
}
}
if(payloadPower != null){
payloadPower.update();
}
for(Payload pay : payloads){
pay.set(x, y, rotation);
pay.update(true);
}
}*/
float payloadUsed(){ float payloadUsed(){
return payloads.sumf(p -> p.size() * p.size()); return payloads.sumf(p -> p.size() * p.size());
} }
@@ -50,7 +82,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
void pickup(Unit unit){ void pickup(Unit unit){
unit.remove(); unit.remove();
payloads.add(new UnitPayload(unit)); addPayload(new UnitPayload(unit));
Fx.unitPickup.at(unit); Fx.unitPickup.at(unit);
if(Vars.net.client()){ if(Vars.net.client()){
Vars.netClient.clearRemovedEntity(unit.id); Vars.netClient.clearRemovedEntity(unit.id);
@@ -62,7 +94,7 @@ abstract class PayloadComp implements Posc, Rotc, Hitboxc, Unitc{
tile.pickedUp(); tile.pickedUp();
tile.tile.remove(); tile.tile.remove();
tile.tile = Vars.emptyTile; tile.tile = Vars.emptyTile;
payloads.add(new BuildPayload(tile)); addPayload(new BuildPayload(tile));
Fx.unitPickup.at(tile); Fx.unitPickup.at(tile);
Events.fire(new PickupEvent(self(), tile)); Events.fire(new PickupEvent(self(), tile));
} }

View File

@@ -544,4 +544,15 @@ public class EventType{
} }
} }
public static class AdminRequestEvent{
public final Player player;
public final @Nullable Player other;
public final AdminAction action;
public AdminRequestEvent(Player player, Player other, AdminAction action){
this.player = player;
this.other = other;
this.action = action;
}
}
} }

View File

@@ -103,6 +103,8 @@ public class Rules{
public ObjectSet<Block> revealedBlocks = new ObjectSet<>(); public ObjectSet<Block> revealedBlocks = new ObjectSet<>();
/** Unlocked content names. Only used in multiplayer when the campaign is enabled. */ /** Unlocked content names. Only used in multiplayer when the campaign is enabled. */
public ObjectSet<String> researched = new ObjectSet<>(); public ObjectSet<String> researched = new ObjectSet<>();
/** Block containing these items as requirements are hidden. */
public ObjectSet<Item> hiddenBuildItems = new ObjectSet<>();
/** Whether ambient lighting is enabled. */ /** Whether ambient lighting is enabled. */
public boolean lighting = false; public boolean lighting = false;
/** Whether enemy lighting is visible. /** Whether enemy lighting is visible.

View File

@@ -1,6 +1,7 @@
package mindustry.graphics.g3d; package mindustry.graphics.g3d;
import arc.graphics.*; import arc.graphics.*;
import arc.math.*;
import arc.math.geom.*; import arc.math.geom.*;
import arc.util.*; import arc.util.*;
import arc.util.noise.*; import arc.util.noise.*;
@@ -42,6 +43,9 @@ public class HexSkyMesh extends PlanetMesh{
@Override @Override
public void render(PlanetParams params, Mat3D projection, Mat3D transform){ public void render(PlanetParams params, Mat3D projection, Mat3D transform){
//don't waste performance rendering 0-alpha clouds
if(Mathf.zero(1f - params.uiAlpha, 0.01f)) return;
preRender(params); preRender(params);
shader.bind(); shader.bind();
shader.setUniformMatrix4("u_proj", projection.val); shader.setUniformMatrix4("u_proj", projection.val);

View File

@@ -210,7 +210,7 @@ public class PlanetGrid{
static int tileCount(int size){ static int tileCount(int size){
return 10 * Mathf.pow(3, size) + 2; return 10 * Mathf.pow(3, size) + 2;
} }///
static int cornerCount(int size){ static int cornerCount(int size){
return 20 * Mathf.pow(3, size); return 20 * Mathf.pow(3, size);

View File

@@ -19,8 +19,7 @@ public abstract class PlanetMesh implements GenericMesh{
public PlanetMesh(){} public PlanetMesh(){}
/** Should be overridden to set up any shader parameters such as planet position, normals, etc. /** Should be overridden to set up any shader parameters such as planet position, normals, etc. */
* @param params*/
public void preRender(PlanetParams params){ public void preRender(PlanetParams params){
} }

View File

@@ -259,15 +259,6 @@ public class FileChooser extends BaseDialog{
Core.settings.put("lastDirectory", directory.absolutePath()); Core.settings.put("lastDirectory", directory.absolutePath());
} }
private String shorten(String string){
int max = 30;
if(string.length() <= max){
return string;
}else{
return string.substring(0, max - 3).concat("...");
}
}
public class FileHistory{ public class FileHistory{
private Seq<Fi> history = new Seq<>(); private Seq<Fi> history = new Seq<>();
private int index; private int index;
@@ -305,19 +296,5 @@ public class FileChooser extends BaseDialog{
public boolean canBack(){ public boolean canBack(){
return !(index == 1) && index > 0; return !(index == 1) && index > 0;
} }
void print(){
System.out.println("\n\n\n\n\n\n");
int i = 0;
for(Fi file : history){
i++;
if(index == i){
System.out.println("[[" + file.toString() + "]]");
}else{
System.out.println("--" + file.toString() + "--");
}
}
}
} }
} }

View File

@@ -8,7 +8,9 @@ import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
import mindustry.*;
import mindustry.core.GameState.*; import mindustry.core.GameState.*;
import mindustry.game.*;
import mindustry.game.Saves.*; import mindustry.game.Saves.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.io.*; import mindustry.io.*;
@@ -20,8 +22,12 @@ import java.io.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class LoadDialog extends BaseDialog{ public class LoadDialog extends BaseDialog{
ScrollPane pane;
Table slots; Table slots;
String searchString;
Gamemode filteredMode;
TextField searchField;
ScrollPane pane;
BaseDialog dialog;
public LoadDialog(){ public LoadDialog(){
this("@loadgame"); this("@loadgame");
@@ -43,9 +49,38 @@ public class LoadDialog extends BaseDialog{
slots = new Table(); slots = new Table();
pane = new ScrollPane(slots); pane = new ScrollPane(slots);
rebuild();
Table search = new Table();
search.image(Icon.zoom);
searchField = search.field("", t -> {
searchString = t.length() > 0 ? t.toLowerCase() : null;
rebuild();
}).maxTextLength(50).growX().get();
searchField.setMessageText("@save.search");
for(Gamemode mode : Gamemode.all){
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()));
boolean sandbox = mode == Gamemode.sandbox;
if(Core.atlas.isFound(icon.getRegion()) || sandbox){
search.button(sandbox ? Icon.terrain : icon, Styles.emptytogglei, () -> {
filteredMode = filteredMode == mode ? null : mode;
rebuild();
}).size(60f).checked(b -> filteredMode == mode).tooltip("@mode." + mode.name() + ".name");
}
}
pane.setFadeScrollBars(false); pane.setFadeScrollBars(false);
pane.setScrollingDisabled(true, false); pane.setScrollingDisabled(true, false);
cont.add(search).growX();
cont.row();
cont.add(pane).growY();
}
public void rebuild(){
slots.clear();
slots.marginRight(24).marginLeft(20f); slots.marginRight(24).marginLeft(20f);
Time.runTask(2f, () -> Core.scene.setScrollFocus(pane)); Time.runTask(2f, () -> Core.scene.setScrollFocus(pane));
@@ -58,7 +93,11 @@ public class LoadDialog extends BaseDialog{
boolean any = false; boolean any = false;
for(SaveSlot slot : array){ for(SaveSlot slot : array){
if(slot.isHidden()) continue; if(slot.isHidden()
|| (searchString != null && !Strings.stripColors(slot.getName()).toLowerCase().contains(searchString))
|| (filteredMode != null && filteredMode != slot.mode())){
continue;
}
any = true; any = true;
@@ -82,14 +121,14 @@ public class LoadDialog extends BaseDialog{
t.button(Icon.trash, Styles.emptyi, () -> { t.button(Icon.trash, Styles.emptyi, () -> {
ui.showConfirm("@confirm", "@save.delete.confirm", () -> { ui.showConfirm("@confirm", "@save.delete.confirm", () -> {
slot.delete(); slot.delete();
setup(); rebuild();
}); });
}).right(); }).right();
t.button(Icon.pencil, Styles.emptyi, () -> { t.button(Icon.pencil, Styles.emptyi, () -> {
ui.showTextInput("@save.rename", "@save.rename.text", slot.getName(), text -> { ui.showTextInput("@save.rename", "@save.rename.text", slot.getName(), text -> {
slot.setName(text); slot.setName(text);
setup(); rebuild();
}); });
}).right(); }).right();
@@ -141,10 +180,8 @@ public class LoadDialog extends BaseDialog{
} }
if(!any){ if(!any){
slots.button("@save.none", () -> {}).disabled(true).fillX().margin(20f).minWidth(340f).height(80f).pad(4f); slots.add("@save.none");
} }
cont.add(pane);
} }
public void addSetup(){ public void addSetup(){
@@ -154,7 +191,7 @@ public class LoadDialog extends BaseDialog{
if(SaveIO.isSaveValid(file)){ if(SaveIO.isSaveValid(file)){
try{ try{
control.saves.importSave(file); control.saves.importSave(file);
setup(); rebuild();
}catch(IOException e){ }catch(IOException e){
e.printStackTrace(); e.printStackTrace();
ui.showException("@save.import.fail", e); ui.showException("@save.import.fail", e);
@@ -193,4 +230,15 @@ public class LoadDialog extends BaseDialog{
} }
}); });
} }
@Override
public Dialog show(){
super.show();
if(Core.app.isDesktop() && searchField != null){
Core.scene.setKeyboardFocus(searchField);
}
return this;
}
} }

View File

@@ -25,7 +25,10 @@ public class MapsDialog extends BaseDialog{
private Table mapTable = new Table(); private Table mapTable = new Table();
private TextField searchField; private TextField searchField;
private boolean showAll = Core.settings.getBool("editorShowAllMaps", true); private boolean showBuiltIn = Core.settings.getBool("editorshowbuiltinmaps", true);
private boolean showCustom = Core.settings.getBool("editorshowcustommaps", true);
private boolean searchAuthor = Core.settings.getBool("editorsearchauthor", false);
private boolean searchDescription = Core.settings.getBool("editorsearchdescription", false);
public MapsDialog(){ public MapsDialog(){
super("@maps"); super("@maps");
@@ -87,7 +90,7 @@ public class MapsDialog extends BaseDialog{
String name = map.tags.get("name", () -> { String name = map.tags.get("name", () -> {
String result = "unknown"; String result = "unknown";
int number = 0; int number = 0;
while(maps.byName(result + number++) != null); while(maps.byName(result + number++) != null) ;
return result + number; return result + number;
}); });
@@ -153,35 +156,43 @@ public class MapsDialog extends BaseDialog{
int i = 0; int i = 0;
Seq<Map> mapList = showAll ? Vars.maps.all() : Vars.maps.customMaps(); Seq<Map> mapList = showCustom ?
for(Map map : mapList){ showBuiltIn ? maps.all() : maps.customMaps() :
showBuiltIn ? maps.defaultMaps() : null;
boolean invalid = false; if(mapList != null){
for(Gamemode mode : modes){ for(Map map : mapList){
invalid |= !mode.valid(map);
boolean invalid = false;
for(Gamemode mode : modes){
invalid |= !mode.valid(map);
}
if(invalid || (searchString != null
&& !Strings.stripColors(map.name()).toLowerCase().contains(searchString)
&& (!searchAuthor || !Strings.stripColors(map.author()).toLowerCase().contains(searchString))
&& (!searchDescription || !Strings.stripColors(map.description()).toLowerCase().contains(searchString)))){
continue;
}
noMapsShown = false;
if(i % maxwidth == 0){
mapTable.row();
}
TextButton button = mapTable.button("", Styles.cleart, () -> showMapInfo(map)).width(mapsize).pad(8).get();
button.clearChildren();
button.margin(9);
button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true);
button.row();
button.image().growX().pad(4).color(Pal.gray);
button.row();
button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f);
button.row();
button.add(map.custom ? "@custom" : map.workshop ? "@workshop" : map.mod != null ? "[lightgray]" + map.mod.meta.displayName() : "@builtin").color(Color.gray).padTop(3);
i++;
} }
if(invalid || (searchString != null && !Strings.stripColors(map.name()).toLowerCase().contains(searchString))){
continue;
}
noMapsShown = false;
if(i % maxwidth == 0){
mapTable.row();
}
TextButton button = mapTable.button("", Styles.cleart, () -> showMapInfo(map)).width(mapsize).pad(8).get();
button.clearChildren();
button.margin(9);
button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true);
button.row();
button.image().growX().pad(4).color(Pal.gray);
button.row();
button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f);
button.row();
button.add(map.custom ? "@custom" : map.workshop ? "@workshop" : map.mod != null ? "[lightgray]" + map.mod.meta.displayName() : "@builtin").color(Color.gray).padTop(3);
i++;
} }
if(noMapsShown){ if(noMapsShown){
@@ -192,30 +203,57 @@ public class MapsDialog extends BaseDialog{
void showMapFilters(){ void showMapFilters(){
dialog = new BaseDialog("@editor.filters"); dialog = new BaseDialog("@editor.filters");
dialog.addCloseButton(); dialog.addCloseButton();
dialog.setFillParent(false); dialog.cont.table(menu -> {
dialog.cont.table(Tex.button, t -> { menu.add("@editor.filters.mode").width(150f).left();
int i = 0; menu.table(t -> {
for(Gamemode mode : Gamemode.all){ for(Gamemode mode : Gamemode.all){
TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name())); TextureRegionDrawable icon = Vars.ui.getIcon("mode" + Strings.capitalize(mode.name()));
if(Core.atlas.isFound(icon.getRegion())){ if(Core.atlas.isFound(icon.getRegion())){
t.button(mode.name(), icon, Styles.clearTogglet, () -> { t.button(icon, Styles.emptytogglei, () -> {
if(modes.contains(mode)){ if(modes.contains(mode)){
modes.remove(mode); modes.remove(mode);
}else{ }else{
modes.add(mode); modes.add(mode);
} }
rebuildMaps(); rebuildMaps();
}).size(150f, 60f).marginLeft(6f).checked(modes.contains(mode)); }).size(60f).checked(modes.contains(mode)).tooltip("@mode." + mode.name() + ".name");
if(++i % 3 == 0) t.row(); }
} }
} }).padBottom(10f);
t.row(); menu.row();
t.button("@editor.showAll", Styles.clearTogglet, () -> {
showAll = !showAll; menu.add("@editor.filters.type").width(150f).left();
Core.settings.put("editorShowAllMaps", showAll); menu.table(Tex.button, t -> {
Core.settings.forceSave(); t.button("@custom", Styles.clearTogglet, () -> {
rebuildMaps(); showCustom = !showCustom;
}).checked(b -> showAll).colspan(3).growX().height(40f); Core.settings.put("editorshowcustommaps", showCustom);
Core.settings.forceSave();
rebuildMaps();
}).size(150f, 60f).checked(showCustom);
t.button("@builtin", Styles.clearTogglet, () -> {
showBuiltIn = !showBuiltIn;
Core.settings.put("editorshowbuiltinmaps", showBuiltIn);
Core.settings.forceSave();
rebuildMaps();
}).size(150f, 60f).checked(showBuiltIn);
}).padBottom(10f);
menu.row();
menu.add("@editor.filters.search").width(150f).left();
menu.table(Tex.button, t -> {
t.button("@editor.filters.author", Styles.clearTogglet, () -> {
searchAuthor = !searchAuthor;
Core.settings.put("editorsearchauthor", searchAuthor);
Core.settings.forceSave();
rebuildMaps();
}).size(150f, 60f).checked(searchAuthor);
t.button("@editor.filters.description", Styles.clearTogglet, () -> {
searchDescription = !searchDescription;
Core.settings.put("editorsearchdescription", searchDescription);
Core.settings.forceSave();
rebuildMaps();
}).size(150f, 60f).checked(searchDescription);
});
}); });
dialog.show(); dialog.show();

View File

@@ -151,13 +151,13 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
} }
zoom = (Mathf.clamp(initialDistance / distance * lastZoom, state.planet.minZoom, 2f)); zoom = (Mathf.clamp(initialDistance / distance * lastZoom, state.planet.minZoom, 2f));
} }
@Override @Override
public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){ public void touchUp(InputEvent event, float x, float y, int pointer, KeyCode button){
lastZoom = zoom; lastZoom = zoom;
} }
}); });
shown(this::setup); shown(this::setup);
} }

View File

@@ -98,7 +98,7 @@ public class PlacementFragment extends Fragment{
boolean gridUpdate(InputHandler input){ boolean gridUpdate(InputHandler input){
scrollPositions.put(currentCategory, blockPane.getScrollY()); scrollPositions.put(currentCategory, blockPane.getScrollY());
if(Core.input.keyTap(Binding.pick) && player.isBuilder()){ //mouse eyedropper select if(Core.input.keyTap(Binding.pick) && player.isBuilder() && !Core.scene.hasDialog()){ //mouse eyedropper select
var build = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y); var build = world.buildWorld(Core.input.mouseWorld().x, Core.input.mouseWorld().y);
Block tryRecipe = build == null ? null : build instanceof ConstructBuild c ? c.current : build.block; Block tryRecipe = build == null ? null : build instanceof ConstructBuild c ? c.current : build.block;
Object tryConfig = build == null || !build.block.copyConfig ? null : build.config(); Object tryConfig = build == null || !build.block.copyConfig ? null : build.config();
@@ -445,7 +445,7 @@ public class PlacementFragment extends Fragment{
} }
boolean unlocked(Block block){ boolean unlocked(Block block){
return block.unlockedNow() && block.placeablePlayer; return block.unlockedNow() && block.placeablePlayer && (state.rules.hiddenBuildItems.isEmpty() || !Structs.contains(block.requirements, i -> state.rules.hiddenBuildItems.contains(i.item)));
} }
boolean hasInfoBox(){ boolean hasInfoBox(){

View File

@@ -1,10 +1,12 @@
package mindustry.ui.fragments; package mindustry.ui.fragments;
import arc.*; import arc.*;
import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.scene.*; import arc.scene.*;
import arc.scene.event.*; import arc.scene.event.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.ImageButton.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*; import arc.util.*;
@@ -115,6 +117,23 @@ public class PlayerListFragment extends Fragment{
button.image(Icon.admin).visible(() -> user.admin && !(!user.isLocal() && net.server())).padRight(5).get().updateVisibility(); button.image(Icon.admin).visible(() -> user.admin && !(!user.isLocal() && net.server())).padRight(5).get().updateVisibility();
var style = new ImageButtonStyle(){{
down = Styles.none;
up = Styles.none;
imageCheckedColor = Pal.accent;
imageDownColor = Pal.accent;
imageUpColor = Color.white;
imageOverColor = Color.lightGray;
}};
var ustyle = new ImageButtonStyle(){{
down = Styles.none;
up = Styles.none;
imageDownColor = Pal.accent;
imageUpColor = Color.white;
imageOverColor = Color.lightGray;
}};
if((net.server() || player.admin) && !user.isLocal() && (!user.admin || net.server())){ if((net.server() || player.admin) && !user.isLocal() && (!user.admin || net.server())){
button.add().growY(); button.add().growY();
@@ -123,35 +142,41 @@ public class PlayerListFragment extends Fragment{
button.table(t -> { button.table(t -> {
t.defaults().size(bs); t.defaults().size(bs);
t.button(Icon.hammer, Styles.clearPartiali, t.button(Icon.hammer, ustyle,
() -> ui.showConfirm("@confirm", Core.bundle.format("confirmban", user.name()), () -> Call.adminRequest(user, AdminAction.ban))); () -> ui.showConfirm("@confirm", Core.bundle.format("confirmban", user.name()), () -> Call.adminRequest(user, AdminAction.ban)));
t.button(Icon.cancel, Styles.clearPartiali, t.button(Icon.cancel, ustyle,
() -> ui.showConfirm("@confirm", Core.bundle.format("confirmkick", user.name()), () -> Call.adminRequest(user, AdminAction.kick))); () -> ui.showConfirm("@confirm", Core.bundle.format("confirmkick", user.name()), () -> Call.adminRequest(user, AdminAction.kick)));
t.row(); t.row();
t.button(Icon.admin, Styles.clearTogglePartiali, () -> { t.button(Icon.admin, style, () -> {
if(net.client()) return; if(net.client()) return;
String id = user.uuid(); String id = user.uuid();
if(netServer.admins.isAdmin(id, connection.address)){ if(user.admin){
ui.showConfirm("@confirm", Core.bundle.format("confirmunadmin", user.name()), () -> netServer.admins.unAdminPlayer(id)); ui.showConfirm("@confirm", Core.bundle.format("confirmunadmin", user.name()), () -> {
netServer.admins.unAdminPlayer(id);
user.admin = false;
});
}else{ }else{
ui.showConfirm("@confirm", Core.bundle.format("confirmadmin", user.name()), () -> netServer.admins.adminPlayer(id, user.usid())); ui.showConfirm("@confirm", Core.bundle.format("confirmadmin", user.name()), () -> {
netServer.admins.adminPlayer(id, user.usid());
user.admin = true;
});
} }
}).update(b -> b.setChecked(user.admin)) }).update(b -> b.setChecked(user.admin))
.disabled(b -> net.client()) .disabled(b -> net.client())
.touchable(() -> net.client() ? Touchable.disabled : Touchable.enabled) .touchable(() -> net.client() ? Touchable.disabled : Touchable.enabled)
.checked(user.admin); .checked(user.admin);
t.button(Icon.zoom, Styles.clearPartiali, () -> Call.adminRequest(user, AdminAction.trace)); t.button(Icon.zoom, ustyle, () -> Call.adminRequest(user, AdminAction.trace));
}).padRight(12).size(bs + 10f, bs); }).padRight(12).size(bs + 10f, bs);
}else if(!user.isLocal() && !user.admin && net.client() && Groups.player.size() >= 3 && player.team() == user.team()){ //votekick }else if(!user.isLocal() && !user.admin && net.client() && Groups.player.size() >= 3 && player.team() == user.team()){ //votekick
button.add().growY(); button.add().growY();
button.button(Icon.hammer, Styles.clearPartiali, button.button(Icon.hammer, ustyle,
() -> { () -> {
ui.showConfirm("@confirm", Core.bundle.format("confirmvotekick", user.name()), () -> { ui.showConfirm("@confirm", Core.bundle.format("confirmvotekick", user.name()), () -> {
Call.sendChatMessage("/votekick " + user.name()); Call.sendChatMessage("/votekick " + user.name());

View File

@@ -120,6 +120,8 @@ public class Block extends UnlockableContent{
public boolean autoResetEnabled = true; public boolean autoResetEnabled = true;
/** if true, the block stops updating when disabled */ /** if true, the block stops updating when disabled */
public boolean noUpdateDisabled = false; public boolean noUpdateDisabled = false;
/** if true, this block updates when a payload of a unit. Currently unused! */
public boolean updateInUnits = true;
/** Whether to use this block's color in the minimap. Only used for overlays. */ /** Whether to use this block's color in the minimap. Only used for overlays. */
public boolean useColor = true; public boolean useColor = true;
/** item that drops from this block, used for drills */ /** item that drops from this block, used for drills */
@@ -152,7 +154,7 @@ public class Block extends UnlockableContent{
public boolean alwaysReplace = false; public boolean alwaysReplace = false;
/** if false, this block can never be replaced. */ /** if false, this block can never be replaced. */
public boolean replaceable = true; public boolean replaceable = true;
/** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */ /** The block group. Unless {@link #canReplace} is overridden, blocks in the same group can replace each other. */
public BlockGroup group = BlockGroup.none; public BlockGroup group = BlockGroup.none;
/** List of block flags. Used for AI indexing. */ /** List of block flags. Used for AI indexing. */
public EnumSet<BlockFlag> flags = EnumSet.of(); public EnumSet<BlockFlag> flags = EnumSet.of();
@@ -264,6 +266,7 @@ public class Block extends UnlockableContent{
/** Main subclass. Non-anonymous. */ /** Main subclass. Non-anonymous. */
public @Nullable Class<?> subclass; public @Nullable Class<?> subclass;
public float selectScroll; //scroll position for certain blocks
public Prov<Building> buildType = null; //initialized later public Prov<Building> buildType = null; //initialized later
public ObjectMap<Class<?>, Cons2> configurations = new ObjectMap<>(); public ObjectMap<Class<?>, Cons2> configurations = new ObjectMap<>();

View File

@@ -5,20 +5,29 @@ import arc.scene.style.*;
import arc.scene.ui.*; import arc.scene.ui.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*; import arc.struct.*;
import arc.util.*;
import mindustry.ctype.*; import mindustry.ctype.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.ui.*; import mindustry.ui.*;
import mindustry.world.*;
import static mindustry.Vars.*; import static mindustry.Vars.*;
public class ItemSelection{ public class ItemSelection{
private static float scrollPos = 0f;
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){ public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
buildTable(table, items, holder, consumer, true); buildTable(table, items, holder, consumer, true);
} }
public static <T extends UnlockableContent> void buildTable(Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer){
buildTable(block, table, items, holder, consumer, true);
}
public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){ public static <T extends UnlockableContent> void buildTable(Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
buildTable(null, table, items, holder, consumer, closeSelect);
}
public static <T extends UnlockableContent> void buildTable(@Nullable Block block, Table table, Seq<T> items, Prov<T> holder, Cons<T> consumer, boolean closeSelect){
ButtonGroup<ImageButton> group = new ButtonGroup<>(); ButtonGroup<ImageButton> group = new ButtonGroup<>();
group.setMinCheckCount(0); group.setMinCheckCount(0);
@@ -52,10 +61,13 @@ public class ItemSelection{
ScrollPane pane = new ScrollPane(cont, Styles.smallPane); ScrollPane pane = new ScrollPane(cont, Styles.smallPane);
pane.setScrollingDisabled(true, false); pane.setScrollingDisabled(true, false);
pane.setScrollYForce(scrollPos);
pane.update(() -> { if(block != null){
scrollPos = pane.getScrollY(); pane.setScrollYForce(block.selectScroll);
}); pane.update(() -> {
block.selectScroll = pane.getScrollY();
});
}
pane.setOverscroll(false, false); pane.setOverscroll(false, false);
table.add(pane).maxHeight(Scl.scl(40 * 5)); table.add(pane).maxHeight(Scl.scl(40 * 5));

View File

@@ -109,7 +109,7 @@ public class OverdriveProjector extends Block{
float realRange = range + phaseHeat * phaseRangeBoost; float realRange = range + phaseHeat * phaseRangeBoost;
charge = 0f; charge = 0f;
indexer.eachBlock(this, realRange, other -> true, other -> other.applyBoost(realBoost(), reload + 1f)); indexer.eachBlock(this, realRange, other -> other.block.canOverdrive, other -> other.applyBoost(realBoost(), reload + 1f));
} }
if(timer(timerUse, useTime) && efficiency() > 0 && consValid()){ if(timer(timerUse, useTime) && efficiency() > 0 && consValid()){

View File

@@ -31,6 +31,7 @@ public class BaseTurret extends Block{
priority = TargetPriority.turret; priority = TargetPriority.turret;
group = BlockGroup.turrets; group = BlockGroup.turrets;
flags = EnumSet.of(BlockFlag.turret); flags = EnumSet.of(BlockFlag.turret);
updateInUnits = false;
} }
@Override @Override

View File

@@ -100,6 +100,7 @@ public class Turret extends ReloadTurret{
public Turret(String name){ public Turret(String name){
super(name); super(name);
liquidCapacity = 20f; liquidCapacity = 20f;
quickRotate = false;
} }
@Override @Override
@@ -184,8 +185,8 @@ public class Turret extends ReloadTurret{
logicControlTime = logicControlCooldown; logicControlTime = logicControlCooldown;
logicShooting = !Mathf.zero(p2); logicShooting = !Mathf.zero(p2);
if(p1 instanceof Posc){ if(p1 instanceof Posc pos){
targetPosition((Posc)p1); targetPosition(pos);
} }
} }

View File

@@ -127,7 +127,7 @@ public class PayloadConveyor extends Block{
if(!enabled) return; if(!enabled) return;
if(item != null){ if(item != null){
item.update(); item.update(false);
} }
lastInterp = curInterp; lastInterp = curInterp;

View File

@@ -124,7 +124,7 @@ public class Sorter extends Block{
@Override @Override
public void buildConfiguration(Table table){ public void buildConfiguration(Table table){
ItemSelection.buildTable(table, content.items(), () -> sortItem, this::configure); ItemSelection.buildTable(Sorter.this, table, content.items(), () -> sortItem, this::configure);
} }
@Override @Override

View File

@@ -37,7 +37,9 @@ public class BuildPayload implements Payload{
} }
@Override @Override
public void update(){ public void update(boolean inUnit){
if(inUnit && !build.block.updateInUnits) return;
if(build.tile == null) build.tile = emptyTile; if(build.tile == null) build.tile = emptyTile;
build.update(); build.update();
} }

View File

@@ -6,6 +6,7 @@ import arc.scene.ui.layout.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
import mindustry.*; import mindustry.*;
import mindustry.gen.*;
import mindustry.world.*; import mindustry.world.*;
import mindustry.world.blocks.*; import mindustry.world.blocks.*;
import mindustry.world.blocks.storage.*; import mindustry.world.blocks.storage.*;
@@ -55,7 +56,18 @@ public class Constructor extends BlockProducer{
@Override @Override
public void buildConfiguration(Table table){ public void buildConfiguration(Table table){
ItemSelection.buildTable(table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure); ItemSelection.buildTable(Constructor.this, table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure);
}
@Override
public boolean onConfigureTileTapped(Building other){
if(this == other){
deselect();
configure(null);
return false;
}
return true;
} }
@Override @Override

View File

@@ -36,8 +36,9 @@ public interface Payload extends Position{
/** @return the time taken to build this payload. */ /** @return the time taken to build this payload. */
float buildTime(); float buildTime();
/** update this payload if it is a block */ /** update this payload if it is a block
default void update(){} * @param inUnit whether this payload is in a unit */
default void update(boolean inUnit){}
/** @return whether this payload was dumped. */ /** @return whether this payload was dumped. */
default boolean dump(){ default boolean dump(){

View File

@@ -138,7 +138,7 @@ public class PayloadBlock extends Block{
@Override @Override
public void updateTile(){ public void updateTile(){
if(payload != null){ if(payload != null){
payload.update(); payload.update(false);
} }
} }

View File

@@ -85,12 +85,23 @@ public class PayloadSource extends PayloadBlock{
@Override @Override
public void buildConfiguration(Table table){ public void buildConfiguration(Table table){
ItemSelection.buildTable(table, ItemSelection.buildTable(PayloadSource.this, table,
content.blocks().select(PayloadSource.this::canProduce).<UnlockableContent>as() content.blocks().select(PayloadSource.this::canProduce).<UnlockableContent>as()
.and(content.units().select(PayloadSource.this::canProduce).as()), .and(content.units().select(PayloadSource.this::canProduce).as()),
() -> (UnlockableContent)config(), this::configure); () -> (UnlockableContent)config(), this::configure);
} }
@Override
public boolean onConfigureTileTapped(Building other){
if(this == other){
deselect();
configure(null);
return false;
}
return true;
}
@Override @Override
public Object config(){ public Object config(){
return unit == null ? block : unit; return unit == null ? block : unit;

View File

@@ -49,6 +49,7 @@ public class NuclearReactor extends PowerGenerator{
public NuclearReactor(String name){ public NuclearReactor(String name){
super(name); super(name);
updateInUnits = false;
itemCapacity = 30; itemCapacity = 30;
liquidCapacity = 30; liquidCapacity = 30;
hasItems = true; hasItems = true;
@@ -138,6 +139,7 @@ public class NuclearReactor extends PowerGenerator{
if((fuel < 5 && heat < 0.5f) || !state.rules.reactorExplosions) return; if((fuel < 5 && heat < 0.5f) || !state.rules.reactorExplosions) return;
Effect.shake(6f, 16f, x, y); Effect.shake(6f, 16f, x, y);
// * ((float)fuel / itemCapacity) to scale based on fullness
Damage.damage(x, y, explosionRadius * tilesize, explosionDamage * 4); Damage.damage(x, y, explosionRadius * tilesize, explosionDamage * 4);
explodeEffect.at(x, y); explodeEffect.at(x, y);

View File

@@ -280,6 +280,13 @@ public class PowerGraph{
} }
} }
public void clear(){
all.clear();
producers.clear();
consumers.clear();
batteries.clear();
}
public void reflow(Building tile){ public void reflow(Building tile){
queue.clear(); queue.clear();
queue.addLast(tile); queue.addLast(tile);

View File

@@ -73,7 +73,7 @@ public class ItemSource extends Block{
@Override @Override
public void buildConfiguration(Table table){ public void buildConfiguration(Table table){
ItemSelection.buildTable(table, content.items(), () -> outputItem, this::configure); ItemSelection.buildTable(ItemSource.this, table, content.items(), () -> outputItem, this::configure);
} }
@Override @Override

View File

@@ -73,7 +73,7 @@ public class LiquidSource extends Block{
@Override @Override
public void buildConfiguration(Table table){ public void buildConfiguration(Table table){
ItemSelection.buildTable(table, content.liquids(), () -> source, this::configure); ItemSelection.buildTable(LiquidSource.this, table, content.liquids(), () -> source, this::configure);
} }
@Override @Override

View File

@@ -3,6 +3,7 @@ package mindustry.world.blocks.storage;
import arc.graphics.*; import arc.graphics.*;
import arc.graphics.g2d.*; import arc.graphics.g2d.*;
import arc.scene.ui.layout.*; import arc.scene.ui.layout.*;
import arc.struct.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
import mindustry.entities.units.*; import mindustry.entities.units.*;
@@ -54,56 +55,133 @@ public class Unloader extends Block{
public class UnloaderBuild extends Building{ public class UnloaderBuild extends Building{
public float unloadTimer = 0f; public float unloadTimer = 0f;
public Item sortItem = null; public Item sortItem = null;
public Building dumpingTo;
public int offset = 0; public int offset = 0;
public int[] rotations; public int rotations = 0;
public Seq<ContainerStat> possibleBlocks = new Seq<>();
public class ContainerStat{
Building building;
float loadFactor;
boolean canLoad;
boolean canUnload;
}
@Override @Override
public void updateTile(){ public void updateTile(){
if((unloadTimer += delta()) >= speed){ if(((unloadTimer += delta()) < speed) || (proximity.size < 2)) return;
boolean any = false; Item item = null;
if(rotations == null || rotations.length != proximity.size){ boolean any = false;
rotations = new int[proximity.size]; int itemslength = content.items().size;
//initialize possibleBlocks only if the new size is bigger than the previous, to avoid unnecessary allocations
if(possibleBlocks.size != proximity.size){
int tmp = possibleBlocks.size;
possibleBlocks.setSize(proximity.size);
for(int i = tmp; i < proximity.size; i++){
possibleBlocks.set(i, new ContainerStat());
}
}
if(sortItem != null){
item = sortItem;
for(int pos = 0; pos < proximity.size; pos++){
var other = proximity.get(pos);
boolean interactable = other.interactable(team);
//set the stats of all buildings in possibleBlocks
ContainerStat pb = possibleBlocks.get(pos);
pb.building = other;
pb.canUnload = interactable && other.canUnload() && other.items != null && other.items.has(sortItem);
pb.canLoad = interactable && !(other.block instanceof StorageBlock) && other.acceptItem(this, sortItem);
}
}else{
//select the next item for nulloaders
//inspired of nextIndex() but for all proximity at once, and also way more powerful
for(int i = 0; i < itemslength; i++){
int total = (rotations + i + 1) % itemslength;
boolean hasProvider = false;
boolean hasReceiver = false;
boolean isDistinct = false;
Item possibleItem = content.item(total);
for(int pos = 0; pos < proximity.size; pos++){
var other = proximity.get(pos);
boolean interactable = other.interactable(team);
//set the stats of all buildings in possibleBlocks while we are at it
ContainerStat pb = possibleBlocks.get(pos);
pb.building = other;
pb.canUnload = interactable && other.canUnload() && other.items != null && other.items.has(possibleItem);
pb.canLoad = interactable && !(other.block instanceof StorageBlock) && other.acceptItem(this, possibleItem);
//the part handling framerate issues and slow conveyor belts, to avoid skipping items
if(hasProvider && pb.canLoad) isDistinct = true;
if(hasReceiver && pb.canUnload) isDistinct = true;
hasProvider = hasProvider || pb.canUnload;
hasReceiver = hasReceiver || pb.canLoad;
}
if(isDistinct){
item = possibleItem;
break;
}
}
}
if(item != null){
//only compute the load factor if a transfer is possible
for(int pos = 0; pos < proximity.size; pos++){
ContainerStat pb = possibleBlocks.get(pos);
var other = pb.building;
pb.loadFactor = (other.getMaximumAccepted(item) == 0) || (other.items == null) ? 0 : other.items.get(item) / (float)other.getMaximumAccepted(item);
} }
for(int i = 0; i < proximity.size; i++){ //sort so it gives full priority to blocks that can give but not receive (mainly plast and storage), and then by load
int pos = (offset + i) % proximity.size; possibleBlocks.sort((e1, e2) -> {
var other = proximity.get(pos); // TODO: instead of canLoad it should be ((instance of Storage) || (is it a plast belt i can unload from))
// otherwise a 100% full factory will get full priority over the storage/plast, barely an issue but still wasting trades and thus speed
int canLoad = Boolean.compare(e2.canLoad, e1.canLoad);
return (canLoad != 0) ? canLoad : Float.compare(e1.loadFactor, e2.loadFactor);
});
if(other.interactable(team) && other.block.unloadable && other.canUnload() && other.block.hasItems ContainerStat dumpingFrom = null;
&& ((sortItem == null && other.items.total() > 0) || (sortItem != null && other.items.has(sortItem)))){ ContainerStat dumpingTo = null;
//make sure the item can't be dumped back into this block
dumpingTo = other;
//get item to be taken //choose the building to accept the item
Item item = sortItem == null ? other.items.takeIndex(rotations[pos]) : sortItem; for(int i = 0; i < possibleBlocks.size; i++){
if(possibleBlocks.get(i).canLoad){
//remove item if it's dumped correctly dumpingTo = possibleBlocks.get(i);
if(put(item)){ break;
other.items.remove(item, 1);
any = true;
if(sortItem == null){
rotations[pos] = item.id + 1;
}
other.itemTaken(item);
}else if(sortItem == null){
rotations[pos] = other.items.nextIndex(rotations[pos]);
}
} }
} }
if(any){ //choose the building to give the item
unloadTimer %= speed; for(int i = possibleBlocks.size - 1; i >= 0; i--){
}else{ if(possibleBlocks.get(i).canUnload){
unloadTimer = Math.min(unloadTimer, speed); dumpingFrom = possibleBlocks.get(i);
break;
}
} }
if(proximity.size > 0){ //trade the items
offset ++; if(dumpingFrom != null && dumpingTo != null && dumpingFrom.loadFactor != dumpingTo.loadFactor){
offset %= proximity.size; dumpingTo.building.handleItem(this, item);
dumpingFrom.building.removeStack(item, 1);
any = true;
} }
if(sortItem == null) rotations = item.id;
}
if(any){
unloadTimer %= speed;
}else{
unloadTimer = Math.min(unloadTimer, speed);
}
if(proximity.size > 0){
offset++;
offset %= proximity.size;
} }
} }
@@ -118,7 +196,7 @@ public class Unloader extends Block{
@Override @Override
public void buildConfiguration(Table table){ public void buildConfiguration(Table table){
ItemSelection.buildTable(table, content.items(), () -> sortItem, this::configure); ItemSelection.buildTable(Unloader.this, table, content.items(), () -> sortItem, this::configure);
} }
@Override @Override
@@ -132,11 +210,6 @@ public class Unloader extends Block{
return true; return true;
} }
@Override
public boolean canDump(Building to, Item item){
return !(to.block instanceof StorageBlock) && to != dumpingTo;
}
@Override @Override
public Item config(){ public Item config(){
return sortItem; return sortItem;

View File

@@ -231,7 +231,7 @@ public class Reconstructor extends UnitBlock{
@Override @Override
public boolean shouldConsume(){ public boolean shouldConsume(){
return constructing(); return constructing() && enabled;
} }
public UnitType unit(){ public UnitType unit(){

View File

@@ -160,12 +160,23 @@ public class UnitFactory extends UnitBlock{
Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned()); Seq<UnitType> units = Seq.with(plans).map(u -> u.unit).filter(u -> u.unlockedNow() && !u.isBanned());
if(units.any()){ if(units.any()){
ItemSelection.buildTable(table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit))); ItemSelection.buildTable(UnitFactory.this, table, units, () -> currentPlan == -1 ? null : plans.get(currentPlan).unit, unit -> configure(plans.indexOf(u -> u.unit == unit)));
}else{ }else{
table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray)); table.table(Styles.black3, t -> t.add("@none").color(Color.lightGray));
} }
} }
@Override
public boolean onConfigureTileTapped(Building other){
if(this == other){
deselect();
configure(null);
return false;
}
return true;
}
@Override @Override
public boolean acceptPayload(Building source, Payload payload){ public boolean acceptPayload(Building source, Payload payload){
return false; return false;

View File

@@ -68,7 +68,8 @@ public class ConsumePower extends Consume{
* @return The amount of power which is requested per tick. * @return The amount of power which is requested per tick.
*/ */
public float requestedPower(Building entity){ public float requestedPower(Building entity){
if(entity.tile == null || entity.tile.build == null) return 0f; if(entity == null) return 0f;
if(buffered){ if(buffered){
return (1f-entity.power.status)*capacity; return (1f-entity.power.status)*capacity;
}else{ }else{

View File

@@ -117,7 +117,7 @@
}, },
{ {
"name": "MindustryBR", "name": "MindustryBR",
"address": ["mindustryptbr.ddns.net", "mindustryptbr.myddns.me", "mindustry.me:4447"] "address": ["mindustryptbr.ddns.net", "mindustryptbr.myddns.me", "n2.mindustry.me:4002", "n2.mindustry.me:4007"]
}, },
{ {
"name": "Conservatory", "name": "Conservatory",

View File

@@ -65,6 +65,10 @@
}, },
{ {
"name": "MindustryBR", "name": "MindustryBR",
"address": ["mindustry.me:4451", "n2.mindustry.me:4446"] "address": ["n2.mindustry.me:4003", "n2.mindustry.me:4005", "n2.mindustry.me:4008", "n2.mindustry.me:4009", "n2.mindustry.me:4010"]
},
{
"name": "LostDustry",
"address": ["lostdustry.northeurope.cloudapp.azure.com:6568", "lostdustry.northeurope.cloudapp.azure.com:6569", "lostdustry.northeurope.cloudapp.azure.com:6570"]
} }
] ]