From 7d4acc5591732e1d99d0e2afdcfded03c6e2aff2 Mon Sep 17 00:00:00 2001 From: TarLaboratories Date: Fri, 26 Dec 2025 18:17:56 +0300 Subject: [PATCH] pull relevant files from tar/mui-central-monitor --- .../resources/assets/gtceu/lang/en_ud.json | 33 +- .../resources/assets/gtceu/lang/en_us.json | 33 +- .../api/mui/drawable/BorderDrawable.java | 44 ++ .../value/sync/GenericListSyncHandler.java | 9 +- .../textfield/BaseTextFieldWidget.java | 55 ++- .../widgets/textfield/CodeEditorWidget.java | 157 +++++++ .../widgets/textfield/TextEditorWidget.java | 93 +++- .../widgets/textfield/TextFieldHandler.java | 31 +- .../widgets/textfield/TextFieldRenderer.java | 21 +- .../widgets/textfield/TextFieldWidget.java | 10 +- .../api/placeholder/MultiLineComponent.java | 11 + .../gtceu/api/placeholder/Placeholder.java | 8 + .../api/placeholder/PlaceholderHandler.java | 413 ++++++++++++++++-- .../transfer/item/CustomItemStackHandler.java | 6 + .../gtceu/common/data/GTPlaceholders.java | 179 +++++++- .../electric/monitor/MonitorGroup.java | 35 +- .../gtceu/common/mui/GTGuiTextures.java | 8 + .../gtceu/data/lang/LangHandler.java | 67 ++- .../gtceu/utils/GTStringUtils.java | 76 ---- .../network/ByteBufAdapters.java | 29 ++ .../assets/gtceu/font/include/mono_space.json | 11 + .../assets/gtceu/font/include/monocraft.json | 101 +++++ .../assets/gtceu/font/monocraft.json | 16 + .../assets/gtceu/textures/font/LICENSE.txt | 86 ++++ .../assets/gtceu/textures/font/ascii_mono.png | Bin 0 -> 6524 bytes .../textures/font/nonlatin_european_mono.png | Bin 0 -> 15742 bytes 26 files changed, 1378 insertions(+), 154 deletions(-) create mode 100644 src/main/java/com/gregtechceu/gtceu/api/mui/drawable/BorderDrawable.java create mode 100644 src/main/java/com/gregtechceu/gtceu/api/mui/widgets/textfield/CodeEditorWidget.java create mode 100644 src/main/resources/assets/gtceu/font/include/mono_space.json create mode 100644 src/main/resources/assets/gtceu/font/include/monocraft.json create mode 100644 src/main/resources/assets/gtceu/font/monocraft.json create mode 100644 src/main/resources/assets/gtceu/textures/font/LICENSE.txt create mode 100644 src/main/resources/assets/gtceu/textures/font/ascii_mono.png create mode 100644 src/main/resources/assets/gtceu/textures/font/nonlatin_european_mono.png diff --git a/src/generated/resources/assets/gtceu/lang/en_ud.json b/src/generated/resources/assets/gtceu/lang/en_ud.json index 394133cb00c..db95ee9237c 100644 --- a/src/generated/resources/assets/gtceu/lang/en_ud.json +++ b/src/generated/resources/assets/gtceu/lang/en_ud.json @@ -2216,6 +2216,10 @@ "gtceu.canner": "ɹǝuuɐƆ", "gtceu.central_monitor.gui.create_group": "dnoɹb ǝʇɐǝɹƆ", "gtceu.central_monitor.gui.currently_editing": "%s :buıʇıpǝ ʎןʇuǝɹɹnƆ", + "gtceu.central_monitor.gui.data_slot": "ʞɔıʇs ɐʇɐp ɟo ɹǝqɯnu ʇoןs ʇǝS", + "gtceu.central_monitor.gui.group_editor": "dnoɹb ɹoʇıuoɯ buıʇıpƎ", + "gtceu.central_monitor.gui.group_name": ":ǝɯɐN", + "gtceu.central_monitor.gui.monitor_groups": "sdnoɹb ɹoʇıuoW", "gtceu.central_monitor.gui.remove_from_group": "dnoɹb ɯoɹɟ ǝʌoɯǝᴚ", "gtceu.central_monitor.gui.set_target": "ʇǝbɹɐʇ ʇǝS", "gtceu.central_monitor.info_tooltip.0": "˙ʇı uı ǝןnpoɯ Ɩ ǝʌɐɥ ʎןuo ʎɐɯ dnoɹb Ɐ ˙ʇsɹıɟ sdnoɹb oʇuı ɯǝɥʇ ʇıןds oʇ ǝʌɐɥ noʎ 'sɹoʇıuoɯ ǝsn oʇ ɹǝpɹo uI", @@ -2351,10 +2355,24 @@ "gtceu.gui.adv_stocking_config.title": "buıʞɔoʇS ɔıʇɐɯoʇnⱯ ǝɹnbıɟuoƆ", "gtceu.gui.all_voiding": "ןןⱯɔ§ buıpıoΛㄥ§", "gtceu.gui.auto_output.name": "oʇnɐ", + "gtceu.gui.central_monitor.data_hatch_target": "˙pɐǝʇsuı ʇǝbɹɐʇ ǝɥʇ pǝɹǝpısuoɔ ǝq ןןıʍ )ɹǝʌoɔ ɹǝʇʇıɯsuɐɹʇ ssǝןǝɹıʍ ɐ buıʞɔıןɔ-ʇɥbıɹ ɐıʌ( oʇ pǝʞuıן sı ʇoןs pǝıɟıɔǝds ǝɥʇ uı ʞɔıʇs ɐʇɐp ǝɥʇ ʇɐɥʇ ʞɔoןq ǝɥʇ uǝɥ⟘ ˙ɹǝqɯnu ʇoןs ɐ ɹǝʇuǝ oʇ pǝʇdɯoɹd ǝq ןןıʍ noʎ 'ʇǝbɹɐʇ ɐ sɐ ɥɔʇɐɥ ɐʇɐp ɐ ʇɔǝןǝs noʎ ɟI", "gtceu.gui.central_monitor.group": "%s :dnoɹ⅁", "gtceu.gui.central_monitor.group_default_name": "%d# dnoɹ⅁", - "gtceu.gui.central_monitor.none": "ǝuou", + "gtceu.gui.central_monitor.gui_module_info": "˙ɹoʇıpǝ dnoɹb ɹoʇıuoɯ ǝɥʇ uı ʇǝbɹɐʇ ɐ ʇɔǝןǝs 'ɯoɹɟ I∩⅁ ǝɥʇ ʇǝb oʇ ʞɔoןq ɐ ʇɔǝןǝs o⟘", + "gtceu.gui.central_monitor.help": ":suoıʇɔǝןǝs ɟo sǝdʎʇ ǝɹɐ ǝɹǝɥ 'xoqʇxǝʇ ǝɯɐu dnoɹb ǝɥʇ ʍoןǝq pıɹb ǝɥʇ uı ɹoʇıuoɯ Ɩ ʇsɐǝן ʇɐ ʇɔǝןǝs oʇ ǝʌɐɥ noʎ uǝɥ⟘\n)ʎɐןdsıp oʇ ʇxǝʇ ǝɥʇ ɹǝʇuǝ ʇsnظ ǝןdɯɐxǝ ɹoɟ( ǝןnpoɯ ǝɥʇ ǝɹnbıɟuoɔ oʇ ɹɐǝddɐ ןןıʍ uoʇʇnq ɐ 'ʇı ʇɹǝsuı noʎ uǝɥM\n˙xoqʇxǝʇ ǝɯɐu dnoɹb ǝɥʇ ɟo ʇɥbıɹ ǝɥʇ oʇ ʇoןs ǝɥʇ uı pǝʇɹǝsuı ǝq ʇsnɯ ǝןnpoɯ Ɐ\nǝןnpoɯ ɹoʇıuoɯ pǝɹnbıɟuoɔ puɐ pǝʇɹǝsuı uɐ - \nuo buıɥʇǝɯos ʎɐןdsıp oʇ ʇuɐʍ noʎ ʇɐɥʇ sɹoʇıuoɯ ǝɥʇ ʇɔǝןǝs oʇ noʎ - \n:sbuıɥʇ ᄅ spǝǝu ʇı 'buıɥʇʎuɐ ʎɐןdsıp oʇ dnoɹb ɐ ɹoℲ\n˙ʞɔoןqıʇןnɯ ǝɥʇ uı sɹoʇıuoɯ ɟo ʇunoɯɐ ʎuɐ ɟo uoıʇɔǝןןoɔ ɐ sı dnoɹb ɹoʇıuoɯ Ɐ", + "gtceu.gui.central_monitor.in_group": "ɟɟnʇs ʎɐןdsıp oʇ pǝsn ǝq ןןıʍ puɐ 'dnoɹb ǝɥʇ oʇ pǝppɐ ǝɹɐ ʎɐʍ sıɥʇ pǝʇɔǝןǝs sɹoʇıuoW", + "gtceu.gui.central_monitor.in_group_and_target": "˙ǝɯıʇ ǝɯɐs ǝɥʇ ʇɐ ʇǝbɹɐʇ ɐ sɐ puɐ buıʎɐןdsıp ɹoɟ pǝsn sı ʎɐʍ sıɥʇ pǝʇɔǝןǝs ɹoʇıuoɯ ǝɥ⟘", + "gtceu.gui.central_monitor.left_click": "ʇı buıʞɔıןɔ-ʇɟǝן ʎq ɹoʇıuoɯ ɐ ʇɔǝןǝsun/ʇɔǝןǝS", + "gtceu.gui.central_monitor.module_editor_button": "ǝןnpoɯ ʇıpƎ", + "gtceu.gui.central_monitor.module_editor_disabled": "ʇı ʇıpǝ oʇ I∩⅁ sıɥʇ uǝdo-ǝɹ ǝsɐǝןd 'ǝןnpoɯ ǝɥʇ pǝbuɐɥɔ ʎןʇuǝɔǝɹ noʎ", + "gtceu.gui.central_monitor.pause": "˙unɹ ǝq ʇ,uoʍ ǝpoɔ puɐ 'pǝʇɐpdn ǝq ʇ,uoʍ ʇxǝ⟘\n˙uoıʇnɔǝxǝ ɹǝpןoɥǝɔɐןd ǝsnɐԀ", + "gtceu.gui.central_monitor.resume": "˙uoıʇnɔǝxǝ ɹǝpןoɥǝɔɐןd ǝsnɐdu∩", + "gtceu.gui.central_monitor.right_click": "˙ʇǝbɹɐʇ ɐ ǝq uɐɔ ʞɔoןq Ɩ ʎןuO ˙ʇı buıʞɔıןɔ-ʇɥbıɹ ʎq ʞɔoןq ɐ ʇɔǝןǝS", + "gtceu.gui.central_monitor.target": "˙ǝןnpoɯ ʇxǝʇ ɐ uı sɹǝpןoɥǝɔɐןd ɥʇıʍ pǝsn ǝq oʇ 'ʇǝbɹɐʇ ɐ pǝɹǝpısuoɔ sı ʎɐʍ sıɥʇ pǝʇɔǝןǝs ʞɔoןq ǝɥ⟘", + "gtceu.gui.central_monitor.text_module_help": "\n:%0ϛ< sı ʎbɹǝuǝ uǝɥʍ ןɐubıs ǝuoʇspǝɹ ɐ spuǝs puɐ oɟuı ʎbɹǝuǝ ǝɯos sʎɐןdsıp ʇɐɥʇ 'sɹǝpןoɥǝɔɐןd ɟo ǝbɐsn ǝןdɯɐxǝ uɐ s,ǝɹǝH\n˙oɟuı ǝɹoɯ ɹoɟ ǝɹǝɥʇ ǝbɐd dןǝɥ ǝɥʇ ʇno ʞɔǝɥɔ 'ʍopuıʍ buıʇıpǝ dnoɹb ɹoʇıuoɯ ǝɥʇ uı ʇǝbɹɐʇ ɐ ʇɔǝןǝS\n˙SSԀ ɐ ɹo ɹǝɟɟnq ʎɹǝʇʇɐq ɐ ʎןןɐnsn 'ʞɔoןq ʇǝbɹɐʇ sʇı uı ʎbɹǝuǝ ɟo ʇunoɯɐ ǝɥʇ sʎɐןdsıp }ʎbɹǝuǝ{ ǝןdɯɐxǝ ɹoℲ ˙ʞɔoןqıʇןnɯ ɹoʇıuoɯ ןɐɹʇuǝɔ\nǝɥʇ ɟo ʇɹɐd sı ɹo sɹǝʌoɔ ʇdǝɔɔɐ uɐɔ ʇɐɥʇ ʞɔoןq ʎuɐ ʎןןɐɔısɐq sı ʇǝbɹɐʇ Ɐ ˙uoıʇɔunɟ oʇ ʇǝbɹɐʇ ɐ ǝʌɐɥ ʇsnɯ }ʎbɹǝuǝ{ ǝʞıן 'sɹǝpןoɥǝɔɐןd ǝɯoS\n˙ɔʇǝ 'suoıʇɐןnɔןɐɔ unɹ 'ʇnduı ǝuoʇspǝɹ pɐǝɹ/ʇndʇno ǝuoʇspǝɹ ɐ ʇǝs sɐ ɥɔns 'sbuıɥʇ ɹǝɥʇo ǝɯos op osןɐ uɐɔ ʎǝɥ⟘\n˙)ʎbɹǝuǝ ɟo ʇunoɯɐ ǝɥʇ ǝsɐɔ sıɥʇ uı( pɐǝʇsuı ǝnןɐʌ ɹıǝɥʇ ʎɐןdsıp ןןıʍ 'pǝʎɐןdsıp uǝɥʍ ʇɐɥʇ \"}ʎbɹǝuǝ{\" ǝʞıן sbuıɹʇs ǝɹɐ sɹǝpןoɥǝɔɐןԀ\n˙sɹǝpןoɥǝɔɐןd ǝʌɐɥ uɐɔ ʇɐɥʇ ʇxǝʇ sʎɐןdsıp ǝןnpoɯ sıɥ⟘", "gtceu.gui.central_monitor.text_scale": "ǝןɐɔs ʇxǝ⟘", + "gtceu.gui.central_monitor.update_once": "˙ǝɔuo ʎןʇɔɐxǝ ʇı uı sɹǝpןoɥǝɔɐןd ןןɐ unɹ puɐ ʇxǝʇ ǝʇɐpd∩", + "gtceu.gui.central_monitor.url": ":Ꞁᴚ∩ ǝbɐɯı ʇnduI", "gtceu.gui.charger_slot.tooltip.0": "ɹ§ʇoןS ɹǝbɹɐɥƆɟ§", "gtceu.gui.charger_slot.tooltip.1": "ɹ§sǝıɹǝʇʇɐq %s ɯoɹɟ ɹǝʍod sʍɐɹᗡㄥ§", "gtceu.gui.charger_slot.tooltip.2": "sǝıɹǝʇʇɐq puɐ sןooʇ %s sǝbɹɐɥƆㄥ§", @@ -2372,8 +2390,7 @@ "gtceu.gui.computer_monitor_cover.placeholder_reference.1": ")oɟuı ǝɹoɯ ɹoɟ ɹǝʌoɥ(", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.0": "˙ǝɹǝɥ ,}{, %s ɟo ǝɔɐןd uı pǝsn ǝq oʇ ɹǝpןoɥǝɔɐןd ʇnduI", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.1": "˙sǝxoq ʇxǝʇ ǝsǝɥʇ uı ,ʎʇıɔɐdɐƆʎbɹǝuǝ, puɐ ,ʎbɹǝuǝ, puɐ ,∩Ǝ }{/}{ :ʎbɹǝuƎ, buıɹʇs ɐ ǝʌɐɥ uɐɔ noʎ 'ǝןdɯɐxǝ ɹoℲ", - "gtceu.gui.computer_monitor_cover.slot_tooltip.0": "ǝɔuǝɹǝɟǝɹ uɐɔ sɹǝpןoɥǝɔɐןd ǝɯos ʇɐɥʇ sɯǝʇı ɹoɟ ʇoןs Ɐ", - "gtceu.gui.computer_monitor_cover.slot_tooltip.1": "%d :ɹǝqɯnu ʇoןS", + "gtceu.gui.computer_monitor_cover.slot_tooltip": "\n%d :ɹǝqɯnu ʇoןS\nǝɔuǝɹǝɟǝɹ uɐɔ sɹǝpןoɥǝɔɐןd ǝɯos ʇɐɥʇ sɯǝʇı ɹoɟ ʇoןs Ɐ", "gtceu.gui.computer_monitor_cover.update_interval": ")sʞɔıʇ uı( ןɐʌɹǝʇuı ǝʇɐpd∩", "gtceu.gui.config_slot": "ɹ§ʇoןS bıɟuoƆɟ§", "gtceu.gui.config_slot.auto_pull_managed": "ןןnԀ-oʇnⱯ ʎq pǝbɐuɐW ㄥ§:pǝןqɐsıᗡㄣ§", @@ -2499,6 +2516,7 @@ "gtceu.io.export": "ʇɹodxƎ", "gtceu.io.import": "ʇɹodɯI", "gtceu.io.none": "ǝuoN", + "gtceu.item.tooltip.image_url": "%s :Ꞁᴚ∩ ǝbɐɯI", "gtceu.item_filter.empty_item": ")ɯǝʇI oN( ʎʇdɯƎ", "gtceu.item_filter.footer": "ǝpıɹɹǝʌo oʇ ɯǝʇı ɥʇıʍ ʞɔıןƆǝ§", "gtceu.item_list.item_stored": "%d :pǝɹoʇSㄥ§", @@ -3515,6 +3533,14 @@ "gtceu.packer": "ɹǝʞɔɐԀ", "gtceu.part_sharing.disabled": "pǝןqɐsıᗡㄣ§ buıɹɐɥS ʞɔoןqıʇןnW", "gtceu.part_sharing.enabled": "pǝןqɐuƎɐ§ buıɹɐɥS ʞɔoןqıʇןnW", + "gtceu.placeholder_editor.constant_value": "˙ʇuɐʇsuoɔ ɐ ɥʇıʍ ʇı buıɔɐןdǝɹ ɹǝpısuoƆ\n˙ʇןnsǝɹ ǝɯɐs ǝɥʇ oʇ sǝʇɐnןɐʌǝ sʎɐʍןɐ uoıssǝɹdxǝ sıɥ⟘", + "gtceu.placeholder_editor.extra_closing_bracket": "ʇǝʞɔɐɹq buısoןɔ ɐɹʇxƎ", + "gtceu.placeholder_editor.no_placeholder": "ʇsıxǝ ʇou sǝop ,%s, ǝɯɐu ɥʇıʍ ɹǝpןoɥǝɔɐןԀ", + "gtceu.placeholder_editor.unclosed_bracket": ")\"}\"( ʇǝʞɔɐɹq pǝsoןɔu∩", + "gtceu.placeholder_editor.unclosed_brackets": "pǝsoןɔun ǝɹɐ )\"}\"( sʇǝʞɔɐɹq %d", + "gtceu.placeholder_editor.unclosed_escape": ")\"],\"( ǝdɐɔsǝ pǝsoןɔu∩", + "gtceu.placeholder_editor.unclosed_escapes": "pǝsoןɔun ǝɹɐ )\"],\"( sǝdɐɔsǝ %d", + "gtceu.placeholder_editor.write_in_if": "˙\"}}\">ǝpoɔ‾ǝsןǝ<\" \">ǝpoɔ<\" >uoıʇıpuoɔ< ɟı{ ןɐʌǝ{\" ǝsn 'sıɥʇ pıoʌɐ o⟘\n˙ʇndʇno ǝuoʇspǝɹ ǝɔnpoɹd ןןıʍ \"}}ϛƖ ʇǝs ǝuoʇspǝɹ{ 0 ɟı{\" 'ǝןdɯɐxǝ ɹoɟ 'ʇɐɥʇ suɐǝɯ sıɥ⟘\n˙uoıʇıpuoɔ ǝɥʇ ɟo ssǝןpɹɐbǝɹ pǝʇnɔǝxǝ ǝɹɐ }ɟı{ ǝpısuı sɹǝpןoɥǝɔɐןԀ", "gtceu.placeholder_info.active.0": "˙ǝsıʍɹǝɥʇo 0 'ǝdıɔǝɹ ɐ buıuunɹ ʎןʇuǝɹɹnɔ sı oʇ pǝɥɔɐʇʇɐ sı ɹǝʌoɔ ǝɥʇ ʞɔoןq ǝɥʇ ɟı Ɩ ɐ suɹnʇǝᴚ", "gtceu.placeholder_info.active.1": ":ǝbɐs∩", "gtceu.placeholder_info.active.2": "ǝdıɔǝɹ buıuunɹ ʎןʇuǝɹɹnɔ ɐ s,ǝɹǝɥʇ ɹǝɥʇǝɥʍ >- }ǝʌıʇɔɐ{ ", @@ -4237,6 +4263,7 @@ "item.gtceu.gray_glass_lens": ")ʎɐɹ⅁( suǝꞀ ssɐן⅁", "item.gtceu.green_dye_spray_can": ")uǝǝɹ⅁( uɐƆ ʎɐɹdS", "item.gtceu.green_glass_lens": ")uǝǝɹ⅁( suǝꞀ ssɐן⅁", + "item.gtceu.gui_module": "ǝןnpoW ın⅁", "item.gtceu.hammer_extruder_mold.tooltip": "sɹǝɯɯɐH buıʞɐɯ ɹoɟ ǝdɐɥS ɹǝpnɹʇxƎㄥ§", "item.gtceu.hazmat_boots": "sʇooᗺ ʇınS sןɐıɹǝʇɐW snopɹɐzɐH", "item.gtceu.hazmat_chestpiece": "ǝɔǝıdʇsǝɥƆ ʇınS sןɐıɹǝʇɐW snopɹɐzɐH", diff --git a/src/generated/resources/assets/gtceu/lang/en_us.json b/src/generated/resources/assets/gtceu/lang/en_us.json index 009854ac171..fbff592cd99 100644 --- a/src/generated/resources/assets/gtceu/lang/en_us.json +++ b/src/generated/resources/assets/gtceu/lang/en_us.json @@ -2216,6 +2216,10 @@ "gtceu.canner": "Canner", "gtceu.central_monitor.gui.create_group": "Create group", "gtceu.central_monitor.gui.currently_editing": "Currently editing: %s", + "gtceu.central_monitor.gui.data_slot": "Set slot number of data stick", + "gtceu.central_monitor.gui.group_editor": "Editing monitor group", + "gtceu.central_monitor.gui.group_name": "Name:", + "gtceu.central_monitor.gui.monitor_groups": "Monitor groups", "gtceu.central_monitor.gui.remove_from_group": "Remove from group", "gtceu.central_monitor.gui.set_target": "Set target", "gtceu.central_monitor.info_tooltip.0": "In order to use monitors, you have to split them into groups first. A group may only have 1 module in it.", @@ -2351,10 +2355,24 @@ "gtceu.gui.adv_stocking_config.title": "Configure Automatic Stocking", "gtceu.gui.all_voiding": "§7Voiding §cAll", "gtceu.gui.auto_output.name": "auto", + "gtceu.gui.central_monitor.data_hatch_target": "If you select a data hatch as a target, you will be prompted to enter a slot number. Then the block that the data stick in the specified slot is linked to (via right-clicking a wireless transmitter cover) will be considered the target instead.", "gtceu.gui.central_monitor.group": "Group: %s", "gtceu.gui.central_monitor.group_default_name": "Group #%d", - "gtceu.gui.central_monitor.none": "none", + "gtceu.gui.central_monitor.gui_module_info": "To select a block to get the GUI from, select a target in the monitor group editor.", + "gtceu.gui.central_monitor.help": "A monitor group is a collection of any amount of monitors in the multiblock.\nFor a group to display anything, it needs 2 things:\n - you to select the monitors that you want to display something on\n - an inserted and configured monitor module\nA module must be inserted in the slot to the right of the group name textbox.\nWhen you insert it, a button will appear to configure the module (for example just enter the text to display)\nThen you have to select at least 1 monitor in the grid below the group name textbox, here are types of selections:", + "gtceu.gui.central_monitor.in_group": "Monitors selected this way are added to the group, and will be used to display stuff", + "gtceu.gui.central_monitor.in_group_and_target": "The monitor selected this way is used for displaying and as a target at the same time.", + "gtceu.gui.central_monitor.left_click": "Select/unselect a monitor by left-clicking it", + "gtceu.gui.central_monitor.module_editor_button": "Edit module", + "gtceu.gui.central_monitor.module_editor_disabled": "You recently changed the module, please re-open this GUI to edit it", + "gtceu.gui.central_monitor.pause": "Pause placeholder execution.\nText won't be updated, and code won't be run.", + "gtceu.gui.central_monitor.resume": "Unpause placeholder execution.", + "gtceu.gui.central_monitor.right_click": "Select a block by right-clicking it. Only 1 block can be a target.", + "gtceu.gui.central_monitor.target": "The block selected this way is considered a target, to be used with placeholders in a text module.", + "gtceu.gui.central_monitor.text_module_help": "This module displays text that can have placeholders.\nPlaceholders are strings like \"{energy}\" that when displayed, will display their value instead (in this case the amount of energy).\nThey can also do some other things, such as set a redstone output/read redstone input, run calculations, etc.\nSome placeholders, like {energy} must have a target to function. A target is basically any block that can accept covers or is part of the\ncentral monitor multiblock. For example {energy} displays the amount of energy in its target block, usually a battery buffer or a PSS.\nSelect a target in the monitor group editing window, check out the help page there for more info.\nHere's an example usage of placeholders, that displays some energy info and sends a redstone signal when energy is <50%:\n", "gtceu.gui.central_monitor.text_scale": "Text scale", + "gtceu.gui.central_monitor.update_once": "Update text and run all placeholders in it exactly once.", + "gtceu.gui.central_monitor.url": "Input image URL:", "gtceu.gui.charger_slot.tooltip.0": "§fCharger Slot§r", "gtceu.gui.charger_slot.tooltip.1": "§7Draws power from %s batteries§r", "gtceu.gui.charger_slot.tooltip.2": "§7Charges %s tools and batteries", @@ -2372,8 +2390,7 @@ "gtceu.gui.computer_monitor_cover.placeholder_reference.1": "(hover for more info)", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.0": "Input placeholder to be used in place of %s '{}' here.", "gtceu.gui.computer_monitor_cover.second_page_textbox_tooltip.1": "For example, you can have a string 'Energy: {}/{} EU' and 'energy' and 'energyCapacity' in these text boxes.", - "gtceu.gui.computer_monitor_cover.slot_tooltip.0": "A slot for items that some placeholders can reference", - "gtceu.gui.computer_monitor_cover.slot_tooltip.1": "Slot number: %d", + "gtceu.gui.computer_monitor_cover.slot_tooltip": "A slot for items that some placeholders can reference\nSlot number: %d\n", "gtceu.gui.computer_monitor_cover.update_interval": "Update interval (in ticks)", "gtceu.gui.config_slot": "§fConfig Slot§r", "gtceu.gui.config_slot.auto_pull_managed": "§4Disabled:§7 Managed by Auto-Pull", @@ -2499,6 +2516,7 @@ "gtceu.io.export": "Export", "gtceu.io.import": "Import", "gtceu.io.none": "None", + "gtceu.item.tooltip.image_url": "Image URL: %s", "gtceu.item_filter.empty_item": "Empty (No Item)", "gtceu.item_filter.footer": "§eClick with item to override", "gtceu.item_list.item_stored": "§7Stored: %d", @@ -3515,6 +3533,14 @@ "gtceu.packer": "Packer", "gtceu.part_sharing.disabled": "Multiblock Sharing §4Disabled", "gtceu.part_sharing.enabled": "Multiblock Sharing §aEnabled", + "gtceu.placeholder_editor.constant_value": "This expression always evaluates to the same result.\nConsider replacing it with a constant.", + "gtceu.placeholder_editor.extra_closing_bracket": "Extra closing bracket", + "gtceu.placeholder_editor.no_placeholder": "Placeholder with name '%s' does not exist", + "gtceu.placeholder_editor.unclosed_bracket": "Unclosed bracket (\"}\")", + "gtceu.placeholder_editor.unclosed_brackets": "%d brackets (\"}\") are unclosed", + "gtceu.placeholder_editor.unclosed_escape": "Unclosed escape (\"']\")", + "gtceu.placeholder_editor.unclosed_escapes": "%d escapes (\"']\") are unclosed", + "gtceu.placeholder_editor.write_in_if": "Placeholders inside {if} are executed regardless of the condition.\nThis means that, for example, \"{if 0 {redstone set 15}}\" will produce redstone output.\nTo avoid this, use \"{eval {if \"\" \"\"}}\".", "gtceu.placeholder_info.active.0": "Returns a 1 if the block the cover is attached to is currently running a recipe, 0 otherwise.", "gtceu.placeholder_info.active.1": "Usage:", "gtceu.placeholder_info.active.2": " {active} -> whether there's a currently running recipe", @@ -4237,6 +4263,7 @@ "item.gtceu.gray_glass_lens": "Glass Lens (Gray)", "item.gtceu.green_dye_spray_can": "Spray Can (Green)", "item.gtceu.green_glass_lens": "Glass Lens (Green)", + "item.gtceu.gui_module": "Gui Module", "item.gtceu.hammer_extruder_mold.tooltip": "§7Extruder Shape for making Hammers", "item.gtceu.hazmat_boots": "Hazardous Materials Suit Boots", "item.gtceu.hazmat_chestpiece": "Hazardous Materials Suit Chestpiece", diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/drawable/BorderDrawable.java b/src/main/java/com/gregtechceu/gtceu/api/mui/drawable/BorderDrawable.java new file mode 100644 index 00000000000..0dbaf0cd222 --- /dev/null +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/drawable/BorderDrawable.java @@ -0,0 +1,44 @@ +package com.gregtechceu.gtceu.api.mui.drawable; + +import com.gregtechceu.gtceu.api.mui.base.drawable.IDrawable; +import com.gregtechceu.gtceu.api.mui.theme.WidgetTheme; +import com.gregtechceu.gtceu.client.mui.screen.viewport.GuiContext; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +import java.util.function.IntSupplier; + +@Accessors(fluent = true) +public class BorderDrawable implements IDrawable { + + @Getter + @Setter + private IntSupplier color = () -> 0xFFFFFFFF; + @Getter + @Setter + private int borderWidth = 2; + + public BorderDrawable() {} + + public BorderDrawable(int color, int borderWidth) { + this.color = () -> color; + this.borderWidth = borderWidth; + } + + public BorderDrawable(IntSupplier color, int borderWidth) { + this.color = color; + this.borderWidth = borderWidth; + } + + @Override + public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { + context.getGraphics().fill(x - borderWidth, y - borderWidth, x + borderWidth + width, y, color.getAsInt()); + context.getGraphics().fill(x - borderWidth, y - borderWidth, x, y + borderWidth + height, color.getAsInt()); + context.getGraphics().fill(x + width, y - borderWidth, x + width + borderWidth, y + height + borderWidth, + color.getAsInt()); + context.getGraphics().fill(x - borderWidth, y + height, x + borderWidth + width, y + height + borderWidth, + color.getAsInt()); + } +} diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java index a6a95772a8f..2150db63f20 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/value/sync/GenericListSyncHandler.java @@ -2,6 +2,7 @@ import com.gregtechceu.gtceu.utils.EqualityTest; import com.gregtechceu.gtceu.utils.ICopy; +import com.gregtechceu.gtceu.utils.serialization.network.IByteBufAdapter; import com.gregtechceu.gtceu.utils.serialization.network.IByteBufDeserializer; import com.gregtechceu.gtceu.utils.serialization.network.IByteBufSerializer; @@ -30,6 +31,11 @@ public GenericListSyncHandler(@NotNull Supplier> getter, @Nullable Consu super(getter, setter, deserializer, serializer, equals, copy); } + public GenericListSyncHandler(@NotNull Supplier> getter, @Nullable Consumer> setter, + IByteBufAdapter adapter) { + this(getter, setter, adapter, adapter, adapter, null); + } + @Override protected void setCache(List value) { this.cache.clear(); @@ -55,7 +61,8 @@ public List getValue() { @Override public void read(FriendlyByteBuf buffer) { this.cache.clear(); - for (int i = 0; i < buffer.readVarInt(); i++) { + int size = buffer.readVarInt(); + for (int i = 0; i < size; i++) { this.cache.add(deserializeValue(buffer)); } onSetCache(getValue(), true, false); diff --git a/src/main/java/com/gregtechceu/gtceu/api/mui/widgets/textfield/BaseTextFieldWidget.java b/src/main/java/com/gregtechceu/gtceu/api/mui/widgets/textfield/BaseTextFieldWidget.java index 8d32977310b..d941d1431fe 100644 --- a/src/main/java/com/gregtechceu/gtceu/api/mui/widgets/textfield/BaseTextFieldWidget.java +++ b/src/main/java/com/gregtechceu/gtceu/api/mui/widgets/textfield/BaseTextFieldWidget.java @@ -3,14 +3,19 @@ import com.gregtechceu.gtceu.api.mui.base.ITheme; import com.gregtechceu.gtceu.api.mui.base.widget.IFocusedWidget; import com.gregtechceu.gtceu.api.mui.base.widget.IWidget; +import com.gregtechceu.gtceu.api.mui.drawable.ItemDrawable; +import com.gregtechceu.gtceu.api.mui.drawable.text.FontRenderHelper; import com.gregtechceu.gtceu.api.mui.theme.TextFieldTheme; import com.gregtechceu.gtceu.api.mui.theme.WidgetTheme; import com.gregtechceu.gtceu.api.mui.theme.WidgetThemeEntry; import com.gregtechceu.gtceu.api.mui.utils.Alignment; +import com.gregtechceu.gtceu.api.mui.utils.Point; import com.gregtechceu.gtceu.api.mui.widget.AbstractScrollWidget; import com.gregtechceu.gtceu.api.mui.widget.scroll.HorizontalScrollData; import com.gregtechceu.gtceu.api.mui.widget.scroll.ScrollData; +import com.gregtechceu.gtceu.api.mui.widget.scroll.VerticalScrollData; import com.gregtechceu.gtceu.api.mui.widgets.VoidWidget; +import com.gregtechceu.gtceu.client.mui.screen.RichTooltip; import com.gregtechceu.gtceu.client.mui.screen.viewport.ModularGuiContext; import com.gregtechceu.gtceu.config.ConfigHolder; @@ -18,16 +23,20 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.HoverEvent; +import net.minecraft.network.chat.Style; import com.mojang.blaze3d.platform.InputConstants; import lombok.Getter; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Optional; import java.util.regex.Pattern; /** @@ -69,7 +78,7 @@ public class BaseTextFieldWidget> extends Abstr protected Integer hintTextColor; public BaseTextFieldWidget() { - super(new HorizontalScrollData(false, 4), null); + super(new HorizontalScrollData(false, 4), new VerticalScrollData()); this.handler.setRenderer(this.renderer); this.handler.setScrollArea(getScrollArea()); padding(4, 0); @@ -213,7 +222,8 @@ public void onRemoveFocus(ModularGuiContext context) { } this.lastClickTime = 0; } - this.handler.setCursor(this.renderer.getCursorPos(this.handler.getText(), x, y), true); + this.handler.setCursor( + this.renderer.getCursorPos(this.handler.getTextAsComponents(), this.handler.getText(), x, y), true); this.lastClickTime = Util.getMillis(); } return Result.SUCCESS; @@ -225,7 +235,8 @@ public void onMouseDrag(double mouseX, double mouseY, int button, double dragX, if (isFocused() && !getScrollArea().isDragging()) { int x = getContext().getMouseX() + getScrollX(); int y = getContext().getMouseY() + getScrollY(); - this.handler.setMainCursor(this.renderer.getCursorPos(this.handler.getText(), x, y), true); + this.handler.setMainCursor( + this.renderer.getCursorPos(this.handler.getTextAsComponents(), this.handler.getText(), x, y), true); } } @@ -322,6 +333,40 @@ public void onMouseDrag(double mouseX, double mouseY, int button, double dragX, return Result.STOP; } + @Override + public @Nullable RichTooltip getTooltip() { + try { + int x = getContext().getMouseX() + getScrollX(); + int y = getContext().getMouseY() + getScrollY(); + List text = handler.getTextAsComponents(); + Point p = renderer.getCursorPos(text, text.stream().map(Component::getString).toList(), x, y); + Component component = text.get(p.y); + if (p.x > FontRenderHelper.length(component.getVisualOrderText())) return super.getTooltip(); + List curX = new ArrayList<>(); + curX.add(0); + Optional