From dd22210ee1f75f00b94b70e37564cc45cc610ece Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Wed, 15 Nov 2023 18:56:27 +0800 Subject: [PATCH 1/8] Add support for in-app notifications --- src/client/java/minicraft/core/Game.java | 5 +- src/client/java/minicraft/core/Renderer.java | 16 ++++-- src/client/java/minicraft/core/Updater.java | 13 ++++- src/client/java/minicraft/core/World.java | 2 +- .../java/minicraft/entity/furniture/Bed.java | 2 +- .../entity/furniture/DeathChest.java | 4 +- .../entity/furniture/KnightStatue.java | 6 +- .../java/minicraft/entity/mob/Player.java | 2 +- .../java/minicraft/item/FishingRodItem.java | 2 +- .../java/minicraft/item/PotionType.java | 2 +- .../java/minicraft/item/SummonItem.java | 12 ++-- src/client/java/minicraft/item/TileItem.java | 2 +- .../minicraft/level/tile/BossDoorTile.java | 4 +- .../minicraft/level/tile/BossFloorTile.java | 2 +- .../minicraft/level/tile/BossWallTile.java | 2 +- .../minicraft/level/tile/HardRockTile.java | 2 +- .../java/minicraft/level/tile/WallTile.java | 4 +- .../minicraft/screen/AchievementsDisplay.java | 2 +- .../java/minicraft/screen/LoadingDisplay.java | 2 +- .../java/minicraft/screen/Notification.java | 56 +++++++++++++++++++ .../screen/TutorialDisplayHandler.java | 2 +- 21 files changed, 109 insertions(+), 35 deletions(-) create mode 100644 src/client/java/minicraft/screen/Notification.java diff --git a/src/client/java/minicraft/core/Game.java b/src/client/java/minicraft/core/Game.java index 8fc3f1e7a..520422aea 100644 --- a/src/client/java/minicraft/core/Game.java +++ b/src/client/java/minicraft/core/Game.java @@ -4,13 +4,13 @@ import minicraft.core.io.Settings; import minicraft.core.io.Sound; import minicraft.entity.mob.Player; -import minicraft.gfx.Screen; import minicraft.level.Level; import minicraft.level.tile.Tiles; import minicraft.network.Analytics; import minicraft.saveload.Load; import minicraft.saveload.Version; import minicraft.screen.Display; +import minicraft.screen.Notification; import minicraft.screen.ResourcePackDisplay; import minicraft.screen.TitleDisplay; import minicraft.util.Logging; @@ -30,7 +30,8 @@ protected Game() {} // Can't instantiate the Game class. public static InputHandler input; // Input used in Game, Player, and just about all the *Menu classes. public static Player player; - public static List notifications = new ArrayList<>(); + public static List inGameNotifications = new ArrayList<>(); + public static ArrayDeque inAppNotifications = new ArrayDeque<>(); public static int MAX_FPS; diff --git a/src/client/java/minicraft/core/Renderer.java b/src/client/java/minicraft/core/Renderer.java index 3d2fcce91..5407e3630 100644 --- a/src/client/java/minicraft/core/Renderer.java +++ b/src/client/java/minicraft/core/Renderer.java @@ -27,6 +27,7 @@ import minicraft.level.Level; import minicraft.screen.LoadingDisplay; import minicraft.screen.Menu; +import minicraft.screen.Notification; import minicraft.screen.QuestsDisplay; import minicraft.screen.RelPos; import minicraft.screen.TutorialDisplayHandler; @@ -123,6 +124,11 @@ public static void render() { if (currentDisplay != null) // Renders menu, if present. currentDisplay.render(screen); + Notification notification; + if ((notification = inAppNotifications.peek()) != null) { + notification.render(screen); + } + if (!canvas.hasFocus()) renderFocusNagger(); // Calls the renderFocusNagger() method, which creates the "Click to Focus" message. @@ -268,18 +274,18 @@ private static void renderGui() { // NOTIFICATIONS Updater.updateNoteTick = false; - if (permStatus.size() == 0 && notifications.size() > 0) { + if (permStatus.size() == 0 && inGameNotifications.size() > 0) { Updater.updateNoteTick = true; - if (notifications.size() > 3) { // Only show 3 notifs max at one time; erase old notifs. - notifications = notifications.subList(notifications.size() - 3, notifications.size()); + if (inGameNotifications.size() > 3) { // Only show 3 notifs max at one time; erase old notifs. + inGameNotifications = inGameNotifications.subList(inGameNotifications.size() - 3, inGameNotifications.size()); } if (Updater.notetick > 180) { // Display time per notification. - notifications.remove(0); + inGameNotifications.remove(0); Updater.notetick = 0; } List print = new ArrayList<>(); - for (String n : notifications) { + for (String n : inGameNotifications) { for (String l : Font.getLines(n, Screen.w, Screen.h, 0)) print.add(l); } diff --git a/src/client/java/minicraft/core/Updater.java b/src/client/java/minicraft/core/Updater.java index fb45c9e29..b86c46738 100644 --- a/src/client/java/minicraft/core/Updater.java +++ b/src/client/java/minicraft/core/Updater.java @@ -11,6 +11,7 @@ import minicraft.screen.Display; import minicraft.screen.EndGameDisplay; import minicraft.screen.LevelTransitionDisplay; +import minicraft.screen.Notification; import minicraft.screen.PlayerDeathDisplay; import minicraft.screen.TutorialDisplayHandler; import minicraft.screen.WorldSelectDisplay; @@ -177,6 +178,16 @@ public static void tick() { } if (updateNoteTick) notetick++; + Notification notification; + if ((notification = inAppNotifications.peek()) != null) { + boolean refresh = true; + if (notification.isExpired()) { + inAppNotifications.pop(); // Removes + refresh = (notification = inAppNotifications.peek()) != null; // Tries getting new + } + + if (refresh) notification.tick(); + } // This is the general action statement thing! Regulates menus, mostly. if (!Renderer.canvas.hasFocus()) { @@ -331,7 +342,7 @@ public static void notifyAll(String msg) { } public static void notifyAll(String msg, int notetick) { msg = Localization.getLocalized(msg); - notifications.add(msg); + inGameNotifications.add(msg); Updater.notetick = notetick; } } diff --git a/src/client/java/minicraft/core/World.java b/src/client/java/minicraft/core/World.java index 4e5a2aa8d..a2dc31376 100644 --- a/src/client/java/minicraft/core/World.java +++ b/src/client/java/minicraft/core/World.java @@ -72,7 +72,7 @@ public static void resetGame(boolean keepPlayer) { playerDeadTime = 0; currentLevel = 3; Updater.asTick = 0; - Updater.notifications.clear(); + Updater.inGameNotifications.clear(); // Adds a new player if (keepPlayer) { diff --git a/src/client/java/minicraft/entity/furniture/Bed.java b/src/client/java/minicraft/entity/furniture/Bed.java index 41f57fd99..fd6849654 100644 --- a/src/client/java/minicraft/entity/furniture/Bed.java +++ b/src/client/java/minicraft/entity/furniture/Bed.java @@ -46,7 +46,7 @@ public static boolean checkCanSleep(Player player) { // It is too early to sleep; display how much time is remaining. int sec = (int)Math.ceil((Updater.sleepStartTime - Updater.tickCount)*1.0 / Updater.normSpeed); // gets the seconds until sleeping is allowed. // normSpeed is in tiks/sec. String note = Localization.getLocalized("minicraft.notification.cannot_sleep", sec / 60, sec % 60); - Game.notifications.add(note); // Add the notification displaying the time remaining in minutes and seconds. + Game.inGameNotifications.add(note); // Add the notification displaying the time remaining in minutes and seconds. return false; } diff --git a/src/client/java/minicraft/entity/furniture/DeathChest.java b/src/client/java/minicraft/entity/furniture/DeathChest.java index 3e7741dd4..eb00bb8e7 100644 --- a/src/client/java/minicraft/entity/furniture/DeathChest.java +++ b/src/client/java/minicraft/entity/furniture/DeathChest.java @@ -103,7 +103,7 @@ public void touchedBy(Entity other) { int returned = playerInv.add(i); if (returned < total) { - Game.notifications.add("Your inventory is full!"); + Game.inGameNotifications.add("Your inventory is full!"); return; } @@ -111,7 +111,7 @@ public void touchedBy(Entity other) { } remove(); - Game.notifications.add(Localization.getLocalized("minicraft.notification.death_chest_retrieved")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.death_chest_retrieved")); } } diff --git a/src/client/java/minicraft/entity/furniture/KnightStatue.java b/src/client/java/minicraft/entity/furniture/KnightStatue.java index 566b0ed13..0d6910127 100644 --- a/src/client/java/minicraft/entity/furniture/KnightStatue.java +++ b/src/client/java/minicraft/entity/furniture/KnightStatue.java @@ -22,10 +22,10 @@ public KnightStatue(int health) { public boolean interact(Player player, Item heldItem, Direction attackDir) { if (!ObsidianKnight.active) { if (touches == 0) { // Touched the first time. - Game.notifications.add(Localization.getLocalized("minicraft.notifications.statue_tapped")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notifications.statue_tapped")); touches++; } else if (touches == 1) { // Touched the second time. - Game.notifications.add(Localization.getLocalized("minicraft.notifications.statue_touched")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notifications.statue_touched")); touches++; } else { // Touched the third time. // Awoken notifications is in Boss class @@ -37,7 +37,7 @@ public boolean interact(Player player, Item heldItem, Direction attackDir) { return true; } else { // The boss is active. - Game.notifications.add(Localization.getLocalized("minicraft.notification.boss_limit")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.boss_limit")); return false; } } diff --git a/src/client/java/minicraft/entity/mob/Player.java b/src/client/java/minicraft/entity/mob/Player.java index a21c083f5..4d88ef95e 100644 --- a/src/client/java/minicraft/entity/mob/Player.java +++ b/src/client/java/minicraft/entity/mob/Player.java @@ -757,7 +757,7 @@ private void goFishing() { } if (itemData.startsWith(";")) { // For secret messages :=) - Game.notifications.add(itemData.substring(1)); + Game.inGameNotifications.add(itemData.substring(1)); } else { if (Items.get(itemData).equals(Items.get("Raw Fish"))) { AchievementsDisplay.setAchievement("minicraft.achievement.fish",true); diff --git a/src/client/java/minicraft/item/FishingRodItem.java b/src/client/java/minicraft/item/FishingRodItem.java index 5a8fade64..72cd0897f 100644 --- a/src/client/java/minicraft/item/FishingRodItem.java +++ b/src/client/java/minicraft/item/FishingRodItem.java @@ -74,7 +74,7 @@ public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, @Override public boolean isDepleted() { if (random.nextInt(100) > 120 - uses + level * 6) { // Breaking is random, the lower the level, and the more times you use it, the higher the chance - Game.notifications.add("Your Fishing rod broke."); + Game.inGameNotifications.add("Your Fishing rod broke."); return true; } return false; diff --git a/src/client/java/minicraft/item/PotionType.java b/src/client/java/minicraft/item/PotionType.java index 51bad8ba3..e80409195 100644 --- a/src/client/java/minicraft/item/PotionType.java +++ b/src/client/java/minicraft/item/PotionType.java @@ -40,7 +40,7 @@ public boolean toggleEffect(Player player, boolean addEffect) { if (playerDepth == 0) { // player is in overworld - Game.notifications.add("You can't escape from here!"); + Game.inGameNotifications.add("You can't escape from here!"); return false; } diff --git a/src/client/java/minicraft/item/SummonItem.java b/src/client/java/minicraft/item/SummonItem.java index 15c0d286e..a39d4b2b0 100644 --- a/src/client/java/minicraft/item/SummonItem.java +++ b/src/client/java/minicraft/item/SummonItem.java @@ -56,10 +56,10 @@ public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, } } else { - Game.notifications.add(Localization.getLocalized("minicraft.notification.boss_limit")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.boss_limit")); } } else { - Game.notifications.add(Localization.getLocalized("minicraft.notification.wrong_level_sky")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.wrong_level_sky")); } break; @@ -85,16 +85,16 @@ public boolean interactOn(Tile tile, Level level, int xt, int yt, Player player, success = true; } } else { - Game.notifications.add(Localization.getLocalized("minicraft.notification.knight_statue_exists")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.knight_statue_exists")); } } else { - Game.notifications.add(Localization.getLocalized("minicraft.notification.boss_limit")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.boss_limit")); } } else { - Game.notifications.add(Localization.getLocalized("minicraft.notification.spawn_on_boss_tile")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.spawn_on_boss_tile")); } } else { - Game.notifications.add(Localization.getLocalized("minicraft.notification.wrong_level_dungeon")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.wrong_level_dungeon")); } break; default: diff --git a/src/client/java/minicraft/item/TileItem.java b/src/client/java/minicraft/item/TileItem.java index dad79ffee..242718083 100644 --- a/src/client/java/minicraft/item/TileItem.java +++ b/src/client/java/minicraft/item/TileItem.java @@ -154,7 +154,7 @@ else if ((model.tile.contains("BRICK") || model.tile.contains("PLANK") || model. } if (note.length() > 0) { - Game.notifications.add(note); + Game.inGameNotifications.add(note); } } diff --git a/src/client/java/minicraft/level/tile/BossDoorTile.java b/src/client/java/minicraft/level/tile/BossDoorTile.java index 581030dd5..700294d88 100644 --- a/src/client/java/minicraft/level/tile/BossDoorTile.java +++ b/src/client/java/minicraft/level/tile/BossDoorTile.java @@ -24,7 +24,7 @@ public boolean interact(Level level, int xt, int yt, Player player, Item item, D ToolItem tool = (ToolItem) item; if (tool.type == type.getRequiredTool()) { if (player.payStamina(1)) { - Game.notifications.add(Localization.getLocalized(doorMsg)); + Game.inGameNotifications.add(Localization.getLocalized(doorMsg)); Sound.play("monsterhurt"); return true; } @@ -41,7 +41,7 @@ public boolean interact(Level level, int xt, int yt, Player player, Item item, D public boolean hurt(Level level, int x, int y, Mob source, int dmg, Direction attackDir) { if (source instanceof Player) { if (ObsidianKnight.active && !Game.isMode("minicraft.settings.mode.creative")) { - Game.notifications.add(doorMsg); + Game.inGameNotifications.add(doorMsg); return true; } } diff --git a/src/client/java/minicraft/level/tile/BossFloorTile.java b/src/client/java/minicraft/level/tile/BossFloorTile.java index b7ac654c5..0624a9a82 100644 --- a/src/client/java/minicraft/level/tile/BossFloorTile.java +++ b/src/client/java/minicraft/level/tile/BossFloorTile.java @@ -23,7 +23,7 @@ public boolean interact(Level level, int xt, int yt, Player player, Item item, D ToolItem tool = (ToolItem) item; if (tool.type == type.getRequiredTool()) { if (player.payStamina(1)) { - Game.notifications.add(Localization.getLocalized(floorMsg)); + Game.inGameNotifications.add(Localization.getLocalized(floorMsg)); Sound.play("monsterhurt"); return true; } diff --git a/src/client/java/minicraft/level/tile/BossWallTile.java b/src/client/java/minicraft/level/tile/BossWallTile.java index 12d1ea05f..9b5136f62 100644 --- a/src/client/java/minicraft/level/tile/BossWallTile.java +++ b/src/client/java/minicraft/level/tile/BossWallTile.java @@ -29,7 +29,7 @@ public boolean interact(Level level, int xt, int yt, Player player, Item item, D ToolItem tool = (ToolItem) item; if (tool.type == type.getRequiredTool()) { if (player.payStamina(1)) { - Game.notifications.add(Localization.getLocalized(wallMsg)); + Game.inGameNotifications.add(Localization.getLocalized(wallMsg)); Sound.play("monsterhurt"); return true; } diff --git a/src/client/java/minicraft/level/tile/HardRockTile.java b/src/client/java/minicraft/level/tile/HardRockTile.java index 07c18c4d2..ac4ab48aa 100644 --- a/src/client/java/minicraft/level/tile/HardRockTile.java +++ b/src/client/java/minicraft/level/tile/HardRockTile.java @@ -55,7 +55,7 @@ public boolean interact(Level level, int xt, int yt, Player player, Item item, D return true; } } else { - Game.notifications.add("minicraft.notification.gem_pickaxe_required"); + Game.inGameNotifications.add("minicraft.notification.gem_pickaxe_required"); } } return false; diff --git a/src/client/java/minicraft/level/tile/WallTile.java b/src/client/java/minicraft/level/tile/WallTile.java index df986e62a..95828cfc0 100644 --- a/src/client/java/minicraft/level/tile/WallTile.java +++ b/src/client/java/minicraft/level/tile/WallTile.java @@ -51,7 +51,7 @@ public boolean hurt(Level level, int x, int y, Mob source, int dmg, Direction at hurt(level, x, y, 0); return true; } else { - Game.notifications.add(Localization.getLocalized(obrickMsg)); + Game.inGameNotifications.add(Localization.getLocalized(obrickMsg)); return false; } } @@ -72,7 +72,7 @@ public boolean interact(Level level, int xt, int yt, Player player, Item item, D return true; } } else { - Game.notifications.add(obrickMsg); + Game.inGameNotifications.add(obrickMsg); } } } diff --git a/src/client/java/minicraft/screen/AchievementsDisplay.java b/src/client/java/minicraft/screen/AchievementsDisplay.java index aceab7e75..6577b04dc 100644 --- a/src/client/java/minicraft/screen/AchievementsDisplay.java +++ b/src/client/java/minicraft/screen/AchievementsDisplay.java @@ -165,7 +165,7 @@ private static boolean setAchievement(String id, boolean unlocked, boolean save, achievementScore += a.score; // Tells the player that they got an achievement. - Game.notifications.add(Localization.getLocalized("minicraft.notification.achievement_unlocked", Localization.getLocalized(id))); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.achievement_unlocked", Localization.getLocalized(id))); } else achievementScore -= a.score; diff --git a/src/client/java/minicraft/screen/LoadingDisplay.java b/src/client/java/minicraft/screen/LoadingDisplay.java index 62c2e20d6..53ce2e80a 100644 --- a/src/client/java/minicraft/screen/LoadingDisplay.java +++ b/src/client/java/minicraft/screen/LoadingDisplay.java @@ -63,7 +63,7 @@ public void onExit() { msg = "minicraft.displays.loading.message.saving"; progressType = "minicraft.displays.loading.message.world"; new Save(WorldSelectDisplay.getWorldName()); - Game.notifications.clear(); + Game.inGameNotifications.clear(); } } diff --git a/src/client/java/minicraft/screen/Notification.java b/src/client/java/minicraft/screen/Notification.java new file mode 100644 index 000000000..4c2e85ca8 --- /dev/null +++ b/src/client/java/minicraft/screen/Notification.java @@ -0,0 +1,56 @@ +package minicraft.screen; + +import minicraft.core.io.Localization; +import minicraft.gfx.Color; +import minicraft.gfx.Font; +import minicraft.gfx.MinicraftImage; +import minicraft.gfx.Point; +import minicraft.gfx.Rectangle; +import minicraft.gfx.Screen; +import minicraft.screen.entry.StringEntry; + +import java.util.ArrayList; +import java.util.Arrays; + +public class Notification { + private static final int GAP = 10; + private static final int ANIMATION_TIME = 20; + + private final int expireTime; + private final Menu menu; + + private int tick = 0; + private int animationTick = 0; // 0 to ANIMATION_TIME, ANIMATION_TIME to 0 + + public Notification(String value) { + this(value, 240, Color.WHITE); + } // Default with 4 seconds + + public Notification(String value, int expireTime, int color) { + this.expireTime = expireTime; + menu = new Menu.Builder(true, 2, RelPos.RIGHT, + StringEntry.useLines(color, false, Font.getLines(value, + Screen.w - (GAP + MinicraftImage.boxWidth) * 2, Screen.h, 2))) + .setPositioning(new Point(Screen.w - GAP, Screen.h - GAP), RelPos.TOP_LEFT) + .createMenu(); + } + + public void tick() { + if (tick == 0 && animationTick < ANIMATION_TIME) animationTick++; + else if (tick < expireTime) tick++; + else if (tick == expireTime) animationTick--; + } + + public void render(Screen screen) { + Rectangle bounds = menu.getBounds(); + int width = bounds.getWidth(); + int curX = bounds.getLeft(); + int toX = Screen.w - (width + GAP) * animationTick / ANIMATION_TIME; // Shifting with animation (sliding) + menu.translate(toX - curX, 0); + menu.render(screen); + } + + public boolean isExpired() { + return tick >= expireTime && animationTick <= 0; + } +} diff --git a/src/client/java/minicraft/screen/TutorialDisplayHandler.java b/src/client/java/minicraft/screen/TutorialDisplayHandler.java index 1e86d9ea0..2475a15be 100644 --- a/src/client/java/minicraft/screen/TutorialDisplayHandler.java +++ b/src/client/java/minicraft/screen/TutorialDisplayHandler.java @@ -152,7 +152,7 @@ public static void turnOffTutorials() { currentOngoingElement = null; Settings.set("tutorials", false); Logging.TUTORIAL.debug("Tutorial completed."); - Game.notifications.add(Localization.getLocalized("minicraft.notification.tutorial_completed")); + Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.tutorial_completed")); } private static void turnOffGuides() { From b9879e46092f1432523933c79c5f36eeeda57fd0 Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Sun, 19 Nov 2023 16:32:02 +0800 Subject: [PATCH 2/8] Change notification max width to half of screen --- src/client/java/minicraft/screen/Notification.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/java/minicraft/screen/Notification.java b/src/client/java/minicraft/screen/Notification.java index 4c2e85ca8..e68a735cd 100644 --- a/src/client/java/minicraft/screen/Notification.java +++ b/src/client/java/minicraft/screen/Notification.java @@ -30,7 +30,7 @@ public Notification(String value, int expireTime, int color) { this.expireTime = expireTime; menu = new Menu.Builder(true, 2, RelPos.RIGHT, StringEntry.useLines(color, false, Font.getLines(value, - Screen.w - (GAP + MinicraftImage.boxWidth) * 2, Screen.h, 2))) + Screen.w / 2 - (GAP + MinicraftImage.boxWidth) * 2, Screen.h, 2))) .setPositioning(new Point(Screen.w - GAP, Screen.h - GAP), RelPos.TOP_LEFT) .createMenu(); } From beb692b1ae10e995a557d7c0a294a2ecf56fbbef Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Fri, 9 Feb 2024 11:49:19 +0800 Subject: [PATCH 3/8] Add AppToast in place of Notification --- src/client/java/minicraft/core/Game.java | 4 +- src/client/java/minicraft/core/Renderer.java | 4 +- src/client/java/minicraft/core/Updater.java | 4 +- .../java/minicraft/screen/AppToast.java | 183 ++++++++++++++++++ .../java/minicraft/screen/Notification.java | 56 ------ .../java/minicraft/screen/TitleDisplay.java | 9 + .../resources/assets/textures/gui/toasts.png | Bin 0 -> 425 bytes 7 files changed, 198 insertions(+), 62 deletions(-) create mode 100644 src/client/java/minicraft/screen/AppToast.java delete mode 100644 src/client/java/minicraft/screen/Notification.java create mode 100644 src/client/resources/assets/textures/gui/toasts.png diff --git a/src/client/java/minicraft/core/Game.java b/src/client/java/minicraft/core/Game.java index 2f9ddd236..03d4f48e0 100644 --- a/src/client/java/minicraft/core/Game.java +++ b/src/client/java/minicraft/core/Game.java @@ -10,7 +10,7 @@ import minicraft.saveload.Load; import minicraft.saveload.Version; import minicraft.screen.Display; -import minicraft.screen.Notification; +import minicraft.screen.AppToast; import minicraft.screen.ResourcePackDisplay; import minicraft.screen.TitleDisplay; import minicraft.util.Logging; @@ -32,7 +32,7 @@ protected Game() { public static Player player; public static List inGameNotifications = new ArrayList<>(); - public static ArrayDeque inAppNotifications = new ArrayDeque<>(); + public static ArrayDeque inAppNotifications = new ArrayDeque<>(); public static int MAX_FPS; diff --git a/src/client/java/minicraft/core/Renderer.java b/src/client/java/minicraft/core/Renderer.java index d1b99c84d..39605d33d 100644 --- a/src/client/java/minicraft/core/Renderer.java +++ b/src/client/java/minicraft/core/Renderer.java @@ -27,7 +27,7 @@ import minicraft.level.Level; import minicraft.screen.LoadingDisplay; import minicraft.screen.Menu; -import minicraft.screen.Notification; +import minicraft.screen.AppToast; import minicraft.screen.QuestsDisplay; import minicraft.screen.RelPos; import minicraft.screen.TutorialDisplayHandler; @@ -124,7 +124,7 @@ public static void render() { if (currentDisplay != null) // Renders menu, if present. currentDisplay.render(screen); - Notification notification; + AppToast notification; if ((notification = inAppNotifications.peek()) != null) { notification.render(screen); } diff --git a/src/client/java/minicraft/core/Updater.java b/src/client/java/minicraft/core/Updater.java index f22be41e8..02f0f1c7b 100644 --- a/src/client/java/minicraft/core/Updater.java +++ b/src/client/java/minicraft/core/Updater.java @@ -11,7 +11,7 @@ import minicraft.screen.Display; import minicraft.screen.EndGameDisplay; import minicraft.screen.LevelTransitionDisplay; -import minicraft.screen.Notification; +import minicraft.screen.AppToast; import minicraft.screen.PlayerDeathDisplay; import minicraft.screen.TutorialDisplayHandler; import minicraft.screen.WorldSelectDisplay; @@ -179,7 +179,7 @@ public static void tick() { } if (updateNoteTick) notetick++; - Notification notification; + AppToast notification; if ((notification = inAppNotifications.peek()) != null) { boolean refresh = true; if (notification.isExpired()) { diff --git a/src/client/java/minicraft/screen/AppToast.java b/src/client/java/minicraft/screen/AppToast.java new file mode 100644 index 000000000..6b050aadf --- /dev/null +++ b/src/client/java/minicraft/screen/AppToast.java @@ -0,0 +1,183 @@ +package minicraft.screen; + +import minicraft.gfx.Color; +import minicraft.gfx.Dimension; +import minicraft.gfx.Font; +import minicraft.gfx.FontStyle; +import minicraft.gfx.Insets; +import minicraft.gfx.MinicraftImage; +import minicraft.gfx.Point; +import minicraft.gfx.Rectangle; +import minicraft.gfx.Screen; +import minicraft.gfx.Sprite; +import minicraft.gfx.SpriteLinker; +import minicraft.screen.entry.StringEntry; +import org.intellij.lang.annotations.MagicConstant; + +import java.util.Arrays; +import java.util.List; + +public class AppToast { + private static final int TOP_PADDING = 30; + private static final int BOTTOM_PADDING = 30; + private static final int MAX_WIDTH = Screen.w * 3 / 8; + private static final int MAX_HEIGHT = Screen.w * 3 / 8; + private static final int SPACING = 2; + private static final int ANIMATION_TIME = 12; + + @MagicConstant(intValues = {0, 1}) + private static int positioning = 0; + + public static void setPositionTop() { + positioning = 0; + } + public static void setPositionBottom() { + positioning = 1; + } + + private final int expireTime; + private final Dimension size; + private final List text; + private final AppToastFrame frame; + private final int color; + + private int tick = 0; + private int animationTick = 0; // 0 to ANIMATION_TIME, ANIMATION_TIME to 0 + + public static abstract class AppToastFrame { + public static final AppToastFrame FRAME_GENERAL = new GeneralAppToastFrame(); + public static final AppToastFrame FRAME_URGENT = new UrgentAppToastFrame(); + public static final AppToastFrame FRAME_WINDOW = new WindowAppToastFrame(); + public static final AppToastFrame FRAME_BRICK = new BrickAppToastFrame(); + + protected final Insets paddings; + + protected AppToastFrame(Insets paddings) { + this.paddings = paddings; + } + + public abstract void render(Screen screen, int x, int y, int w, int h); // w, h in units of cells + + protected void render(Screen screen, int x, int y, int w, int h, Sprite sprite) { + for (int i = 0; i < w; ++i) { + for (int j = 0; j < h; ++j) { + Sprite.Px[][] pxs = sprite.spritePixels; + if (i == 0 && j == 0) + screen.render(x, y, pxs[0][0]); + else if (i == 0 && j == h - 1) + screen.render(x, y + j * 8, pxs[2][0]); + else if (i == w - 1 && j == 0) + screen.render(x + i * 8, y, pxs[0][2]); + else if (i == w - 1 && j == h - 1) + screen.render(x + i * 8, y + j * 8, pxs[2][2]); + else if (i == 0) + screen.render(x, y + j * 8, pxs[1][0]); + else if (j == 0) + screen.render(x + i * 8, y, pxs[0][1]); + else if (i == w - 1) + screen.render(x + i * 8, y + j * 8, pxs[1][2]); + else if (j == h - 1) + screen.render(x + i * 8, y + j * 8, pxs[2][1]); + else + screen.render(x + i * 8, y + j * 8, pxs[1][1]); + } + } + } + + private static class GeneralAppToastFrame extends AppToastFrame { + private static final SpriteLinker.LinkedSprite sprite = + new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(0, 0, 3, 3); + + private GeneralAppToastFrame() { + super(new Insets(4)); + } + + @Override + public void render(Screen screen, int x, int y, int w, int h) { + render(screen, x, y, w, h, sprite.getSprite()); + } + } + + private static class UrgentAppToastFrame extends AppToastFrame { + private static final SpriteLinker.LinkedSprite sprite = + new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(3, 0, 3, 3); + + private UrgentAppToastFrame() { + super(new Insets(4)); + } + + @Override + public void render(Screen screen, int x, int y, int w, int h) { + render(screen, x, y, w, h, sprite.getSprite()); + } + } + + private static class WindowAppToastFrame extends AppToastFrame { + private static final SpriteLinker.LinkedSprite sprite = + new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(0, 3, 3, 3); + + private WindowAppToastFrame() { + super(new Insets(6, 4, 2, 8)); + } + + @Override + public void render(Screen screen, int x, int y, int w, int h) { + render(screen, x, y, w, h, sprite.getSprite()); + } + } + + private static class BrickAppToastFrame extends AppToastFrame { + private static final SpriteLinker.LinkedSprite sprite = + new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(3, 3, 3, 3); + + private BrickAppToastFrame() { + super(new Insets(6, 6, 2, 6)); + } + + @Override + public void render(Screen screen, int x, int y, int w, int h) { + render(screen, x, y, w, h, sprite.getSprite()); + } + } + } + + public AppToast(AppToastFrame frame, String message) { + this(frame, message, 180, Color.WHITE); // Default with 3 seconds + } + + public AppToast(AppToastFrame frame, String message, int expireTime, int color) { // Align left + this.expireTime = expireTime; + this.frame = frame; + this.color = color; + String[] lines = Font.getLines(message, MAX_WIDTH - frame.paddings.left - frame.paddings.right, + MAX_HEIGHT - frame.paddings.top - frame.paddings.bottom, SPACING); + size = new Dimension((Font.textWidth(lines) + frame.paddings.left + frame.paddings.right + 7) / 8 * 8, + (Math.max(0, lines.length * Font.textHeight() + + SPACING * (lines.length - 1) + frame.paddings.top + frame.paddings.bottom) + 7) / 8 * 8); + // There is little a chance that the resultant height may still exceed the max height, but the problem is negligible. + text = Arrays.asList(lines); + } + + public void tick() { + if (tick == 0 && animationTick < ANIMATION_TIME) animationTick++; + else if (tick < expireTime) tick++; + else if (tick == expireTime) animationTick--; + } + + public void render(Screen screen) { + int x = Screen.w - size.width * animationTick / ANIMATION_TIME; // Shifting with animation (sliding) + int y = positioning == 0 ? TOP_PADDING : Screen.h - BOTTOM_PADDING - size.height; + frame.render(screen, x, y, size.width / 8, size.height / 8); + Font.drawParagraph(text, screen, new FontStyle(color) + .setAnchor(x + frame.paddings.left, y + frame.paddings.top) + .setRelTextPos(RelPos.BOTTOM_RIGHT, true), SPACING); + } + + public boolean isExpired() { + return tick >= expireTime && animationTick <= 0; + } +} diff --git a/src/client/java/minicraft/screen/Notification.java b/src/client/java/minicraft/screen/Notification.java deleted file mode 100644 index e68a735cd..000000000 --- a/src/client/java/minicraft/screen/Notification.java +++ /dev/null @@ -1,56 +0,0 @@ -package minicraft.screen; - -import minicraft.core.io.Localization; -import minicraft.gfx.Color; -import minicraft.gfx.Font; -import minicraft.gfx.MinicraftImage; -import minicraft.gfx.Point; -import minicraft.gfx.Rectangle; -import minicraft.gfx.Screen; -import minicraft.screen.entry.StringEntry; - -import java.util.ArrayList; -import java.util.Arrays; - -public class Notification { - private static final int GAP = 10; - private static final int ANIMATION_TIME = 20; - - private final int expireTime; - private final Menu menu; - - private int tick = 0; - private int animationTick = 0; // 0 to ANIMATION_TIME, ANIMATION_TIME to 0 - - public Notification(String value) { - this(value, 240, Color.WHITE); - } // Default with 4 seconds - - public Notification(String value, int expireTime, int color) { - this.expireTime = expireTime; - menu = new Menu.Builder(true, 2, RelPos.RIGHT, - StringEntry.useLines(color, false, Font.getLines(value, - Screen.w / 2 - (GAP + MinicraftImage.boxWidth) * 2, Screen.h, 2))) - .setPositioning(new Point(Screen.w - GAP, Screen.h - GAP), RelPos.TOP_LEFT) - .createMenu(); - } - - public void tick() { - if (tick == 0 && animationTick < ANIMATION_TIME) animationTick++; - else if (tick < expireTime) tick++; - else if (tick == expireTime) animationTick--; - } - - public void render(Screen screen) { - Rectangle bounds = menu.getBounds(); - int width = bounds.getWidth(); - int curX = bounds.getLeft(); - int toX = Screen.w - (width + GAP) * animationTick / ANIMATION_TIME; // Shifting with animation (sliding) - menu.translate(toX - curX, 0); - menu.render(screen); - } - - public boolean isExpired() { - return tick >= expireTime && animationTick <= 0; - } -} diff --git a/src/client/java/minicraft/screen/TitleDisplay.java b/src/client/java/minicraft/screen/TitleDisplay.java index de083b95f..eb090d143 100644 --- a/src/client/java/minicraft/screen/TitleDisplay.java +++ b/src/client/java/minicraft/screen/TitleDisplay.java @@ -106,6 +106,15 @@ private void checkVersion() { public void tick(InputHandler input) { if (input.getMappedKey("F3-r").isClicked()) rand = random.nextInt(splashes.length - 3) + 3; + if (input.getMappedKey("1").isClicked()) + Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_GENERAL, "General TEST MESSAGE")); + if (input.getMappedKey("2").isClicked()) + Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_URGENT, "URGENT TEST MESSAGE")); + if (input.getMappedKey("3").isClicked()) + Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_WINDOW, "WiNdOw TEST MESSAGE")); + if (input.getMappedKey("4").isClicked()) + Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_BRICK, "BricK TEST MESSAGE")); + super.tick(input); } diff --git a/src/client/resources/assets/textures/gui/toasts.png b/src/client/resources/assets/textures/gui/toasts.png new file mode 100644 index 0000000000000000000000000000000000000000..885645360bdbc011a4a5e6bceaec913f34255d70 GIT binary patch literal 425 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`1!2l#}z-nen&^5x6hw{Ks=%X*H7?ew{Gjtg#UH*A&8Up#Z>%!3CH8V8+Q zwQALwGiM|%wqCn-O(FB3gx^FCmC47B9Rr%NQE^)qkPd=! zz0Y+i7Rs0&Yq0ik7rDo>OYmrt+3WOtG@Q<3bSpT1rOI%nlGx3f3@2yDIwr<7Q<>4M!EA&GmgseGP`Al zHXPT`W%#?|u#TF8;|j(-jBGh9KEh@DvlztERIf07mSO$pdT;+LhFFGstp?qi4D-1g zgeSD>Co?^Gy6CI=TmQ2MPVpEx7#(0xTEzcw?-O&K87t-ieaGPG>gTe~DWM4fT>Y}- literal 0 HcmV?d00001 From 5cc21682bbf9c8e79d14e688b08c5a0784c95868 Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Fri, 9 Feb 2024 17:36:31 +0800 Subject: [PATCH 4/8] Add AppStatusBar --- src/client/java/minicraft/core/Renderer.java | 128 ++++++++++++++++++ src/client/java/minicraft/core/Updater.java | 3 + .../java/minicraft/screen/TitleDisplay.java | 9 -- .../assets/textures/gui/app_status_bar.png | Bin 0 -> 737 bytes 4 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 src/client/resources/assets/textures/gui/app_status_bar.png diff --git a/src/client/java/minicraft/core/Renderer.java b/src/client/java/minicraft/core/Renderer.java index 39605d33d..961f01403 100644 --- a/src/client/java/minicraft/core/Renderer.java +++ b/src/client/java/minicraft/core/Renderer.java @@ -35,6 +35,7 @@ import minicraft.screen.entry.StringEntry; import minicraft.util.Quest; import minicraft.util.Quest.QuestSeries; +import org.intellij.lang.annotations.MagicConstant; import javax.imageio.ImageIO; @@ -107,6 +108,7 @@ public static void initScreen() { hudSheet = new LinkedSprite(SpriteType.Gui, "hud"); canvas.createBufferStrategy(3); + appStatusBar.initialize(); } @@ -124,6 +126,8 @@ public static void render() { if (currentDisplay != null) // Renders menu, if present. currentDisplay.render(screen); + appStatusBar.render(); + AppToast notification; if ((notification = inAppNotifications.peek()) != null) { notification.render(screen); @@ -189,6 +193,130 @@ public static void render() { } } + public static final AppStatusBar appStatusBar = new AppStatusBar(); + + public static class AppStatusBar { + private static final int DURATION_ON_UPDATE = 90; // 1.5s + + public final AppStatusElement HARDWARE_ACCELERATION_STATUS = new HardwareAccelerationElementStatus(); + + private AppStatusBar() {} + + private int duration = 120; // Shows for 2 seconds initially. + + private void render() { + if (duration == 0) return; + + MinicraftImage sheet = spriteLinker.getSheet(SpriteType.Gui, "app_status_bar"); // Obtains sheet. + + // Background + for (int x = 0; x < 12; ++x) { + for (int y = 0; y < 2; ++y) { + screen.render(Screen.w - 16 * 8 + x * 8, y * 8, x, y, 0, sheet); + } + } + + // Hardware Acceleration Status (width = 16) + HARDWARE_ACCELERATION_STATUS.render(Screen.w - 16 * 8 + 5, 2, sheet); + } + + void tick() { + if (duration > 0) + duration--; + } + + void show(int duration) { + this.duration = Math.max(this.duration, duration); + } + + private void onStatusUpdate() { + show(DURATION_ON_UPDATE); + } + + private void initialize() { + HARDWARE_ACCELERATION_STATUS.initialize(); + } + + public abstract class AppStatusElement { + // width == 16 - size * 2 + protected final int size; // 0: largest, 1: smaller, etc. (gradually) + + private AppStatusElement(int size) { + this.size = size; + } + + private static final int BLINK_PERIOD = 10; // 6 Hz + + private int durationUpdated = 0; + private boolean blinking = false; + private int blinkTick = 0; + + protected void render(int x, int y, MinicraftImage sheet) { + if (durationUpdated > 0) { + durationUpdated--; + if (blinkTick == 0) { + blinkTick = BLINK_PERIOD; + blinking = !blinking; + } else blinkTick--; + if (blinking) { + screen.render(x, y, 10, 3 + size, 0, sheet); + } + } + } + + protected void tick() { + + } + + protected void updateStatus() { + durationUpdated = DURATION_ON_UPDATE; + blinking = false; + blinkTick = 0; + onStatusUpdate(); + } + + public abstract void updateStatus(int status); + + protected void initialize() {} + } + + public class HardwareAccelerationElementStatus extends AppStatusElement { + public final int ACCELERATION_ON = 0; + public final int ACCELERATION_OFF = 1; + + @MagicConstant(intValues = {ACCELERATION_ON, ACCELERATION_OFF}) + private int status = ACCELERATION_ON; + + private HardwareAccelerationElementStatus() { + super(0); + } + + @Override + protected void initialize() { + status = Boolean.parseBoolean(System.getProperty("sun.java2d.opengl")) ? + ACCELERATION_ON : ACCELERATION_OFF; + } + + @Override + protected void render(int x, int y, MinicraftImage sheet) { + super.render(x, y, sheet); + if (status == ACCELERATION_ON) { + for (int xx = 0; xx < 2; ++xx) + screen.render(x + xx * 8, y, xx, 4, 0, sheet); + } else { + for (int xx = 0; xx < 2; ++xx) + screen.render(x + xx * 8, y, 2 + xx, 4, 0, sheet); + } + } + + @Override + public void updateStatus(int status) { + super.updateStatus(); + this.status = status; + } + } + } + private static void renderLevel() { Level level = levels[currentLevel]; diff --git a/src/client/java/minicraft/core/Updater.java b/src/client/java/minicraft/core/Updater.java index 02f0f1c7b..9374d7f62 100644 --- a/src/client/java/minicraft/core/Updater.java +++ b/src/client/java/minicraft/core/Updater.java @@ -178,6 +178,9 @@ public static void tick() { scoreTime--; } + Renderer.appStatusBar.tick(); + if (input.getMappedKey("9").isDown()) + Renderer.appStatusBar.show(1); if (updateNoteTick) notetick++; AppToast notification; if ((notification = inAppNotifications.peek()) != null) { diff --git a/src/client/java/minicraft/screen/TitleDisplay.java b/src/client/java/minicraft/screen/TitleDisplay.java index eb090d143..de083b95f 100644 --- a/src/client/java/minicraft/screen/TitleDisplay.java +++ b/src/client/java/minicraft/screen/TitleDisplay.java @@ -106,15 +106,6 @@ private void checkVersion() { public void tick(InputHandler input) { if (input.getMappedKey("F3-r").isClicked()) rand = random.nextInt(splashes.length - 3) + 3; - if (input.getMappedKey("1").isClicked()) - Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_GENERAL, "General TEST MESSAGE")); - if (input.getMappedKey("2").isClicked()) - Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_URGENT, "URGENT TEST MESSAGE")); - if (input.getMappedKey("3").isClicked()) - Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_WINDOW, "WiNdOw TEST MESSAGE")); - if (input.getMappedKey("4").isClicked()) - Game.inAppNotifications.add(new AppToast(AppToast.AppToastFrame.FRAME_BRICK, "BricK TEST MESSAGE")); - super.tick(input); } diff --git a/src/client/resources/assets/textures/gui/app_status_bar.png b/src/client/resources/assets/textures/gui/app_status_bar.png new file mode 100644 index 0000000000000000000000000000000000000000..8cc9deb7124306a8cb63a9c586f309485aff365c GIT binary patch literal 737 zcmeAS@N?(olHy`uVBq!ia0vp^2|#SY!3-o#XY)<~QjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`T?2eVT-g=u`DIF_cuyV_7B-hC@?t3EXOK({DAJj~NYKtccm4v7s?Q8u zB3a4DIJSOfGO(AKdxKd>QbIybR#r}cPt)Ao9%#}8jlg;!C0-Kb7yKV9V0h;6EDorI zv%n*=n1O-sFbFdq&tH+kz`(@h>Eaj?;r@17XWk(L0T=Jy;;&7Yp8dDqYP>mHeHrU4 zjX>9_>aAbB&e`O!Pi+5}_V%JEgez^3e;PhDwsY4u?TyEG7!>TgtM8bjl(9+CO!1h(m(b`&GwE0B*kaAD z{N8m;s3?Bx!c|RYr!UA%$VfVD=qNv7{_kzA3)e>F|6bR;aJ6;*O=J7-Gvp_%|0!Y+ zqy1t1nM4lf^95@UOg{i5_8YaI@wZ*x_TaOxKqZq76LVhRJHd0p34$EYIXC>dk*u`+ z#547S0Tvg29#~+eD&Dm427|ke(2c*57nUbz|Eqc0WZl(tWKqU}bdB$if2#`k#|fX0 zQ~y-d#vON_C7+vnN`HULr;mor=g)c^$k0)cmgr?YV^oo+#<{~WnbADMl5x>-?u0LQ zSYxc77}ft{ixn0*Q`6G$JWa!*<6pzXXELt!M?C(T*xY!?-@B5>pJ|!VpK~mWbtfg< z)J@uRDfU3cQhn76-+EYX&9fFNXrGcZzi0XZlgS@b+?hVUyQ;A}vtoFAKTxW zy|QAP!NHS1Eav90N$)#)#-w7~4xJ0LCv6S>m{S-i@Yr*`QSpbIiLCP(j;1YWZCI~= z&Hu<|*NsdG#uk$f+yZMpRIx3>HDD8G9tdq(@P0o-uCvqiKWusbfJubG)78&qol`;+ E0Qd((8vp Date: Fri, 9 Feb 2024 19:41:13 +0800 Subject: [PATCH 5/8] Add Achievement Toast in place of notifications --- src/client/java/minicraft/core/Game.java | 4 +- src/client/java/minicraft/core/Renderer.java | 12 +- src/client/java/minicraft/core/Updater.java | 23 +++- src/client/java/minicraft/gfx/Color.java | 1 + .../minicraft/screen/AchievementsDisplay.java | 61 +++++++++- .../java/minicraft/screen/AppToast.java | 113 ++++-------------- .../java/minicraft/screen/GameToast.java | 7 ++ src/client/java/minicraft/screen/Toast.java | 80 +++++++++++++ .../resources/assets/localization/en-us.json | 2 +- .../resources/assets/textures/gui/toasts.png | Bin 425 -> 496 bytes 10 files changed, 198 insertions(+), 105 deletions(-) create mode 100644 src/client/java/minicraft/screen/GameToast.java create mode 100644 src/client/java/minicraft/screen/Toast.java diff --git a/src/client/java/minicraft/core/Game.java b/src/client/java/minicraft/core/Game.java index 03d4f48e0..5754b21e3 100644 --- a/src/client/java/minicraft/core/Game.java +++ b/src/client/java/minicraft/core/Game.java @@ -11,6 +11,7 @@ import minicraft.saveload.Version; import minicraft.screen.Display; import minicraft.screen.AppToast; +import minicraft.screen.GameToast; import minicraft.screen.ResourcePackDisplay; import minicraft.screen.TitleDisplay; import minicraft.util.Logging; @@ -32,7 +33,8 @@ protected Game() { public static Player player; public static List inGameNotifications = new ArrayList<>(); - public static ArrayDeque inAppNotifications = new ArrayDeque<>(); + public static ArrayDeque inAppToasts = new ArrayDeque<>(); + public static ArrayDeque inGameToasts = new ArrayDeque<>(); // Canvas size is limited, so handled one by one public static int MAX_FPS; diff --git a/src/client/java/minicraft/core/Renderer.java b/src/client/java/minicraft/core/Renderer.java index 961f01403..5bcf7b419 100644 --- a/src/client/java/minicraft/core/Renderer.java +++ b/src/client/java/minicraft/core/Renderer.java @@ -25,6 +25,7 @@ import minicraft.item.ToolType; import minicraft.item.WateringCanItem; import minicraft.level.Level; +import minicraft.screen.GameToast; import minicraft.screen.LoadingDisplay; import minicraft.screen.Menu; import minicraft.screen.AppToast; @@ -128,9 +129,9 @@ public static void render() { appStatusBar.render(); - AppToast notification; - if ((notification = inAppNotifications.peek()) != null) { - notification.render(screen); + AppToast toast; + if ((toast = inAppToasts.peek()) != null) { + toast.render(screen); } if (!canvas.hasFocus()) @@ -556,6 +557,11 @@ private static void renderGui() { TutorialDisplayHandler.render(screen); renderQuestsDisplay(); renderDebugInfo(); + + GameToast toast; + if ((toast = inGameToasts.peek()) != null) { + toast.render(screen); + } } public static void renderBossbar(int length, String title) { diff --git a/src/client/java/minicraft/core/Updater.java b/src/client/java/minicraft/core/Updater.java index 9374d7f62..04057047f 100644 --- a/src/client/java/minicraft/core/Updater.java +++ b/src/client/java/minicraft/core/Updater.java @@ -10,6 +10,7 @@ import minicraft.saveload.Save; import minicraft.screen.Display; import minicraft.screen.EndGameDisplay; +import minicraft.screen.GameToast; import minicraft.screen.LevelTransitionDisplay; import minicraft.screen.AppToast; import minicraft.screen.PlayerDeathDisplay; @@ -182,15 +183,15 @@ public static void tick() { if (input.getMappedKey("9").isDown()) Renderer.appStatusBar.show(1); if (updateNoteTick) notetick++; - AppToast notification; - if ((notification = inAppNotifications.peek()) != null) { + AppToast appToast; + if ((appToast = inAppToasts.peek()) != null) { boolean refresh = true; - if (notification.isExpired()) { - inAppNotifications.pop(); // Removes - refresh = (notification = inAppNotifications.peek()) != null; // Tries getting new + if (appToast.isExpired()) { + inAppToasts.pop(); // Removes + refresh = (appToast = inAppToasts.peek()) != null; // Tries getting new } - if (refresh) notification.tick(); + if (refresh) appToast.tick(); } // This is the general action statement thing! Regulates menus, mostly. @@ -227,6 +228,16 @@ public static void tick() { } player.tick(); // Ticks the player when there's no menu. + GameToast gameToast; + if ((gameToast = inGameToasts.peek()) != null) { + boolean refresh = true; + if (gameToast.isExpired()) { + inGameToasts.pop(); // Removes + refresh = (gameToast = inGameToasts.peek()) != null; // Tries getting new + } + + if (refresh) gameToast.tick(); + } if (level != null) { level.tick(true); diff --git a/src/client/java/minicraft/gfx/Color.java b/src/client/java/minicraft/gfx/Color.java index b71ed651a..ed18dc546 100644 --- a/src/client/java/minicraft/gfx/Color.java +++ b/src/client/java/minicraft/gfx/Color.java @@ -36,6 +36,7 @@ public class Color { public static final int YELLOW = Color.get(1, 255, 255, 0); public static final int MAGENTA = Color.get(1, 255, 0, 255); public static final int CYAN = Color.get(1, 90, 204, 204); + public static final int GOLD = Color.get(1, 255, 193, 37); public static final char COLOR_CHAR = '\u00A7'; diff --git a/src/client/java/minicraft/screen/AchievementsDisplay.java b/src/client/java/minicraft/screen/AchievementsDisplay.java index d1ce460a4..cce138a79 100644 --- a/src/client/java/minicraft/screen/AchievementsDisplay.java +++ b/src/client/java/minicraft/screen/AchievementsDisplay.java @@ -1,13 +1,19 @@ package minicraft.screen; import minicraft.core.Game; +import minicraft.core.Renderer; import minicraft.core.io.InputHandler; import minicraft.core.io.Localization; import minicraft.core.io.Sound; import minicraft.gfx.Color; +import minicraft.gfx.Dimension; import minicraft.gfx.Font; +import minicraft.gfx.FontStyle; +import minicraft.gfx.Insets; +import minicraft.gfx.MinicraftImage; import minicraft.gfx.Point; import minicraft.gfx.Screen; +import minicraft.gfx.SpriteLinker; import minicraft.saveload.Save; import minicraft.screen.entry.ListEntry; import minicraft.screen.entry.SelectEntry; @@ -24,8 +30,10 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; public class AchievementsDisplay extends Display { @@ -169,9 +177,9 @@ private static boolean setAchievement(String id, boolean unlocked, boolean save, achievementScore += a.score; // Tells the player that they got an achievement. - Game.inGameNotifications.add(Localization.getLocalized("minicraft.notification.achievement_unlocked", Localization.getLocalized(id))); + Game.inGameToasts.add(new AchievementUnlockToast(id)); } else - achievementScore -= a.score; + achievementScore -= a.score; // Logical? // Save the new list of achievements stored in memory. if (save) new Save(); @@ -179,6 +187,55 @@ private static boolean setAchievement(String id, boolean unlocked, boolean save, return true; } + private static class AchievementUnlockToast extends GameToast { + private static final int ICON_PADDING = 16; // 16 pixels wide space is reserved. + + private static final AchievementUnlockToastFrame FRAME = new AchievementUnlockToastFrame(); + + private static class AchievementUnlockToastFrame extends ToastFrame { + private static final SpriteLinker.LinkedSprite sprite = + new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(0, 6, 3, 3); + + protected AchievementUnlockToastFrame() { + super(new Insets(3)); + } + + @Override + public void render(Screen screen, int x, int y, int w, int h) { + render(screen, x, y, w, h, sprite.getSprite()); + } + } + + private final String title = Localization.getLocalized( + "minicraft.toast.achievements.achievement_unlocked.title"); + private final String name; + private final Dimension size; + + public AchievementUnlockToast(String id) { + super(240); // 4 seconds + name = Localization.getLocalized(id); + size = new Dimension((Math.max(Font.textWidth(name), Font.textWidth(title)) + + FRAME.paddings.left + FRAME.paddings.right + ICON_PADDING + 7) / 8 * 8, + (Math.max(0, 2 * Font.textHeight() + SPACING + + FRAME.paddings.top + FRAME.paddings.bottom) + 7) / 8 * 8); + } + + @Override + public void render(Screen screen) { + // From the left + int x = -size.width * (ANIMATION_TIME - animationTick) / ANIMATION_TIME; // Shifting with animation (sliding) + int y = 0; + FRAME.render(screen, x, y, size.width / 8, size.height / 8); + screen.render(x + FRAME.paddings.left + (ICON_PADDING - MinicraftImage.boxWidth) / 2, + y + FRAME.paddings.top + MinicraftImage.boxWidth / 2, + Objects.requireNonNull(SpriteLinker.missingTexture(SpriteLinker.SpriteType.Item))); + Font.draw(title, screen, x + FRAME.paddings.left + ICON_PADDING, y + FRAME.paddings.top, Color.GOLD); + Font.draw(name, screen, x + FRAME.paddings.left + ICON_PADDING, + y + FRAME.paddings.top + SPACING + Font.textHeight(), Color.WHITE); + } + } + /** * Gets an array of all the unlocked achievements. * diff --git a/src/client/java/minicraft/screen/AppToast.java b/src/client/java/minicraft/screen/AppToast.java index 6b050aadf..1b1c863b8 100644 --- a/src/client/java/minicraft/screen/AppToast.java +++ b/src/client/java/minicraft/screen/AppToast.java @@ -5,25 +5,20 @@ import minicraft.gfx.Font; import minicraft.gfx.FontStyle; import minicraft.gfx.Insets; -import minicraft.gfx.MinicraftImage; -import minicraft.gfx.Point; -import minicraft.gfx.Rectangle; import minicraft.gfx.Screen; import minicraft.gfx.Sprite; import minicraft.gfx.SpriteLinker; -import minicraft.screen.entry.StringEntry; import org.intellij.lang.annotations.MagicConstant; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.List; -public class AppToast { +public class AppToast extends Toast { private static final int TOP_PADDING = 30; private static final int BOTTOM_PADDING = 30; private static final int MAX_WIDTH = Screen.w * 3 / 8; private static final int MAX_HEIGHT = Screen.w * 3 / 8; - private static final int SPACING = 2; - private static final int ANIMATION_TIME = 12; @MagicConstant(intValues = {0, 1}) private static int positioning = 0; @@ -35,112 +30,55 @@ public static void setPositionBottom() { positioning = 1; } - private final int expireTime; private final Dimension size; private final List text; private final AppToastFrame frame; private final int color; - private int tick = 0; - private int animationTick = 0; // 0 to ANIMATION_TIME, ANIMATION_TIME to 0 - - public static abstract class AppToastFrame { + public static abstract class AppToastFrame extends ToastFrame { public static final AppToastFrame FRAME_GENERAL = new GeneralAppToastFrame(); public static final AppToastFrame FRAME_URGENT = new UrgentAppToastFrame(); public static final AppToastFrame FRAME_WINDOW = new WindowAppToastFrame(); public static final AppToastFrame FRAME_BRICK = new BrickAppToastFrame(); - protected final Insets paddings; + protected final @Nullable SpriteLinker.LinkedSprite sprite; - protected AppToastFrame(Insets paddings) { - this.paddings = paddings; + protected AppToastFrame(@Nullable SpriteLinker.LinkedSprite sprite, Insets paddings) { + super(paddings); + this.sprite = sprite; } - public abstract void render(Screen screen, int x, int y, int w, int h); // w, h in units of cells - - protected void render(Screen screen, int x, int y, int w, int h, Sprite sprite) { - for (int i = 0; i < w; ++i) { - for (int j = 0; j < h; ++j) { - Sprite.Px[][] pxs = sprite.spritePixels; - if (i == 0 && j == 0) - screen.render(x, y, pxs[0][0]); - else if (i == 0 && j == h - 1) - screen.render(x, y + j * 8, pxs[2][0]); - else if (i == w - 1 && j == 0) - screen.render(x + i * 8, y, pxs[0][2]); - else if (i == w - 1 && j == h - 1) - screen.render(x + i * 8, y + j * 8, pxs[2][2]); - else if (i == 0) - screen.render(x, y + j * 8, pxs[1][0]); - else if (j == 0) - screen.render(x + i * 8, y, pxs[0][1]); - else if (i == w - 1) - screen.render(x + i * 8, y + j * 8, pxs[1][2]); - else if (j == h - 1) - screen.render(x + i * 8, y + j * 8, pxs[2][1]); - else - screen.render(x + i * 8, y + j * 8, pxs[1][1]); - } - } + @Override + public void render(Screen screen, int x, int y, int w, int h) { + assert sprite != null; // If sprite == null, this implementation should be overridden. + render(screen, x, y, w, h, sprite.getSprite()); } private static class GeneralAppToastFrame extends AppToastFrame { - private static final SpriteLinker.LinkedSprite sprite = - new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") - .setSpriteDim(0, 0, 3, 3); - private GeneralAppToastFrame() { - super(new Insets(4)); - } - - @Override - public void render(Screen screen, int x, int y, int w, int h) { - render(screen, x, y, w, h, sprite.getSprite()); + super(new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(0, 0, 3, 3), new Insets(4)); } } private static class UrgentAppToastFrame extends AppToastFrame { - private static final SpriteLinker.LinkedSprite sprite = - new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") - .setSpriteDim(3, 0, 3, 3); - private UrgentAppToastFrame() { - super(new Insets(4)); - } - - @Override - public void render(Screen screen, int x, int y, int w, int h) { - render(screen, x, y, w, h, sprite.getSprite()); + super(new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(3, 0, 3, 3), new Insets(4)); } } private static class WindowAppToastFrame extends AppToastFrame { - private static final SpriteLinker.LinkedSprite sprite = - new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") - .setSpriteDim(0, 3, 3, 3); - private WindowAppToastFrame() { - super(new Insets(6, 4, 2, 8)); - } - - @Override - public void render(Screen screen, int x, int y, int w, int h) { - render(screen, x, y, w, h, sprite.getSprite()); + super(new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(0, 3, 3, 3), new Insets(6, 4, 2, 8)); } } private static class BrickAppToastFrame extends AppToastFrame { - private static final SpriteLinker.LinkedSprite sprite = - new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") - .setSpriteDim(3, 3, 3, 3); - private BrickAppToastFrame() { - super(new Insets(6, 6, 2, 6)); - } - - @Override - public void render(Screen screen, int x, int y, int w, int h) { - render(screen, x, y, w, h, sprite.getSprite()); + super(new SpriteLinker.LinkedSprite(SpriteLinker.SpriteType.Gui, "toasts") + .setSpriteDim(3, 3, 3, 3), new Insets(6, 6, 2, 6)); } } } @@ -150,7 +88,7 @@ public AppToast(AppToastFrame frame, String message) { } public AppToast(AppToastFrame frame, String message, int expireTime, int color) { // Align left - this.expireTime = expireTime; + super(expireTime); this.frame = frame; this.color = color; String[] lines = Font.getLines(message, MAX_WIDTH - frame.paddings.left - frame.paddings.right, @@ -162,12 +100,7 @@ public AppToast(AppToastFrame frame, String message, int expireTime, int color) text = Arrays.asList(lines); } - public void tick() { - if (tick == 0 && animationTick < ANIMATION_TIME) animationTick++; - else if (tick < expireTime) tick++; - else if (tick == expireTime) animationTick--; - } - + @Override public void render(Screen screen) { int x = Screen.w - size.width * animationTick / ANIMATION_TIME; // Shifting with animation (sliding) int y = positioning == 0 ? TOP_PADDING : Screen.h - BOTTOM_PADDING - size.height; @@ -176,8 +109,4 @@ public void render(Screen screen) { .setAnchor(x + frame.paddings.left, y + frame.paddings.top) .setRelTextPos(RelPos.BOTTOM_RIGHT, true), SPACING); } - - public boolean isExpired() { - return tick >= expireTime && animationTick <= 0; - } } diff --git a/src/client/java/minicraft/screen/GameToast.java b/src/client/java/minicraft/screen/GameToast.java new file mode 100644 index 000000000..8cebb52a6 --- /dev/null +++ b/src/client/java/minicraft/screen/GameToast.java @@ -0,0 +1,7 @@ +package minicraft.screen; + +public abstract class GameToast extends Toast { + public GameToast(int expireTime) { + super(expireTime); + } +} diff --git a/src/client/java/minicraft/screen/Toast.java b/src/client/java/minicraft/screen/Toast.java new file mode 100644 index 000000000..fd6105017 --- /dev/null +++ b/src/client/java/minicraft/screen/Toast.java @@ -0,0 +1,80 @@ +package minicraft.screen; + +import minicraft.gfx.Dimension; +import minicraft.gfx.Insets; +import minicraft.gfx.Screen; +import minicraft.gfx.Sprite; + +import java.util.List; + +public abstract class Toast { + protected static final int SPACING = 2; + protected static final int ANIMATION_TIME = 12; + + protected final int expireTime; + + protected int tick = 0; + protected int animationTick = 0; // 0 to ANIMATION_TIME, ANIMATION_TIME to 0 + + protected static abstract class ToastFrame { + protected final Insets paddings; + + protected ToastFrame(Insets paddings) { + this.paddings = paddings; + } + + public abstract void render(Screen screen, int x, int y, int w, int h); // w, h in units of cells + + /* + * Standard Frame Texture Format + * + * 3 * 3 cells for a sprite + * [Top-left corner] [Top frame edge (pattern)] [Top-right corner] + * [Left frame edge (pattern)] [content background (pattern)] [Right frame edge (pattern)] + * [Bottom-left corner] [Bottom frame edge] [Bottom-right corner] + */ + + // Acts as a helper method in case some implementations may still use the standard texture formats. + protected void render(Screen screen, int x, int y, int w, int h, Sprite sprite) { + for (int i = 0; i < w; ++i) { + for (int j = 0; j < h; ++j) { + Sprite.Px[][] pxs = sprite.spritePixels; + if (i == 0 && j == 0) + screen.render(x, y, pxs[0][0]); + else if (i == 0 && j == h - 1) + screen.render(x, y + j * 8, pxs[2][0]); + else if (i == w - 1 && j == 0) + screen.render(x + i * 8, y, pxs[0][2]); + else if (i == w - 1 && j == h - 1) + screen.render(x + i * 8, y + j * 8, pxs[2][2]); + else if (i == 0) + screen.render(x, y + j * 8, pxs[1][0]); + else if (j == 0) + screen.render(x + i * 8, y, pxs[0][1]); + else if (i == w - 1) + screen.render(x + i * 8, y + j * 8, pxs[1][2]); + else if (j == h - 1) + screen.render(x + i * 8, y + j * 8, pxs[2][1]); + else + screen.render(x + i * 8, y + j * 8, pxs[1][1]); + } + } + } + } + + protected Toast(int expireTime) { + this.expireTime = expireTime; + } + + public void tick() { + if (tick == 0 && animationTick < ANIMATION_TIME) animationTick++; + else if (tick < expireTime) tick++; + else if (tick == expireTime) animationTick--; + } + + public abstract void render(Screen screen); + + public boolean isExpired() { + return tick >= expireTime && animationTick <= 0; + } +} diff --git a/src/client/resources/assets/localization/en-us.json b/src/client/resources/assets/localization/en-us.json index e10178853..e926c43cb 100644 --- a/src/client/resources/assets/localization/en-us.json +++ b/src/client/resources/assets/localization/en-us.json @@ -216,7 +216,6 @@ "minicraft.displays.world_select.popups.display.confirm": "%s to confirm", "minicraft.displays.world_select.popups.display.delete": "Are you sure you want to delete\n%s\"%s\"%s?\nThis can not be undone!", "minicraft.displays.world_select.select_world": "Select World", - "minicraft.notification.achievement_unlocked": "Achivement unlocked: %s", "minicraft.notification.air_wizard_defeated": "Air Wizard Defeated!", "minicraft.notification.obsidian_knight_defeated": "Obsidian Knight: Defeated!", "minicraft.notification.obsidian_knight_awoken": "The Obsidian Knight has awoken!", @@ -305,6 +304,7 @@ "minicraft.skin.minecraft_steve": "Familiar boy", "minicraft.skin.minecraft_alex": "Familiar girl", "minicraft.text_particales.key_consumed": "-1 key", + "minicraft.toast.achievements.achievement_unlocked.title": "Achievement Unlocked!", "minicraft.tutorial.getting_rocks": "Getting stones and coals", "minicraft.tutorial.getting_rocks.description": "Getting at least 5 stone and 5 coal items by destroying rocks with the pickaxe crafted.", "minicraft.tutorial.getting_wood": "Getting more wood", diff --git a/src/client/resources/assets/textures/gui/toasts.png b/src/client/resources/assets/textures/gui/toasts.png index 885645360bdbc011a4a5e6bceaec913f34255d70..8f735f60d75686c478db7341c9a3af7d8535ae52 100644 GIT binary patch delta 372 zcmV-)0gL{r1MmZo7YaxS0{{R3apVJmks%-fQISGG9S{s)4GBrl&g#Ly+ZYs+9vHF! z007AmsRRH302`5w7?Gd_fByg{Gz&EV000SaNLh0L01m?d01m?e$8V@)00032NklpEt3<07i?_0A^9|2I${Ve#HvB8&LlXe*!2W@1PW)wBn;$ z*i(QVw_kQ}?(3N9vWjA$Rr72Bt0)1!e-dF9BG1%@FA{EfQqoCoMU@S6y;kOJ_z05}1Q@Gv9*Uf#6+q}{0)SQ$Ap zCNg;ZI5NggDr;5?HZ)p0tE?UI{9!as^Pg&-Do}w6NELWBPHq)$32;bRa{vGi!vFvd!vV){sAK>D0MbcBK~z{r?bO>2f-n$8(JEd+3+Vj+w>nc# zY|GSyro1ux$xF_PA#ofv#(+CWM-<)!wks4iS&sLZCW+8>Csjdk#QXCi78t-Ns|;Y4 zv^PLMLwSk@> Date: Fri, 9 Feb 2024 21:08:09 +0800 Subject: [PATCH 6/8] Renderer AppStatusBar add missing tick method --- src/client/java/minicraft/core/Renderer.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/client/java/minicraft/core/Renderer.java b/src/client/java/minicraft/core/Renderer.java index 5bcf7b419..edb1398b6 100644 --- a/src/client/java/minicraft/core/Renderer.java +++ b/src/client/java/minicraft/core/Renderer.java @@ -207,7 +207,6 @@ private AppStatusBar() {} private void render() { if (duration == 0) return; - MinicraftImage sheet = spriteLinker.getSheet(SpriteType.Gui, "app_status_bar"); // Obtains sheet. // Background @@ -224,6 +223,7 @@ private void render() { void tick() { if (duration > 0) duration--; + HARDWARE_ACCELERATION_STATUS.tick(); } void show(int duration) { @@ -254,11 +254,6 @@ private AppStatusElement(int size) { protected void render(int x, int y, MinicraftImage sheet) { if (durationUpdated > 0) { - durationUpdated--; - if (blinkTick == 0) { - blinkTick = BLINK_PERIOD; - blinking = !blinking; - } else blinkTick--; if (blinking) { screen.render(x, y, 10, 3 + size, 0, sheet); } @@ -266,7 +261,13 @@ protected void render(int x, int y, MinicraftImage sheet) { } protected void tick() { - + if (durationUpdated > 0) { + durationUpdated--; + if (blinkTick == 0) { + blinkTick = BLINK_PERIOD; + blinking = !blinking; + } else blinkTick--; + } } protected void updateStatus() { From c491dad609f864119448f9c846a9141799b63132 Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Tue, 13 Feb 2024 18:29:09 +0800 Subject: [PATCH 7/8] Remove GameToast --- src/client/java/minicraft/core/Game.java | 4 ++-- src/client/java/minicraft/core/Renderer.java | 4 ++-- src/client/java/minicraft/core/Updater.java | 4 ++-- src/client/java/minicraft/screen/AchievementsDisplay.java | 5 +---- src/client/java/minicraft/screen/GameToast.java | 7 ------- 5 files changed, 7 insertions(+), 17 deletions(-) delete mode 100644 src/client/java/minicraft/screen/GameToast.java diff --git a/src/client/java/minicraft/core/Game.java b/src/client/java/minicraft/core/Game.java index 5754b21e3..980836d18 100644 --- a/src/client/java/minicraft/core/Game.java +++ b/src/client/java/minicraft/core/Game.java @@ -11,9 +11,9 @@ import minicraft.saveload.Version; import minicraft.screen.Display; import minicraft.screen.AppToast; -import minicraft.screen.GameToast; import minicraft.screen.ResourcePackDisplay; import minicraft.screen.TitleDisplay; +import minicraft.screen.Toast; import minicraft.util.Logging; import org.jetbrains.annotations.Nullable; @@ -34,7 +34,7 @@ protected Game() { public static List inGameNotifications = new ArrayList<>(); public static ArrayDeque inAppToasts = new ArrayDeque<>(); - public static ArrayDeque inGameToasts = new ArrayDeque<>(); // Canvas size is limited, so handled one by one + public static ArrayDeque inGameToasts = new ArrayDeque<>(); // Canvas size is limited, so handled one by one public static int MAX_FPS; diff --git a/src/client/java/minicraft/core/Renderer.java b/src/client/java/minicraft/core/Renderer.java index edb1398b6..dae8267aa 100644 --- a/src/client/java/minicraft/core/Renderer.java +++ b/src/client/java/minicraft/core/Renderer.java @@ -25,12 +25,12 @@ import minicraft.item.ToolType; import minicraft.item.WateringCanItem; import minicraft.level.Level; -import minicraft.screen.GameToast; import minicraft.screen.LoadingDisplay; import minicraft.screen.Menu; import minicraft.screen.AppToast; import minicraft.screen.QuestsDisplay; import minicraft.screen.RelPos; +import minicraft.screen.Toast; import minicraft.screen.TutorialDisplayHandler; import minicraft.screen.entry.ListEntry; import minicraft.screen.entry.StringEntry; @@ -559,7 +559,7 @@ private static void renderGui() { renderQuestsDisplay(); renderDebugInfo(); - GameToast toast; + Toast toast; if ((toast = inGameToasts.peek()) != null) { toast.render(screen); } diff --git a/src/client/java/minicraft/core/Updater.java b/src/client/java/minicraft/core/Updater.java index 04057047f..3d15f47f4 100644 --- a/src/client/java/minicraft/core/Updater.java +++ b/src/client/java/minicraft/core/Updater.java @@ -10,10 +10,10 @@ import minicraft.saveload.Save; import minicraft.screen.Display; import minicraft.screen.EndGameDisplay; -import minicraft.screen.GameToast; import minicraft.screen.LevelTransitionDisplay; import minicraft.screen.AppToast; import minicraft.screen.PlayerDeathDisplay; +import minicraft.screen.Toast; import minicraft.screen.TutorialDisplayHandler; import minicraft.screen.WorldSelectDisplay; import minicraft.util.AdvancementElement; @@ -228,7 +228,7 @@ public static void tick() { } player.tick(); // Ticks the player when there's no menu. - GameToast gameToast; + Toast gameToast; if ((gameToast = inGameToasts.peek()) != null) { boolean refresh = true; if (gameToast.isExpired()) { diff --git a/src/client/java/minicraft/screen/AchievementsDisplay.java b/src/client/java/minicraft/screen/AchievementsDisplay.java index cce138a79..756006072 100644 --- a/src/client/java/minicraft/screen/AchievementsDisplay.java +++ b/src/client/java/minicraft/screen/AchievementsDisplay.java @@ -1,14 +1,12 @@ package minicraft.screen; import minicraft.core.Game; -import minicraft.core.Renderer; import minicraft.core.io.InputHandler; import minicraft.core.io.Localization; import minicraft.core.io.Sound; import minicraft.gfx.Color; import minicraft.gfx.Dimension; import minicraft.gfx.Font; -import minicraft.gfx.FontStyle; import minicraft.gfx.Insets; import minicraft.gfx.MinicraftImage; import minicraft.gfx.Point; @@ -30,7 +28,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Objects; @@ -187,7 +184,7 @@ private static boolean setAchievement(String id, boolean unlocked, boolean save, return true; } - private static class AchievementUnlockToast extends GameToast { + private static class AchievementUnlockToast extends Toast { private static final int ICON_PADDING = 16; // 16 pixels wide space is reserved. private static final AchievementUnlockToastFrame FRAME = new AchievementUnlockToastFrame(); diff --git a/src/client/java/minicraft/screen/GameToast.java b/src/client/java/minicraft/screen/GameToast.java deleted file mode 100644 index 8cebb52a6..000000000 --- a/src/client/java/minicraft/screen/GameToast.java +++ /dev/null @@ -1,7 +0,0 @@ -package minicraft.screen; - -public abstract class GameToast extends Toast { - public GameToast(int expireTime) { - super(expireTime); - } -} From e962b570f8edef52be24cb2b14adc645cde02517 Mon Sep 17 00:00:00 2001 From: BenCheung0422 <74168521+BenCheung0422@users.noreply.github.com> Date: Sat, 17 Feb 2024 03:10:16 +0800 Subject: [PATCH 8/8] Change hot key to show status bar to back quote --- src/client/java/minicraft/core/Updater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/java/minicraft/core/Updater.java b/src/client/java/minicraft/core/Updater.java index 3d15f47f4..11a66c571 100644 --- a/src/client/java/minicraft/core/Updater.java +++ b/src/client/java/minicraft/core/Updater.java @@ -180,7 +180,7 @@ public static void tick() { } Renderer.appStatusBar.tick(); - if (input.getMappedKey("9").isDown()) + if (input.getMappedKey("BACK_QUOTE").isDown()) Renderer.appStatusBar.show(1); if (updateNoteTick) notetick++; AppToast appToast;