diff --git a/core/src/mindustry/core/NetClient.java b/core/src/mindustry/core/NetClient.java index e1ac7f97f1..11653e2d0c 100644 --- a/core/src/mindustry/core/NetClient.java +++ b/core/src/mindustry/core/NetClient.java @@ -2,7 +2,6 @@ package mindustry.core; import arc.*; import arc.func.*; -import arc.graphics.*; import arc.math.*; import arc.struct.*; import arc.util.*; @@ -12,7 +11,6 @@ import arc.util.serialization.*; import mindustry.*; import mindustry.annotations.Annotations.*; import mindustry.core.GameState.*; -import mindustry.entities.*; import mindustry.entities.units.*; import mindustry.game.EventType.*; import mindustry.game.*; @@ -21,7 +19,6 @@ import mindustry.gen.*; import mindustry.net.Administration.*; import mindustry.net.*; import mindustry.net.Packets.*; -import mindustry.ui.*; import mindustry.world.*; import mindustry.world.modules.*; @@ -314,78 +311,6 @@ public class NetClient implements ApplicationListener{ ui.loadfrag.hide(); } - @Remote(variants = Variant.both, unreliable = true) - public static void setHudText(String message){ - if(message == null) return; - - ui.hudfrag.setHudText(message); - } - - @Remote(variants = Variant.both) - public static void hideHudText(){ - ui.hudfrag.toggleHudText(false); - } - - /** TCP version */ - @Remote(variants = Variant.both) - public static void setHudTextReliable(String message){ - setHudText(message); - } - - @Remote(variants = Variant.both) - public static void announce(String message){ - if(message == null) return; - - ui.announce(message); - } - - @Remote(variants = Variant.both) - public static void infoMessage(String message){ - if(message == null) return; - - ui.showText("", message); - } - - @Remote(variants = Variant.both) - public static void infoPopup(String message, float duration, int align, int top, int left, int bottom, int right){ - if(message == null) return; - - ui.showInfoPopup(message, duration, align, top, left, bottom, right); - } - - @Remote(variants = Variant.both) - public static void label(String message, float duration, float worldx, float worldy){ - if(message == null) return; - - ui.showLabel(message, duration, worldx, worldy); - } - - @Remote(variants = Variant.both, unreliable = true) - public static void effect(Effect effect, float x, float y, float rotation, Color color){ - if(effect == null) return; - - effect.at(x, y, rotation, color); - } - - @Remote(variants = Variant.both) - public static void effectReliable(Effect effect, float x, float y, float rotation, Color color){ - effect(effect, x, y, rotation, color); - } - - @Remote(variants = Variant.both) - public static void infoToast(String message, float duration){ - if(message == null) return; - - ui.showInfoToast(message, duration); - } - - @Remote(variants = Variant.both) - public static void warningToast(int unicode, String text){ - if(text == null || Fonts.icon.getData().getGlyph((char)unicode) == null) return; - - ui.hudfrag.showToast(Fonts.getGlyph(Fonts.icon, (char)unicode), text); - } - @Remote(variants = Variant.both) public static void setRules(Rules rules){ state.rules = rules; diff --git a/core/src/mindustry/core/UI.java b/core/src/mindustry/core/UI.java index 44d4008dba..d6aff3d11d 100644 --- a/core/src/mindustry/core/UI.java +++ b/core/src/mindustry/core/UI.java @@ -539,6 +539,38 @@ public class UI implements ApplicationListener, Loadable{ dialog.show(); } + /** Shows a menu that fires a callback when an option is selected. If nothing is selected, -1 is returned. */ + public void showMenu(String title, String message, String[][] options, Intc callback){ + new Dialog(title){{ + cont.row(); + cont.image().width(400f).pad(2).colspan(2).height(4f).color(Pal.accent); + cont.row(); + cont.add(message).width(400f).wrap().get().setAlignment(Align.center); + cont.row(); + + int option = 0; + for(var optionsRow : options){ + Table buttonRow = buttons.row().table().get().row(); + int fullWidth = 400 - (optionsRow.length - 1) * 8; // adjust to count padding as well + int width = fullWidth / optionsRow.length; + int lastWidth = fullWidth - width * (optionsRow.length - 1); // take the rest of space for uneven table + + for(int i = 0; i < optionsRow.length; i++){ + if(optionsRow[i] == null) continue; + + String optionName = optionsRow[i]; + int finalOption = option; + buttonRow.button(optionName, () -> { + callback.get(finalOption); + hide(); + }).size(i == optionsRow.length - 1 ? lastWidth : width, 50).pad(4); + option++; + } + } + closeOnBack(() -> callback.get(-1)); + }}.show(); + } + public static String formatTime(float ticks){ int time = (int)(ticks / 60); if(time < 60) return "0:" + (time < 10 ? "0" : "") + time; diff --git a/core/src/mindustry/entities/comp/BoundedComp.java b/core/src/mindustry/entities/comp/BoundedComp.java index 9976ed31c8..6ecb94052f 100644 --- a/core/src/mindustry/entities/comp/BoundedComp.java +++ b/core/src/mindustry/entities/comp/BoundedComp.java @@ -1,7 +1,6 @@ package mindustry.entities.comp; import arc.math.*; -import arc.math.geom.*; import mindustry.annotations.Annotations.*; import mindustry.gen.*; @@ -12,7 +11,6 @@ abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{ static final float warpDst = 40f; @Import float x, y; - @Import Vec2 vel; @Override public void update(){ diff --git a/core/src/mindustry/game/EventType.java b/core/src/mindustry/game/EventType.java index 61faeaffd0..015eac0c97 100644 --- a/core/src/mindustry/game/EventType.java +++ b/core/src/mindustry/game/EventType.java @@ -134,6 +134,18 @@ public class EventType{ } } + /** Consider using Menus.registerMenu instead. */ + public static class MenuOptionChooseEvent{ + public final Player player; + public final int menuId, option; + + public MenuOptionChooseEvent(Player player, int menuId, int option){ + this.player = player; + this.option = option; + this.menuId = menuId; + } + } + public static class PlayerChatEvent{ public final Player player; public final String message; diff --git a/core/src/mindustry/io/TypeIO.java b/core/src/mindustry/io/TypeIO.java index f070c3446b..5902413a1c 100644 --- a/core/src/mindustry/io/TypeIO.java +++ b/core/src/mindustry/io/TypeIO.java @@ -588,6 +588,30 @@ public class TypeIO{ return new TraceInfo(readString(read), readString(read), read.b() == 1, read.b() == 1, read.i(), read.i()); } + public static void writeStrings(Writes write, String[][] strings){ + write.b(strings.length); + for(String[] string : strings){ + write.b(string.length); + for(String s : string){ + writeString(write, s); + } + } + } + + public static String[][] readStrings(Reads read){ + int rows = read.ub(); + + String[][] strings = new String[rows][]; + for(int i = 0; i < rows; i++){ + int columns = read.ub(); + strings[i] = new String[columns]; + for(int j = 0; j < columns; j++){ + strings[i][j] = readString(read); + } + } + return strings; + } + public static void writeStringData(DataOutput buffer, String string) throws IOException{ if(string != null){ byte[] bytes = string.getBytes(charset); diff --git a/core/src/mindustry/ui/Menus.java b/core/src/mindustry/ui/Menus.java new file mode 100644 index 0000000000..90fe7a5b57 --- /dev/null +++ b/core/src/mindustry/ui/Menus.java @@ -0,0 +1,116 @@ +package mindustry.ui; + +import arc.*; +import arc.graphics.*; +import arc.struct.*; +import arc.util.*; +import mindustry.annotations.Annotations.*; +import mindustry.entities.*; +import mindustry.game.EventType.*; +import mindustry.gen.*; + +import static mindustry.Vars.*; + +/** Class for handling menus and notifications across the network. Unstable API! */ +public class Menus{ + private static IntMap menuListeners = new IntMap<>(); + + /** Register a *global* menu listener. If no option is chosen, the option is returned as -1. */ + public static void registerMenu(int id, MenuListener listener){ + menuListeners.put(id, listener); + } + + //do not invoke any of the below methods directly, use Call + + @Remote(variants = Variant.both) + public static void menu(int menuId, String title, String message, String[][] options){ + if(title == null) title = ""; + if(options == null) options = new String[0][0]; + + ui.showMenu(title, message, options, (option) -> Call.menuChoose(player, menuId, option)); + } + + @Remote(targets = Loc.both, called = Loc.both) + public static void menuChoose(@Nullable Player player, int menuId, int option){ + if(player != null && menuListeners.containsKey(menuId)){ + Events.fire(new MenuOptionChooseEvent(player, menuId, option)); + menuListeners.get(menuId).get(player, option); + } + } + + @Remote(variants = Variant.both, unreliable = true) + public static void setHudText(String message){ + if(message == null) return; + + ui.hudfrag.setHudText(message); + } + + @Remote(variants = Variant.both) + public static void hideHudText(){ + ui.hudfrag.toggleHudText(false); + } + + /** TCP version */ + @Remote(variants = Variant.both) + public static void setHudTextReliable(String message){ + setHudText(message); + } + + @Remote(variants = Variant.both) + public static void announce(String message){ + if(message == null) return; + + ui.announce(message); + } + + @Remote(variants = Variant.both) + public static void infoMessage(String message){ + if(message == null) return; + + ui.showText("", message); + } + + @Remote(variants = Variant.both) + public static void infoPopup(String message, float duration, int align, int top, int left, int bottom, int right){ + if(message == null) return; + + ui.showInfoPopup(message, duration, align, top, left, bottom, right); + } + + @Remote(variants = Variant.both) + public static void label(String message, float duration, float worldx, float worldy){ + if(message == null) return; + + ui.showLabel(message, duration, worldx, worldy); + } + + @Remote(variants = Variant.both, unreliable = true) + public static void effect(Effect effect, float x, float y, float rotation, Color color){ + if(effect == null) return; + + effect.at(x, y, rotation, color); + } + + @Remote(variants = Variant.both) + public static void effectReliable(Effect effect, float x, float y, float rotation, Color color){ + effect(effect, x, y, rotation, color); + } + + @Remote(variants = Variant.both) + public static void infoToast(String message, float duration){ + if(message == null) return; + + ui.showInfoToast(message, duration); + } + + @Remote(variants = Variant.both) + public static void warningToast(int unicode, String text){ + if(text == null || Fonts.icon.getData().getGlyph((char)unicode) == null) return; + + ui.hudfrag.showToast(Fonts.getGlyph(Fonts.icon, (char)unicode), text); + } + + public interface MenuListener{ + void get(Player player, int option); + } +}