diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index cb194c37cc..c73764184b 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -41,6 +41,12 @@ be.ignore = Ignore be.noupdates = No updates found. be.check = Check for updates +mod.featured.title = Mod browser +mod.featured.dialog.title = Mod Browser +mods.browser.selected = Selected mod +mods.browser.add = Install Mod +mods.github.open = Open in Github + schematic = Schematic schematic.add = Save Schematic... schematics = Schematics diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 13cab33d75..f925d0bc0a 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -40,6 +40,12 @@ be.ignore = Ignorieren be.noupdates = Keine Aktualisierungen gefunden. be.check = Auf Aktualisierungen prüfen +mod.featured.title = Mod Browser +mod.featured.dialog.title = Mod Browser +mods.browser.selected = Ausgewählter Mod +mods.browser.add = Mod installieren +mods.github.open = Auf GitHub ansehen + schematic = Entwurf schematic.add = Entwurf speichern... schematics = Entwürfe diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 6e68a8f3b9..63fd6d8055 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -41,6 +41,12 @@ be.ignore = Ignorar be.noupdates = No se encontraron actualizaciones. be.check = Buscar actualizaciones +mod.featured.title = Explorador de mods +mod.featured.dialog.title = Explorador de Mods +mods.browser.selected = Mod seleccionado +mods.browser.add = Installar Mod +mods.github.open = Abrir en Github + schematic = Plantilla schematic.add = Guardar plantilla... schematics = Plantillas diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index 307a8f586b..79de4a4865 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -38,6 +38,12 @@ be.ignore = Ignorer be.noupdates = Aucune mise à jour trouvée. be.check = Vérifiez les mises à jour +mod.featured.title = Explorateur de mods +mod.featured.dialog.title = Explorateur de Mods +mods.browser.selected = Mod sélectionné +mods.browser.add = Installer le mod +mods.github.open = Ouvrir au Github + schematic = Schéma schematic.add = Sauvegarder le schéma... schematics = Schémas diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index 48c2a8c5fd..af5bdab68d 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -41,6 +41,12 @@ be.ignore = Abaikan be.noupdates = Tidak ada pembaruan yang ditemukan. be.check = Cek versi baru +mod.featured.title = Browser mod +mod.featured.dialog.title = Browser Mod +mods.browser.selected = Mod yang Dipilih +mods.browser.add = Unduh Mod +mods.github.open = Buka di GitHub + schematic = Skema schematic.add = Menyimpan skema... schematics = Kumpulan skema diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 89c1a49aab..762e8a3cd8 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -41,6 +41,12 @@ be.ignore = 무시 be.noupdates = 업데이트가 없습니다. be.check = 업데이트 확인 +mod.featured.title = 모드 탐색기 +mod.featured.dialog.title = 모드 탐색 +mods.browser.selected = 선택된 모드 +mods.browser.add = 모드 설치 +mods.github.open = 깃허브 사이트 열기 + schematic = 설계도 schematic.add = 설계도 저장하기 schematics = 설계도들 diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 251c887c84..aa26f651db 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -41,6 +41,12 @@ be.ignore = Zignoruj be.noupdates = Nie znaleziono aktualizacji. be.check = Sprawdź aktualizacje +mod.featured.title = Wyszukiwarka Modów +mod.featured.dialog.title = Wyszukiwarka Modów +mods.browser.selected = Wybrany Mod +mods.browser.add = Zainstaluj Moda +mods.github.open = Otwórz w GitHub'ie + schematic = Schemat schematic.add = Zapisz schemat... schematics = Schematy @@ -104,6 +110,7 @@ committingchanges = Zatwierdzanie Zmian done = Gotowe feature.unsupported = Twoje urządzenie nie wspiera tej funkcji. + mods.alphainfo = Pamiętaj, że mody są wersji alpha, i[scarlet] mogą być pełne błędów[].\nZgłaszaj wszystkie znalezione problemy na Mindustry GitHub lub Discord. mods = Mody mods.none = [lightgray]Nie znaleziono modów! diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index 4f7c12999c..e7646b68db 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -40,6 +40,12 @@ be.ignore = Игнорировать be.noupdates = Обновления не найдены. be.check = Проверить обновления +mod.featured.title = Обозреватель модов +mod.featured.dialog.title = Обозреватель модов +mods.browser.selected = Выбранный мод +mods.browser.add = Установить мод +mods.github.open = Открыть GitHub страницу + schematic = Схема schematic.add = Сохранить схему… schematics = Схемы diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 5087985f0c..bfe05a9828 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -38,6 +38,12 @@ be.ignore = Hayır be.noupdates = Yeni güncelleme bulunamadı. be.check = Güncellemeleri kontrol et +mod.featured.title = Mod Tarayıcısı +mod.featured.dialog.title = Mod Tarayıcısı +mods.browser.selected = Seçilen Mod +mods.browser.add = Modu İndir +mods.github.open = Modun GitHub Sayfasını Aç + schematic = Şema schematic.add = Şemayı Kaydet... schematics = Şemalar diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index f6985c41d6..bdb83b4ca3 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -55,6 +55,13 @@ schematic.delete.confirm = Ви справді хочете видалити ц schematic.rename = Перейменувати схему schematic.info = {0}x{1}, блоків: {2} schematic.disabled = [scarlet]Схеми вимкнені[]\nВам не дозволяється використовувати схеми на цій [accent]мапі[] чи [accent]сервері. + +mod.featured.title = Переглядач модифікацій +mod.featured.dialog.title = Переглядач модифікацій +mods.browser.selected = Обрана модифікація +mods.browser.add = Установити модифікацію +mods.github.open = Відкрити в Github + stats = Статистика stat.wave = Хвиль відбито:[accent] {0} stat.enemiesDestroyed = Противників знищено:[accent] {0} diff --git a/core/src/mindustry/ui/Styles.java b/core/src/mindustry/ui/Styles.java index 6b47d6d0b3..bad2dbc5a7 100644 --- a/core/src/mindustry/ui/Styles.java +++ b/core/src/mindustry/ui/Styles.java @@ -25,7 +25,7 @@ import static mindustry.gen.Tex.*; public class Styles{ //TODO all these names are inconsistent and not descriptive public static Drawable black, black9, black8, black6, black3, black5, none, flatDown, flatOver; - public static ButtonStyle defaultb, waveb; + public static ButtonStyle defaultb, waveb, modsb; public static TextButtonStyle defaultt, squaret, nodet, cleart, discordt, nonet, infot, clearPartialt, clearTogglet, clearToggleMenut, togglet, transt, fullTogglet, logict; public static ImageButtonStyle defaulti, nodei, righti, emptyi, emptytogglei, selecti, logici, geni, colori, accenti, cleari, clearFulli, clearPartiali, clearPartial2i, clearTogglei, clearTransi, clearToggleTransi, clearTogglePartiali; public static ScrollPaneStyle defaultPane, horizontalPane, smallPane; @@ -53,6 +53,12 @@ public class Styles{ over = buttonOver; disabled = buttonDisabled; }}; + + modsb = new ButtonStyle(){{ + down = flatOver; + up = underline; + over = underlineWhite; + }}; waveb = new ButtonStyle(){{ up = wavepane; diff --git a/core/src/mindustry/ui/dialogs/ModsDialog.java b/core/src/mindustry/ui/dialogs/ModsDialog.java index a54d2fee59..de2a7c18e9 100644 --- a/core/src/mindustry/ui/dialogs/ModsDialog.java +++ b/core/src/mindustry/ui/dialogs/ModsDialog.java @@ -6,14 +6,17 @@ import arc.files.*; import arc.func.*; import arc.graphics.*; import arc.graphics.g2d.*; +import arc.input.*; import arc.scene.style.*; import arc.scene.ui.TextButton.*; import arc.struct.*; import arc.util.*; import arc.util.io.*; +import arc.util.serialization.*; import mindustry.ctype.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.mod.*; import mindustry.mod.Mods.*; import mindustry.ui.*; @@ -22,6 +25,8 @@ import java.io.*; import static mindustry.Vars.*; public class ModsDialog extends BaseDialog{ + private String searchtxt = ""; + private @Nullable Seq modList; public ModsDialog(){ super("@mods"); @@ -54,6 +59,25 @@ public class ModsDialog extends BaseDialog{ } } + void getModList(Cons> listener){ + if(modList == null){ + Core.net.httpGet("https://raw.githubusercontent.com/Anuken/MindustryMods/master/mods.json", response -> { + String strResult = response.getResultAsString(); + var status = response.getStatus(); + + Core.app.post(() -> { + if(status != HttpStatus.OK){ + ui.showErrorMessage(Core.bundle.format("connectfail", status)); + }else{ + listener.get(modList = new Json().fromJson(Seq.class, ModListing.class, strResult)); + } + }); + }, error -> Core.app.post(() -> ui.showException(error))); + }else{ + listener.get(modList); + } + } + void setup(){ float h = 110f; float w = mobile ? 440f : 524f; @@ -110,22 +134,82 @@ public class ModsDialog extends BaseDialog{ Core.settings.put("lastmod", text); ui.loadfrag.show(); - //Try to download the 6.0 branch first, but if it doesn't exist, try master. - githubImport("6.0", text, e1 -> { - githubImport("master", text, e2 -> { - githubImport("main", text, e3 -> { - ui.showErrorMessage(Core.bundle.format("connectfail", e2)); - ui.loadfrag.hide(); - }); - }); - }); + githubImportMod(text); }); }).margin(12f); - }); + t.row(); + + t.button("@mod.featured.title", Icon.star, bstyle, () -> { + Runnable[] rebuildBrowser = {null}; + dialog.hide(); + BaseDialog browser = new BaseDialog("$mod.featured.dialog.title"); + browser.cont.table(table -> { + table.left(); + table.image(Icon.zoom); + table.field(searchtxt, res -> { + searchtxt = res; + rebuildBrowser[0].run(); + }).growX().get(); + }).fillX().padBottom(4); + + browser.cont.row(); + + browser.cont.pane(tablebrow -> { + tablebrow.margin(10f).top(); + rebuildBrowser[0] = () -> { + tablebrow.clear(); + tablebrow.add("@loading"); + + getModList(listings -> { + tablebrow.clear(); + + for(ModListing mod : listings){ + if(!searchtxt.isEmpty() && !mod.repo.contains(searchtxt)) continue; + + tablebrow.button(btn -> { + btn.top().left(); + btn.margin(12f); + btn.table(con -> { + con.left(); + con.add("[lightgray]Name:[] " + mod.name + "\n[lightgray]Author:[] " + mod.author + "\n[accent]\uE809 " + mod.stars) + .width(388f).wrap().growX().pad(0f, 6f, 0f, 6f).left().labelAlign(Align.left); + con.add().growX().pad(0f, 6f, 0f, 6f); + }).fillY().growX().pad(0f, 6f, 0f, 6f); + }, Styles.modsb, () -> { + var sel = new BaseDialog((Core.bundle.get("mods.browser.selected")) + ": " + mod.name); + sel.cont.add(mod.description).width(mobile ? 400f : 500f).wrap().pad(4f).labelAlign(Align.center, Align.left); + sel.buttons.defaults().size(200f, 54f).pad(2f); + sel.setFillParent(false); + sel.buttons.button("@back", Icon.left, () -> { + sel.clear(); + sel.hide(); + }); + sel.buttons.button("@mods.browser.add", Icon.download, () -> { + sel.hide(); + githubImportMod(mod.repo); + }); + sel.buttons.button("@mods.github.open", Icon.link, () -> { + Core.app.openURI("https://github.com/" + mod.repo); + }); + sel.keyDown(KeyCode.escape, sel::hide); + sel.keyDown(KeyCode.back, sel::hide); + sel.show(); + }).width(480f).growX().left().fillY(); + tablebrow.row(); + } + }); + }; + rebuildBrowser[0].run(); + }); + browser.addCloseButton(); + browser.show(); + }).margin(12f); + }); dialog.addCloseButton(); dialog.show(); + }).margin(margin); if(!mobile){ @@ -315,7 +399,20 @@ public class ModsDialog extends BaseDialog{ } } - private void githubImport(String branch, String repo, Cons err){ + private void githubImportMod(String name){ + //try several branches + //TODO use only the main branch as specified in meta + githubImportBranch("6.0", name, e1 -> { + githubImportBranch("master", name, e2 -> { + githubImportBranch("main", name, e3 -> { + ui.showErrorMessage(Core.bundle.format("connectfail", e2)); + ui.loadfrag.hide(); + }); + }); + }); + } + + private void githubImportBranch(String branch, String repo, Cons err){ Core.net.httpGet("https://api.github.com/repos/" + repo + "/zipball/" + branch, loc -> { if(loc.getStatus() == HttpStatus.OK){ if(loc.getHeader("Location") != null){