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 f8442e25b..ce8eb276c 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 @@ -18,15 +18,22 @@ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.controls.JFXButton; +import javafx.animation.Animation; +import javafx.animation.KeyFrame; +import javafx.animation.Timeline; import javafx.application.Platform; import javafx.beans.property.StringProperty; import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.control.Label; import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; import javafx.scene.layout.Priority; import javafx.scene.layout.VBox; +import javafx.util.Duration; import org.jackhuang.hmcl.task.*; import org.jackhuang.hmcl.ui.FXUtils; +import org.jackhuang.hmcl.util.RandomTip; import org.jackhuang.hmcl.util.TaskCancellationAction; import org.jetbrains.annotations.NotNull; @@ -35,6 +42,7 @@ import java.util.function.Consumer; import static org.jackhuang.hmcl.ui.FXUtils.onEscPressed; import static org.jackhuang.hmcl.ui.FXUtils.runInFX; +import static org.jackhuang.hmcl.util.RandomTip.getRandomTip; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class TaskExecutorDialogPane extends BorderPane { @@ -45,6 +53,8 @@ public class TaskExecutorDialogPane extends BorderPane { private final Label lblTitle; private final Label lblProgress; private final JFXButton btnCancel; + private final Label lblBottomTip; + private final Timeline tipTimeline; private final TaskListPane taskListPane; public TaskExecutorDialogPane(@NotNull TaskCancellationAction cancel) { @@ -68,8 +78,17 @@ public class TaskExecutorDialogPane extends BorderPane { 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)); + + lblBottomTip = new Label(getRandomTip()); + lblBottomTip.setStyle("-fx-text-fill: rgba(100, 100, 100, 0.9)"); + lblBottomTip.setPadding(new Insets(0, 8, 0, 0)); + + HBox centerBox = new HBox(lblBottomTip); + centerBox.setAlignment(Pos.CENTER); + bottom.setCenter(centerBox); btnCancel = new JFXButton(i18n("button.cancel")); bottom.setRight(btnCancel); @@ -102,6 +121,10 @@ public class TaskExecutorDialogPane extends BorderPane { FileDownloadTask.speedEvent.channel(FetchTask.SpeedEvent.class).registerWeak(speedEventHandler); onEscPressed(this, btnCancel::fire); + + tipTimeline = new Timeline(new KeyFrame(Duration.seconds(2), e -> nextTip())); + tipTimeline.setCycleCount(Animation.INDEFINITE); + tipTimeline.play(); } public void setExecutor(TaskExecutor executor) { @@ -118,6 +141,7 @@ public class TaskExecutorDialogPane extends BorderPane { executor.addTaskListener(new TaskListener() { @Override public void onStop(boolean success, TaskExecutor executor) { + tipTimeline.stop(); Platform.runLater(() -> fireEvent(new DialogCloseEvent())); } }); @@ -141,4 +165,9 @@ public class TaskExecutorDialogPane extends BorderPane { runInFX(() -> btnCancel.setDisable(onCancel == null)); } + + private void nextTip() { + String next = RandomTip.getRandomTip(); // It's certain that there will be no duplication + Platform.runLater(() -> lblBottomTip.setText(next)); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/util/RandomTip.java b/HMCL/src/main/java/org/jackhuang/hmcl/util/RandomTip.java new file mode 100644 index 000000000..d7d1a8f24 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hmcl/util/RandomTip.java @@ -0,0 +1,111 @@ +/* + * 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.util; + +import java.util.*; + +import java.util.stream.IntStream; +import java.util.stream.Collectors; + +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; + +public final class RandomTip { + + private static final List tips; + private static final int maxTipNumber = 30; + + private static final FakeRandomIndex indexGenerator; + static { + // Initialization tips list + tips = IntStream.rangeClosed(1, maxTipNumber) + .mapToObj(i -> i18n(String.format("message.tips_%s", i))) + .collect(Collectors.toList()); + + indexGenerator = new FakeRandomIndex(tips.size()); + } + + public static String getRandomTip() { + String tip = tips.get(indexGenerator.next()); + return formatTip(tip); + } + + private static String formatTip(String tip) { + StringBuilder formattedTip = new StringBuilder(); + int lineLength = 0; + + for (int i = 0; i < tip.length(); i++) { + char c = tip.charAt(i); + int charLength = 1; + + if (Character.toString(c).matches("\\p{IsHan}")) { + charLength = 2; // One Chinese character is considered as two characters + } + + // avoid leaving a single punctuation on the new line + if (lineLength + charLength > 51 && + !(Character.toString(c).matches("\\p{P}") && lineLength + charLength == 52)) { + formattedTip.append('\n'); + lineLength = 0; + } + + formattedTip.append(c); + lineLength += charLength; + } + + String result = formattedTip.toString(); + + // it's just a single line + if (!result.contains("\n")) { + result += "\n\t"; + } + + return result.toString(); + } + + private static final class FakeRandomIndex { + private final List indices; + private final Random random; + private int cursor; + + FakeRandomIndex(int size) { + this.indices = new ArrayList<>(size); + for (int i = 0; i < size; i++) { + indices.add(i); + } + this.random = new Random(); + shuffle(); + this.cursor = 0; + } + + private void shuffle() { + for (int i = indices.size() - 1; i > 0; i--) { + int j = random.nextInt(i + 1); + Collections.swap(indices, i, j); + } + } + + int next() { + if (cursor >= indices.size()) { + shuffle(); + cursor = 0; + } + return indices.get(cursor++); + } + } + private RandomTip() {} +} \ No newline at end of file diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 56064f3d5..a2cfe6efa 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -871,6 +871,37 @@ message.success=Operation successfully completed message.unknown=Unknown message.warning=Warning +message.tips_1=HMCL started by huanghongxun, now powered by many contributors. +message.tips_2=Minecraft's first build came out in 2009 as a tiny prototype. +message.tips_3=Every horse spawns with random speed stats. +message.tips_4=Name a vindicator "Johnny" and it'll attack anything. +message.tips_5=The HMCL team is active on GitHub—new features land often. +message.tips_6=HMCL runs on Windows, macOS and Linux. +message.tips_7=Developers post updates on Bilibili and GitHub. +message.tips_8=Iron golems hand poppies to copper golems; the copper ones wear them. +message.tips_9=Endermen can't teleport if stuck in a minecart or web. +message.tips_10=Creepers began as a pig model bug. +message.tips_11=Skip three nights and the fourth will be dangerous. +message.tips_12=Odds of four chicks from one egg: 1 in 256. +message.tips_13=Golden pickaxes enchant easily, but break fast. +message.tips_14=Ocelots and iron golems ignore fall damage. +message.tips_15=Hay bales cushion falls. +message.tips_16=In early versions you could mine coal with bare hands. +message.tips_17=Chests turn into presents at Christmas. +message.tips_18=Cats sit on beds, chests and furnaces uninvited. +message.tips_19=Endermen are the only mobs that spawn in all three dimensions. +message.tips_20=Banners wave in the Overworld, not in Nether or End. +message.tips_21=One tick = 0.05 s; a full day is 24,000 ticks (20 min). +message.tips_22=Tropical fish have 2 700 pattern combos. +message.tips_23=Name a sheep "jeb_" for a rainbow fleece. +message.tips_24=Skeletons have a 21 % chance to shoot left-handed. +message.tips_25=Skeleton arrows don't care which way you face. +message.tips_26=Tie two horses together and walk opposite ways—whoever gets pulled has the slower horse. +message.tips_27=Only the squid's head takes damage. +message.tips_28=Adult turtles are safe from undead—unless the mob hated them as babies. +message.tips_29=Jungle temples always contain 1,185 stone or mossy blocks. +message.tips_30=Shields can take Unbreaking and Mending via anvil, not enchanting table. + modpack=Modpacks modpack.choose=Choose Modpack modpack.choose.local=Import from Local File diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index d01764c5f..4c62f9241 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -678,6 +678,37 @@ message.success=完成 message.unknown=未知 message.warning=警告 +message.tips_1=HMCL 最初由 huanghongxun 開發,後來有越來越多的貢獻者加入其中。 +message.tips_2=Minecraft 的第一個版本在 2009 年推出,當時只是個簡單的原型。 +message.tips_3=在 Minecraft 中,每匹馬的速度都不同,這些數值是隨機生成的。 +message.tips_4=把衛道士命名為「Johnny」會讓他變得暴躁。 +message.tips_5=HMCL 的開發社群非常活躍,經常推出新功能與改進。歡迎到 GitHub 追蹤討論。 +message.tips_6=HMCL 支援多平台,包含 Windows、macOS 與 Linux。 +message.tips_7=HMCL 開發者常在 Bilibili 與 GitHub 社群分享開發進度與企劃。 +message.tips_8=鐵巨人會把罌粟送給附近的銅巨人,收到花的銅巨人會把它戴在頭上。 +message.tips_9=如果終界使者被困在礦車裡或被蜘蛛網黏住,就無法瞬移。 +message.tips_10=苦力怕的原型其實是豬,因程式錯誤而誕生。 +message.tips_11=如果你在遊戲中連續三天不睡覺,第四天晚上最好提高警覺。 +message.tips_12=一次丟蛋就孵出 4 隻小雞的機率是 1/256。 +message.tips_13=金製鎬子耐久雖低,但附魔出好屬性的機率較高。 +message.tips_14=山貓與鐵巨人不會受到摔落傷害。 +message.tips_15=摔到乾草塊上可減輕摔落傷害。 +message.tips_16=早期版本的 Minecraft 中,煤礦可以徒手挖掘。 +message.tips_17=聖誕節期間,箱子的外觀會變成禮物盒。 +message.tips_18=貓會自己跳上床、箱子或熔爐坐著。 +message.tips_19=終界使者是原版 Minecraft 中唯一在主世界、地獄與終界都會自然生成的生物。 +message.tips_20=旗幟在主世界會微微飄動,但在地獄與終界不會。 +message.tips_21=Minecraft 的基本時間單位是「刻」,1 刻 = 0.05 秒;一天共 24000 刻,相當於現實 20 分鐘。 +message.tips_22=熱帶魚有 2 種體型,每種體型各有 6 種花紋,底色與花紋色各有 15 種,因此共有 2700 種組合。 +message.tips_23=把羊命名為「jeb_」會讓牠變成彩虹羊。 +message.tips_24=骷髏有 21% 的機率用左手持弓,據說這是參考現實人類左撇子比例所設計的。 +message.tips_25=骷髏的攻擊沒有方向性,別以為背對牠就安全。 +message.tips_26=比較馬的速度小技巧:兩人各騎一匹馬,用拴繩互相綁住後朝反方向前進,先被拉動的那匹馬速度較慢。 +message.tips_27=攻擊魷魚的觸手不會造成傷害,正確做法是攻擊頭部。 +message.tips_28=成年海龜不會受到亡靈生物攻擊,除非那隻亡靈在小海龜時就對牠產生敵意。 +message.tips_29=叢林神廟總是由 1185 個石頭或苔石組成。 +message.tips_30=盾牌可用鐵砧附上耐久與修補,但無法透過附魔台取得. + modpack=模組包 modpack.choose=選取要安裝的遊戲模組包檔案 modpack.choose.local=匯入本機模組包檔案 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 43603a3cb..ae47ea02d 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -688,6 +688,37 @@ message.success=完成 message.unknown=未知 message.warning=警告 +message.tips_1=HMCL 最初由 huanghongxun 开发,后来有越来越多的贡献者加入了其中。 +message.tips_2=Minecraft 的第一个版本是在 2009 年发布的,当时它只是一个简单的原型。 +message.tips_3=在 Minecraft 中,每匹马都有不同的速度。这些属性是随机生成的。 +message.tips_4=给卫道士命名为“Johnny”会让他变得很暴躁。 +message.tips_5=HMCL 的开发者社区非常活跃,经常会有新的功能和改进。您可以在 GitHub 上关注相关讨论。 +message.tips_6=HMCL支持多平台,包括 Windows、MacOS 和 Linux。 +message.tips_7=HMCL 的开发者经常会在 B站 和 GitHub 社区中分享开发进度和计划。 +message.tips_8=铁傀会将虞美人赠予附近的铜傀,接受的铜傀会将其戴到头上。 +message.tips_9=末影人如果被困在矿车中或粘到蜘蛛网,它的瞬移技能会消失。 +message.tips_10=苦力怕的原型是一只猪,因游戏错误而诞生。 +message.tips_11=如果你在游戏里连续三天不睡觉,第四天晚上最好小心点。 +message.tips_12=鸡蛋一次性砸出 4 只小鸡的几率是 256 分之一。 +message.tips_13=虽然金镐的耐久度很低,但是附魔出好属性的几率很高。 +message.tips_14=豹猫和铁傀是不会摔死的,因为它们没有摔落伤害。 +message.tips_15=摔落在干草上可以减少摔落伤害。 +message.tips_16=在早期的我的世界中,煤矿可以空手撸。 +message.tips_17=在圣诞节的时候,箱子会变成礼物箱的材质。 +message.tips_18=猫会自己坐到床、箱子、熔炉上。 +message.tips_19=末影人是原版 Minecraft 中唯一一种在三个世界都自然生成的生物。 +message.tips_20=旗帜在主世界会轻微晃动,而在下界和末地不会。 +message.tips_21=Minecraft 的基本时间单位是刻,1刻=0.05秒,一天 = 24000刻 = 20分钟。 +message.tips_22=热带鱼有 2 种体型,每种体型有6种花纹,底色与花纹颜色各15种,所以共有 2700 种。 +message.tips_23=给羊命名为“jeb_”会使其变成一道彩虹。 +message.tips_24=骷髅有 21% 的概率使用左手拿弓。据说,这个概率是依据现实世界人类真实的数据设定的。 +message.tips_25=骷攻击没有角度的,不要以为背对着骷髅,它就攻击不到你。 +message.tips_26=比较马的速度: 让两人各骑一匹马,用拴绳相连,朝反方向拉。谁的马被拉动,谁的马就更快。 +message.tips_27=你攻击鱿鱼的触手时,它们不会受到伤害。最好的方法是攻击头部。 +message.tips_28=成年的海龟不会受到亡灵的攻击...除非它碰到幼年时就对它起了敌意的亡灵。 +message.tips_29=丛林神庙总是会由 1185 个原石或苔石组成。 +message.tips_30=盾牌可以用铁砧附魔耐久和经验修补,但没法用附魔台。 + modpack=整合包 modpack.choose=选择要安装的游戏整合包文件 modpack.choose.local=导入本地整合包文件 diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips-en.json b/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips-en.json new file mode 100644 index 000000000..e69de29bb diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips_ja-JP.json b/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips_ja-JP.json new file mode 100644 index 000000000..e69de29bb diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips_zh-Hans-TW.json b/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips_zh-Hans-TW.json new file mode 100644 index 000000000..e69de29bb diff --git a/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips_zh_Hans_CN.json b/HMCL/src/main/resources/assets/lang/launch_tips/launch_tips_zh_Hans_CN.json new file mode 100644 index 000000000..e69de29bb