diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java index 24e8acfd6ab..886516a5a31 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Config.java @@ -398,6 +398,21 @@ public void setTitleTransparent(boolean titleTransparent) { this.titleTransparent.set(titleTransparent); } + @SerializedName("launchTips") + private final BooleanProperty launchTips = new SimpleBooleanProperty(true); + + public BooleanProperty launchTipsProperty() { + return launchTips; + } + + public boolean isShowLaunchTips() { + return launchTips.get(); + } + + public void setLaunchTipsVisible(boolean launchTips) { + this.launchTips.set(launchTips); + } + @SerializedName("backgroundType") private final ObjectProperty backgroundImageType = new RawPreservingObjectProperty<>(EnumBackgroundImage.DEFAULT); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LaunchTipLabel.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LaunchTipLabel.java new file mode 100644 index 00000000000..8d4cab2aa51 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/LaunchTipLabel.java @@ -0,0 +1,123 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.jackhuang.hmcl.ui.construct; + +import javafx.animation.Animation; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; +import javafx.application.Platform; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.layout.HBox; +import javafx.scene.text.Text; +import javafx.scene.text.TextAlignment; +import javafx.scene.text.TextFlow; +import javafx.util.Duration; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.google.gson.annotations.SerializedName; + +import org.jackhuang.hmcl.util.i18n.I18n; + + +public class LaunchTipLabel extends HBox { + private final Text bottomTipText; + private final TextFlow tfwBottomTip; + private final Timeline tipTimeline; + private static final List tips; + private static int index = 0; + private static final int nextTipDelay = 3; + + static { + tips = loadTipsFromJson(); + Collections.shuffle(tips, ThreadLocalRandom.current()); + } + + public LaunchTipLabel() { + setAlignment(Pos.CENTER); + + tfwBottomTip = new TextFlow(); + tfwBottomTip.setTextAlignment(TextAlignment.CENTER); + tfwBottomTip.setStyle("-fx-text-fill: rgba(100, 100, 100, 0.9)"); + tfwBottomTip.setPadding(new Insets(0, 50, 0, 50)); + + bottomTipText = new Text(getRandomTip()); + tfwBottomTip.getChildren().add(bottomTipText); + + getChildren().add(tfwBottomTip); + + tipTimeline = new Timeline(new KeyFrame(Duration.seconds(nextTipDelay), e -> nextTip())); + tipTimeline.setCycleCount(Animation.INDEFINITE); + tipTimeline.play(); + } + + private void nextTip() { + String next = getRandomTip(); + Platform.runLater(() -> bottomTipText.setText(next)); + } + + private static String getRandomTip() { + if (index >= tips.size()){ + Collections.shuffle(tips, ThreadLocalRandom.current()); + index = 0; + } + return tips.get(index++); + } + private static List loadTipsFromJson() { + List result = new ArrayList<>(); + String resourceName = "assets.lang.launch_tips.tips"; + + try { + java.net.URL url = I18n.getBuiltinResource(resourceName, "json"); + if (url != null) { + Gson gson = new Gson(); + try (InputStream inputStream = url.openStream(); + InputStreamReader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8)) { + LaunchTipsData data = gson.fromJson(reader, LaunchTipsData.class); + if (data != null && data.tips != null) { + result.addAll(data.tips); + } + } + } + } catch (IOException | JsonSyntaxException ignored) { + // ignored + } + + if (result.isEmpty()) { + result.add("Welcome to HMCL!"); + } + + return result; + } + + + private static class LaunchTipsData { + @SerializedName("tips") + private List tips; + } +} \ No newline at end of file diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java index f8442e25bdd..0b44bb32700 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/TaskExecutorDialogPane.java @@ -33,6 +33,7 @@ import java.util.Optional; import java.util.function.Consumer; +import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -68,8 +69,14 @@ public TaskExecutorDialogPane(@NotNull TaskCancellationAction cancel) { this.setBottom(bottom); bottom.setPadding(new Insets(0, 8, 8, 8)); { - lblProgress = new Label(); + lblProgress = new Label("0.0 B/s"); // Prevent sudden changes in layout bottom.setLeft(lblProgress); + BorderPane.setMargin(lblProgress, new Insets(0, 0, 4, 14)); + + if (config().isShowLaunchTips()) { + LaunchTipLabel lblBottomTip = new LaunchTipLabel(); + bottom.setCenter(lblBottomTip); + } btnCancel = new JFXButton(i18n("button.cancel")); bottom.setRight(btnCancel); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java index bbf5925f4d9..0c64d17514f 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/PersonalizationPage.java @@ -112,6 +112,12 @@ public PersonalizationPage() { animationButton.selectedProperty().bindBidirectional(config().animationDisabledProperty()); animationButton.setTitle(i18n("settings.launcher.turn_off_animations")); } + { + OptionToggleButton launchTipsButton = new OptionToggleButton(); + themeList.getContent().add(launchTipsButton); + launchTipsButton.selectedProperty().bindBidirectional(config().launchTipsProperty()); + launchTipsButton.setTitle(i18n("settings.launcher.turn_on_launch_tips")); + } content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.appearance")), themeList); { diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 3e813e492fa..89b078f8e98 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -1382,6 +1382,7 @@ settings.launcher.proxy.username=Username settings.launcher.theme=Theme settings.launcher.title_transparent=Transparent Titlebar settings.launcher.turn_off_animations=Disable Animation (Applies After Restart) +settings.launcher.turn_on_launch_tips=Show "Tips" while the game starts settings.launcher.version_list_source=Version List settings.launcher.background.settings.opacity=Opacity diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 29ce5106b6b..374f0a5f7b9 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -1170,6 +1170,7 @@ settings.launcher.proxy.username=帳戶 settings.launcher.theme=主題 settings.launcher.title_transparent=標題欄透明 settings.launcher.turn_off_animations=關閉動畫 (重啟後生效) +settings.launcher.turn_on_launch_tips=遊戲開始時顯示「小提示」 settings.launcher.version_list_source=版本清單來源 settings.launcher.background.settings.opacity=不透明度 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 43603a3cbbe..73f045f0b96 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -1180,6 +1180,7 @@ settings.launcher.proxy.username=账户 settings.launcher.theme=主题 settings.launcher.title_transparent=标题栏透明 settings.launcher.turn_off_animations=关闭动画 (重启后生效) +settings.launcher.turn_on_launch_tips=启动游戏时展示“小提示” settings.launcher.version_list_source=版本列表源 settings.launcher.background.settings.opacity=不透明度 diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/tips_en.json b/HMCL/src/main/resources/assets/lang/launch_tips/tips_en.json new file mode 100644 index 00000000000..b69bd5265dc --- /dev/null +++ b/HMCL/src/main/resources/assets/lang/launch_tips/tips_en.json @@ -0,0 +1,34 @@ +{ + "tips": [ + "HMCL was originally made by huanghongxun; more contributors later joined.", + "Minecraft’s first version launched in 2009 as a simple prototype.", + "Every horse in Minecraft has a random unique speed.", + "Name a Vindicator \"Johnny\" to make it very aggressive.", + "HMCL’s dev community is active (new features often added); follow GitHub discussions.", + "HMCL works on Windows, MacOS and Linux.", + "HMCL devs share progress/plans on Bilibili and GitHub.", + "Iron Golems give Poppies to Copper Golems, which then wear them.", + "Endermen lose teleport if trapped in a minecart or cobweb.", + "Creepers started as a pig glitch in the game.", + "Skip sleep for 3 in-game days? Be careful on day 4’s night.", + "1/256 chance to get 4 chicks from one egg.", + "Golden Pickaxe has low durability but high good enchant chance.", + "Ocelots and Iron Golems take no fall damage—they can’t die from falling.", + "Falling on hay bales reduces fall damage.", + "Early Minecraft let you mine coal ore with bare hands.", + "Chests turn into gift box textures at Christmas.", + "Cats sit on beds, chests and furnaces automatically.", + "Endermen are the only mobs spawning naturally in all 3 Minecraft dimensions.", + "Banners sway in the Overworld, not in the Nether/End.", + "Minecraft’s \"tick\" = 0.05s; 1 in-game day = 24,000 ticks (20 mins).", + "Tropical Fish: 2 sizes, 6 patterns each, 15 base/pattern colors—2,700 total types.", + "Name a sheep \"jeb_\" to make it rainbow-colored.", + "Skeletons have 21% left-hand bow use (based on real human data).", + "Skeletons attack from any angle—turning away won’t stop them.", + "Test horse speed: Two riders, leashed together, pull opposite—loser’s horse is slower.", + "Hit squids’ heads, not tentacles—tentacles take no damage.", + "Adult turtles avoid undead unless the undead hated them as babies.", + "Jungle Temples always use 1,185 cobblestone or mossy cobblestone.", + "Enchant shields with Unbreaking/Mending via anvil, not enchantment table." + ] +} \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/tips_zh.json b/HMCL/src/main/resources/assets/lang/launch_tips/tips_zh.json new file mode 100644 index 00000000000..76b05ab5c5c --- /dev/null +++ b/HMCL/src/main/resources/assets/lang/launch_tips/tips_zh.json @@ -0,0 +1,34 @@ +{ + "tips": [ + "HMCL 最初由 huanghongxun 開發,後來有越來越多的貢獻者加入其中。", + "Minecraft 的第一個版本在 2009 年發布,當時它還只是一個簡單的原型。", + "在 Minecraft 中,每一匹馬的速度都不同,這些屬性是隨機生成的。", + "將衛道士命名為「Johnny」會讓牠變得非常暴躁。", + "HMCL 的開發者社群相當活躍,時常會有新功能與改進推出。您可以在 GitHub 上追蹤相關討論。", + "HMCL 支援多平台,包括 Windows、MacOS 與 Linux。", + "HMCL 的開發者經常在 B站 和 GitHub 社群中分享開發進度與規劃。", + "鐵傀會將罌粟贈送給附近的銅傀,接受贈送的銅傀會把罌粟戴在頭上。", + "末影人若被困在礦車中或沾到蜘蛛網,牠的瞬移技能就會消失。", + "苦力怕的原型是一隻豬,因遊戲錯誤而誕生。", + "如果您在遊戲中連續三天不睡覺,第四天晚上最好多加小心。", + "用雞蛋一次砸出 4 隻小雞的機率是 256 分之一。", + "雖然金鎬的耐久度很低,但附魔出好屬性的機率相當高。", + "豹貓和鐵傀不會摔死,因為牠們沒有摔落傷害。", + "摔落在乾草上可以減少摔落傷害。", + "在早期的《我的世界》中,煤礦可以空手挖掘。", + "聖誕節期間,箱子會變成禮物箱的材質。", + "貓會自己坐到床、箱子、熔爐上。", + "末影人是原版 Minecraft 中唯一一種能在三個世界自然生成的生物。", + "旗幟在主世界會輕微晃動,但在下界和末地則不會。", + "Minecraft 的基本時間單位是「刻」,1刻=0.05秒,一天=24000刻=20分鐘。", + "熱帶魚有 2 種體型,每種體型有 6 種花紋,底色與花紋顏色各 15 種,因此總共共有 2700 種。", + "將羊命名為「jeb_」會讓牠變成一道彩虹。", + "骷髏有 21% 的機率用左手拿弓。據說這個機率是依據現實世界中人類的真實數據設定的。", + "骷髏攻擊沒有角度限制,別以為背對著骷髏,牠就攻擊不到您。", + "比較馬的速度:讓兩人各騎一匹馬,用拴繩相連後朝相反方向拉。哪個人的馬被拉動,那匹馬的速度就比較慢。", + "攻擊魷魚的觸手時,牠們不會受到傷害,最好的方法是攻擊牠們的頭部。", + "成年海龜不會受到亡靈的攻擊……除非牠碰到幼年時就對牠抱有敵意的亡靈。", + "叢林神廟一定是由 1185 個原石或苔石組成的。", + "盾牌可以用鐵砧附魔「耐久」和「經驗修補」,但無法用附魔台進行附魔。" + ] +} \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/tips_zh_CN.json b/HMCL/src/main/resources/assets/lang/launch_tips/tips_zh_CN.json new file mode 100644 index 00000000000..27b2fcb4dbf --- /dev/null +++ b/HMCL/src/main/resources/assets/lang/launch_tips/tips_zh_CN.json @@ -0,0 +1,34 @@ +{ + "tips": [ + "HMCL 最初由 huanghongxun 开发,后来有越来越多的贡献者加入了其中。", + "Minecraft 的第一个版本是在 2009 年发布的,当时它只是一个简单的原型。", + "在 Minecraft 中,每匹马都有不同的速度。这些属性是随机生成的。", + "给卫道士命名为“Johnny”会让他变得很暴躁。", + "HMCL 的开发者社区非常活跃,经常会有新的功能和改进。您可以在 GitHub 上关注相关讨论。", + "HMCL支持多平台,包括 Windows、MacOS 和 Linux。", + "HMCL 的开发者经常会在 B站 和 GitHub 社区中分享开发进度和计划。", + "铁傀会将虞美人赠予附近的铜傀,接受的铜傀会将其戴到头上。", + "末影人如果被困在矿车中或粘到蜘蛛网,它的瞬移技能会消失。", + "苦力怕的原型是一只猪,因游戏错误而诞生。", + "如果你在游戏里连续三天不睡觉,第四天晚上最好小心点。", + "鸡蛋一次性砸出 4 只小鸡的几率是 256 分之一。", + "虽然金镐的耐久度很低,但是附魔出好属性的几率很高。", + "豹猫和铁傀是不会摔死的,因为它们没有摔落伤害。", + "摔落在干草上可以减少摔落伤害。", + "在早期的我的世界中,煤矿可以空手撸。", + "在圣诞节的时候,箱子会变成礼物箱的材质。", + "猫会自己坐到床、箱子、熔炉上。", + "末影人是原版 Minecraft 中唯一一种在三个世界都自然生成的生物。", + "旗帜在主世界会轻微晃动,而在下界和末地不会。", + "Minecraft 的基本时间单位是刻,1刻=0.05秒,一天 = 24000刻 = 20分钟。", + "热带鱼有 2 种体型,每种体型有6种花纹,底色与花纹颜色各15种,所以共有 2700 种。", + "给羊命名为“jeb_”会使其变成一道彩虹。", + "骷髅有 21% 的概率使用左手拿弓。据说,这个概率是依据现实世界人类真实的数据设定的。", + "骷攻击没有角度的,不要以为背对着骷髅,它就攻击不到你。", + "比较马的速度: 让两人各骑一匹马,用拴绳相连,朝反方向拉。谁的马被拉动,谁的马就更快。", + "你攻击鱿鱼的触手时,它们不会受到伤害。最好的方法是攻击头部。", + "成年的海龟不会受到亡灵的攻击...除非它碰到幼年时就对它起了敌意的亡灵。", + "丛林神庙总是会由 1185 个原石或苔石组成。", + "盾牌可以用铁砧附魔耐久和经验修补,但没法用附魔台。" + ] +} \ No newline at end of file