From d9d1cc4344219957e0eeae9afccf1d489b865760 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 01:38:53 +0200 Subject: [PATCH 01/13] feat: emissaries --- .../dwarvenmines/TypeDwarvenMinesLoader.java | 5 +- .../type/dwarvenmines/gui/GUICommisions.java | 31 +++++++++ .../type/dwarvenmines/npcs/EmissaryBraum.java | 66 +++++++++++++++++++ .../dwarvenmines/npcs/EmissaryCarlton.java | 44 +++++++++++++ .../dwarvenmines/npcs/EmissaryCeanna.java | 44 +++++++++++++ .../type/dwarvenmines/npcs/EmissaryEliza.java | 44 +++++++++++++ .../dwarvenmines/npcs/EmissaryFraiser.java | 44 +++++++++++++ .../dwarvenmines/npcs/EmissaryLilith.java | 44 +++++++++++++ .../dwarvenmines/npcs/EmissaryWilson.java | 44 +++++++++++++ .../data/datapoints/DatapointToggles.java | 1 + 10 files changed, 366 insertions(+), 1 deletion(-) create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/TypeDwarvenMinesLoader.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/TypeDwarvenMinesLoader.java index 381dfc4f5..7cd0c94d5 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/TypeDwarvenMinesLoader.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/TypeDwarvenMinesLoader.java @@ -5,6 +5,8 @@ import net.minestom.server.coordinate.Pos; import net.minestom.server.registry.RegistryKey; import net.minestom.server.world.DimensionType; +import net.minestom.server.world.biome.Biome; +import net.minestom.server.world.biome.BiomeEffects; import net.swofty.commons.CustomWorlds; import net.swofty.commons.ServerType; import net.swofty.commons.ServiceType; @@ -110,7 +112,8 @@ public List getRequiredServices() { return MinecraftServer.getDimensionTypeRegistry().register( Key.key("skyblock:dwarven_mines"), DimensionType.builder() - .ambientLight(0.4f) + .ambientLight(1f) .build()); } + } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java new file mode 100644 index 000000000..987eae8cd --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java @@ -0,0 +1,31 @@ +package net.swofty.type.dwarvenmines.gui; + +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; + +public class GUICommisions extends HypixelInventoryGUI { + + public GUICommisions() { + super("Commissions", InventoryType.CHEST_4_ROW); + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + fill(FILLER_ITEM); + + set(GUIClickableItem.getCloseItem(31)); + updateItemStacks(getInventory(), getPlayer()); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java new file mode 100644 index 000000000..c374ab24f --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java @@ -0,0 +1,66 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.data.datapoints.DatapointToggles; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryBraum extends HypixelNPC { + + public EmissaryBraum() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Braum", "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYyNDU0NjIwMjAwMiwKICAicHJvZmlsZUlkIiA6ICJmNDY0NTcxNDNkMTU0ZmEwOTkxNjBlNGJmNzI3ZGNiOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWxhcGFnbzA1IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzNiNmJiMDUyZmQ3NDM0NDliNTY0NTRlNDRjMTkxYTYwZTFkOWFmZTJmZmNlMGM3MTRlMWE1YjdiOGJjMzNmZTkiCiAgICB9CiAgfQp9"; + } + + @Override + public String signature(HypixelPlayer player) { + return "Dq8FhgjZhwXIOlyBfL3uKysAbeI9j7Q5jNFFFPpDbQ5xoq7USXP6PI/E18gTZG/1G7VWaRZj2677c8R8ftNS9gq2iBSfgyCKEhjYoqRRAQiRFr1O4FsTuCEvoeOdti2p5PY/5nxs0fVYJpeBYm6UBJ5WJEci/pcuzhugYLPL5N1YNoeBaUCZzMj1FcTaTY42uSiHrrJ2BuvuvhyS48GFGcYOC87NKHv13jbQmiiS/pLoObmSvK4rkl8PqnpqM0BwOxLsdM0IKinC/Qq0SNS2mL+iOy99E7X4vLtVR4aHVycdbn3M1S8m0eWSkJA9stYSD0gWNcXQh6PwfguLovwMdy7otQWRHpubo5JNeBWoc8k12i4ry/uk0c8yTn34cmCLzu6igstnFM/Y7vYV2KYudpAWg/vTFNksLuIPo0tcxjOxygattSBej70HE9TVNFQJlfZtuwUbYA58f5KIwbJU7+hzcBJh1XGOQbYL/4I2/kIDR9WseYs98Bj47oKXIQbzA2baeHJcL+pmNsg1lU3SSfMXMh5Un856kjTetes40M0yI5YmChPukQv4OSESAzuAkFi3MjvJ/GjJS1bXoH2+X6YWRA7pxGnC1+UD26SnAGxjyyknAuo+H0we4K5jVfegCwMrySp4B/LzQtnQX2fJqeEKPiywP1U8kjEwzyX963w="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(89, 198, -92, 90, 0); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + HypixelPlayer player = event.player(); + if (isInDialogue(player)) return; + if (player.getToggles().get(DatapointToggles.Toggles.ToggleType.HAS_SPOKEN_TO_EMISSARY_BRAUM)) { + setDialogue(player, "first-interaction").thenRun(() -> { + player.getToggles().set(DatapointToggles.Toggles.ToggleType.HAS_SPOKEN_TO_EMISSARY_BRAUM, true); + }); + return; + } + new GUICommisions().open(player); + } + + @Override + protected DialogueSet[] dialogues(HypixelPlayer player) { + return new DialogueSet[]{ + DialogueSet.builder().key("first-interaction").lines(new String[]{ + "I am the King's favorite Emissary, which is why I'm the furthest away from him!", + "Commissions inside the Crystal Hollows are different from the ones in the Dwarven Mines.", + "Click me again to receive your first set of Crystal Hollows commissions.", + "Once you complete them, come back to me!" + }).build() + }; + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java new file mode 100644 index 000000000..e62465a76 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryCarlton extends HypixelNPC { + + public EmissaryCarlton() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Carlton", "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTA4NzI1OCwKICAicHJvZmlsZUlkIiA6ICJlYjIwYWVkYTRiYTM0NzVmOTczZGNmZjkzNTE2OGZhYSIsCiAgInByb2ZpbGVOYW1lIiA6ICJTa3lGYWxsZWVlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M3NjVmZWU5N2JjZmFlN2MxMzZiNmE2YjhjYTk1MzgxYWY5NjRkNmFlYmMwOGJmZGQyMzUwYWY3OGUyY2Y1MWEiCiAgICB9CiAgfQp9"; + } + + @Override + public String signature(HypixelPlayer player) { + return "PgoHqTQyGXmASeqSaXsNZ3goo42oPiEt12zOF6+OLXWv7e2muUtXiumreY4SwTZ3DOyaPKbdGrkGMa1gaiGgOaC5mifkcXifydRA+37N5djc4vyT5tnz9trC1SRuBip9yO8GhgX2nxrRoaa+mCltQAKw/1ZrceTTDfdyv0syCcede7CXUTaS3gxwxGoNBHEbXh+6E5SCjwopDzqwdvgm4/ea3tretAflUNq7z2IKR+yg9DuzRt59TjncYcyw8nxkoaB/wzLmM5QDabY8we3495Gf/1JhvydXggnnbzBf8qzEcwvV9XTk+VI233Dr0GfTvt1CKyr62H53dGsE15dKbAdRj9/9dSa82TckdoTrgBKe+9rugf00shLoZwVHu8K5DdorPhJ+FcD2eAzCIZgeVOQyH4W4m4Yjzz4SV9jiAtRe4kXnRw8260wh86EuOL0ywUizD9Rjo8FR1G8MxqRVQYUP+zgwMo1iO1GFiymanoB++Msn/Ty8No0rZungrrwYAwkAc5GVa7G+FcR6duUmwLNxRr8mdOwj295yQibzXcyqTPk7TlJYIcTd10jdQGtEycn7Ped3fSv8Qe9Tx75qQsYdgjvgo3utRD5ROY9RDyrRDtHPOsoAlNSipZx7iUk/ggMN0vtcM0DS+prxL9guYvIbKbZFTMApzR5wxYLGNAw="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-72, 153, -10); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java new file mode 100644 index 000000000..78ae16932 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryCeanna extends HypixelNPC { + + public EmissaryCeanna() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Ceanna", "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTIwNDMxMSwKICAicHJvZmlsZUlkIiA6ICJiMGQ0YjI4YmMxZDc0ODg5YWYwZTg2NjFjZWU5NmFhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaW5lU2tpbl9vcmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTc4YzI1YWM4ZDc5M2E3M2FmMzFlNWRhM2U4YmYyZDYzYTZjMDAyNmZkZTlhOTY4MmZjOWNhZjYxNTU0MGM3OSIKICAgIH0KICB9Cn0="; + } + + @Override + public String signature(HypixelPlayer player) { + return "DrMH4v9Oi0l9tG/YDSe+otDmchtVR6b8nW8duUBKTveRl72fVlQQS1LVC6sdlQTWzx/ckaTdzmYKCio8TVtaIuTDIj4hj5s1CAwPG34Ix0Od8jQJxINoFcJD4fB1AeFYc9lmdOXp77J99xRM8s5wHGrzPgRPtkAjam9T46AC2d72rCVQmQ8HsEJoGt1XKgfSoUCEYKWileu1U0s5iML8jiAimW4lcYVOqjVCZG1dMaip8LUL08y/UqfZFynl8M3OLH1SD+p7HFL8uic57MGFi3UGLspUji3X+C8Cx/60ke54QUeHGIIph8Nff4lCoOU6RHDxpmdgtg4xV/ekw+Gl8jnZ5srgY5zCkpqLWqDm/nzpijgzpZzHkKEEMpPIeza12iGKYyJ7igqpE73Rpxjgm2RkYB73BTzkBlJoV7XePX7+fFsvU+4pZcw3ES1EKIqJe0RYHvgaxRLGVoZ9uRZi/rx7baV28K/gad+CHvfyXz5QNIVb+Kmqj2UR8uczVcV1OdnaCKnJQjabFlsdb371ev/4InAyiFxLLmucozxPpDRKSGeHcKv2hjri7WktwJ+mie0CmTW8PFktYnKS/h/7st3kAAh8gTmKAyMfVhlHTUizJvwfoM+rV6NpIRKrXgIumq3qRitJwYaf1VlC2Cc6t0aUwu7QeXB/Xk1Hy6jKQDw="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(42, 134, 22); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java new file mode 100644 index 000000000..2a9b22af5 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryEliza extends HypixelNPC { + + public EmissaryEliza() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Eliza", "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTE2ODgzMSwKICAicHJvZmlsZUlkIiA6ICJmNThkZWJkNTlmNTA0MjIyOGY2MDIyMjExZDRjMTQwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ1bnZlbnRpdmV0YWxlbnQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FmNjEzZTRkODExMGFlM2RmNjFlMWRlZTBjMDhjMzVkN2I5MDJmYTVkZjJhYWUwMjc3OWM5MTJkMzFlMzkxNCIKICAgIH0KICB9Cn0="; + } + + @Override + public String signature(HypixelPlayer player) { + return "Aynp0bVkCCtaez7h6or2/FXlUdVMyii2XHFHUWtKZpVJlivloUiOMMu+OsR1EdETjmyF1tB8HGkAmoLezPaQPYlyUnbmipWuAei547y0WS+ezclsW6tmeMcDeWIrI+1yLFBjDSsoM5+aYyC6H7Hmr/kziLXuhNt//ySuqF9G1QiG45VnOEETcuqyxlcWAAsOh8flCMWiMI4PiAdnEQIILs3/M/Wg48jZJTNddQ+cMuHd1IUgtg5NaFkgKWp+X8ZoLZ5lV8RAjC6qiJPiN/PIotRZkSDuGu1CA4HSL6MdBj3GqLQZLC67P7C5ZnRxnATth7Blxz5p4NCNBTstAvtdmxTCNPBLpXRS9yZmNfCdg8OFDboLw//RPSB7sDUug1tUliGt84/l4/YJ8HLGWLF8waK96aQauhGVPMsgDRc2ej+k8Wg//hEaiCFJ6SgcPXwEI6Ss9pUtpedsA3BOx6OBsA9aPg4qKXtsWgIvY8mMABBV5o808WZMt/X/HFU4wISnoN41txtKZ0oYDNH/xUOBmGcUsbLKB0P8P1noEXzzdOSQVdgMVgzeawvvb3U6sR4TbCwx0gEQZlny0+Yjnu16bHr3nktSIGO7VHpDyJGf2AahZDO1Q2B6As6z3JwPhguznHEfqJUInZGvUvus7aLND7SlECt1JuAXOPsA1BgpNKE="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-37, 200, -131); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java new file mode 100644 index 000000000..693f0b0be --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryFraiser extends HypixelNPC { + + public EmissaryFraiser() { + super(new HumanConfiguration() { + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDI0NzQ3MjczNCwKICAicHJvZmlsZUlkIiA6ICI3NDM3MGQ1Mjk5Mjk0ZThjODRlYjRlODlhYjc2MGY5MiIsCiAgInByb2ZpbGVOYW1lIiA6ICJQdXRZb3VySmFzT2ZmIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzlhNDMzMjI1MTFmNGJiYTcxMGJkNzhjOThjOTBlODNhYzkyYTJkYTBmMDVhMGE2OTUxMDg5YmFjZTBjZjIwM2EiCiAgICB9CiAgfQp9"; + } + + @Override + public String signature(HypixelPlayer player) { + return "qAyWpwOq2eisCXEGouDHWawThUooLgahqF2NIqu3TukkgnOK6sOzOsbDHSYo1zSUNgqKM2ywGNjgxN8wlzTM18kbvt7ZQeZ08SB8WGlIs3riCf7ePk8UsC91D0bjTnTp6zqS6dERyvgL8NNyMFxB5xzU4EFAwNA0o8R8oOZlTnSslIdCc46ML7AFYgcx5+J1mfQRJZUX5eJdoqGVZxQPdyxmisjy2+zajWZxtq4G75q743ewmz9F91xAJ3W6VjKejWiHfQVhJgjO7IPbTSRcrGF80z/22Nt5hj3QQifGH3zaMk/b+tY91CHwd8ZEIlTuHefFgCjREVnj39gVXocHjuir7SJganPRhB0Oq6xM7TRPyL9bhb59F7uUE51GFV28g2qjtQBz4gXCPWuslDJh09W0QYozWkvjTDYr/HzcipBXIZuojTgRUk7nLXhz/Dzri45xneB9dspi3SUPAwIZv9skD4wtry/2i65287N9yEprdh5GSad8CXkoUPhEslLHoLez44joDOYtqLldcrOXcBWZvMmKf7akYSmCMOClT44oW/Q3hm35gPWBYNNS/OSnn6JmSlaa1OknBxZu01KKTppsyWFWNT9C+y0rcbTtJGh4/PKqtqgj+4pd1khS7KsZ/kLm1C9AmR0TRlzMX+SsyMG3vyOJKfy1dkcQBG6Z3ps="; + } + + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Fraiser", "§e§lCLICK"}; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(-132, 174, -50); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java new file mode 100644 index 000000000..714e53db8 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryLilith extends HypixelNPC { + + public EmissaryLilith() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Lilith", "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTE0NzkwMSwKICAicHJvZmlsZUlkIiA6ICJkZTU3MWExMDJjYjg0ODgwOGZlN2M5ZjQ0OTZlY2RhZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNSEZfTWluZXNraW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzhkZmFiMmE5M2U1YjUwMzAwMDNjZGIxZTNhYjgyYzExNWFlMWZjYTc1YjQ1ZDc1NmUyNzRlMGFmMmFmNWY1MCIKICAgIH0KICB9Cn0="; + } + + @Override + public String signature(HypixelPlayer player) { + return "mjzfJ9D2gyxpHM1h60M6fnrwXkNkeik76dt7LWoGoME4+16PFkj+dMnmKoQm8eLs/6PRoMbWp6UATEpT7fsEcR7sKr/5EWdkcxpuBNgOlf4K2kREiFokE4Ri1cvBsM5YrfMFLlw417CmLmmrauSNuCOm1oUjWLzP/JexiRxmQ4yeWrg4TEmN1rE9F4RNaWQ0jKCZwSIf8DCbqx2w/kGA5prWrArgS2tIZiYCo1ydgNEag4nbZyny6siGyx817VjFt+UNIXqrwQ2PHRjpLyTlFUq6x8HXgyw2ZfHT4DqlH5pGdaE97dvUWuPt0rAU8iN3v1zxiegsCIjZ8xnuGFcgXMsHibLkJbBREdVnSd9LjJbGdD/jEQjCi+iquIs+ozwzhxN2emXZsJnrdbfFf0DD6pg7guUDhdVFZOA+b52hCB4e/N7Inmr9bE/KGsDnIEGfTk9YqUK9hznmIgcE8nAzzwl1SSFmZF8NQWOoZ5BirJztTD+Qfg+7hOzz3STrtIM5xVD1HrYpYHEFHV6DDri0thnHRvuQwllSXkr15nymnQPrCL+LEkRyg6n1iofHcVQGLTPXyJJ0mMZ7Z4W2uQePyeQMaFansZKk4NBaq4Juoz4TmvLIoSzgFjFaENQhHPccsyaSPWPi9iQ1nTjpNlUwvsjAfFgw/29/G1efPEI2sRg="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(58, 198, -8); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java new file mode 100644 index 000000000..cc0331d8b --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class EmissaryWilson extends HypixelNPC { + + public EmissaryWilson() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary Wilson", "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTExNDI0MiwKICAicHJvZmlsZUlkIiA6ICI2MTZiODhkNDMwNzM0ZTM3OWM3NDc1ODdlZTJkNzlmZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJfX25vdGFodW1hbl9fIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2UxMTcyYjE3ZWIzMzE4Yjg0MWZhOTRiZTBiOGZiZDBiN2NkZGI1YWRkMWQyYjM1YWQ1ZTZhZGM4YWI3ZDUyMDYiCiAgICB9CiAgfQp9"; + } + + @Override + public String signature(HypixelPlayer player) { + return "OfpJzikHSkXmvhaThpA3qdkGkN+zn0pcq6Mf9pSoskz6KVDMhpIpZIyxWjyeugUWmYkp7tkweKCahCtmqoykAltkuuucBHJvQ9j7CxA3PyXQceLvhmEynmQoRB2qHPJTJeR2BXVBTt0VQsv3x64TiEL9U4C0MNg8gBY13z6RALf6FKqzTRImqAlx/9D7M4fhT0fnFAwbzbCPmTlz5zfHKd1L6cPfu/KJKvJLXI9aoM9AgWjARcP3lKRXmgbv431+B0a2ICqngKohVXEWqHLcGI9jK/N1KDEZcy4MNrQ49WJrPn2tnAEqeRmcvab4sjyMqwzrKaLyo71aEAXPFm9UbhZ2d0rknYOo7gxzIirVQMnJR9HxbBslrlZuUwHDOsb4GPwzHUYnL1zZiTRpnspkaADE4vLlt6cyozBCkZI2WZNd30P/15GCLUk0XsETMYlfPsXiQ/CUw8ikZRtP1x1xhWNltQCUcpnbrbJHKZblW/zfXWfEBgCC/kod46VJHHAW+m6PPJZBgceGQrf49MuUbSHfTWk7LHqiDnoahV9rQyb3l1BTUvRgJCdbg9kpYutkMEe8jSPm9xylG1O2ap09cXjqCwhpXiqG0c2jqf4gXEoYEqAPZYJxPQP26Ji2Pk7b/xS5ix6YubDxiQXWLA++LCch6xMwL2pyPxqfDnO4Qk0="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(181, 150, 31); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java b/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java index 5f338df74..b6bc2761f 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java +++ b/type.generic/src/main/java/net/swofty/type/generic/data/datapoints/DatapointToggles.java @@ -99,6 +99,7 @@ public enum ToggleType { HAS_SPOKEN_TO_JAX(false), HAS_REALLY_SPOKEN_TO_JAX(false), HAS_SPOKEN_TO_ALCHEMIST(false), + HAS_SPOKEN_TO_EMISSARY_BRAUM(false), PAPER_ICONS(false), LOBBY_SHOW_PLAYERS(true), AUTO_ACCEPT_QUESTS(false), From 69c3dac0ae0626fac36d5234fca90d61c19eecaa Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 01:46:24 +0200 Subject: [PATCH 02/13] fix: move Ceanna out of the slabs --- .../java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java index 78ae16932..7b8b8dfc2 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java @@ -27,7 +27,7 @@ public String signature(HypixelPlayer player) { @Override public Pos position(HypixelPlayer player) { - return new Pos(42, 134, 22); + return new Pos(42.5, 134.5, 22.5); } @Override From 802b3ceb3405c3d54f43314e99e7ef75f7621870 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 01:55:58 +0200 Subject: [PATCH 03/13] feat: mithril and titanium lores --- .../skyblock/items/mining/dwarven.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/configuration/skyblock/items/mining/dwarven.yml b/configuration/skyblock/items/mining/dwarven.yml index 5d0f56483..09174ada5 100644 --- a/configuration/skyblock/items/mining/dwarven.yml +++ b/configuration/skyblock/items/mining/dwarven.yml @@ -10,12 +10,25 @@ items: rarity: COMMON - id: MITHRIL rarity: COMMON + lore: + - "§7§o\"The Man called it \"true-silver\" while" + - "§7§othe Dwarves, who loved it above all" + - "§7§othings, had their own, secret name" + - "§7§ofor it.\"" components: - id: SELLABLE value: 8.0 - id: SKILLABLE_MINE category: MINING mining_value: 6.0 + - id: EXTRA_RARITY + display: DWARVEN METAL + - id: BREWING_INGREDIENT + brewing_time_seconds: 20 + effect: SPELUNKER_POTION_1 + effect_duration: 0 + effect_amplifier: 0 + alchemy_xp: 5 - id: PLASMA rarity: COMMON components: @@ -49,6 +62,10 @@ items: value: 15.0 - id: TITANIUM rarity: COMMON + lore: + - "§7Its strength and resistance to" + - "§7corrosion are the highest of any" + - "§7metallic element." components: - id: SELLABLE value: 20.0 @@ -57,6 +74,8 @@ items: mining_value: 0.0 - id: SKULL_HEAD texture: a14c6e41a762d37863a9fff6888c738905b92cc6c3898892a38dfdfe2ac4bf + - id: EXTRA_RARITY + display: DWARVEN METAL - id: TREASURITE rarity: COMMON components: From 1ea1bff9dcc7d961e62ebbf28dafa447f1ffc815 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 15:22:33 +0200 Subject: [PATCH 04/13] feat: commissions --- .../dwarvenmines/commission/Commission.java | 115 ++++++++ .../commission/CommissionCategory.java | 7 + .../commission/CommissionMilestone.java | 86 ++++++ .../commission/CommissionReward.java | 117 ++++++++ .../dwarvenmines/commission/Commissions.java | 279 ++++++++++++++++++ .../dwarvenmines/commission/EventType.java | 8 + .../dwarvenmines/commission/HOTMTier.java | 77 +++++ .../commission/LocationSelector.java | 38 +++ .../dwarvenmines/commission/Objective.java | 39 +++ .../commission/ObjectiveType.java | 10 + .../events/ActionPlayerCommissions.java | 107 +++++++ .../type/dwarvenmines/gui/GUICommisions.java | 182 ++++++++++++ .../gui/GUICommissionMilestones.java | 245 +++++++++++++++ .../type/dwarvenmines/npcs/NPCKingName.java | 44 +++ .../data/SkyBlockDataHandler.java | 9 + .../data/datapoints/DatapointCommissions.java | 237 +++++++++++++++ .../data/datapoints/DatapointHOTM.java | 227 ++++++++++++++ .../mobs/dwarvenmines/MobGlaciteWalker.java | 147 +++++++++ .../skyblockgeneric/region/RegionType.java | 6 + 19 files changed, 1980 insertions(+) create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionCategory.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionMilestone.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commissions.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/EventType.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/HOTMTier.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/LocationSelector.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Objective.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/ObjectiveType.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointCommissions.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java new file mode 100644 index 000000000..6992a1f92 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java @@ -0,0 +1,115 @@ +package net.swofty.type.dwarvenmines.commission; + +public class Commission { + public final String name; + public final CommissionCategory category; + public final Objective objective; + public final boolean oneTimeOnly; + + public Commission( + String name, + CommissionCategory category, + Objective objective, + boolean oneTimeOnly + ) { + this.name = name; + this.category = category; + this.objective = objective; + this.oneTimeOnly = oneTimeOnly; + } + + public String generateDescription() { + StringBuilder sb = new StringBuilder(); + + switch (objective.type) { + case MINE -> { + sb.append("Mine ").append(objective.amount).append(" "); + sb.append(getTargetName(objective.target)).append(" Ore"); + appendLocation(sb); + sb.append("."); + } + case SLAY -> { + sb.append("Slay ").append(objective.amount).append(" "); + sb.append(getTargetNamePlural(objective.target)); + appendLocation(sb); + appendEvent(sb); + sb.append("."); + } + case DAMAGE -> { + sb.append("Damage ").append(getTargetNamePlural(objective.target)); + sb.append(" ").append(objective.amount).append(" times"); + appendLocation(sb); + sb.append("."); + } + case PARTICIPATE -> sb.append("Participate in the ").append(getEventName(objective.event)).append("."); + case COLLECT -> { + sb.append("Collect ").append(objective.amount).append(" "); + sb.append(getCollectibleName(objective.target)); + appendEvent(sb); + sb.append("."); + } + case DEPOSIT -> { + sb.append("Deposit ").append(objective.amount).append(" Tickets"); + appendEvent(sb); + sb.append("."); + } + } + + return sb.toString(); + } + + private void appendLocation(StringBuilder sb) { + if (!objective.location.isAny()) { + objective.location.getRegion().ifPresent(region -> + sb.append(" in ").append(region.getName())); + } + } + + private void appendEvent(StringBuilder sb) { + if (objective.event != EventType.NONE) { + sb.append(" during the ").append(getEventName(objective.event)); + } + } + + private String getTargetName(Objective.BlockTarget target) { + return switch (target) { + case MITHRIL -> "Mithril"; + case TITANIUM -> "Titanium"; + case GOBLIN -> "Goblin"; + case GLACITE_WALKER -> "Glacite Walker"; + case TREASURE_HOARDER -> "Treasure Hoarder"; + case GOLDEN_GOBLIN -> "Golden Goblin"; + case STAR_SENTRY -> "Star Sentry"; + case NONE -> ""; + }; + } + + private String getTargetNamePlural(Objective.BlockTarget target) { + return switch (target) { + case MITHRIL -> "Mithril Ore"; + case TITANIUM -> "Titanium Ore"; + case GOBLIN -> "Goblins"; + case GLACITE_WALKER -> "Glacite Walkers"; + case TREASURE_HOARDER -> "Treasure Hoarders"; + case GOLDEN_GOBLIN -> "Golden Goblin"; + case STAR_SENTRY -> "Star Sentrys"; + case NONE -> ""; + }; + } + + private String getCollectibleName(Objective.BlockTarget target) { + return switch (target) { + case MITHRIL -> "Mithril Powder"; + default -> target.name(); + }; + } + + private String getEventName(EventType event) { + return switch (event) { + case GOBLIN_RAID -> "Goblin Raid Event"; + case RAFFLE -> "Raffle Event"; + case DOUBLE_POWDER -> "2x Powder Event"; + case NONE -> ""; + }; + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionCategory.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionCategory.java new file mode 100644 index 000000000..b47fa817d --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionCategory.java @@ -0,0 +1,7 @@ +package net.swofty.type.dwarvenmines.commission; + +public enum CommissionCategory { + CONSISTENT, + SITUATIONAL, + TUTORIAL +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionMilestone.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionMilestone.java new file mode 100644 index 000000000..f075dd298 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionMilestone.java @@ -0,0 +1,86 @@ +package net.swofty.type.dwarvenmines.commission; + +import lombok.Getter; + +@Getter +public enum CommissionMilestone { + TIER_1(1, 5, 100_000, 20, true, false, false, false, false, false), + TIER_2(2, 25, 200_000, 30, false, false, false, false, false, false), + TIER_3(3, 100, 400_000, 30, false, true, false, false, false, false), + TIER_4(4, 250, 800_000, 50, false, false, true, false, false, false), + TIER_5(5, 500, 1_200_000, 50, false, false, false, true, false, false), + TIER_6(6, 750, 1_600_000, 75, false, false, false, false, true, false); + + private final int tier; + private final int commissionsRequired; + private final int miningXpReward; + private final int skyBlockXpReward; + private final boolean unlocksEmissaries; + private final boolean unlocksExtraSlot; + private final boolean unlocksDwarvenMinesScroll; + private final boolean unlocksRoyalPigeon; + private final boolean unlocksCrystalNucleusScroll; + private final boolean hasSpecialReward; + + CommissionMilestone(int tier, int commissionsRequired, int miningXpReward, int skyBlockXpReward, + boolean unlocksEmissaries, boolean unlocksExtraSlot, + boolean unlocksDwarvenMinesScroll, boolean unlocksRoyalPigeon, + boolean unlocksCrystalNucleusScroll, boolean hasSpecialReward) { + this.tier = tier; + this.commissionsRequired = commissionsRequired; + this.miningXpReward = miningXpReward; + this.skyBlockXpReward = skyBlockXpReward; + this.unlocksEmissaries = unlocksEmissaries; + this.unlocksExtraSlot = unlocksExtraSlot; + this.unlocksDwarvenMinesScroll = unlocksDwarvenMinesScroll; + this.unlocksRoyalPigeon = unlocksRoyalPigeon; + this.unlocksCrystalNucleusScroll = unlocksCrystalNucleusScroll; + this.hasSpecialReward = hasSpecialReward; + } + + public static CommissionMilestone getMilestoneForCompleted(int totalCompleted) { + CommissionMilestone result = null; + for (CommissionMilestone milestone : values()) { + if (totalCompleted >= milestone.commissionsRequired) { + result = milestone; + } + } + return result; + } + + public static CommissionMilestone getNextMilestone(int totalCompleted) { + for (CommissionMilestone milestone : values()) { + if (totalCompleted < milestone.commissionsRequired) { + return milestone; + } + } + return null; + } + + public String[] getRewardDescriptions() { + java.util.List rewards = new java.util.ArrayList<>(); + + if (unlocksEmissaries) { + rewards.add("§7- §aEmissaries"); + rewards.add("§7- §6Royal Compass"); + } + if (unlocksExtraSlot) { + rewards.add("§7- §a+1 Commission Slot"); + } + if (unlocksDwarvenMinesScroll) { + rewards.add("§7- §5Travel Scroll to Dwarven Mines"); + } + if (unlocksRoyalPigeon) { + rewards.add("§7- §6Royal Pigeon"); + } + if (unlocksCrystalNucleusScroll) { + rewards.add("§7- §5Travel Scroll to Crystal Nucleus"); + } + + rewards.add("§7- §3+" + String.format("%,d", miningXpReward) + " Mining XP"); + rewards.add("§7- §b+" + skyBlockXpReward + " SkyBlock XP"); + + return rewards.toArray(new String[0]); + } +} + diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java new file mode 100644 index 000000000..6805e25a2 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java @@ -0,0 +1,117 @@ +package net.swofty.type.dwarvenmines.commission; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * Commission reward calculator based on HOTM tier and daily bonus status. + */ +@Getter +@AllArgsConstructor +public class CommissionReward { + private final int hotmXp; + private final int miningXp; + private final int mithrilPowder; + private final boolean isDailyBonus; + + /** + * Calculates rewards for completing a commission. + * + * @param hotmTier the player's current HOTM tier (1-10) + * @param isHotmMaxed whether HOTM is maxed (tier 10) + * @param isDailyBonus whether this is one of the first 4 daily commissions + * @return the commission reward + */ + public static CommissionReward calculate(int hotmTier, boolean isHotmMaxed, boolean isDailyBonus) { + int hotmXp; + int miningXp; + int mithrilPowder; + + // Base HOTM XP based on tier (when not maxed) + if (!isHotmMaxed) { + if (hotmTier == 1) { + hotmXp = 100; + } else if (hotmTier == 2) { + hotmXp = 200; + } else { + hotmXp = 400; + } + } else { + hotmXp = 0; // No HOTM XP when maxed + } + + // Mining XP: random between 5,000 and 10,000 + miningXp = ThreadLocalRandom.current().nextInt(5_000, 10_001); + + // Mithril Powder: 100-200 when not maxed, 500 when maxed + if (!isHotmMaxed) { + mithrilPowder = ThreadLocalRandom.current().nextInt(100, 201); + } else { + mithrilPowder = 500; + } + + // Daily bonus for first 4 commissions + int dailyBonusHotmXp = 0; + int dailyBonusPowder = 0; + if (isDailyBonus) { + if (!isHotmMaxed) { + dailyBonusHotmXp = 900; // +900 HOTM XP daily bonus + } else { + dailyBonusPowder = 2000; // +2000 Mithril Powder when maxed + } + } + + return new CommissionReward( + hotmXp + dailyBonusHotmXp, + miningXp, + mithrilPowder + dailyBonusPowder, + isDailyBonus + ); + } + + /** + * Gets the formatted reward lines for display in the GUI. + * + * @param hotmTier the player's current HOTM tier (1-10) + * @param isHotmMaxed whether HOTM is maxed + * @param isDailyBonus whether this is a daily bonus commission + * @return array of formatted reward strings + */ + public static String[] getRewardLore(int hotmTier, boolean isHotmMaxed, boolean isDailyBonus) { + java.util.List lore = new java.util.ArrayList<>(); + + if (!isHotmMaxed) { + int baseHotmXp; + if (hotmTier == 1) { + baseHotmXp = 100; + } else if (hotmTier == 2) { + baseHotmXp = 200; + } else { + baseHotmXp = 400; + } + + if (isDailyBonus) { + lore.add("§7- §5+" + (baseHotmXp + 900) + " Heart of the Mountain XP §e(Daily Bonus)"); + } else { + lore.add("§7- §5+" + baseHotmXp + " Heart of the Mountain XP"); + } + } + + if (!isHotmMaxed) { + if (isDailyBonus) { + lore.add("§7- §2+100 Mithril Powder"); + } else { + lore.add("§7- §2+100 Mithril Powder"); + } + } else { + lore.add("§7- §2+500 Mithril Powder"); + } + + lore.add("§7- §3+7.5k Mining XP"); + + return lore.toArray(new String[0]); + } +} + diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commissions.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commissions.java new file mode 100644 index 000000000..6dd3c1b82 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commissions.java @@ -0,0 +1,279 @@ +package net.swofty.type.dwarvenmines.commission; + +import net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler; +import net.swofty.type.skyblockgeneric.data.datapoints.DatapointCommissions; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class Commissions { + public static List CONSISTENT = List.of( + + new Commission("Mithril Miner", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 350, LocationSelector.any(), EventType.NONE), + false + ), + + new Commission("Lava Springs Mithril", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 250, LocationSelector.of(RegionType.LAVA_SPRINGS), EventType.NONE), + false + ), + + new Commission("Royal Mines Mithril", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 250, LocationSelector.of(RegionType.ROYAL_MINES), EventType.NONE), + false + ), + + new Commission("Cliffside Veins Mithril", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 250, LocationSelector.of(RegionType.CLIFFSIDE_VEINS), EventType.NONE), + false + ), + + new Commission("Rampart's Quarry Mithril", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 250, LocationSelector.of(RegionType.RAMPARTS_QUARRY), EventType.NONE), + false + ), + + new Commission("Upper Mines Mithril", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 250, LocationSelector.of(RegionType.UPPER_MINES), EventType.NONE), + false + ), + + new Commission("Titanium Miner", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 15, LocationSelector.any(), EventType.NONE), + false + ), + + new Commission("Lava Springs Titanium", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 10, LocationSelector.of(RegionType.LAVA_SPRINGS), EventType.NONE), + false + ), + + new Commission("Royal Mines Titanium", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 10, LocationSelector.of(RegionType.ROYAL_MINES), EventType.NONE), + false + ), + + new Commission("Cliffside Veins Titanium", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 10, LocationSelector.of(RegionType.CLIFFSIDE_VEINS), EventType.NONE), + false + ), + + new Commission("Rampart's Quarry Titanium", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 10, LocationSelector.of(RegionType.RAMPARTS_QUARRY), EventType.NONE), + false + ), + + new Commission("Upper Mines Titanium", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 10, LocationSelector.of(RegionType.UPPER_MINES), EventType.NONE), + false + ), + + new Commission("Goblin Slayer", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.SLAY, Objective.BlockTarget.GOBLIN, 100, LocationSelector.any(), EventType.NONE), + false + ), + + new Commission("Glacite Walker Slayer", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.SLAY, Objective.BlockTarget.GLACITE_WALKER, 50, LocationSelector.any(), EventType.NONE), + false + ), + + new Commission("Treasure Hoarder Puncher", CommissionCategory.CONSISTENT, + new Objective(ObjectiveType.DAMAGE, Objective.BlockTarget.TREASURE_HOARDER, 10, LocationSelector.any(), EventType.NONE), + false + ) + ); + + public static List SITUATIONAL = List.of( + new Commission("Goblin Raid Slayer", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.SLAY, Objective.BlockTarget.GOBLIN, 20, LocationSelector.any(), EventType.GOBLIN_RAID), + false + ), + + new Commission("Goblin Raid", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.PARTICIPATE, Objective.BlockTarget.NONE, 1, LocationSelector.any(), EventType.GOBLIN_RAID), + false + ), + + new Commission("Raffle", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.PARTICIPATE, Objective.BlockTarget.NONE, 1, LocationSelector.any(), EventType.RAFFLE), + false + ), + + new Commission("Golden Goblin Slayer", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.SLAY, Objective.BlockTarget.GOLDEN_GOBLIN, 1, LocationSelector.any(), EventType.NONE), + false + ), + + new Commission("Star Sentry Puncher", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.DAMAGE, Objective.BlockTarget.STAR_SENTRY, 10, LocationSelector.any(), EventType.NONE), + false + ), + + new Commission("Lucky Raffle", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.DEPOSIT, Objective.BlockTarget.NONE, 20, LocationSelector.any(), EventType.RAFFLE), + false + ), + + new Commission("2x Mithril Powder Collector", CommissionCategory.SITUATIONAL, + new Objective(ObjectiveType.COLLECT, Objective.BlockTarget.MITHRIL, 500, LocationSelector.any(), EventType.DOUBLE_POWDER), + false + ) + ); + + public static List TUTORIAL = List.of( + + new Commission("Mithril Miner", CommissionCategory.TUTORIAL, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 50, LocationSelector.any(), EventType.NONE), + true + ), + + new Commission("First Event", CommissionCategory.TUTORIAL, + new Objective(ObjectiveType.PARTICIPATE, Objective.BlockTarget.NONE, 1, LocationSelector.any(), EventType.NONE), + true + ), + + new Commission("Titanium Miner", CommissionCategory.TUTORIAL, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.TITANIUM, 2, LocationSelector.any(), EventType.NONE), + true + ), + + new Commission("Mithril Miner II", CommissionCategory.TUTORIAL, + new Objective(ObjectiveType.MINE, Objective.BlockTarget.MITHRIL, 150, LocationSelector.any(), EventType.NONE), + true + ) + ); + + public static int getCommissionSlots(SkyBlockPlayer player) { + DatapointCommissions.PlayerCommissionData data = getCommissionData(player); + return data.getCommissionSlots(); + } + + public static DatapointCommissions.PlayerCommissionData getCommissionData(SkyBlockPlayer player) { + SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); + return dataHandler.get(SkyBlockDataHandler.Data.COMMISSIONS, DatapointCommissions.class).getValue(); + } + + public static void saveCommissionData(SkyBlockPlayer player, DatapointCommissions.PlayerCommissionData data) { + SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); + dataHandler.get(SkyBlockDataHandler.Data.COMMISSIONS, DatapointCommissions.class).setValue(data); + } + + public static void generateCommissions(SkyBlockPlayer player) { + DatapointCommissions.PlayerCommissionData data = getCommissionData(player); + + data.getActiveCommissions().clear(); + int slots = data.getCommissionSlots(); + List usedNames = new ArrayList<>(); + + for (int i = 0; i < slots; i++) { + Commission commission; + + if (i % 2 == 0) { + commission = selectRandomCommission(CONSISTENT, usedNames); + } else { + commission = selectRandomCommission(SITUATIONAL, usedNames); + if (commission == null) { + commission = selectRandomCommission(CONSISTENT, usedNames); + } + } + + if (commission != null) { + usedNames.add(commission.name); + data.getActiveCommissions().add(new DatapointCommissions.ActiveCommission(commission.name)); + } + } + + saveCommissionData(player, data); + } + + private static Commission selectRandomCommission(List pool, List usedNames) { + List available = new ArrayList<>(); + for (Commission commission : pool) { + if (!usedNames.contains(commission.name)) { + available.add(commission); + } + } + + if (available.isEmpty()) { + return null; + } + + return available.get(ThreadLocalRandom.current().nextInt(available.size())); + } + + public static Commission getCommissionByName(String name) { + for (Commission c : CONSISTENT) { + if (c.name.equals(name)) return c; + } + for (Commission c : SITUATIONAL) { + if (c.name.equals(name)) return c; + } + for (Commission c : TUTORIAL) { + if (c.name.equals(name)) return c; + } + return null; + } + + public static boolean needsGeneration(SkyBlockPlayer player) { + DatapointCommissions.PlayerCommissionData data = getCommissionData(player); + if (data.getActiveCommissions().isEmpty()) { + return true; + } + + boolean allCompleted = true; + for (DatapointCommissions.ActiveCommission ac : data.getActiveCommissions()) { + if (!ac.isCompleted()) { + allCompleted = false; + break; + } + } + + return allCompleted; + } + + public static int[] getGuiSlots(int slotCount) { + return switch (slotCount) { + case 2 -> new int[]{12, 14}; + case 3 -> new int[]{11, 13, 15}; + case 4 -> new int[]{11, 12, 14, 15}; + default -> new int[]{}; + }; + } + + @Deprecated + public static int getCommissionLevel(SkyBlockPlayer player) { + return getCommissionSlots(player); + } + + public static void replaceCommissionAt(SkyBlockPlayer player, int slotIndex) { + DatapointCommissions.PlayerCommissionData data = getCommissionData(player); + if (slotIndex < 0 || slotIndex >= data.getActiveCommissions().size()) return; + + List usedNames = new ArrayList<>(); + for (DatapointCommissions.ActiveCommission ac : data.getActiveCommissions()) { + if (ac != null && ac.getCommissionName() != null) usedNames.add(ac.getCommissionName()); + } + + Commission newComm; + if (slotIndex % 2 == 0) { + newComm = selectRandomCommission(CONSISTENT, usedNames); + } else { + newComm = selectRandomCommission(SITUATIONAL, usedNames); + if (newComm == null) newComm = selectRandomCommission(CONSISTENT, usedNames); + } + + if (newComm == null) { + data.getActiveCommissions().remove(slotIndex); + } else { + data.getActiveCommissions().set(slotIndex, new DatapointCommissions.ActiveCommission(newComm.name)); + } + + saveCommissionData(player, data); + } + +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/EventType.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/EventType.java new file mode 100644 index 000000000..cf51b97b0 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/EventType.java @@ -0,0 +1,8 @@ +package net.swofty.type.dwarvenmines.commission; + +public enum EventType { + GOBLIN_RAID, + RAFFLE, + DOUBLE_POWDER, + NONE +} \ No newline at end of file diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/HOTMTier.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/HOTMTier.java new file mode 100644 index 000000000..284dea1bd --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/HOTMTier.java @@ -0,0 +1,77 @@ +package net.swofty.type.dwarvenmines.commission; + +import lombok.Getter; + +@Getter +public enum HOTMTier { + TIER_1(1, 0, 0, 1, 0, 35), + TIER_2(2, 3_000, 3_000, 2, 0, 45), + TIER_3(3, 9_000, 12_000, 2, 1, 60), + TIER_4(4, 25_000, 37_000, 2, 1, 75), + TIER_5(5, 60_000, 97_000, 2, 1, 90), + TIER_6(6, 100_000, 197_000, 2, 1, 110), + TIER_7(7, 150_000, 347_000, 3, 1, 130), + TIER_8(8, 210_000, 557_000, 2, 0, 180), + TIER_9(9, 290_000, 847_000, 2, 0, 210), + TIER_10(10, 400_000, 1_247_000, 2, 0, 240); + + private final int tier; + private final int xpRequired; + private final int cumulativeXp; + private final int tokenReward; + private final int forgeSlotReward; + private final int skyBlockXpReward; + + HOTMTier(int tier, int xpRequired, int cumulativeXp, int tokenReward, int forgeSlotReward, int skyBlockXpReward) { + this.tier = tier; + this.xpRequired = xpRequired; + this.cumulativeXp = cumulativeXp; + this.tokenReward = tokenReward; + this.forgeSlotReward = forgeSlotReward; + this.skyBlockXpReward = skyBlockXpReward; + } + + public static HOTMTier getTierForXp(long totalXp) { + HOTMTier result = TIER_1; + for (HOTMTier tier : values()) { + if (totalXp >= tier.cumulativeXp) { + result = tier; + } + } + return result; + } + + public static HOTMTier getNextTier(long totalXp) { + for (HOTMTier tier : values()) { + if (totalXp < tier.cumulativeXp) { + return tier; + } + } + return null; // Maxed + } + + public static boolean isMaxed(long totalXp) { + return totalXp >= TIER_10.cumulativeXp; + } + + public int getTotalForgeSlots() { + int slots = 0; + for (HOTMTier t : values()) { + if (t.tier <= this.tier) { + slots += t.forgeSlotReward; + } + } + return slots; + } + + public int getTotalTokens() { + int tokens = 0; + for (HOTMTier t : values()) { + if (t.tier <= this.tier) { + tokens += t.tokenReward; + } + } + return tokens; + } +} + diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/LocationSelector.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/LocationSelector.java new file mode 100644 index 000000000..52aeb7d57 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/LocationSelector.java @@ -0,0 +1,38 @@ +package net.swofty.type.dwarvenmines.commission; + +import net.swofty.type.skyblockgeneric.region.RegionType; + +import java.util.Objects; +import java.util.Optional; + +public final class LocationSelector { + + private static final LocationSelector ANY = new LocationSelector(null); + private final RegionType region; + + private LocationSelector(RegionType region) { + this.region = region; + } + + public static LocationSelector any() { + return ANY; + } + + public static LocationSelector of(RegionType region) { + Objects.requireNonNull(region); + return new LocationSelector(region); + } + + public boolean allows(RegionType region) { + return this.region == null || this.region == region; + } + + public boolean isAny() { + return region == null; + } + + public Optional getRegion() { + return Optional.ofNullable(region); + } + +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Objective.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Objective.java new file mode 100644 index 000000000..c53b8046f --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Objective.java @@ -0,0 +1,39 @@ +package net.swofty.type.dwarvenmines.commission; + +import net.minestom.server.entity.Entity; +import net.minestom.server.item.Material; + +import java.util.List; + +public class Objective { + public final ObjectiveType type; + public final BlockTarget target; + public final int amount; + public final LocationSelector location; + public final EventType event; + + public Objective( + ObjectiveType type, + BlockTarget target, + int amount, + LocationSelector location, + EventType event + ) { + this.type = type; + this.target = target; + this.amount = amount; + this.location = location; + this.event = event; + } + + public enum BlockTarget { + NONE, + GOBLIN, + GLACITE_WALKER, + TREASURE_HOARDER, + GOLDEN_GOBLIN, + STAR_SENTRY, + MITHRIL, + TITANIUM; + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/ObjectiveType.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/ObjectiveType.java new file mode 100644 index 000000000..e4bac732c --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/ObjectiveType.java @@ -0,0 +1,10 @@ +package net.swofty.type.dwarvenmines.commission; + +public enum ObjectiveType { + MINE, + SLAY, + DAMAGE, + PARTICIPATE, + COLLECT, + DEPOSIT +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java new file mode 100644 index 000000000..dc7b88b59 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java @@ -0,0 +1,107 @@ +package net.swofty.type.dwarvenmines.events; + +import net.minestom.server.event.player.PlayerBlockBreakEvent; +import net.minestom.server.item.Material; +import net.swofty.type.dwarvenmines.commission.Commission; +import net.swofty.type.dwarvenmines.commission.Commissions; +import net.swofty.type.dwarvenmines.commission.Objective; +import net.swofty.type.dwarvenmines.commission.ObjectiveType; +import net.swofty.type.generic.event.EventNodes; +import net.swofty.type.generic.event.HypixelEvent; +import net.swofty.type.generic.event.HypixelEventClass; +import net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler; +import net.swofty.type.skyblockgeneric.data.datapoints.DatapointCommissions; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.region.SkyBlockRegion; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; + +import java.util.Set; + +public class ActionPlayerCommissions implements HypixelEventClass { + + private static final Set MITHRIL_BLOCKS = Set.of( + Material.LIGHT_BLUE_WOOL, + Material.GRAY_WOOL, + Material.CYAN_TERRACOTTA, + Material.PRISMARINE, + Material.DARK_PRISMARINE, + Material.PRISMARINE_BRICKS + ); + + private static final Set TITANIUM_BLOCKS = Set.of( + Material.POLISHED_DIORITE + ); + + @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = true) + public void run(PlayerBlockBreakEvent event) { + if (!(event.getPlayer() instanceof SkyBlockPlayer player)) return; + + Material brokenMaterial = event.getBlock().registry().material(); + if (brokenMaterial == null) return; + + // Determine what type of block was broken + Objective.BlockTarget target = null; + if (MITHRIL_BLOCKS.contains(brokenMaterial)) { + target = Objective.BlockTarget.MITHRIL; + } else if (TITANIUM_BLOCKS.contains(brokenMaterial)) { + target = Objective.BlockTarget.TITANIUM; + } + + if (target == null) return; + + SkyBlockRegion region = player.getRegion(); + RegionType regionType = region != null ? region.getType() : null; + + updateCommissionProgress(player, ObjectiveType.MINE, target, 1, regionType); + } + + /** + * Updates the progress of matching commissions for the player. + * + * @param player the player + * @param type the objective type (MINE, SLAY, etc.) + * @param target the target (MITHRIL, TITANIUM, GOBLIN, etc.) + * @param amount the amount to add to progress + * @param regionType the current region (can be null for any region) + */ + public static void updateCommissionProgress(SkyBlockPlayer player, ObjectiveType type, + Objective.BlockTarget target, int amount, RegionType regionType) { + SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); + DatapointCommissions.PlayerCommissionData commissionData = + dataHandler.get(SkyBlockDataHandler.Data.COMMISSIONS, DatapointCommissions.class).getValue(); + + boolean anyUpdated = false; + + for (DatapointCommissions.ActiveCommission activeCommission : commissionData.getActiveCommissions()) { + if (activeCommission.isCompleted()) continue; + + Commission commission = Commissions.getCommissionByName(activeCommission.getCommissionName()); + if (commission == null) continue; + + // Check if this commission matches the action + if (commission.objective.type != type) continue; + if (commission.objective.target != target) continue; + + if (!commission.objective.location.isAny() && regionType != null) { + if (!commission.objective.location.allows(regionType)) continue; + } + + int newProgress = activeCommission.getProgress() + amount; + activeCommission.setProgress(newProgress); + anyUpdated = true; + + if (newProgress >= commission.objective.amount) { + activeCommission.setCompleted(true); + onCommissionComplete(player, commission); + } + } + + if (anyUpdated) { + Commissions.saveCommissionData(player, commissionData); + } + } + + private static void onCommissionComplete(SkyBlockPlayer player, Commission commission) { + player.sendMessage("§a§l" + commission.name + " §eCommission Complete! Visit the King to claim your rewards!"); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java index 987eae8cd..4a19d1f3f 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java @@ -2,8 +2,22 @@ import net.minestom.server.event.inventory.InventoryPreClickEvent; import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.commons.StringUtility; +import net.swofty.type.dwarvenmines.commission.*; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.data.SkyBlockDataHandler; +import net.swofty.type.skyblockgeneric.data.datapoints.DatapointCommissions; +import net.swofty.type.skyblockgeneric.data.datapoints.DatapointHOTM; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; + +import java.util.ArrayList; +import java.util.List; public class GUICommisions extends HypixelInventoryGUI { @@ -15,10 +29,178 @@ public GUICommisions() { public void onOpen(InventoryGUIOpenEvent e) { fill(FILLER_ITEM); + SkyBlockPlayer player = (SkyBlockPlayer) getPlayer(); + DatapointCommissions.PlayerCommissionData commissionData = Commissions.getCommissionData(player); + commissionData.checkAndResetDaily(); + + if (Commissions.needsGeneration(player)) { + Commissions.generateCommissions(player); + commissionData = Commissions.getCommissionData(player); // refresh + } + + int slotCount = commissionData.getCommissionSlots(); + int[] slots = Commissions.getGuiSlots(slotCount); + + List activeCommissions = commissionData.getActiveCommissions(); + + DatapointHOTM.PlayerHOTMData hotmData = player.getSkyblockDataHandler() + .get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).getValue(); + int hotmTier = hotmData.getTier(); + boolean isHotmMaxed = hotmData.isMaxed(); + int remainingDailyBonus = commissionData.getRemainingDailyBonus(); + + for (int i = 0; i < slots.length && i < activeCommissions.size(); i++) { + int index = i; + DatapointCommissions.ActiveCommission activeCommission = activeCommissions.get(i); + Commission commission = Commissions.getCommissionByName(activeCommission.getCommissionName()); + boolean willGetDailyBonus = index < remainingDailyBonus; + + set(new GUIClickableItem(slots[i]) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer p) { + SkyBlockPlayer player = (SkyBlockPlayer) p; + DatapointCommissions.PlayerCommissionData commissionData = Commissions.getCommissionData(player); + if (activeCommission.isCompleted() && !activeCommission.isClaimed()) { + SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); + + DatapointHOTM.PlayerHOTMData hotmData = + dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).getValue(); + + int hotmTier = hotmData.getTier(); + boolean isHotmMaxed = hotmData.isMaxed(); + boolean isDailyBonus = commissionData.hasDailyBonus(); + + CommissionReward reward = CommissionReward.calculate(hotmTier, isHotmMaxed, isDailyBonus); + + if (reward.getHotmXp() > 0) { + hotmData.addExperience(reward.getHotmXp()); + dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).setValue(hotmData); + } + + if (reward.getMithrilPowder() > 0) { + hotmData.addMithrilPowder(reward.getMithrilPowder()); + dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).setValue(hotmData); + } + + if (reward.getMiningXp() > 0) { + player.getSkills().increase(player, SkillCategories.MINING, (double) reward.getMiningXp()); + } + + activeCommission.setClaimed(true); + commissionData.completeCommission(); + Commissions.saveCommissionData(player, commissionData); + Commissions.replaceCommissionAt(player, index); + new GUICommisions().open(player); + } + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + List lore = new ArrayList<>(); + lore.add("§7Commissions are tasks given directly"); + lore.add("§7by the king which give bountiful"); + lore.add("§7rewards."); + lore.add(" "); + + if (commission != null) { + lore.add("§9" + commission.name); + lore.add("§7" + commission.generateDescription()); + } else { + lore.add("§9Unknown Commission"); + lore.add("§7Complete this task for rewards."); + } + + lore.add(""); + lore.add("§9Rewards"); + + String[] rewardLines = CommissionReward.getRewardLore(hotmTier, isHotmMaxed, willGetDailyBonus); + for (String line : rewardLines) { + lore.add(line); + } + + lore.add(" "); + + if (activeCommission.isCompleted()) { + lore.add("§a§lCOMPLETED!"); + lore.add(""); + lore.add("§eClick to claim rewards!"); + } else { + lore.add("§9Progress"); + int progress = activeCommission.getProgress(); + int target = commission != null ? commission.objective.amount : 100; + int percentage = Math.min(100, (int) ((progress / (double) target) * 100)); + String progressBar = buildProgressBar(percentage); + lore.add(progressBar + " §9" + percentage + "%"); + } + + return ItemStackCreator.getStack("§6Commission #" + (index + 1), Material.WRITABLE_BOOK, 1, lore); + } + }); + } + + set(new GUIClickableItem(30) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + new GUICommissionMilestones().open(player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + DatapointCommissions.PlayerCommissionData data = Commissions.getCommissionData((SkyBlockPlayer) player); + int totalCompleted = data.getTotalCompleted(); + + List lore = new ArrayList<>(); + lore.add("§7View milestone progress and rewards!"); + lore.add(" "); + + CommissionMilestone nextMilestone = CommissionMilestone.getNextMilestone(totalCompleted); + if (nextMilestone != null) { + double progress = data.getMilestoneProgress(nextMilestone.getTier()); + String progressBar = buildMilestoneProgressBar(progress); + + lore.add("§7Progress to milestone " + StringUtility.getAsRomanNumeral(nextMilestone.getTier()) + ": §e" + String.format("%.1f", progress) + "§6%"); + lore.add(progressBar + " §e" + totalCompleted + "§6/§e" + nextMilestone.getCommissionsRequired()); + lore.add(" "); + lore.add("§7Tier " + StringUtility.getAsRomanNumeral(nextMilestone.getTier()) + " Rewards:"); + for (String reward : nextMilestone.getRewardDescriptions()) { + lore.add(" " + reward.replace("§7- ", "")); + } + } else { + lore.add("§a§lALL MILESTONES COMPLETED!"); + } + + lore.add(" "); + lore.add("§eClick to view!"); + + return ItemStackCreator.getStack("§eCommission Milestones", Material.FILLED_MAP, 1, lore); + } + }); + set(GUIClickableItem.getCloseItem(31)); updateItemStacks(getInventory(), getPlayer()); } + private String buildProgressBar(int percentage) { + int filled = percentage / 5; // 20 segments total + int empty = 20 - filled; + + StringBuilder bar = new StringBuilder("§f§l§m"); + for (int i = 0; i < filled; i++) { + bar.append(" "); + } + bar.append("§7§l§m"); + for (int i = 0; i < empty; i++) { + bar.append(" "); + } + return bar.toString(); + } + + private String buildMilestoneProgressBar(double percentage) { + int filled = (int) (percentage / 5); // 20 segments total + int empty = 20 - filled; + return "§2§l§m" + " ".repeat(Math.max(0, filled)) + "§f§l§m" + " ".repeat(Math.max(0, empty)); + } + @Override public boolean allowHotkeying() { return false; diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java new file mode 100644 index 000000000..22cadc379 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java @@ -0,0 +1,245 @@ +package net.swofty.type.dwarvenmines.gui; + +import net.minestom.server.event.inventory.InventoryPreClickEvent; +import net.minestom.server.inventory.InventoryType; +import net.minestom.server.item.ItemStack; +import net.minestom.server.item.Material; +import net.swofty.commons.StringUtility; +import net.swofty.type.dwarvenmines.commission.CommissionMilestone; +import net.swofty.type.dwarvenmines.commission.Commissions; +import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; +import net.swofty.type.generic.gui.inventory.ItemStackCreator; +import net.swofty.type.generic.gui.inventory.item.GUIClickableItem; +import net.swofty.type.generic.gui.inventory.item.GUIItem; +import net.swofty.type.generic.user.HypixelPlayer; +import net.swofty.type.skyblockgeneric.data.datapoints.DatapointCommissions; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; + +import java.util.ArrayList; +import java.util.List; + +public class GUICommissionMilestones extends HypixelInventoryGUI { + + private static final int[] MILESTONE_SLOTS = {19, 20, 21, 23, 24, 25}; + + public GUICommissionMilestones() { + super("§eCommission Milestones", InventoryType.CHEST_6_ROW); + } + + @Override + public void onOpen(InventoryGUIOpenEvent e) { + fill(FILLER_ITEM); + + SkyBlockPlayer player = (SkyBlockPlayer) getPlayer(); + DatapointCommissions.PlayerCommissionData commissionData = Commissions.getCommissionData(player); + int totalCompleted = commissionData.getTotalCompleted(); + int currentTier = commissionData.getMilestoneTier(); + + set(new GUIItem(4) { + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + List lore = new ArrayList<>(); + lore.add("§7View milestone progress and rewards!"); + lore.add(""); + + CommissionMilestone nextMilestone = null; + for (CommissionMilestone m : CommissionMilestone.values()) { + if (totalCompleted < m.getCommissionsRequired()) { + nextMilestone = m; + break; + } + } + + if (nextMilestone != null) { + double progress = commissionData.getMilestoneProgress(nextMilestone.getTier()); + String progressBar = buildProgressBar(progress); + lore.add("§7Progress to milestone " + StringUtility.getAsRomanNumeral(nextMilestone.getTier()) + ": §e" + String.format("%.1f", progress) + "§6%"); + lore.add(progressBar + " §e" + totalCompleted + "§6/§e" + nextMilestone.getCommissionsRequired()); + lore.add(""); + lore.add("§7Tier " + StringUtility.getAsRomanNumeral(nextMilestone.getTier()) + " Rewards:"); + for (String reward : nextMilestone.getRewardDescriptions()) { + lore.add(" " + reward.replace("§7- ", "")); + } + } else { + lore.add("§a§lALL MILESTONES COMPLETED!"); + lore.add(""); + lore.add("§7Total Commissions: §e" + totalCompleted); + } + + return ItemStackCreator.getStack( + "§eCommission Milestones", + Material.FILLED_MAP, + 1, + lore + ); + } + }); + + for (int i = 0; i < CommissionMilestone.values().length; i++) { + CommissionMilestone milestone = CommissionMilestone.values()[i]; + int slot = MILESTONE_SLOTS[i]; + + set(new GUIClickableItem(slot) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + SkyBlockPlayer sbPlayer = (SkyBlockPlayer) player; + DatapointCommissions.PlayerCommissionData data = Commissions.getCommissionData(sbPlayer); + + if (data.getTotalCompleted() >= milestone.getCommissionsRequired() + && !data.isMilestoneClaimed(milestone.getTier())) { + claimMilestone(sbPlayer, milestone, data); + new GUICommissionMilestones().open(sbPlayer); + } + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + SkyBlockPlayer sbPlayer = (SkyBlockPlayer) player; + DatapointCommissions.PlayerCommissionData data = Commissions.getCommissionData(sbPlayer); + + boolean reached = data.getTotalCompleted() >= milestone.getCommissionsRequired(); + boolean claimed = data.isMilestoneClaimed(milestone.getTier()); + double progress = data.getMilestoneProgress(milestone.getTier()); + + List lore = new ArrayList<>(); + lore.add(""); + lore.add("§7Progress: " + (reached ? "§a100%" : "§e" + String.format("%.1f", progress) + "§6%")); + + String progressBar = buildProgressBar(progress); + lore.add(progressBar + " §e" + data.getTotalCompleted() + "§6/§e" + milestone.getCommissionsRequired()); + lore.add(""); + lore.add("§7Rewards:"); + + String[] rewards = getMilestoneRewardLines(milestone); + for (String reward : rewards) { + if (claimed) { + lore.add("§a ✔ " + reward); + } else { + lore.add(" " + reward); + } + } + + lore.add(""); + if (claimed) { + lore.add("§a§lCLAIMED"); + } else if (reached) { + lore.add("§e§lCLICK TO CLAIM!"); + } + + Material material; + String titleColor; + if (claimed) { + material = Material.LIME_STAINED_GLASS_PANE; + titleColor = "§a"; + } else if (reached) { + material = Material.YELLOW_STAINED_GLASS_PANE; + titleColor = "§e"; + } else { + material = Material.RED_STAINED_GLASS_PANE; + titleColor = "§c"; + } + + return ItemStackCreator.getStack( + titleColor + "Milestone " + StringUtility.getAsRomanNumeral(milestone.getTier()) + " Rewards", + material, + milestone.getTier(), + lore + ); + } + }); + } + + set(new GUIClickableItem(48) { + @Override + public void run(InventoryPreClickEvent e, HypixelPlayer player) { + new GUICommisions().open((SkyBlockPlayer) player); + } + + @Override + public ItemStack.Builder getItem(HypixelPlayer player) { + return ItemStackCreator.getStack( + "§aGo Back", + Material.ARROW, + 1, + "§7To Commissions" + ); + } + }); + + set(GUIClickableItem.getCloseItem(49)); + updateItemStacks(getInventory(), getPlayer()); + } + + private void claimMilestone(SkyBlockPlayer player, CommissionMilestone milestone, + DatapointCommissions.PlayerCommissionData data) { + data.claimMilestone(milestone.getTier()); + Commissions.saveCommissionData(player, data); + + player.getSkills().increase(player, SkillCategories.MINING, (double) milestone.getMiningXpReward()); + player.getExperienceHandler().addExperience(milestone.getSkyBlockXpReward()); + + + player.sendMessage("§6§l MILESTONE CLAIMED! §r§eTier " + StringUtility.getAsRomanNumeral(milestone.getTier())); + player.sendMessage("§7Rewards:"); + player.sendMessage("§7 - §3+" + String.format("%,d", milestone.getMiningXpReward()) + " Mining XP"); + player.sendMessage("§7 - §b+" + milestone.getSkyBlockXpReward() + " SkyBlock XP"); + + if (milestone.isUnlocksEmissaries()) { + // TODO: Give Royal Compass item + } + if (milestone.isUnlocksExtraSlot()) { + } + if (milestone.isUnlocksDwarvenMinesScroll()) { + // TODO: Give Travel Scroll item + } + if (milestone.isUnlocksRoyalPigeon()) { + // TODO: Give Royal Pigeon item + } + if (milestone.isUnlocksCrystalNucleusScroll()) { + // TODO: Give Travel Scroll item + } + } + + private String[] getMilestoneRewardLines(CommissionMilestone milestone) { + List rewards = new ArrayList<>(); + + if (milestone.isUnlocksEmissaries()) { + rewards.add("§6Emissaries"); + rewards.add("§9Royal Compass"); + } + if (milestone.isUnlocksExtraSlot()) { + rewards.add("§a+1 Commission Slot"); + } + if (milestone.isUnlocksDwarvenMinesScroll()) { + rewards.add("§9Travel Scroll to Dwarven Mines"); + } + if (milestone.isUnlocksRoyalPigeon()) { + rewards.add("§6Royal Pigeon"); + } + if (milestone.isUnlocksCrystalNucleusScroll()) { + rewards.add("§9Travel Scroll to the Crystal Nucleus"); + } + + rewards.add("§8+§3" + String.format("%,d", milestone.getMiningXpReward()) + " §7Mining Experience"); + rewards.add("§8+§b" + milestone.getSkyBlockXpReward() + " SkyBlock XP"); + + return rewards.toArray(new String[0]); + } + + private String buildProgressBar(double percentage) { + int filled = (int) (percentage / 5); // 20 segments total + int empty = 20 - filled; + return "§2§l§m" + " ".repeat(Math.max(0, filled)) + "§f§l§m" + " ".repeat(Math.max(0, empty)); + } + + @Override + public boolean allowHotkeying() { + return false; + } + + @Override + public void onBottomClick(InventoryPreClickEvent e) { + e.setCancelled(true); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java new file mode 100644 index 000000000..2e2f9b989 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java @@ -0,0 +1,44 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.user.HypixelPlayer; + +public class NPCKingName extends HypixelNPC { + + public NPCKingName() { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6§lKing Name", "§e§lCLICK"}; + } + + @Override + public String signature(HypixelPlayer player) { + return "eQJvD9YaY1wSp3+8UppiGXJfsYzTuyKaIi2kEMN3p+okeYZPgO93YlOFMQK77rtO/IHipI+nboWTOEhHfYqXDIbkdX3br3Rt9oiaDXVeENRvBux/6LkIf2UImM09blWd1bDiZXFbIG44MrTjVrU1OuSOvK5+YDg1dg9tjN3J1NqAs4BEZJzo+hyxF6PlOSE/qNHkCUxISo+INL9JCRs6n07o/EBaZfJCTC1lSe39c4cUVUstZsQUf92x15ZUr1sk/gOnYhtjkunqKjAOeY07DHy8oZrO7yt2Mjz5Cpzo+cBFx7U+BEYpIbaHdR5avY2LFuLrt7hokrV3ftbqI24+TWK5doSoLcZQJ8J+9mn1nF8mdXrE6mF6otd7S7q9Px7EPQp2ZMA0IZDrLvkPbT0QHS3/igS/dPyk9TfdAGzTjMCQUlsOShSN5aYYTFQTlvFZ6F+8LNHaXev515MiA1ZbQMeP1jyNUHIQ8/nrPCd4G28Vw2UH53doFpGBHIRJSXWSQbTkq3m8IKQGqqZ2Du3VMmiv7+kEczS9jHwRNxWl9n2uiQwXobgjj4icsO7Gy4LI6lvq1iCqpc/VEXwBag08jK4InHAe6XbS7aLkv0CZ9/x/Q4WCmten5PSj4TGz0CSGhJx04GCTbk8ZymTyFfpPbVi+W9HDh7T7NPfXHMq9swA="; + } + + @Override + public String texture(HypixelPlayer player) { + return "ewogICJ0aW1lc3RhbXAiIDogMTYwODMxNTA1OTM1OSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWQxZjQxNjFhZjZkNGZkZmJhYzE3YWRjZjlkMGI2ZjFmZmI1MTdlN2I5MzZhYWQ5YzM3Yjc0N2NlNjRlYzRjNiIKICAgIH0KICB9Cn0="; + } + + @Override + public Pos position(HypixelPlayer player) { + return new Pos(129.500, 196.000, 196.500, 180, 0); + } + + @Override + public boolean looking() { + return true; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + new GUICommisions().open(event.player()); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/SkyBlockDataHandler.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/SkyBlockDataHandler.java index 200ea043c..ffedc8b90 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/SkyBlockDataHandler.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/SkyBlockDataHandler.java @@ -428,6 +428,15 @@ DatapointLong.class, new DatapointLong("booster_cookie_expiration_date", 1L)), LATEST_NEW_YEAR_CAKE_YEAR("latest_new_year_cake_year", false, false, false, DatapointInteger.class, new DatapointInteger("latest_new_year_cake_year", 0)), + COMMISSIONS_COMPLETED("commissions_completed", false, false, false, + DatapointInteger.class, new DatapointInteger("commissions_completed", 0)), + + COMMISSIONS("commissions", false, false, false, + DatapointCommissions.class, new DatapointCommissions("commissions")), + + HOTM("hotm", false, false, false, + DatapointHOTM.class, new DatapointHOTM("hotm")), + KAT("kat", false, false, false, DatapointKat.class, new DatapointKat("kat")), diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointCommissions.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointCommissions.java new file mode 100644 index 000000000..cbea500a4 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointCommissions.java @@ -0,0 +1,237 @@ +package net.swofty.type.skyblockgeneric.data.datapoints; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.protocol.Serializer; +import net.swofty.type.skyblockgeneric.data.SkyBlockDatapoint; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.List; + +public class DatapointCommissions extends SkyBlockDatapoint { + private static final Serializer serializer = new Serializer<>() { + @Override + public String serialize(PlayerCommissionData value) { + JSONObject json = new JSONObject(); + json.put("totalCompleted", value.totalCompleted); + json.put("dailyCompletedCount", value.dailyCompletedCount); + json.put("lastDailyReset", value.lastDailyReset); + + JSONArray commissionsArray = new JSONArray(); + for (ActiveCommission commission : value.activeCommissions) { + JSONObject commObj = new JSONObject(); + commObj.put("commissionName", commission.commissionName); + commObj.put("progress", commission.progress); + commObj.put("completed", commission.completed); + commObj.put("claimed", commission.claimed); + commissionsArray.put(commObj); + } + json.put("activeCommissions", commissionsArray); + + JSONArray claimedArray = new JSONArray(); + for (Integer tier : value.claimedMilestones) { + claimedArray.put(tier); + } + json.put("claimedMilestones", claimedArray); + + return json.toString(); + } + + @Override + public PlayerCommissionData deserialize(String json) { + if (json == null || json.isEmpty()) { + return PlayerCommissionData.createDefault(); + } + + try { + JSONObject obj = new JSONObject(json); + PlayerCommissionData data = new PlayerCommissionData(); + data.totalCompleted = obj.optInt("totalCompleted", 0); + data.dailyCompletedCount = obj.optInt("dailyCompletedCount", 0); + data.lastDailyReset = obj.optLong("lastDailyReset", 0L); + data.activeCommissions = new ArrayList<>(); + data.claimedMilestones = new ArrayList<>(); + + JSONArray commissionsArray = obj.optJSONArray("activeCommissions"); + if (commissionsArray != null) { + for (int i = 0; i < commissionsArray.length(); i++) { + JSONObject commObj = commissionsArray.getJSONObject(i); + ActiveCommission commission = new ActiveCommission( + commObj.getString("commissionName"), + commObj.getInt("progress"), + commObj.getBoolean("completed") + , commObj.optBoolean("claimed", false) + ); + data.activeCommissions.add(commission); + } + } + + JSONArray claimedArray = obj.optJSONArray("claimedMilestones"); + if (claimedArray != null) { + for (int i = 0; i < claimedArray.length(); i++) { + data.claimedMilestones.add(claimedArray.getInt(i)); + } + } + + return data; + } catch (Exception e) { + return PlayerCommissionData.createDefault(); + } + } + + @Override + public PlayerCommissionData clone(PlayerCommissionData value) { + PlayerCommissionData cloned = new PlayerCommissionData(); + cloned.totalCompleted = value.totalCompleted; + cloned.dailyCompletedCount = value.dailyCompletedCount; + cloned.lastDailyReset = value.lastDailyReset; + cloned.activeCommissions = new ArrayList<>(); + for (ActiveCommission commission : value.activeCommissions) { + cloned.activeCommissions.add(new ActiveCommission( + commission.commissionName, + commission.progress, + commission.completed + , commission.claimed + )); + } + cloned.claimedMilestones = new ArrayList<>(value.claimedMilestones); + return cloned; + } + }; + + public DatapointCommissions(String key, PlayerCommissionData value) { + super(key, value, serializer); + } + + public DatapointCommissions(String key) { + super(key, PlayerCommissionData.createDefault(), serializer); + } + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class ActiveCommission { + private String commissionName; + private int progress; + private boolean completed; + private boolean claimed; + + public ActiveCommission(String commissionName) { + this.commissionName = commissionName; + this.progress = 0; + this.completed = false; + this.claimed = false; + } + } + + @Getter + @Setter + @NoArgsConstructor + public static class PlayerCommissionData { + private int totalCompleted; + private int dailyCompletedCount; + private long lastDailyReset; + private List activeCommissions = new ArrayList<>(); + private List claimedMilestones = new ArrayList<>(); // tracks which milestone tiers have been claimed + + public static PlayerCommissionData createDefault() { + PlayerCommissionData data = new PlayerCommissionData(); + data.totalCompleted = 0; + data.dailyCompletedCount = 0; + data.lastDailyReset = 0L; + data.activeCommissions = new ArrayList<>(); + data.claimedMilestones = new ArrayList<>(); + return data; + } + + public boolean checkAndResetDaily() { + long todayStart = LocalDate.now(ZoneOffset.UTC).atStartOfDay(ZoneOffset.UTC).toEpochSecond() * 1000; + if (lastDailyReset < todayStart) { + dailyCompletedCount = 0; + lastDailyReset = System.currentTimeMillis(); + return true; + } + return false; + } + + public int getRemainingDailyBonus() { + checkAndResetDaily(); + return Math.max(0, 4 - dailyCompletedCount); + } + + public boolean hasDailyBonus() { + checkAndResetDaily(); + return dailyCompletedCount < 4; + } + + public void completeCommission() { + checkAndResetDaily(); + totalCompleted++; + dailyCompletedCount++; + } + + public int getMilestoneTier() { + if (totalCompleted >= 750) return 6; + if (totalCompleted >= 500) return 5; + if (totalCompleted >= 250) return 4; + if (totalCompleted >= 100) return 3; + if (totalCompleted >= 25) return 2; + if (totalCompleted >= 5) return 1; + return 0; + } + + public int getCommissionSlots() { + int slots = 2; // base slots + if (getMilestoneTier() >= 3) { + slots++; // +1 slot at tier 3 + } + return slots; + } + + public boolean isMilestoneClaimed(int tier) { + return claimedMilestones.contains(tier); + } + + public boolean claimMilestone(int tier) { + if (isMilestoneClaimed(tier)) return false; + if (getMilestoneTier() < tier) return false; + claimedMilestones.add(tier); + return true; + } + + public int getNextClaimableMilestone() { + int currentTier = getMilestoneTier(); + for (int i = 1; i <= currentTier; i++) { + if (!isMilestoneClaimed(i)) { + return i; + } + } + return -1; + } + + public double getMilestoneProgress(int tier) { + int required = getMilestoneRequirement(tier); + if (required == 0) return 100.0; + return Math.min(100.0, (totalCompleted * 100.0) / required); + } + + public int getMilestoneRequirement(int tier) { + return switch (tier) { + case 1 -> 5; + case 2 -> 25; + case 3 -> 100; + case 4 -> 250; + case 5 -> 500; + case 6 -> 750; + default -> 0; + }; + } + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java new file mode 100644 index 000000000..8421bee9b --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java @@ -0,0 +1,227 @@ +package net.swofty.type.skyblockgeneric.data.datapoints; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import net.swofty.commons.protocol.Serializer; +import net.swofty.type.skyblockgeneric.data.SkyBlockDatapoint; +import org.json.JSONObject; + +/** + * Datapoint for storing Heart of the Mountain (HOTM) data. + */ +public class DatapointHOTM extends SkyBlockDatapoint { + private static final Serializer serializer = new Serializer<>() { + @Override + public String serialize(PlayerHOTMData value) { + JSONObject json = new JSONObject(); + json.put("experience", value.experience); + json.put("mithrilPowder", value.mithrilPowder); + json.put("gemstonePowder", value.gemstonePowder); + json.put("tokens", value.tokens); + json.put("tokensSpent", value.tokensSpent); + return json.toString(); + } + + @Override + public PlayerHOTMData deserialize(String json) { + if (json == null || json.isEmpty()) { + return PlayerHOTMData.createDefault(); + } + + try { + JSONObject obj = new JSONObject(json); + PlayerHOTMData data = new PlayerHOTMData(); + data.experience = obj.optLong("experience", 0L); + data.mithrilPowder = obj.optLong("mithrilPowder", 0L); + data.gemstonePowder = obj.optLong("gemstonePowder", 0L); + data.tokens = obj.optInt("tokens", 0); + data.tokensSpent = obj.optInt("tokensSpent", 0); + return data; + } catch (Exception e) { + return PlayerHOTMData.createDefault(); + } + } + + @Override + public PlayerHOTMData clone(PlayerHOTMData value) { + PlayerHOTMData cloned = new PlayerHOTMData(); + cloned.experience = value.experience; + cloned.mithrilPowder = value.mithrilPowder; + cloned.gemstonePowder = value.gemstonePowder; + cloned.tokens = value.tokens; + cloned.tokensSpent = value.tokensSpent; + return cloned; + } + }; + + public DatapointHOTM(String key, PlayerHOTMData value) { + super(key, value, serializer); + } + + public DatapointHOTM(String key) { + super(key, PlayerHOTMData.createDefault(), serializer); + } + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class PlayerHOTMData { + private long experience; + private long mithrilPowder; + private long gemstonePowder; + private int tokens; + private int tokensSpent; + + public static PlayerHOTMData createDefault() { + PlayerHOTMData data = new PlayerHOTMData(); + data.experience = 0L; + data.mithrilPowder = 0L; + data.gemstonePowder = 0L; + data.tokens = 1; // Start with 1 token at tier 1 + data.tokensSpent = 0; + return data; + } + + /** + * Gets the current HOTM tier based on experience. + * @return tier 1-10 + */ + public int getTier() { + if (experience >= 1_247_000) return 10; + if (experience >= 847_000) return 9; + if (experience >= 557_000) return 8; + if (experience >= 347_000) return 7; + if (experience >= 197_000) return 6; + if (experience >= 97_000) return 5; + if (experience >= 37_000) return 4; + if (experience >= 12_000) return 3; + if (experience >= 3_000) return 2; + return 1; + } + + /** + * Gets the cumulative XP required for the next tier. + * @return XP needed for next tier, or -1 if maxed + */ + public long getNextTierXp() { + int currentTier = getTier(); + return switch (currentTier) { + case 1 -> 3_000; + case 2 -> 12_000; + case 3 -> 37_000; + case 4 -> 97_000; + case 5 -> 197_000; + case 6 -> 347_000; + case 7 -> 557_000; + case 8 -> 847_000; + case 9 -> 1_247_000; + default -> -1; // Maxed + }; + } + + /** + * Checks if HOTM is maxed (tier 10). + * @return true if tier 10 reached + */ + public boolean isMaxed() { + return getTier() >= 10; + } + + /** + * Adds HOTM experience and handles level ups. + * @param amount the amount of XP to add + * @return the number of level ups that occurred + */ + public int addExperience(long amount) { + int previousTier = getTier(); + experience += amount; + int newTier = getTier(); + + int levelUps = newTier - previousTier; + if (levelUps > 0) { + // Award tokens for each tier gained + for (int tier = previousTier + 1; tier <= newTier; tier++) { + tokens += getTokensForTier(tier); + } + } + return levelUps; + } + + private int getTokensForTier(int tier) { + return switch (tier) { + case 1 -> 1; + case 2, 3, 4, 5, 6 -> 2; + case 7 -> 3; + case 8, 9, 10 -> 2; + default -> 0; + }; + } + + /** + * Adds mithril powder. + * @param amount the amount to add + */ + public void addMithrilPowder(long amount) { + mithrilPowder += amount; + } + + /** + * Adds gemstone powder. + * @param amount the amount to add + */ + public void addGemstonePowder(long amount) { + gemstonePowder += amount; + } + + /** + * Gets the number of available (unspent) tokens. + * @return available tokens + */ + public int getAvailableTokens() { + return tokens - tokensSpent; + } + + /** + * Spends a token on a perk. + * @return true if token was spent, false if not enough tokens + */ + public boolean spendToken() { + if (getAvailableTokens() <= 0) return false; + tokensSpent++; + return true; + } + + /** + * Gets progress to next tier as a percentage (0-100). + * @return progress percentage + */ + public int getProgressPercent() { + if (isMaxed()) return 100; + + int currentTier = getTier(); + long currentTierXp = switch (currentTier) { + case 1 -> 0; + case 2 -> 3_000; + case 3 -> 12_000; + case 4 -> 37_000; + case 5 -> 97_000; + case 6 -> 197_000; + case 7 -> 347_000; + case 8 -> 557_000; + case 9 -> 847_000; + default -> 1_247_000; + }; + long nextTierXp = getNextTierXp(); + if (nextTierXp == -1) return 100; + + long progressInTier = experience - currentTierXp; + long xpNeededForTier = nextTierXp - currentTierXp; + + return (int) ((progressInTier * 100) / xpNeededForTier); + } + } +} + diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java new file mode 100644 index 000000000..e9efdb678 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java @@ -0,0 +1,147 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines; + +import lombok.NonNull; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.utils.time.TimeUnit; +import net.swofty.commons.skyblock.item.ItemType; +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.generic.gui.inventory.item.GUIMaterial; +import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; +import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.ai.ClosestEntityRegionTarget; +import net.swofty.type.skyblockgeneric.entity.mob.ai.MeleeAttackWithinRegionGoal; +import net.swofty.type.skyblockgeneric.entity.mob.ai.RandomRegionStrollGoal; +import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; +import net.swofty.type.skyblockgeneric.item.SkyBlockItem; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; +import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class MobGlaciteWalker extends BestiaryMob implements RegionPopulator { + + public MobGlaciteWalker() { + super(EntityType.ZOMBIE); // it's a player + } + + @Override + public Integer getLevel() { + return 45; + } + + @Override + public int getMaxBestiaryTier() { + return 15; + } + + @Override + public int getBestiaryBracket() { + return 2; + } + + @Override + public String getMobID() { + return "ICE_WALKER"; + } + + @Override + public void onInit() { + setBoots(new SkyBlockItem(ItemType.LAPIS_ARMOR_BOOTS).getItemStack()); + setLeggings(new SkyBlockItem(ItemType.LAPIS_ARMOR_LEGGINGS).getItemStack()); + setChestplate(new SkyBlockItem(ItemType.LAPIS_ARMOR_CHESTPLATE).getItemStack()); + setHelmet(new SkyBlockItem(ItemType.LAPIS_ARMOR_HELMET).getItemStack()); + } + + @Override + public GUIMaterial getGuiMaterial() { + return null; + } + + @Override + public String getDisplayName() { + return "Glacite Walker"; + } + + @Override + public List getGoalSelectors() { + return List.of( + new MeleeAttackWithinRegionGoal(this, + 1.6, + 20, + TimeUnit.SERVER_TICK, + RegionType.GREAT_ICE_WALL), + new RandomRegionStrollGoal(this, 15, RegionType.GREAT_ICE_WALL) + ); + } + + @Override + public List getTargetSelectors() { + return List.of( + new LastEntityDamagerTarget(this, 16), + new ClosestEntityRegionTarget(this, + 6, + entity -> entity instanceof SkyBlockPlayer, + RegionType.GREAT_ICE_WALL) + ); + } + + @Override + public ItemStatistics getBaseStatistics() { + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 200D) + .withBase(ItemStatistic.DAMAGE, 50D) + .withBase(ItemStatistic.SPEED, 100D) + .build(); + } + + @Override + public @Nullable SkyBlockLootTable getLootTable() { + return new SkyBlockLootTable() { + @Override + public @NonNull List getLootTable() { + return List.of( + new LootRecord(ItemType.GLACITE_JEWEL, 1, 0.5) + ); + } + + @Override + public @NotNull CalculationMode getCalculationMode() { + return CalculationMode.CALCULATE_INDIVIDUAL; + } + }; + } + + @Override + public SkillCategories getSkillCategory() { + return SkillCategories.COMBAT; + } + + @Override + public long damageCooldown() { + return 500; + } + + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(40, 8, 8); + } + + @Override + public List getMobTypes() { + return List.of(MobType.GLACIAL, MobType.HUMANOID); + } + + @Override + public List getPopulators() { + return List.of(new Populator(RegionType.GREAT_ICE_WALL, 20)); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java index 31ee5525b..5ec0ec3a9 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/region/RegionType.java @@ -83,7 +83,13 @@ public enum RegionType { THE_FORGE("The Forge", DwarvenMinesConfiguration.class), CLIFFSIDE_VEINS("Cliffside Veins", DwarvenMinesConfiguration.class), ROYAL_MINES("Royal Mines", DwarvenMinesConfiguration.class), + UPPER_MINES("Upper Mines", DwarvenMinesConfiguration.class), + LAVA_SPRINGS("Lava Springs", DwarvenMinesConfiguration.class), DIVANS_GATEWAY("Divan's Gateway", DwarvenMinesConfiguration.class), + FAR_REACH("Far Reserve", DwarvenMinesConfiguration.class), + PALACE_BRIDGE("Palace Bridge", DwarvenMinesConfiguration.class), + ROYAL_PALACE("Royal Palace", DwarvenMinesConfiguration.class), + ARISTOCRAT_PASSAGE("Aristocrat's Passage", DwarvenMinesConfiguration.class), FAR_RESERVE("Far Reserve", DwarvenMinesConfiguration.class); private final String name; From 6f9daf36dafd11981604ee0eced616ade797743c Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 15:25:30 +0200 Subject: [PATCH 05/13] refactor: use a record --- .../commission/CommissionReward.java | 190 ++++----- .../events/ActionPlayerCommissions.java | 31 +- .../type/dwarvenmines/gui/GUICommisions.java | 14 +- .../data/datapoints/DatapointHOTM.java | 386 ++++++++---------- 4 files changed, 263 insertions(+), 358 deletions(-) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java index 6805e25a2..96cd7d8a6 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/CommissionReward.java @@ -1,117 +1,85 @@ package net.swofty.type.dwarvenmines.commission; -import lombok.AllArgsConstructor; -import lombok.Getter; - +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ThreadLocalRandom; -/** - * Commission reward calculator based on HOTM tier and daily bonus status. - */ -@Getter -@AllArgsConstructor -public class CommissionReward { - private final int hotmXp; - private final int miningXp; - private final int mithrilPowder; - private final boolean isDailyBonus; - - /** - * Calculates rewards for completing a commission. - * - * @param hotmTier the player's current HOTM tier (1-10) - * @param isHotmMaxed whether HOTM is maxed (tier 10) - * @param isDailyBonus whether this is one of the first 4 daily commissions - * @return the commission reward - */ - public static CommissionReward calculate(int hotmTier, boolean isHotmMaxed, boolean isDailyBonus) { - int hotmXp; - int miningXp; - int mithrilPowder; - - // Base HOTM XP based on tier (when not maxed) - if (!isHotmMaxed) { - if (hotmTier == 1) { - hotmXp = 100; - } else if (hotmTier == 2) { - hotmXp = 200; - } else { - hotmXp = 400; - } - } else { - hotmXp = 0; // No HOTM XP when maxed - } - - // Mining XP: random between 5,000 and 10,000 - miningXp = ThreadLocalRandom.current().nextInt(5_000, 10_001); - - // Mithril Powder: 100-200 when not maxed, 500 when maxed - if (!isHotmMaxed) { - mithrilPowder = ThreadLocalRandom.current().nextInt(100, 201); - } else { - mithrilPowder = 500; - } - - // Daily bonus for first 4 commissions - int dailyBonusHotmXp = 0; - int dailyBonusPowder = 0; - if (isDailyBonus) { - if (!isHotmMaxed) { - dailyBonusHotmXp = 900; // +900 HOTM XP daily bonus - } else { - dailyBonusPowder = 2000; // +2000 Mithril Powder when maxed - } - } - - return new CommissionReward( - hotmXp + dailyBonusHotmXp, - miningXp, - mithrilPowder + dailyBonusPowder, - isDailyBonus - ); - } - - /** - * Gets the formatted reward lines for display in the GUI. - * - * @param hotmTier the player's current HOTM tier (1-10) - * @param isHotmMaxed whether HOTM is maxed - * @param isDailyBonus whether this is a daily bonus commission - * @return array of formatted reward strings - */ - public static String[] getRewardLore(int hotmTier, boolean isHotmMaxed, boolean isDailyBonus) { - java.util.List lore = new java.util.ArrayList<>(); - - if (!isHotmMaxed) { - int baseHotmXp; - if (hotmTier == 1) { - baseHotmXp = 100; - } else if (hotmTier == 2) { - baseHotmXp = 200; - } else { - baseHotmXp = 400; - } - - if (isDailyBonus) { - lore.add("§7- §5+" + (baseHotmXp + 900) + " Heart of the Mountain XP §e(Daily Bonus)"); - } else { - lore.add("§7- §5+" + baseHotmXp + " Heart of the Mountain XP"); - } - } - - if (!isHotmMaxed) { - if (isDailyBonus) { - lore.add("§7- §2+100 Mithril Powder"); - } else { - lore.add("§7- §2+100 Mithril Powder"); - } - } else { - lore.add("§7- §2+500 Mithril Powder"); - } - - lore.add("§7- §3+7.5k Mining XP"); - - return lore.toArray(new String[0]); - } +public record CommissionReward(int hotmXp, int miningXp, int mithrilPowder, boolean isDailyBonus) { + public static CommissionReward calculate(int hotmTier, boolean isHotmMaxed, boolean isDailyBonus) { + int hotmXp; + int miningXp; + int mithrilPowder; + + if (!isHotmMaxed) { + if (hotmTier == 1) { + hotmXp = 100; + } else if (hotmTier == 2) { + hotmXp = 200; + } else { + hotmXp = 400; + } + } else { + hotmXp = 0; + } + + miningXp = ThreadLocalRandom.current().nextInt(5_000, 10_001); + if (!isHotmMaxed) { + mithrilPowder = ThreadLocalRandom.current().nextInt(100, 201); + } else { + mithrilPowder = 500; + } + + int dailyBonusHotmXp = 0; + int dailyBonusPowder = 0; + if (isDailyBonus) { + if (!isHotmMaxed) { + dailyBonusHotmXp = 900; + } else { + dailyBonusPowder = 2000; + } + } + + return new CommissionReward( + hotmXp + dailyBonusHotmXp, + miningXp, + mithrilPowder + dailyBonusPowder, + isDailyBonus + ); + } + + public static String[] getRewardLore(int hotmTier, boolean isHotmMaxed, boolean isDailyBonus) { + List lore = new ArrayList<>(); + + if (!isHotmMaxed) { + int baseHotmXp; + if (hotmTier == 1) { + baseHotmXp = 100; + } else if (hotmTier == 2) { + baseHotmXp = 200; + } else { + baseHotmXp = 400; + } + + if (isDailyBonus) { + lore.add("§7- §5+" + (baseHotmXp + 900) + " Heart of the Mountain XP §e(Daily Bonus)"); + } else { + lore.add("§7- §5+" + baseHotmXp + " Heart of the Mountain XP"); + } + } + + if (!isHotmMaxed) { + if (isDailyBonus) { + lore.add("§7- §2+100 Mithril Powder"); + } else { + lore.add("§7- §2+100 Mithril Powder"); + } + } else { + lore.add("§7- §2+500 Mithril Powder"); + } + + lore.add("§7- §3+7.5k Mining XP"); + + return lore.toArray(new String[0]); + } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java index dc7b88b59..af9c1d81b 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/events/ActionPlayerCommissions.java @@ -19,18 +19,9 @@ public class ActionPlayerCommissions implements HypixelEventClass { - private static final Set MITHRIL_BLOCKS = Set.of( - Material.LIGHT_BLUE_WOOL, - Material.GRAY_WOOL, - Material.CYAN_TERRACOTTA, - Material.PRISMARINE, - Material.DARK_PRISMARINE, - Material.PRISMARINE_BRICKS - ); - - private static final Set TITANIUM_BLOCKS = Set.of( - Material.POLISHED_DIORITE - ); + private static final Set MITHRIL_BLOCKS = Set.of(Material.LIGHT_BLUE_WOOL, Material.GRAY_WOOL, Material.CYAN_TERRACOTTA, Material.PRISMARINE, Material.DARK_PRISMARINE, Material.PRISMARINE_BRICKS); + + private static final Set TITANIUM_BLOCKS = Set.of(Material.POLISHED_DIORITE); @HypixelEvent(node = EventNodes.PLAYER, requireDataLoaded = true) public void run(PlayerBlockBreakEvent event) { @@ -39,7 +30,6 @@ public void run(PlayerBlockBreakEvent event) { Material brokenMaterial = event.getBlock().registry().material(); if (brokenMaterial == null) return; - // Determine what type of block was broken Objective.BlockTarget target = null; if (MITHRIL_BLOCKS.contains(brokenMaterial)) { target = Objective.BlockTarget.MITHRIL; @@ -55,20 +45,9 @@ public void run(PlayerBlockBreakEvent event) { updateCommissionProgress(player, ObjectiveType.MINE, target, 1, regionType); } - /** - * Updates the progress of matching commissions for the player. - * - * @param player the player - * @param type the objective type (MINE, SLAY, etc.) - * @param target the target (MITHRIL, TITANIUM, GOBLIN, etc.) - * @param amount the amount to add to progress - * @param regionType the current region (can be null for any region) - */ - public static void updateCommissionProgress(SkyBlockPlayer player, ObjectiveType type, - Objective.BlockTarget target, int amount, RegionType regionType) { + public static void updateCommissionProgress(SkyBlockPlayer player, ObjectiveType type, Objective.BlockTarget target, int amount, RegionType regionType) { SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); - DatapointCommissions.PlayerCommissionData commissionData = - dataHandler.get(SkyBlockDataHandler.Data.COMMISSIONS, DatapointCommissions.class).getValue(); + DatapointCommissions.PlayerCommissionData commissionData = dataHandler.get(SkyBlockDataHandler.Data.COMMISSIONS, DatapointCommissions.class).getValue(); boolean anyUpdated = false; diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java index 4a19d1f3f..1c016ff27 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommisions.java @@ -64,7 +64,7 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { SkyBlockDataHandler dataHandler = player.getSkyblockDataHandler(); DatapointHOTM.PlayerHOTMData hotmData = - dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).getValue(); + dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).getValue(); int hotmTier = hotmData.getTier(); boolean isHotmMaxed = hotmData.isMaxed(); @@ -72,18 +72,18 @@ public void run(InventoryPreClickEvent e, HypixelPlayer p) { CommissionReward reward = CommissionReward.calculate(hotmTier, isHotmMaxed, isDailyBonus); - if (reward.getHotmXp() > 0) { - hotmData.addExperience(reward.getHotmXp()); + if (reward.hotmXp() > 0) { + hotmData.addExperience(reward.hotmXp()); dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).setValue(hotmData); } - if (reward.getMithrilPowder() > 0) { - hotmData.addMithrilPowder(reward.getMithrilPowder()); + if (reward.mithrilPowder() > 0) { + hotmData.addMithrilPowder(reward.mithrilPowder()); dataHandler.get(SkyBlockDataHandler.Data.HOTM, DatapointHOTM.class).setValue(hotmData); } - if (reward.getMiningXp() > 0) { - player.getSkills().increase(player, SkillCategories.MINING, (double) reward.getMiningXp()); + if (reward.miningXp() > 0) { + player.getSkills().increase(player, SkillCategories.MINING, (double) reward.miningXp()); } activeCommission.setClaimed(true); diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java index 8421bee9b..9579a5fd4 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/data/datapoints/DatapointHOTM.java @@ -8,220 +8,178 @@ import net.swofty.type.skyblockgeneric.data.SkyBlockDatapoint; import org.json.JSONObject; -/** - * Datapoint for storing Heart of the Mountain (HOTM) data. - */ public class DatapointHOTM extends SkyBlockDatapoint { - private static final Serializer serializer = new Serializer<>() { - @Override - public String serialize(PlayerHOTMData value) { - JSONObject json = new JSONObject(); - json.put("experience", value.experience); - json.put("mithrilPowder", value.mithrilPowder); - json.put("gemstonePowder", value.gemstonePowder); - json.put("tokens", value.tokens); - json.put("tokensSpent", value.tokensSpent); - return json.toString(); - } - - @Override - public PlayerHOTMData deserialize(String json) { - if (json == null || json.isEmpty()) { - return PlayerHOTMData.createDefault(); - } - - try { - JSONObject obj = new JSONObject(json); - PlayerHOTMData data = new PlayerHOTMData(); - data.experience = obj.optLong("experience", 0L); - data.mithrilPowder = obj.optLong("mithrilPowder", 0L); - data.gemstonePowder = obj.optLong("gemstonePowder", 0L); - data.tokens = obj.optInt("tokens", 0); - data.tokensSpent = obj.optInt("tokensSpent", 0); - return data; - } catch (Exception e) { - return PlayerHOTMData.createDefault(); - } - } - - @Override - public PlayerHOTMData clone(PlayerHOTMData value) { - PlayerHOTMData cloned = new PlayerHOTMData(); - cloned.experience = value.experience; - cloned.mithrilPowder = value.mithrilPowder; - cloned.gemstonePowder = value.gemstonePowder; - cloned.tokens = value.tokens; - cloned.tokensSpent = value.tokensSpent; - return cloned; - } - }; - - public DatapointHOTM(String key, PlayerHOTMData value) { - super(key, value, serializer); - } - - public DatapointHOTM(String key) { - super(key, PlayerHOTMData.createDefault(), serializer); - } - - @Getter - @Setter - @NoArgsConstructor - @AllArgsConstructor - public static class PlayerHOTMData { - private long experience; - private long mithrilPowder; - private long gemstonePowder; - private int tokens; - private int tokensSpent; - - public static PlayerHOTMData createDefault() { - PlayerHOTMData data = new PlayerHOTMData(); - data.experience = 0L; - data.mithrilPowder = 0L; - data.gemstonePowder = 0L; - data.tokens = 1; // Start with 1 token at tier 1 - data.tokensSpent = 0; - return data; - } - - /** - * Gets the current HOTM tier based on experience. - * @return tier 1-10 - */ - public int getTier() { - if (experience >= 1_247_000) return 10; - if (experience >= 847_000) return 9; - if (experience >= 557_000) return 8; - if (experience >= 347_000) return 7; - if (experience >= 197_000) return 6; - if (experience >= 97_000) return 5; - if (experience >= 37_000) return 4; - if (experience >= 12_000) return 3; - if (experience >= 3_000) return 2; - return 1; - } - - /** - * Gets the cumulative XP required for the next tier. - * @return XP needed for next tier, or -1 if maxed - */ - public long getNextTierXp() { - int currentTier = getTier(); - return switch (currentTier) { - case 1 -> 3_000; - case 2 -> 12_000; - case 3 -> 37_000; - case 4 -> 97_000; - case 5 -> 197_000; - case 6 -> 347_000; - case 7 -> 557_000; - case 8 -> 847_000; - case 9 -> 1_247_000; - default -> -1; // Maxed - }; - } - - /** - * Checks if HOTM is maxed (tier 10). - * @return true if tier 10 reached - */ - public boolean isMaxed() { - return getTier() >= 10; - } - - /** - * Adds HOTM experience and handles level ups. - * @param amount the amount of XP to add - * @return the number of level ups that occurred - */ - public int addExperience(long amount) { - int previousTier = getTier(); - experience += amount; - int newTier = getTier(); - - int levelUps = newTier - previousTier; - if (levelUps > 0) { - // Award tokens for each tier gained - for (int tier = previousTier + 1; tier <= newTier; tier++) { - tokens += getTokensForTier(tier); - } - } - return levelUps; - } - - private int getTokensForTier(int tier) { - return switch (tier) { - case 1 -> 1; - case 2, 3, 4, 5, 6 -> 2; - case 7 -> 3; - case 8, 9, 10 -> 2; - default -> 0; - }; - } - - /** - * Adds mithril powder. - * @param amount the amount to add - */ - public void addMithrilPowder(long amount) { - mithrilPowder += amount; - } - - /** - * Adds gemstone powder. - * @param amount the amount to add - */ - public void addGemstonePowder(long amount) { - gemstonePowder += amount; - } - - /** - * Gets the number of available (unspent) tokens. - * @return available tokens - */ - public int getAvailableTokens() { - return tokens - tokensSpent; - } - - /** - * Spends a token on a perk. - * @return true if token was spent, false if not enough tokens - */ - public boolean spendToken() { - if (getAvailableTokens() <= 0) return false; - tokensSpent++; - return true; - } - - /** - * Gets progress to next tier as a percentage (0-100). - * @return progress percentage - */ - public int getProgressPercent() { - if (isMaxed()) return 100; - - int currentTier = getTier(); - long currentTierXp = switch (currentTier) { - case 1 -> 0; - case 2 -> 3_000; - case 3 -> 12_000; - case 4 -> 37_000; - case 5 -> 97_000; - case 6 -> 197_000; - case 7 -> 347_000; - case 8 -> 557_000; - case 9 -> 847_000; - default -> 1_247_000; - }; - long nextTierXp = getNextTierXp(); - if (nextTierXp == -1) return 100; - - long progressInTier = experience - currentTierXp; - long xpNeededForTier = nextTierXp - currentTierXp; - - return (int) ((progressInTier * 100) / xpNeededForTier); - } - } + private static final Serializer serializer = new Serializer<>() { + @Override + public String serialize(PlayerHOTMData value) { + JSONObject json = new JSONObject(); + json.put("experience", value.experience); + json.put("mithrilPowder", value.mithrilPowder); + json.put("gemstonePowder", value.gemstonePowder); + json.put("tokens", value.tokens); + json.put("tokensSpent", value.tokensSpent); + return json.toString(); + } + + @Override + public PlayerHOTMData deserialize(String json) { + if (json == null || json.isEmpty()) { + return PlayerHOTMData.createDefault(); + } + + try { + JSONObject obj = new JSONObject(json); + PlayerHOTMData data = new PlayerHOTMData(); + data.experience = obj.optLong("experience", 0L); + data.mithrilPowder = obj.optLong("mithrilPowder", 0L); + data.gemstonePowder = obj.optLong("gemstonePowder", 0L); + data.tokens = obj.optInt("tokens", 0); + data.tokensSpent = obj.optInt("tokensSpent", 0); + return data; + } catch (Exception e) { + return PlayerHOTMData.createDefault(); + } + } + + @Override + public PlayerHOTMData clone(PlayerHOTMData value) { + PlayerHOTMData cloned = new PlayerHOTMData(); + cloned.experience = value.experience; + cloned.mithrilPowder = value.mithrilPowder; + cloned.gemstonePowder = value.gemstonePowder; + cloned.tokens = value.tokens; + cloned.tokensSpent = value.tokensSpent; + return cloned; + } + }; + + public DatapointHOTM(String key, PlayerHOTMData value) { + super(key, value, serializer); + } + + public DatapointHOTM(String key) { + super(key, PlayerHOTMData.createDefault(), serializer); + } + + @Getter + @Setter + @NoArgsConstructor + @AllArgsConstructor + public static class PlayerHOTMData { + private long experience; + private long mithrilPowder; + private long gemstonePowder; + private int tokens; + private int tokensSpent; + + public static PlayerHOTMData createDefault() { + PlayerHOTMData data = new PlayerHOTMData(); + data.experience = 0L; + data.mithrilPowder = 0L; + data.gemstonePowder = 0L; + data.tokens = 1; + data.tokensSpent = 0; + return data; + } + + public int getTier() { + if (experience >= 1_247_000) return 10; + if (experience >= 847_000) return 9; + if (experience >= 557_000) return 8; + if (experience >= 347_000) return 7; + if (experience >= 197_000) return 6; + if (experience >= 97_000) return 5; + if (experience >= 37_000) return 4; + if (experience >= 12_000) return 3; + if (experience >= 3_000) return 2; + return 1; + } + + public long getNextTierXp() { + int currentTier = getTier(); + return switch (currentTier) { + case 1 -> 3_000; + case 2 -> 12_000; + case 3 -> 37_000; + case 4 -> 97_000; + case 5 -> 197_000; + case 6 -> 347_000; + case 7 -> 557_000; + case 8 -> 847_000; + case 9 -> 1_247_000; + default -> -1; // maxed out + }; + } + + public boolean isMaxed() { + return getTier() >= 10; + } + + public int addExperience(long amount) { + int previousTier = getTier(); + experience += amount; + int newTier = getTier(); + + int levelUps = newTier - previousTier; + if (levelUps > 0) { + for (int tier = previousTier + 1; tier <= newTier; tier++) { + tokens += getTokensForTier(tier); + } + } + return levelUps; + } + + private int getTokensForTier(int tier) { + return switch (tier) { + case 1 -> 1; + case 2, 3, 4, 5, 6, 8, 9, 10 -> 2; + case 7 -> 3; + default -> 0; + }; + } + + public void addMithrilPowder(long amount) { + mithrilPowder += amount; + } + + public void addGemstonePowder(long amount) { + gemstonePowder += amount; + } + + public int getAvailableTokens() { + return tokens - tokensSpent; + } + + public boolean spendToken() { + if (getAvailableTokens() <= 0) return false; + tokensSpent++; + return true; + } + + public int getProgressPercent() { + if (isMaxed()) return 100; + + int currentTier = getTier(); + long currentTierXp = switch (currentTier) { + case 1 -> 0; + case 2 -> 3_000; + case 3 -> 12_000; + case 4 -> 37_000; + case 5 -> 97_000; + case 6 -> 197_000; + case 7 -> 347_000; + case 8 -> 557_000; + case 9 -> 847_000; + default -> 1_247_000; + }; + long nextTierXp = getNextTierXp(); + if (nextTierXp == -1) return 100; + + long progressInTier = experience - currentTierXp; + long xpNeededForTier = nextTierXp - currentTierXp; + + return (int) ((progressInTier * 100) / xpNeededForTier); + } + } } From 582ed29b04a7d59f2ae82a06c3f71252fc3b96d6 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:08:52 +0200 Subject: [PATCH 06/13] feat: unfinished dwarven mines mobs --- .../entity/mob/SkyBlockMob.java | 54 +++++- .../entity/mob/impl/MobPlayerSkin.java | 6 + .../mob/mobs/dwarvenmines/DiamondGoblin.java | 134 +++++++++++++++ .../mob/mobs/dwarvenmines/GoldenGoblin.java | 133 +++++++++++++++ .../mobs/dwarvenmines/MobGlaciteWalker.java | 5 +- .../mobs/dwarvenmines/MobTreasureHoarder.java | 98 +++++++++++ .../dwarvenmines/goblin/MobFireslinger.java | 40 +++++ .../mobs/dwarvenmines/goblin/MobGoblin.java | 159 ++++++++++++++++++ .../goblin/MobGoblinFlamethrower.java | 82 +++++++++ .../dwarvenmines/goblin/MobKnifethrower.java | 33 ++++ 10 files changed, 736 insertions(+), 8 deletions(-) create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/impl/MobPlayerSkin.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/DiamondGoblin.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/GoldenGoblin.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobFireslinger.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblinFlamethrower.java create mode 100644 type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobKnifethrower.java diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/SkyBlockMob.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/SkyBlockMob.java index d947c4b4b..75d042aec 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/SkyBlockMob.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/SkyBlockMob.java @@ -8,14 +8,18 @@ import net.kyori.adventure.text.Component; import net.minestom.server.component.DataComponents; import net.minestom.server.coordinate.Pos; -import net.minestom.server.entity.Entity; -import net.minestom.server.entity.EntityCreature; -import net.minestom.server.entity.EntityType; +import net.minestom.server.coordinate.Vec; +import net.minestom.server.entity.*; import net.minestom.server.entity.ai.GoalSelector; import net.minestom.server.entity.ai.TargetSelector; import net.minestom.server.entity.attribute.Attribute; import net.minestom.server.entity.damage.Damage; +import net.minestom.server.entity.metadata.avatar.PlayerMeta; import net.minestom.server.instance.Instance; +import net.minestom.server.network.packet.server.play.EntityHeadLookPacket; +import net.minestom.server.network.packet.server.play.EntityMetaDataPacket; +import net.minestom.server.network.packet.server.play.PlayerInfoUpdatePacket; +import net.minestom.server.network.packet.server.play.SpawnEntityPacket; import net.minestom.server.timer.Scheduler; import net.minestom.server.timer.TaskSchedule; import net.swofty.commons.skyblock.item.ItemType; @@ -25,6 +29,7 @@ import net.swofty.type.generic.utility.MathUtility; import net.swofty.type.skyblockgeneric.SkyBlockGenericLoader; import net.swofty.type.skyblockgeneric.entity.DroppedItemEntityImpl; +import net.swofty.type.skyblockgeneric.entity.mob.impl.MobPlayerSkin; import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; import net.swofty.type.skyblockgeneric.event.custom.PlayerKilledSkyBlockMobEvent; import net.swofty.type.skyblockgeneric.item.SkyBlockItem; @@ -53,6 +58,8 @@ public abstract class SkyBlockMob extends EntityCreature { @Getter private boolean hasBeenDamaged = false; + private Component customName; + public SkyBlockMob(EntityType entityType) { super(entityType); init(); @@ -67,14 +74,15 @@ private void init() { .setBaseValue((float) ((getBaseStatistics().getOverall(ItemStatistic.SPEED).floatValue() / 1000) * 2.5)); this.setHealth(getBaseStatistics().getOverall(ItemStatistic.HEALTH).floatValue()); - this.set(DataComponents.CUSTOM_NAME, Component.text( + this.customName = Component.text( "§8[§7Lv" + getLevel() + "§8] §c" + getMobTypes().getFirst().getColor() + getMobTypes().getFirst().getSymbol() + "§c " + getDisplayName() + " §a" + Math.round(getHealth()) + "§f/§a" + Math.round(getBaseStatistics().getOverall(ItemStatistic.HEALTH).floatValue()) - )); + ); + this.set(DataComponents.CUSTOM_NAME, customName); setAutoViewable(true); setAutoViewEntities(true); @@ -82,6 +90,40 @@ private void init() { onInit(); } + @Override + public void updateNewViewer(@NotNull Player player) { + super.updateNewViewer(player); + if (this instanceof MobPlayerSkin skin) { + List properties = new ArrayList<>(); + if (skin.getSkinTexture() != null && skin.getSkinSignature() != null) { + properties.add(new PlayerInfoUpdatePacket.Property("textures", skin.getSkinTexture(), skin.getSkinSignature())); + } + player.sendPackets( + new PlayerInfoUpdatePacket(PlayerInfoUpdatePacket.Action.ADD_PLAYER, + new PlayerInfoUpdatePacket.Entry( + getUuid(), + "SB_MOB_" + getEntityId(), + properties, + false, + 0, + GameMode.SURVIVAL, + customName, + null, + 1, true)), + new SpawnEntityPacket(this.getEntityId(), this.getUuid(), EntityType.PLAYER, + getPosition(), + (float) 0, + 0, + Vec.ZERO), + new EntityHeadLookPacket(getEntityId(), 0), + new EntityMetaDataPacket(getEntityId(), Map.of( + MetadataDef.Avatar.DISPLAYED_MODEL_PARTS_FLAGS.index(), + Metadata.Byte((byte) 127) // 127 is all parts + )) + ); + } + } + @Override public void spawn() { super.spawn(); @@ -138,7 +180,7 @@ public boolean damage(@NotNull Damage damage) { -Math.cos(sourcePoint.getPosition().yaw() * Math.PI / 180)); } - this.setCustomName(Component.text( + this.set(DataComponents.CUSTOM_NAME, Component.text( "§8[§7Lv" + getLevel() + "§8] §c" + getDisplayName() + " §a" + Math.round(getHealth()) + "§f/§a" diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/impl/MobPlayerSkin.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/impl/MobPlayerSkin.java new file mode 100644 index 000000000..26eb37171 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/impl/MobPlayerSkin.java @@ -0,0 +1,6 @@ +package net.swofty.type.skyblockgeneric.entity.mob.impl; + +public interface MobPlayerSkin { + String getSkinTexture(); + String getSkinSignature(); +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/DiamondGoblin.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/DiamondGoblin.java new file mode 100644 index 000000000..10f4c961a --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/DiamondGoblin.java @@ -0,0 +1,134 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines; + +import lombok.NonNull; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.entity.ai.goal.RandomStrollGoal; +import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.item.Material; +import net.minestom.server.utils.time.TimeUnit; +import net.swofty.commons.skyblock.item.ItemType; +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.generic.gui.inventory.item.GUIMaterial; +import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; +import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.ai.ClosestEntityRegionTarget; +import net.swofty.type.skyblockgeneric.entity.mob.ai.MeleeAttackWithinRegionGoal; +import net.swofty.type.skyblockgeneric.entity.mob.ai.RandomRegionStrollGoal; +import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; +import net.swofty.type.skyblockgeneric.item.SkyBlockItem; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; +import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class DiamondGoblin extends BestiaryMob { + + public DiamondGoblin() { + super(EntityType.PLAYER); + } + + @Override + public Integer getLevel() { + return 500; + } + + @Override + public int getMaxBestiaryTier() { + return 15; + } + + @Override + public int getBestiaryBracket() { + return 7; + } + + @Override + public String getMobID() { + return "GOBLIN_2"; + } + + @Override + public void onInit() { + setBoots(new SkyBlockItem(ItemType.DIAMOND_BOOTS).getItemStack()); + setLeggings(new SkyBlockItem(ItemType.DIAMOND_LEGGINGS).getItemStack()); + setChestplate(new SkyBlockItem(ItemType.DIAMOND_CHESTPLATE).getItemStack()); + setHelmet(new SkyBlockItem(ItemType.DIAMOND_HELMET).getItemStack()); + } + + @Override + public GUIMaterial getGuiMaterial() { + return new GUIMaterial("81d2116827a41a713660bb52c9ba3bc6dd038175afb74a473b85f0cf60ff70e2"); + } + + @Override + public String getDisplayName() { + return "Diamond Goblin"; + } + + @Override + public List getGoalSelectors() { + return List.of( + new RandomStrollGoal(this, 50) + ); + } + + @Override + public List getTargetSelectors() { + return List.of(); + } + + @Override + public ItemStatistics getBaseStatistics() { + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 5D) + .withBase(ItemStatistic.DAMAGE, 250D) + .withBase(ItemStatistic.SPEED, 150D) + .build(); + } + + @Override + public @Nullable SkyBlockLootTable getLootTable() { + return new SkyBlockLootTable() { + @Override + public @NonNull List getLootTable() { + return List.of( + new LootRecord(ItemType.MITHRIL, 20, 100) + ); + } + + @Override + public @NotNull CalculationMode getCalculationMode() { + return CalculationMode.CALCULATE_INDIVIDUAL; + } + }; + } + + @Override + public SkillCategories getSkillCategory() { + return SkillCategories.COMBAT; + } + + @Override + public long damageCooldown() { + return 500; + } + + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(20, 250, 100); + } + + @Override + public List getMobTypes() { + return List.of(MobType.GLACIAL, MobType.HUMANOID); + } + +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/GoldenGoblin.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/GoldenGoblin.java new file mode 100644 index 000000000..e984c5295 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/GoldenGoblin.java @@ -0,0 +1,133 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines; + +import lombok.NonNull; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.entity.ai.goal.RandomStrollGoal; +import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.item.Material; +import net.minestom.server.utils.time.TimeUnit; +import net.swofty.commons.skyblock.item.ItemType; +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.generic.gui.inventory.item.GUIMaterial; +import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; +import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.ai.ClosestEntityRegionTarget; +import net.swofty.type.skyblockgeneric.entity.mob.ai.MeleeAttackWithinRegionGoal; +import net.swofty.type.skyblockgeneric.entity.mob.ai.RandomRegionStrollGoal; +import net.swofty.type.skyblockgeneric.item.SkyBlockItem; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; +import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class GoldenGoblin extends BestiaryMob { + + public GoldenGoblin() { + super(EntityType.PLAYER); + } + + @Override + public Integer getLevel() { + return 500; + } + + @Override + public int getMaxBestiaryTier() { + return 15; + } + + @Override + public int getBestiaryBracket() { + return 5; + } + + @Override + public String getMobID() { + return "GOBLIN"; + } + + @Override + public void onInit() { + setBoots(new SkyBlockItem(ItemType.GOLDEN_BOOTS).getItemStack()); + setLeggings(new SkyBlockItem(ItemType.GOLDEN_LEGGINGS).getItemStack()); + setChestplate(new SkyBlockItem(ItemType.GOLDEN_CHESTPLATE).getItemStack()); + setHelmet(new SkyBlockItem(ItemType.GOLDEN_HELMET).getItemStack()); + } + + @Override + public GUIMaterial getGuiMaterial() { + return new GUIMaterial("29d9fbe74cbd9ebeda4d571a4176c66e298ec409dc10510f6ddf1496f48840b1"); + } + + @Override + public String getDisplayName() { + return "Golden Goblin"; + } + + @Override + public List getGoalSelectors() { + return List.of( + new RandomStrollGoal(this, 50) + ); + } + + @Override + public List getTargetSelectors() { + return List.of(); + } + + @Override + public ItemStatistics getBaseStatistics() { + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 3D) + .withBase(ItemStatistic.DAMAGE, 250D) + .withBase(ItemStatistic.SPEED, 100D) + .build(); + } + + @Override + public @Nullable SkyBlockLootTable getLootTable() { + return new SkyBlockLootTable() { + @Override + public @NonNull List getLootTable() { + return List.of( + new LootRecord(ItemType.MITHRIL, 5, 100) + ); + } + + @Override + public @NotNull CalculationMode getCalculationMode() { + return CalculationMode.CALCULATE_INDIVIDUAL; + } + }; + } + + @Override + public SkillCategories getSkillCategory() { + return SkillCategories.COMBAT; + } + + @Override + public long damageCooldown() { + return 500; + } + + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(0, 100, 50); + } + + @Override + public List getMobTypes() { + return List.of(MobType.HUMANOID, MobType.SHIELDED); + } + +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java index e9efdb678..e5b5ac529 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobGlaciteWalker.java @@ -5,6 +5,7 @@ import net.minestom.server.entity.ai.GoalSelector; import net.minestom.server.entity.ai.TargetSelector; import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.item.Material; import net.minestom.server.utils.time.TimeUnit; import net.swofty.commons.skyblock.item.ItemType; import net.swofty.commons.skyblock.statistics.ItemStatistic; @@ -30,7 +31,7 @@ public class MobGlaciteWalker extends BestiaryMob implements RegionPopulator { public MobGlaciteWalker() { - super(EntityType.ZOMBIE); // it's a player + super(EntityType.PLAYER); } @Override @@ -63,7 +64,7 @@ public void onInit() { @Override public GUIMaterial getGuiMaterial() { - return null; + return new GUIMaterial(Material.PACKED_ICE); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java new file mode 100644 index 000000000..b27c860ab --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java @@ -0,0 +1,98 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines; + +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.entity.ai.TargetSelector; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.generic.gui.inventory.item.GUIMaterial; +import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; +import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; +import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class MobTreasureHoarder extends BestiaryMob implements RegionPopulator { + + public MobTreasureHoarder() { + super(EntityType.PLAYER); + } + + @Override + public int getMaxBestiaryTier() { + return 0; + } + + @Override + public int getBestiaryBracket() { + return 0; + } + + @Override + public String getMobID() { + return "TREASURE_HOARDER"; + } + + @Override + public GUIMaterial getGuiMaterial() { + return null; + } + + @Override + public String getDisplayName() { + return "Treasure Hoarder"; + } + + @Override + public Integer getLevel() { + return 0; + } + + @Override + public List getGoalSelectors() { + return List.of(); + } + + @Override + public List getTargetSelectors() { + return List.of(); + } + + @Override + public ItemStatistics getBaseStatistics() { + return null; + } + + @Override + public @Nullable SkyBlockLootTable getLootTable() { + return null; + } + + @Override + public SkillCategories getSkillCategory() { + return null; + } + + @Override + public long damageCooldown() { + return 0; + } + + @Override + public OtherLoot getOtherLoot() { + return null; + } + + @Override + public List getMobTypes() { + return List.of(); + } + + @Override + public List getPopulators() { + return List.of(); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobFireslinger.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobFireslinger.java new file mode 100644 index 000000000..94d916e41 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobFireslinger.java @@ -0,0 +1,40 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines.goblin; + +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; + +public class MobFireslinger extends MobGoblin { + + @Override + public Integer getLevel() { + return 25; + } + + @Override + public String getMobID() { + return "GOBLIN_FIRESLINGER"; + } + + @Override + public String getDisplayName() { + return "Goblin Flamethrower"; + } + + @Override + public ItemStatistics getBaseStatistics() { + double health = 200 + (Math.random() * ((800 - 200) + 1)); + double damage = 20 + (Math.random() * ((30 - 20) + 1)); + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, health) + .withBase(ItemStatistic.DAMAGE, damage) + .withBase(ItemStatistic.SPEED, 100D) + .build(); + } + + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(0, 10, 5); + } + +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java new file mode 100644 index 000000000..119933475 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java @@ -0,0 +1,159 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines.goblin; + +import lombok.NonNull; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.item.Material; +import net.minestom.server.utils.time.TimeUnit; +import net.swofty.commons.skyblock.item.ItemType; +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.generic.gui.inventory.item.GUIMaterial; +import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; +import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.ai.ClosestEntityRegionTarget; +import net.swofty.type.skyblockgeneric.entity.mob.ai.MeleeAttackWithinRegionGoal; +import net.swofty.type.skyblockgeneric.entity.mob.ai.RandomRegionStrollGoal; +import net.swofty.type.skyblockgeneric.entity.mob.impl.MobPlayerSkin; +import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; +import net.swofty.type.skyblockgeneric.item.SkyBlockItem; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; +import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.tinylog.Logger; + +import java.util.List; + +public class MobGoblin extends BestiaryMob implements RegionPopulator, MobPlayerSkin { + + public MobGoblin() { + super(EntityType.PLAYER); + } + + @Override + public Integer getLevel() { + return 25; + } + + @Override + public int getMaxBestiaryTier() { + return 20; + } + + @Override + public int getBestiaryBracket() { + return 2; + } + + @Override + public String getMobID() { + return "GOBLIN_WEAKLING_MELEE_2"; + } + + @Override + public GUIMaterial getGuiMaterial() { + return new GUIMaterial("172850906b7f0d952c0e508073cc439fd3374ccf5b889c06f7e8d90cc0cc255c"); + } + + @Override + public String getDisplayName() { + return "Goblin"; + } + + @Override + public void tick(long time) { + setView(0, 0); + super.tick(time); + } + + @Override + public List getGoalSelectors() { + return List.of( + new MeleeAttackWithinRegionGoal(this, + 1.6, + 20, + TimeUnit.SERVER_TICK, + RegionType.GOBLIN_BURROWS), + new RandomRegionStrollGoal(this, 5, RegionType.GOBLIN_BURROWS) + ); + } + + @Override + public List getTargetSelectors() { + return List.of( + new LastEntityDamagerTarget(this, 16), + new ClosestEntityRegionTarget(this, + 6, + entity -> entity instanceof SkyBlockPlayer, + RegionType.GOBLIN_BURROWS) + ); + } + + @Override + public ItemStatistics getBaseStatistics() { + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 800D) + .withBase(ItemStatistic.DAMAGE, 300D) + .withBase(ItemStatistic.SPEED, 100D) + .build(); + } + + @Override + public @Nullable SkyBlockLootTable getLootTable() { + return new SkyBlockLootTable() { + @Override + public @NonNull List getLootTable() { + return List.of( + new LootRecord(ItemType.GOBLIN_EGG, 1, 100) + ); + } + + @Override + public @NotNull CalculationMode getCalculationMode() { + return CalculationMode.CALCULATE_INDIVIDUAL; + } + }; + } + + @Override + public SkillCategories getSkillCategory() { + return SkillCategories.COMBAT; + } + + @Override + public long damageCooldown() { + return 500; + } + + // Goblins also have a 1% or 1/100 chance of dropping between 1,000 Coins and 10,000 Coins, which is unaffected by Magic Find. + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(0, 10, 5); + } + + @Override + public List getMobTypes() { + return List.of(MobType.SUBTERRANEAN, MobType.HUMANOID); + } + + @Override + public List getPopulators() { + return List.of(new Populator(RegionType.GOBLIN_BURROWS, 20)); + } + + @Override + public String getSkinTexture() { + return "ewogICJ0aW1lc3RhbXAiIDogMTYwODMxNDEyODAyMCwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmFjMDNiMTRiN2EyYTBjMmY4MDkwMzAzNWJiZmRmODk4ZmViNDA1ZDdiZTM5ODBiNjdiYzQ5NmYxNTNhOTBkZCIKICAgIH0KICB9Cn0="; + } + + @Override + public String getSkinSignature() { + return "YDiw8Yj4pk0TFQwGfiO8XEGp+Afq4O6IETqnQOrIweXiqo3kKTCXxkPMkM7ALWuWpIL+e/3neOWFLNujAbahF4SCpeYBeXN2KHg4BJW3KwBiDMBWlOaiyody8yx9/B20N/aHB1jRgZIWagi+flvlUhEd0ipb8Mmaz2VP03SD17q2DkX8DpjmQ2LFpUC4f4rwum+tY81d8zmr/htMUPWOoeWr7pmwGukvuE/0/1TnUBdXWzlviuTlII2CSNIs6MFoFZpiocQLtkdzHy+NEL8afqHFvKBD8OE5hIz84v01bFfgdGXvA5LIGr4b8WzvdbCQx6HlcnkliWZtTraWGTDPCca99rQRY2/Sy++uPd6Qf1gE22J3bIfjniTVufz2/VaDpkuVqW/MtKR+7ZQOit9vjVosINxFQN0ZNjFTrSF4NR9Tlcy3qEDdUtziuA7RK1Gj//KG9McRODXJXek8GCkHZep1RQd5VIG5/u/4c97vDez5O25fxdGDiyu7J0n/Rb+xBbhWCua4yJam2FjWAbW6oEFqqHGAH5+PnWDzjMBaGPAnxGcksFDxZ+0gj+1wm+fqfiasIdD2dCimOrMyBIkUE/egP7hbpt+Tr3CjIkdfdIzcIAOeip1UszmxVEUiCKBA5xrP7xK6Y9TXQObvk4TGbhMRdb5vYmSpDsAVMUNgk60="; + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblinFlamethrower.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblinFlamethrower.java new file mode 100644 index 000000000..f6bd9e405 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblinFlamethrower.java @@ -0,0 +1,82 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines.goblin; + +import lombok.NonNull; +import net.minestom.server.entity.EntityType; +import net.minestom.server.entity.ai.GoalSelector; +import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.item.Material; +import net.minestom.server.utils.time.TimeUnit; +import net.swofty.commons.skyblock.item.ItemType; +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.generic.gui.inventory.item.GUIMaterial; +import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; +import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.ai.ClosestEntityRegionTarget; +import net.swofty.type.skyblockgeneric.entity.mob.ai.MeleeAttackWithinRegionGoal; +import net.swofty.type.skyblockgeneric.entity.mob.ai.RandomRegionStrollGoal; +import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; +import net.swofty.type.skyblockgeneric.item.SkyBlockItem; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; +import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.region.RegionType; +import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class MobGoblinFlamethrower extends MobGoblin { + + @Override + public Integer getLevel() { + return 100; + } + + @Override + public String getMobID() { + return "GOBLIN_FLAMETHROWER"; + } + + @Override + public String getDisplayName() { + return "Goblin Flamethrower"; + } + + @Override + public ItemStatistics getBaseStatistics() { + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 20000D) + .withBase(ItemStatistic.DAMAGE, 500D) + .withBase(ItemStatistic.SPEED, 100D) + .build(); + } + + @Override + public @Nullable SkyBlockLootTable getLootTable() { + return new SkyBlockLootTable() { + @Override + public @NonNull List getLootTable() { + return List.of( + new LootRecord(ItemType.GOBLIN_EGG, 1, 0.6), + new LootRecord(ItemType.GREEN_GOBLIN_EGG, 1, 0.25), + new LootRecord(ItemType.YELLOW_GOBLIN_EGG, 1, 0.1), + new LootRecord(ItemType.RED_GOBLIN_EGG, 1, 0.04), + new LootRecord(ItemType.BLUE_GOBLIN_EGG, 1, 0.02) + ); + } + + @Override + public @NotNull CalculationMode getCalculationMode() { + return CalculationMode.CALCULATE_INDIVIDUAL; + } + }; + } + + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(40, 10, 10); + } +} diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobKnifethrower.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobKnifethrower.java new file mode 100644 index 000000000..97b0295e0 --- /dev/null +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobKnifethrower.java @@ -0,0 +1,33 @@ +package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines.goblin; + +import net.swofty.commons.skyblock.statistics.ItemStatistic; +import net.swofty.commons.skyblock.statistics.ItemStatistics; +import net.swofty.type.skyblockgeneric.loottable.OtherLoot; + +public class MobKnifethrower extends MobGoblin { + + @Override + public String getMobID() { + return "GOBLIN_KNIFE_THROWER"; + } + + @Override + public String getDisplayName() { + return "Knifethrower"; + } + + @Override + public ItemStatistics getBaseStatistics() { + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 800D) + .withBase(ItemStatistic.DAMAGE, 300D) + .withBase(ItemStatistic.SPEED, 100D) + .build(); + } + + @Override + public OtherLoot getOtherLoot() { + return new OtherLoot(28, 10, 5); + } + +} From ca673afeb3e4f99454ec3890b1d0fab2ec993383 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:15:18 +0200 Subject: [PATCH 07/13] feat: more proper treasure hoarder --- .../mobs/dwarvenmines/MobTreasureHoarder.java | 67 +++++++++++++++---- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java index b27c860ab..50c47ae76 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/MobTreasureHoarder.java @@ -1,16 +1,27 @@ package net.swofty.type.skyblockgeneric.entity.mob.mobs.dwarvenmines; +import lombok.NonNull; import net.minestom.server.entity.EntityType; import net.minestom.server.entity.ai.GoalSelector; import net.minestom.server.entity.ai.TargetSelector; +import net.minestom.server.entity.ai.target.LastEntityDamagerTarget; +import net.minestom.server.utils.time.TimeUnit; +import net.swofty.commons.skyblock.item.ItemType; +import net.swofty.commons.skyblock.statistics.ItemStatistic; import net.swofty.commons.skyblock.statistics.ItemStatistics; import net.swofty.type.generic.gui.inventory.item.GUIMaterial; import net.swofty.type.skyblockgeneric.entity.mob.BestiaryMob; import net.swofty.type.skyblockgeneric.entity.mob.MobType; +import net.swofty.type.skyblockgeneric.entity.mob.ai.ClosestEntityRegionTarget; +import net.swofty.type.skyblockgeneric.entity.mob.ai.MeleeAttackWithinRegionGoal; +import net.swofty.type.skyblockgeneric.entity.mob.ai.RandomRegionStrollGoal; import net.swofty.type.skyblockgeneric.entity.mob.impl.RegionPopulator; import net.swofty.type.skyblockgeneric.loottable.OtherLoot; import net.swofty.type.skyblockgeneric.loottable.SkyBlockLootTable; +import net.swofty.type.skyblockgeneric.region.RegionType; import net.swofty.type.skyblockgeneric.skill.SkillCategories; +import net.swofty.type.skyblockgeneric.user.SkyBlockPlayer; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -23,12 +34,12 @@ public MobTreasureHoarder() { @Override public int getMaxBestiaryTier() { - return 0; + return 15; } @Override public int getBestiaryBracket() { - return 0; + return 4; } @Override @@ -48,51 +59,83 @@ public String getDisplayName() { @Override public Integer getLevel() { - return 0; + return 70; } @Override public List getGoalSelectors() { - return List.of(); + return List.of( + new MeleeAttackWithinRegionGoal(this, + 1.6, + 20, + TimeUnit.SERVER_TICK, + RegionType.UPPER_MINES), + new RandomRegionStrollGoal(this, 15, RegionType.UPPER_MINES) + ); } @Override public List getTargetSelectors() { - return List.of(); + return List.of( + new LastEntityDamagerTarget(this, 16), + new ClosestEntityRegionTarget(this, + 6, + entity -> entity instanceof SkyBlockPlayer, + RegionType.UPPER_MINES) + ); } @Override public ItemStatistics getBaseStatistics() { - return null; + return ItemStatistics.builder() + .withBase(ItemStatistic.HEALTH, 15000D) + .withBase(ItemStatistic.DAMAGE, 500D) + .withBase(ItemStatistic.SPEED, 100D) + .build(); } + @Override public @Nullable SkyBlockLootTable getLootTable() { - return null; + return new SkyBlockLootTable() { + @Override + public @NonNull List getLootTable() { + return List.of( + new LootRecord(ItemType.STARFALL, 1, 100), + new LootRecord(ItemType.STARFALL, 1, 50), + new LootRecord(ItemType.TREASURITE, 1, 0.5) + ); + } + + @Override + public @NotNull CalculationMode getCalculationMode() { + return CalculationMode.CALCULATE_INDIVIDUAL; + } + }; } @Override public SkillCategories getSkillCategory() { - return null; + return SkillCategories.COMBAT; } @Override public long damageCooldown() { - return 0; + return 500; } @Override public OtherLoot getOtherLoot() { - return null; + return new OtherLoot(70, 0, 0); } @Override public List getMobTypes() { - return List.of(); + return List.of(MobType.HUMANOID); } @Override public List getPopulators() { - return List.of(); + return List.of(new Populator(RegionType.UPPER_MINES, 20)); } } From 4aa6cec43eac997510727a06f2db4901e1bba6b5 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:17:06 +0200 Subject: [PATCH 08/13] fix: lilith yaw and pitch --- .../java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java index 714e53db8..188a4af8f 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java @@ -27,7 +27,7 @@ public String signature(HypixelPlayer player) { @Override public Pos position(HypixelPlayer player) { - return new Pos(58, 198, -8); + return new Pos(58, 198, -8, -180, 0); } @Override From f6291b845f8f25754336e94127dee094a7676d1c Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Sun, 28 Dec 2025 19:22:00 +0200 Subject: [PATCH 09/13] fix: import after merge --- .../java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java | 1 + .../java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java | 1 + .../java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java | 1 + .../java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java | 1 + .../java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java | 1 + .../java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java | 1 + .../java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java | 1 + .../main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java | 1 + .../net/swofty/type/generic/entity/npc/DialogueController.java | 1 - 9 files changed, 8 insertions(+), 1 deletion(-) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java index c374ab24f..fdd8fcaff 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java @@ -5,6 +5,7 @@ import net.swofty.type.generic.data.datapoints.DatapointToggles; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; import net.swofty.type.generic.user.HypixelPlayer; diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java index e62465a76..c09405eed 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class EmissaryCarlton extends HypixelNPC { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java index 7b8b8dfc2..6fc8139f5 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class EmissaryCeanna extends HypixelNPC { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java index 2a9b22af5..1e1199131 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class EmissaryEliza extends HypixelNPC { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java index 693f0b0be..8949d5cd5 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class EmissaryFraiser extends HypixelNPC { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java index 188a4af8f..e7bb81b13 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class EmissaryLilith extends HypixelNPC { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java index cc0331d8b..01a93fafa 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class EmissaryWilson extends HypixelNPC { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java index 2e2f9b989..c0822c726 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java @@ -4,6 +4,7 @@ import net.swofty.type.dwarvenmines.gui.GUICommisions; import net.swofty.type.generic.entity.npc.HypixelNPC; import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; import net.swofty.type.generic.user.HypixelPlayer; public class NPCKingName extends HypixelNPC { diff --git a/type.generic/src/main/java/net/swofty/type/generic/entity/npc/DialogueController.java b/type.generic/src/main/java/net/swofty/type/generic/entity/npc/DialogueController.java index 92f26d690..27d4720a8 100644 --- a/type.generic/src/main/java/net/swofty/type/generic/entity/npc/DialogueController.java +++ b/type.generic/src/main/java/net/swofty/type/generic/entity/npc/DialogueController.java @@ -66,7 +66,6 @@ public void cancelDialogue(HypixelPlayer player) { private void handleLineSendingLoop(HypixelPlayer player, HypixelNPC.DialogueSet dialogueSet) { npc.sendNPCMessage(player, dialogueSet.lines()[0]); - String[] newLines = new String[dialogueSet.lines().length - 1]; System.arraycopy(dialogueSet.lines(), 1, newLines, 0, dialogueSet.lines().length - 1); From 86ee06fa73ddeae1fb254a064cc9dcf12c564b7c Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Mon, 29 Dec 2025 23:43:37 +0200 Subject: [PATCH 10/13] feat: AbstractEmissary for consistent logic --- .../dwarvenmines/npcs/AbstractEmissary.java | 52 +++++++++++++++++++ ...oyalGuard.java => AbstractRoyalGuard.java} | 4 +- .../type/dwarvenmines/npcs/EmissaryBraum.java | 2 +- .../dwarvenmines/npcs/EmissaryCarlton.java | 42 +++------------ .../dwarvenmines/npcs/EmissaryCeanna.java | 43 +++------------ .../type/dwarvenmines/npcs/EmissaryEliza.java | 43 +++------------ .../dwarvenmines/npcs/EmissaryFraiser.java | 43 +++------------ .../dwarvenmines/npcs/EmissaryLilith.java | 43 +++------------ .../dwarvenmines/npcs/EmissaryWilson.java | 43 +++------------ .../type/dwarvenmines/npcs/NPCKingName.java | 2 +- .../dwarvenmines/npcs/NPCRoyalGuardOne.java | 2 +- .../dwarvenmines/npcs/NPCRoyalGuardTwo.java | 2 +- .../mobs/dwarvenmines/goblin/MobGoblin.java | 6 --- 13 files changed, 94 insertions(+), 233 deletions(-) create mode 100644 type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractEmissary.java rename type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/{INPCRoyalGuard.java => AbstractRoyalGuard.java} (91%) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractEmissary.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractEmissary.java new file mode 100644 index 000000000..2c7dfde10 --- /dev/null +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractEmissary.java @@ -0,0 +1,52 @@ +package net.swofty.type.dwarvenmines.npcs; + +import net.minestom.server.coordinate.Pos; +import net.swofty.type.dwarvenmines.gui.GUICommisions; +import net.swofty.type.generic.entity.npc.HypixelNPC; +import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; +import net.swofty.type.generic.event.custom.NPCInteractEvent; +import net.swofty.type.generic.user.HypixelPlayer; +import org.jspecify.annotations.NonNull; + +public abstract class AbstractEmissary extends HypixelNPC { + + public AbstractEmissary(String name, String texture, String signature, Pos pos) { + super(new HumanConfiguration() { + @Override + public String[] holograms(HypixelPlayer player) { + return new String[]{"§6Emissary " + name, "§e§lCLICK"}; + } + + @Override + public String texture(HypixelPlayer player) { + return texture; + } + + @Override + public String signature(HypixelPlayer player) { + return signature; + } + + @Override + public Pos position(HypixelPlayer player) { + return pos; + } + + @Override + public boolean looking(HypixelPlayer player) { + return true; + } + + @Override + public @NonNull String chatName() { + return "§6" + name; + } + }); + } + + @Override + public void onClick(NPCInteractEvent event) { + HypixelPlayer player = event.player(); + new GUICommisions().open(player); + } +} diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/INPCRoyalGuard.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java similarity index 91% rename from type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/INPCRoyalGuard.java rename to type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java index b1055f1d1..9042fc0fb 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/INPCRoyalGuard.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java @@ -11,9 +11,9 @@ import net.swofty.type.generic.event.custom.NPCInteractEvent; -public class INPCRoyalGuard extends HypixelNPC { +public class AbstractRoyalGuard extends HypixelNPC { - public INPCRoyalGuard(Function signature, Function texture, Function position) { + public AbstractRoyalGuard(Function signature, Function texture, Function position) { super(new HumanConfiguration() { @Override public String[] holograms(HypixelPlayer player) { diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java index fdd8fcaff..965f402da 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryBraum.java @@ -34,7 +34,7 @@ public Pos position(HypixelPlayer player) { } @Override - public boolean looking() { + public boolean looking(HypixelPlayer player) { return true; } }); diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java index c09405eed..c23a152e7 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCarlton.java @@ -1,45 +1,15 @@ package net.swofty.type.dwarvenmines.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.dwarvenmines.gui.GUICommisions; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -public class EmissaryCarlton extends HypixelNPC { +public class EmissaryCarlton extends AbstractEmissary { public EmissaryCarlton() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§6Emissary Carlton", "§e§lCLICK"}; - } - - @Override - public String texture(HypixelPlayer player) { - return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTA4NzI1OCwKICAicHJvZmlsZUlkIiA6ICJlYjIwYWVkYTRiYTM0NzVmOTczZGNmZjkzNTE2OGZhYSIsCiAgInByb2ZpbGVOYW1lIiA6ICJTa3lGYWxsZWVlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M3NjVmZWU5N2JjZmFlN2MxMzZiNmE2YjhjYTk1MzgxYWY5NjRkNmFlYmMwOGJmZGQyMzUwYWY3OGUyY2Y1MWEiCiAgICB9CiAgfQp9"; - } - - @Override - public String signature(HypixelPlayer player) { - return "PgoHqTQyGXmASeqSaXsNZ3goo42oPiEt12zOF6+OLXWv7e2muUtXiumreY4SwTZ3DOyaPKbdGrkGMa1gaiGgOaC5mifkcXifydRA+37N5djc4vyT5tnz9trC1SRuBip9yO8GhgX2nxrRoaa+mCltQAKw/1ZrceTTDfdyv0syCcede7CXUTaS3gxwxGoNBHEbXh+6E5SCjwopDzqwdvgm4/ea3tretAflUNq7z2IKR+yg9DuzRt59TjncYcyw8nxkoaB/wzLmM5QDabY8we3495Gf/1JhvydXggnnbzBf8qzEcwvV9XTk+VI233Dr0GfTvt1CKyr62H53dGsE15dKbAdRj9/9dSa82TckdoTrgBKe+9rugf00shLoZwVHu8K5DdorPhJ+FcD2eAzCIZgeVOQyH4W4m4Yjzz4SV9jiAtRe4kXnRw8260wh86EuOL0ywUizD9Rjo8FR1G8MxqRVQYUP+zgwMo1iO1GFiymanoB++Msn/Ty8No0rZungrrwYAwkAc5GVa7G+FcR6duUmwLNxRr8mdOwj295yQibzXcyqTPk7TlJYIcTd10jdQGtEycn7Ped3fSv8Qe9Tx75qQsYdgjvgo3utRD5ROY9RDyrRDtHPOsoAlNSipZx7iUk/ggMN0vtcM0DS+prxL9guYvIbKbZFTMApzR5wxYLGNAw="; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(-72, 153, -10); - } - - @Override - public boolean looking() { - return true; - } - }); + super( + "Carlton", + "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTA4NzI1OCwKICAicHJvZmlsZUlkIiA6ICJlYjIwYWVkYTRiYTM0NzVmOTczZGNmZjkzNTE2OGZhYSIsCiAgInByb2ZpbGVOYW1lIiA6ICJTa3lGYWxsZWVlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M3NjVmZWU5N2JjZmFlN2MxMzZiNmE2YjhjYTk1MzgxYWY5NjRkNmFlYmMwOGJmZGQyMzUwYWY3OGUyY2Y1MWEiCiAgICB9CiAgfQp9", + "PgoHqTQyGXmASeqSaXsNZ3goo42oPiEt12zOF6+OLXWv7e2muUtXiumreY4SwTZ3DOyaPKbdGrkGMa1gaiGgOaC5mifkcXifydRA+37N5djc4vyT5tnz9trC1SRuBip9yO8GhgX2nxrRoaa+mCltQAKw/1ZrceTTDfdyv0syCcede7CXUTaS3gxwxGoNBHEbXh+6E5SCjwopDzqwdvgm4/ea3tretAflUNq7z2IKR+yg9DuzRt59TjncYcyw8nxkoaB/wzLmM5QDabY8we3495Gf/1JhvydXggnnbzBf8qzEcwvV9XTk+VI233Dr0GfTvt1CKyr62H53dGsE15dKbAdRj9/9dSa82TckdoTrgBKe+9rugf00shLoZwVHu8K5DdorPhJ+FcD2eAzCIZgeVOQyH4W4m4Yjzz4SV9jiAtRe4kXnRw8260wh86EuOL0ywUizD9Rjo8FR1G8MxqRVQYUP+zgwMo1iO1GFiymanoB++Msn/Ty8No0rZungrrwYAwkAc5GVa7G+FcR6duUmwLNxRr8mdOwj295yQibzXcyqTPk7TlJYIcTd10jdQGtEycn7Ped3fSv8Qe9Tx75qQsYdgjvgo3utRD5ROY9RDyrRDtHPOsoAlNSipZx7iUk/ggMN0vtcM0DS+prxL9guYvIbKbZFTMApzR5wxYLGNAw=", + new Pos(-72, 153, -10)); } - @Override - public void onClick(NPCInteractEvent event) { - new GUICommisions().open(event.player()); - } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java index 6fc8139f5..775867837 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryCeanna.java @@ -1,45 +1,14 @@ package net.swofty.type.dwarvenmines.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.dwarvenmines.gui.GUICommisions; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -public class EmissaryCeanna extends HypixelNPC { +public class EmissaryCeanna extends AbstractEmissary { public EmissaryCeanna() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§6Emissary Ceanna", "§e§lCLICK"}; - } - - @Override - public String texture(HypixelPlayer player) { - return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTIwNDMxMSwKICAicHJvZmlsZUlkIiA6ICJiMGQ0YjI4YmMxZDc0ODg5YWYwZTg2NjFjZWU5NmFhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaW5lU2tpbl9vcmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTc4YzI1YWM4ZDc5M2E3M2FmMzFlNWRhM2U4YmYyZDYzYTZjMDAyNmZkZTlhOTY4MmZjOWNhZjYxNTU0MGM3OSIKICAgIH0KICB9Cn0="; - } - - @Override - public String signature(HypixelPlayer player) { - return "DrMH4v9Oi0l9tG/YDSe+otDmchtVR6b8nW8duUBKTveRl72fVlQQS1LVC6sdlQTWzx/ckaTdzmYKCio8TVtaIuTDIj4hj5s1CAwPG34Ix0Od8jQJxINoFcJD4fB1AeFYc9lmdOXp77J99xRM8s5wHGrzPgRPtkAjam9T46AC2d72rCVQmQ8HsEJoGt1XKgfSoUCEYKWileu1U0s5iML8jiAimW4lcYVOqjVCZG1dMaip8LUL08y/UqfZFynl8M3OLH1SD+p7HFL8uic57MGFi3UGLspUji3X+C8Cx/60ke54QUeHGIIph8Nff4lCoOU6RHDxpmdgtg4xV/ekw+Gl8jnZ5srgY5zCkpqLWqDm/nzpijgzpZzHkKEEMpPIeza12iGKYyJ7igqpE73Rpxjgm2RkYB73BTzkBlJoV7XePX7+fFsvU+4pZcw3ES1EKIqJe0RYHvgaxRLGVoZ9uRZi/rx7baV28K/gad+CHvfyXz5QNIVb+Kmqj2UR8uczVcV1OdnaCKnJQjabFlsdb371ev/4InAyiFxLLmucozxPpDRKSGeHcKv2hjri7WktwJ+mie0CmTW8PFktYnKS/h/7st3kAAh8gTmKAyMfVhlHTUizJvwfoM+rV6NpIRKrXgIumq3qRitJwYaf1VlC2Cc6t0aUwu7QeXB/Xk1Hy6jKQDw="; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(42.5, 134.5, 22.5); - } - - @Override - public boolean looking() { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - new GUICommisions().open(event.player()); + super( + "Ceanna", + "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTIwNDMxMSwKICAicHJvZmlsZUlkIiA6ICJiMGQ0YjI4YmMxZDc0ODg5YWYwZTg2NjFjZWU5NmFhYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNaW5lU2tpbl9vcmciLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTc4YzI1YWM4ZDc5M2E3M2FmMzFlNWRhM2U4YmYyZDYzYTZjMDAyNmZkZTlhOTY4MmZjOWNhZjYxNTU0MGM3OSIKICAgIH0KICB9Cn0=", + "DrMH4v9Oi0l9tG/YDSe+otDmchtVR6b8nW8duUBKTveRl72fVlQQS1LVC6sdlQTWzx/ckaTdzmYKCio8TVtaIuTDIj4hj5s1CAwPG34Ix0Od8jQJxINoFcJD4fB1AeFYc9lmdOXp77J99xRM8s5wHGrzPgRPtkAjam9T46AC2d72rCVQmQ8HsEJoGt1XKgfSoUCEYKWileu1U0s5iML8jiAimW4lcYVOqjVCZG1dMaip8LUL08y/UqfZFynl8M3OLH1SD+p7HFL8uic57MGFi3UGLspUji3X+C8Cx/60ke54QUeHGIIph8Nff4lCoOU6RHDxpmdgtg4xV/ekw+Gl8jnZ5srgY5zCkpqLWqDm/nzpijgzpZzHkKEEMpPIeza12iGKYyJ7igqpE73Rpxjgm2RkYB73BTzkBlJoV7XePX7+fFsvU+4pZcw3ES1EKIqJe0RYHvgaxRLGVoZ9uRZi/rx7baV28K/gad+CHvfyXz5QNIVb+Kmqj2UR8uczVcV1OdnaCKnJQjabFlsdb371ev/4InAyiFxLLmucozxPpDRKSGeHcKv2hjri7WktwJ+mie0CmTW8PFktYnKS/h/7st3kAAh8gTmKAyMfVhlHTUizJvwfoM+rV6NpIRKrXgIumq3qRitJwYaf1VlC2Cc6t0aUwu7QeXB/Xk1Hy6jKQDw=", + new Pos(42.5, 134.5, 22.5)); } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java index 1e1199131..a5c5f1aaa 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryEliza.java @@ -1,45 +1,14 @@ package net.swofty.type.dwarvenmines.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.dwarvenmines.gui.GUICommisions; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -public class EmissaryEliza extends HypixelNPC { +public class EmissaryEliza extends AbstractEmissary { public EmissaryEliza() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§6Emissary Eliza", "§e§lCLICK"}; - } - - @Override - public String texture(HypixelPlayer player) { - return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTE2ODgzMSwKICAicHJvZmlsZUlkIiA6ICJmNThkZWJkNTlmNTA0MjIyOGY2MDIyMjExZDRjMTQwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ1bnZlbnRpdmV0YWxlbnQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FmNjEzZTRkODExMGFlM2RmNjFlMWRlZTBjMDhjMzVkN2I5MDJmYTVkZjJhYWUwMjc3OWM5MTJkMzFlMzkxNCIKICAgIH0KICB9Cn0="; - } - - @Override - public String signature(HypixelPlayer player) { - return "Aynp0bVkCCtaez7h6or2/FXlUdVMyii2XHFHUWtKZpVJlivloUiOMMu+OsR1EdETjmyF1tB8HGkAmoLezPaQPYlyUnbmipWuAei547y0WS+ezclsW6tmeMcDeWIrI+1yLFBjDSsoM5+aYyC6H7Hmr/kziLXuhNt//ySuqF9G1QiG45VnOEETcuqyxlcWAAsOh8flCMWiMI4PiAdnEQIILs3/M/Wg48jZJTNddQ+cMuHd1IUgtg5NaFkgKWp+X8ZoLZ5lV8RAjC6qiJPiN/PIotRZkSDuGu1CA4HSL6MdBj3GqLQZLC67P7C5ZnRxnATth7Blxz5p4NCNBTstAvtdmxTCNPBLpXRS9yZmNfCdg8OFDboLw//RPSB7sDUug1tUliGt84/l4/YJ8HLGWLF8waK96aQauhGVPMsgDRc2ej+k8Wg//hEaiCFJ6SgcPXwEI6Ss9pUtpedsA3BOx6OBsA9aPg4qKXtsWgIvY8mMABBV5o808WZMt/X/HFU4wISnoN41txtKZ0oYDNH/xUOBmGcUsbLKB0P8P1noEXzzdOSQVdgMVgzeawvvb3U6sR4TbCwx0gEQZlny0+Yjnu16bHr3nktSIGO7VHpDyJGf2AahZDO1Q2B6As6z3JwPhguznHEfqJUInZGvUvus7aLND7SlECt1JuAXOPsA1BgpNKE="; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(-37, 200, -131); - } - - @Override - public boolean looking() { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - new GUICommisions().open(event.player()); + super( + "Eliza", + "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTE2ODgzMSwKICAicHJvZmlsZUlkIiA6ICJmNThkZWJkNTlmNTA0MjIyOGY2MDIyMjExZDRjMTQwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ1bnZlbnRpdmV0YWxlbnQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FmNjEzZTRkODExMGFlM2RmNjFlMWRlZTBjMDhjMzVkN2I5MDJmYTVkZjJhYWUwMjc3OWM5MTJkMzFlMzkxNCIKICAgIH0KICB9Cn0=", + "Aynp0bVkCCtaez7h6or2/FXlUdVMyii2XHFHUWtKZpVJlivloUiOMMu+OsR1EdETjmyF1tB8HGkAmoLezPaQPYlyUnbmipWuAei547y0WS+ezclsW6tmeMcDeWIrI+1yLFBjDSsoM5+aYyC6H7Hmr/kziLXuhNt//ySuqF9G1QiG45VnOEETcuqyxlcWAAsOh8flCMWiMI4PiAdnEQIILs3/M/Wg48jZJTNddQ+cMuHd1IUgtg5NaFkgKWp+X8ZoLZ5lV8RAjC6qiJPiN/PIotRZkSDuGu1CA4HSL6MdBj3GqLQZLC67P7C5ZnRxnATth7Blxz5p4NCNBTstAvtdmxTCNPBLpXRS9yZmNfCdg8OFDboLw//RPSB7sDUug1tUliGt84/l4/YJ8HLGWLF8waK96aQauhGVPMsgDRc2ej+k8Wg//hEaiCFJ6SgcPXwEI6Ss9pUtpedsA3BOx6OBsA9aPg4qKXtsWgIvY8mMABBV5o808WZMt/X/HFU4wISnoN41txtKZ0oYDNH/xUOBmGcUsbLKB0P8P1noEXzzdOSQVdgMVgzeawvvb3U6sR4TbCwx0gEQZlny0+Yjnu16bHr3nktSIGO7VHpDyJGf2AahZDO1Q2B6As6z3JwPhguznHEfqJUInZGvUvus7aLND7SlECt1JuAXOPsA1BgpNKE=", + new Pos(-37, 200, -131)); } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java index 8949d5cd5..0893716a2 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryFraiser.java @@ -1,45 +1,14 @@ package net.swofty.type.dwarvenmines.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.dwarvenmines.gui.GUICommisions; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -public class EmissaryFraiser extends HypixelNPC { +public class EmissaryFraiser extends AbstractEmissary { public EmissaryFraiser() { - super(new HumanConfiguration() { - @Override - public String texture(HypixelPlayer player) { - return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDI0NzQ3MjczNCwKICAicHJvZmlsZUlkIiA6ICI3NDM3MGQ1Mjk5Mjk0ZThjODRlYjRlODlhYjc2MGY5MiIsCiAgInByb2ZpbGVOYW1lIiA6ICJQdXRZb3VySmFzT2ZmIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzlhNDMzMjI1MTFmNGJiYTcxMGJkNzhjOThjOTBlODNhYzkyYTJkYTBmMDVhMGE2OTUxMDg5YmFjZTBjZjIwM2EiCiAgICB9CiAgfQp9"; - } - - @Override - public String signature(HypixelPlayer player) { - return "qAyWpwOq2eisCXEGouDHWawThUooLgahqF2NIqu3TukkgnOK6sOzOsbDHSYo1zSUNgqKM2ywGNjgxN8wlzTM18kbvt7ZQeZ08SB8WGlIs3riCf7ePk8UsC91D0bjTnTp6zqS6dERyvgL8NNyMFxB5xzU4EFAwNA0o8R8oOZlTnSslIdCc46ML7AFYgcx5+J1mfQRJZUX5eJdoqGVZxQPdyxmisjy2+zajWZxtq4G75q743ewmz9F91xAJ3W6VjKejWiHfQVhJgjO7IPbTSRcrGF80z/22Nt5hj3QQifGH3zaMk/b+tY91CHwd8ZEIlTuHefFgCjREVnj39gVXocHjuir7SJganPRhB0Oq6xM7TRPyL9bhb59F7uUE51GFV28g2qjtQBz4gXCPWuslDJh09W0QYozWkvjTDYr/HzcipBXIZuojTgRUk7nLXhz/Dzri45xneB9dspi3SUPAwIZv9skD4wtry/2i65287N9yEprdh5GSad8CXkoUPhEslLHoLez44joDOYtqLldcrOXcBWZvMmKf7akYSmCMOClT44oW/Q3hm35gPWBYNNS/OSnn6JmSlaa1OknBxZu01KKTppsyWFWNT9C+y0rcbTtJGh4/PKqtqgj+4pd1khS7KsZ/kLm1C9AmR0TRlzMX+SsyMG3vyOJKfy1dkcQBG6Z3ps="; - } - - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§6Emissary Fraiser", "§e§lCLICK"}; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(-132, 174, -50); - } - - @Override - public boolean looking() { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - new GUICommisions().open(event.player()); + super( + "Fraiser", + "ewogICJ0aW1lc3RhbXAiIDogMTYxMDI0NzQ3MjczNCwKICAicHJvZmlsZUlkIiA6ICI3NDM3MGQ1Mjk5Mjk0ZThjODRlYjRlODlhYjc2MGY5MiIsCiAgInByb2ZpbGVOYW1lIiA6ICJQdXRZb3VySmFzT2ZmIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzlhNDMzMjI1MTFmNGJiYTcxMGJkNzhjOThjOTBlODNhYzkyYTJkYTBmMDVhMGE2OTUxMDg5YmFjZTBjZjIwM2EiCiAgICB9CiAgfQp9", + "qAyWpwOq2eisCXEGouDHWawThUooLgahqF2NIqu3TukkgnOK6sOzOsbDHSYo1zSUNgqKM2ywGNjgxN8wlzTM18kbvt7ZQeZ08SB8WGlIs3riCf7ePk8UsC91D0bjTnTp6zqS6dERyvgL8NNyMFxB5xzU4EFAwNA0o8R8oOZlTnSslIdCc46ML7AFYgcx5+J1mfQRJZUX5eJdoqGVZxQPdyxmisjy2+zajWZxtq4G75q743ewmz9F91xAJ3W6VjKejWiHfQVhJgjO7IPbTSRcrGF80z/22Nt5hj3QQifGH3zaMk/b+tY91CHwd8ZEIlTuHefFgCjREVnj39gVXocHjuir7SJganPRhB0Oq6xM7TRPyL9bhb59F7uUE51GFV28g2qjtQBz4gXCPWuslDJh09W0QYozWkvjTDYr/HzcipBXIZuojTgRUk7nLXhz/Dzri45xneB9dspi3SUPAwIZv9skD4wtry/2i65287N9yEprdh5GSad8CXkoUPhEslLHoLez44joDOYtqLldcrOXcBWZvMmKf7akYSmCMOClT44oW/Q3hm35gPWBYNNS/OSnn6JmSlaa1OknBxZu01KKTppsyWFWNT9C+y0rcbTtJGh4/PKqtqgj+4pd1khS7KsZ/kLm1C9AmR0TRlzMX+SsyMG3vyOJKfy1dkcQBG6Z3ps=", + new Pos(-132, 174, -50)); } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java index e7bb81b13..d93fae536 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryLilith.java @@ -1,45 +1,14 @@ package net.swofty.type.dwarvenmines.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.dwarvenmines.gui.GUICommisions; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -public class EmissaryLilith extends HypixelNPC { +public class EmissaryLilith extends AbstractEmissary { public EmissaryLilith() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§6Emissary Lilith", "§e§lCLICK"}; - } - - @Override - public String texture(HypixelPlayer player) { - return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTE0NzkwMSwKICAicHJvZmlsZUlkIiA6ICJkZTU3MWExMDJjYjg0ODgwOGZlN2M5ZjQ0OTZlY2RhZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNSEZfTWluZXNraW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzhkZmFiMmE5M2U1YjUwMzAwMDNjZGIxZTNhYjgyYzExNWFlMWZjYTc1YjQ1ZDc1NmUyNzRlMGFmMmFmNWY1MCIKICAgIH0KICB9Cn0="; - } - - @Override - public String signature(HypixelPlayer player) { - return "mjzfJ9D2gyxpHM1h60M6fnrwXkNkeik76dt7LWoGoME4+16PFkj+dMnmKoQm8eLs/6PRoMbWp6UATEpT7fsEcR7sKr/5EWdkcxpuBNgOlf4K2kREiFokE4Ri1cvBsM5YrfMFLlw417CmLmmrauSNuCOm1oUjWLzP/JexiRxmQ4yeWrg4TEmN1rE9F4RNaWQ0jKCZwSIf8DCbqx2w/kGA5prWrArgS2tIZiYCo1ydgNEag4nbZyny6siGyx817VjFt+UNIXqrwQ2PHRjpLyTlFUq6x8HXgyw2ZfHT4DqlH5pGdaE97dvUWuPt0rAU8iN3v1zxiegsCIjZ8xnuGFcgXMsHibLkJbBREdVnSd9LjJbGdD/jEQjCi+iquIs+ozwzhxN2emXZsJnrdbfFf0DD6pg7guUDhdVFZOA+b52hCB4e/N7Inmr9bE/KGsDnIEGfTk9YqUK9hznmIgcE8nAzzwl1SSFmZF8NQWOoZ5BirJztTD+Qfg+7hOzz3STrtIM5xVD1HrYpYHEFHV6DDri0thnHRvuQwllSXkr15nymnQPrCL+LEkRyg6n1iofHcVQGLTPXyJJ0mMZ7Z4W2uQePyeQMaFansZKk4NBaq4Juoz4TmvLIoSzgFjFaENQhHPccsyaSPWPi9iQ1nTjpNlUwvsjAfFgw/29/G1efPEI2sRg="; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(58, 198, -8, -180, 0); - } - - @Override - public boolean looking() { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - new GUICommisions().open(event.player()); + super( + "Lilith", + "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTE0NzkwMSwKICAicHJvZmlsZUlkIiA6ICJkZTU3MWExMDJjYjg0ODgwOGZlN2M5ZjQ0OTZlY2RhZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJNSEZfTWluZXNraW4iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzhkZmFiMmE5M2U1YjUwMzAwMDNjZGIxZTNhYjgyYzExNWFlMWZjYTc1YjQ1ZDc1NmUyNzRlMGFmMmFmNWY1MCIKICAgIH0KICB9Cn0=", + "mjzfJ9D2gyxpHM1h60M6fnrwXkNkeik76dt7LWoGoME4+16PFkj+dMnmKoQm8eLs/6PRoMbWp6UATEpT7fsEcR7sKr/5EWdkcxpuBNgOlf4K2kREiFokE4Ri1cvBsM5YrfMFLlw417CmLmmrauSNuCOm1oUjWLzP/JexiRxmQ4yeWrg4TEmN1rE9F4RNaWQ0jKCZwSIf8DCbqx2w/kGA5prWrArgS2tIZiYCo1ydgNEag4nbZyny6siGyx817VjFt+UNIXqrwQ2PHRjpLyTlFUq6x8HXgyw2ZfHT4DqlH5pGdaE97dvUWuPt0rAU8iN3v1zxiegsCIjZ8xnuGFcgXMsHibLkJbBREdVnSd9LjJbGdD/jEQjCi+iquIs+ozwzhxN2emXZsJnrdbfFf0DD6pg7guUDhdVFZOA+b52hCB4e/N7Inmr9bE/KGsDnIEGfTk9YqUK9hznmIgcE8nAzzwl1SSFmZF8NQWOoZ5BirJztTD+Qfg+7hOzz3STrtIM5xVD1HrYpYHEFHV6DDri0thnHRvuQwllSXkr15nymnQPrCL+LEkRyg6n1iofHcVQGLTPXyJJ0mMZ7Z4W2uQePyeQMaFansZKk4NBaq4Juoz4TmvLIoSzgFjFaENQhHPccsyaSPWPi9iQ1nTjpNlUwvsjAfFgw/29/G1efPEI2sRg=", + new Pos(58, 198, -8, -180, 0)); } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java index 01a93fafa..4b124d907 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/EmissaryWilson.java @@ -1,45 +1,14 @@ package net.swofty.type.dwarvenmines.npcs; import net.minestom.server.coordinate.Pos; -import net.swofty.type.dwarvenmines.gui.GUICommisions; -import net.swofty.type.generic.entity.npc.HypixelNPC; -import net.swofty.type.generic.entity.npc.configuration.HumanConfiguration; -import net.swofty.type.generic.event.custom.NPCInteractEvent; -import net.swofty.type.generic.user.HypixelPlayer; -public class EmissaryWilson extends HypixelNPC { +public class EmissaryWilson extends AbstractEmissary { public EmissaryWilson() { - super(new HumanConfiguration() { - @Override - public String[] holograms(HypixelPlayer player) { - return new String[]{"§6Emissary Wilson", "§e§lCLICK"}; - } - - @Override - public String texture(HypixelPlayer player) { - return "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTExNDI0MiwKICAicHJvZmlsZUlkIiA6ICI2MTZiODhkNDMwNzM0ZTM3OWM3NDc1ODdlZTJkNzlmZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJfX25vdGFodW1hbl9fIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2UxMTcyYjE3ZWIzMzE4Yjg0MWZhOTRiZTBiOGZiZDBiN2NkZGI1YWRkMWQyYjM1YWQ1ZTZhZGM4YWI3ZDUyMDYiCiAgICB9CiAgfQp9"; - } - - @Override - public String signature(HypixelPlayer player) { - return "OfpJzikHSkXmvhaThpA3qdkGkN+zn0pcq6Mf9pSoskz6KVDMhpIpZIyxWjyeugUWmYkp7tkweKCahCtmqoykAltkuuucBHJvQ9j7CxA3PyXQceLvhmEynmQoRB2qHPJTJeR2BXVBTt0VQsv3x64TiEL9U4C0MNg8gBY13z6RALf6FKqzTRImqAlx/9D7M4fhT0fnFAwbzbCPmTlz5zfHKd1L6cPfu/KJKvJLXI9aoM9AgWjARcP3lKRXmgbv431+B0a2ICqngKohVXEWqHLcGI9jK/N1KDEZcy4MNrQ49WJrPn2tnAEqeRmcvab4sjyMqwzrKaLyo71aEAXPFm9UbhZ2d0rknYOo7gxzIirVQMnJR9HxbBslrlZuUwHDOsb4GPwzHUYnL1zZiTRpnspkaADE4vLlt6cyozBCkZI2WZNd30P/15GCLUk0XsETMYlfPsXiQ/CUw8ikZRtP1x1xhWNltQCUcpnbrbJHKZblW/zfXWfEBgCC/kod46VJHHAW+m6PPJZBgceGQrf49MuUbSHfTWk7LHqiDnoahV9rQyb3l1BTUvRgJCdbg9kpYutkMEe8jSPm9xylG1O2ap09cXjqCwhpXiqG0c2jqf4gXEoYEqAPZYJxPQP26Ji2Pk7b/xS5ix6YubDxiQXWLA++LCch6xMwL2pyPxqfDnO4Qk0="; - } - - @Override - public Pos position(HypixelPlayer player) { - return new Pos(181, 150, 31); - } - - @Override - public boolean looking() { - return true; - } - }); - } - - @Override - public void onClick(NPCInteractEvent event) { - new GUICommisions().open(event.player()); + super( + "Wilson", + "ewogICJ0aW1lc3RhbXAiIDogMTYxMDIyNTExNDI0MiwKICAicHJvZmlsZUlkIiA6ICI2MTZiODhkNDMwNzM0ZTM3OWM3NDc1ODdlZTJkNzlmZCIsCiAgInByb2ZpbGVOYW1lIiA6ICJfX25vdGFodW1hbl9fIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2UxMTcyYjE3ZWIzMzE4Yjg0MWZhOTRiZTBiOGZiZDBiN2NkZGI1YWRkMWQyYjM1YWQ1ZTZhZGM4YWI3ZDUyMDYiCiAgICB9CiAgfQp9", + "OfpJzikHSkXmvhaThpA3qdkGkN+zn0pcq6Mf9pSoskz6KVDMhpIpZIyxWjyeugUWmYkp7tkweKCahCtmqoykAltkuuucBHJvQ9j7CxA3PyXQceLvhmEynmQoRB2qHPJTJeR2BXVBTt0VQsv3x64TiEL9U4C0MNg8gBY13z6RALf6FKqzTRImqAlx/9D7M4fhT0fnFAwbzbCPmTlz5zfHKd1L6cPfu/KJKvJLXI9aoM9AgWjARcP3lKRXmgbv431+B0a2ICqngKohVXEWqHLcGI9jK/N1KDEZcy4MNrQ49WJrPn2tnAEqeRmcvab4sjyMqwzrKaLyo71aEAXPFm9UbhZ2d0rknYOo7gxzIirVQMnJR9HxbBslrlZuUwHDOsb4GPwzHUYnL1zZiTRpnspkaADE4vLlt6cyozBCkZI2WZNd30P/15GCLUk0XsETMYlfPsXiQ/CUw8ikZRtP1x1xhWNltQCUcpnbrbJHKZblW/zfXWfEBgCC/kod46VJHHAW+m6PPJZBgceGQrf49MuUbSHfTWk7LHqiDnoahV9rQyb3l1BTUvRgJCdbg9kpYutkMEe8jSPm9xylG1O2ap09cXjqCwhpXiqG0c2jqf4gXEoYEqAPZYJxPQP26Ji2Pk7b/xS5ix6YubDxiQXWLA++LCch6xMwL2pyPxqfDnO4Qk0=", + new Pos(181, 150, 31)); } } diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java index c0822c726..697c4d5a0 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java @@ -32,7 +32,7 @@ public Pos position(HypixelPlayer player) { } @Override - public boolean looking() { + public boolean looking(HypixelPlayer player) { return true; } }); diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardOne.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardOne.java index 5ec497db4..334f3f9e2 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardOne.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardOne.java @@ -2,7 +2,7 @@ import net.minestom.server.coordinate.Pos; -public class NPCRoyalGuardOne extends INPCRoyalGuard { +public class NPCRoyalGuardOne extends AbstractRoyalGuard { public NPCRoyalGuardOne() { super( diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardTwo.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardTwo.java index d68873d42..7f3a1f5e7 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardTwo.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCRoyalGuardTwo.java @@ -2,7 +2,7 @@ import net.minestom.server.coordinate.Pos; -public class NPCRoyalGuardTwo extends INPCRoyalGuard { +public class NPCRoyalGuardTwo extends AbstractRoyalGuard { public NPCRoyalGuardTwo() { super( diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java index 119933475..e413e833a 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/entity/mob/mobs/dwarvenmines/goblin/MobGoblin.java @@ -66,12 +66,6 @@ public String getDisplayName() { return "Goblin"; } - @Override - public void tick(long time) { - setView(0, 0); - super.tick(time); - } - @Override public List getGoalSelectors() { return List.of( From d5aca619123d61b37e58743baf7c1c87a72a109c Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Tue, 30 Dec 2025 01:15:02 +0200 Subject: [PATCH 11/13] refactor: remove extra 0s on positions --- .../java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java | 2 +- .../missions/thepark/birchpark/MissionGiveCharlieBirchLogs.java | 2 +- .../missions/thepark/birchpark/MissionTalkToCharlie.java | 2 +- .../missions/thepark/birchpark/MissionTalkToCharlieAgain.java | 2 +- .../thepark/darkthicket/MissionGiveRyanDarkOakLogs.java | 2 +- .../missions/thepark/darkthicket/MissionSneakUpOnRyan.java | 2 +- .../mission/missions/thepark/darkthicket/MissionTalkToRyan.java | 2 +- .../mission/missions/thepark/jungle/MissionTalkToMolbert.java | 2 +- .../mission/missions/thepark/savanna/MissionCheckOnMelody.java | 2 +- .../missions/thepark/savanna/MissionGiveMelodyAcaciaLogs.java | 2 +- .../mission/missions/thepark/spruce/MissionFindKelly.java | 2 +- .../missions/thepark/spruce/MissionGiveKellySpruceLogs.java | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java index 697c4d5a0..22ddf45d5 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/NPCKingName.java @@ -28,7 +28,7 @@ public String texture(HypixelPlayer player) { @Override public Pos position(HypixelPlayer player) { - return new Pos(129.500, 196.000, 196.500, 180, 0); + return new Pos(129.5, 196.000, 196.5, 180, 0); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionGiveCharlieBirchLogs.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionGiveCharlieBirchLogs.java index d796dc2ba..70a517d61 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionGiveCharlieBirchLogs.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionGiveCharlieBirchLogs.java @@ -44,6 +44,6 @@ public Set getValidRegions() { @Override public Pos getLocation() { - return new Pos(-277.5, 80, -17.500); + return new Pos(-277.5, 80, -17.5); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlie.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlie.java index ef062d1f5..a0e35b5b0 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlie.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlie.java @@ -40,6 +40,6 @@ public Set getValidRegions() { @Override public Pos getLocation() { - return new Pos(-277.5, 80, -17.500); + return new Pos(-277.5, 80, -17.5); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlieAgain.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlieAgain.java index f8c7ba560..fac3eb988 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlieAgain.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/birchpark/MissionTalkToCharlieAgain.java @@ -45,6 +45,6 @@ public Set getValidRegions() { @Override public Pos getLocation() { - return new Pos(-277.5, 80, -17.500); + return new Pos(-277.5, 80, -17.5); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionGiveRyanDarkOakLogs.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionGiveRyanDarkOakLogs.java index 42ec99156..4b7c983fd 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionGiveRyanDarkOakLogs.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionGiveRyanDarkOakLogs.java @@ -22,7 +22,7 @@ public class MissionGiveRyanDarkOakLogs extends SkyBlockMission implements Locat @Override public Pos getLocation() { - return new Pos(-364.5, 102.5, -90.500); + return new Pos(-364.5, 102.5, -90.5); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionSneakUpOnRyan.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionSneakUpOnRyan.java index d4971f034..6acbbb650 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionSneakUpOnRyan.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionSneakUpOnRyan.java @@ -14,7 +14,7 @@ public class MissionSneakUpOnRyan extends SkyBlockMission implements LocationAss @Override public Pos getLocation() { - return new Pos(-364.5, 102.5, -90.500); + return new Pos(-364.5, 102.5, -90.5); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionTalkToRyan.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionTalkToRyan.java index 8f6f02b65..62136e8d3 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionTalkToRyan.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/darkthicket/MissionTalkToRyan.java @@ -14,7 +14,7 @@ public class MissionTalkToRyan extends SkyBlockMission implements LocationAssoci @Override public Pos getLocation() { - return new Pos(-364.5, 102.5, -90.500); + return new Pos(-364.5, 102.5, -90.5); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/jungle/MissionTalkToMolbert.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/jungle/MissionTalkToMolbert.java index f29d22c30..60bf01d1c 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/jungle/MissionTalkToMolbert.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/jungle/MissionTalkToMolbert.java @@ -14,7 +14,7 @@ public class MissionTalkToMolbert extends SkyBlockMission implements LocationAss @Override public Pos getLocation() { - return new Pos(-447.5, 120, -63.500); + return new Pos(-447.5, 120, -63.5); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionCheckOnMelody.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionCheckOnMelody.java index 4ab4fbc35..b14c2813f 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionCheckOnMelody.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionCheckOnMelody.java @@ -40,6 +40,6 @@ public Set getValidRegions() { @Override public Pos getLocation() { - return new Pos(-411.5, 109, 71.500); + return new Pos(-411.5, 109, 71.5); } } diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionGiveMelodyAcaciaLogs.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionGiveMelodyAcaciaLogs.java index 2072491f5..3efc71140 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionGiveMelodyAcaciaLogs.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/savanna/MissionGiveMelodyAcaciaLogs.java @@ -21,7 +21,7 @@ public class MissionGiveMelodyAcaciaLogs extends SkyBlockMission implements Loca @Override public Pos getLocation() { - return new Pos(-411.5, 109, 71.500); + return new Pos(-411.5, 109, 71.5); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionFindKelly.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionFindKelly.java index de04e80a7..5cc574129 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionFindKelly.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionFindKelly.java @@ -14,7 +14,7 @@ public class MissionFindKelly extends SkyBlockMission implements LocationAssocia @Override public Pos getLocation() { - return new Pos(-350.5, 94, 33.500); + return new Pos(-350.5, 94, 33.5); } @Override diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionGiveKellySpruceLogs.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionGiveKellySpruceLogs.java index 471cd78cc..f5e79f5dd 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionGiveKellySpruceLogs.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/mission/missions/thepark/spruce/MissionGiveKellySpruceLogs.java @@ -15,7 +15,7 @@ public class MissionGiveKellySpruceLogs extends SkyBlockMission implements Locat @Override public Pos getLocation() { - return new Pos(-350.5, 94, 33.500); + return new Pos(-350.5, 94, 33.5); } @Override From d959e452cf82b8741ffaa53437edb7b7c5064d82 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Wed, 31 Dec 2025 15:07:11 +0200 Subject: [PATCH 12/13] feat: give royal pigeon and royal compass --- .../commons/skyblock/item/ItemType.java | 3 +++ .../skyblock/items/mining/dwarven.yml | 19 +++++++++++++++++ .../dwarvenmines/commission/Commission.java | 21 ++++++++++--------- .../gui/GUICommissionMilestones.java | 5 +++-- .../handlers/ability/AbilityRegistry.java | 15 +++++++++++++ 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/commons/src/main/java/net/swofty/commons/skyblock/item/ItemType.java b/commons/src/main/java/net/swofty/commons/skyblock/item/ItemType.java index b5405fac8..65c733f8f 100644 --- a/commons/src/main/java/net/swofty/commons/skyblock/item/ItemType.java +++ b/commons/src/main/java/net/swofty/commons/skyblock/item/ItemType.java @@ -37,6 +37,9 @@ public enum ItemType { RAW_SOULFLOW(Material.PLAYER_HEAD, Rarity.UNCOMMON), SOULFLOW(Material.PLAYER_HEAD, Rarity.RARE), + ROYAL_COMPASS(Material.PLAYER_HEAD, Rarity.RARE), + ROYAL_PIGEON(Material.PLAYER_HEAD, Rarity.LEGENDARY), + /** * Accessories */ diff --git a/configuration/skyblock/items/mining/dwarven.yml b/configuration/skyblock/items/mining/dwarven.yml index 09174ada5..21660d74a 100644 --- a/configuration/skyblock/items/mining/dwarven.yml +++ b/configuration/skyblock/items/mining/dwarven.yml @@ -90,3 +90,22 @@ items: texture: 63a405fb286dbb32e9b3908f60948f0207306c825e63ac9e626ed1dbb2f7a2be - id: EXTRA_UNDER_NAME display: Machine Fuel + - id: ROYAL_PIGEON + rarity: LEGENDARY + material: PLAYER_HEAD + components: + - id: SKULL_HEAD + texture: 63a405fb286dbb32e9b3908f60948f0207306c825e63ac9e626ed1dbb2f7a2be + - id: DEFAULT_SOULBOUND + coop_allowed: true + - id: ROYAL_COMPASS + rarity: RARE + material: PLAYER_HEAD + components: + - id: ABILITY + abilities: + - TRUE_DWARTH + - id: SKULL_HEAD + texture: f106277ad541aa76d9d4a19e7aac92621a3f0251ff9427dfdea539b51dd8d1ea + - id: DEFAULT_SOULBOUND + coop_allowed: true \ No newline at end of file diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java index 6992a1f92..98f836f8c 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/commission/Commission.java @@ -23,21 +23,22 @@ public String generateDescription() { switch (objective.type) { case MINE -> { - sb.append("Mine ").append(objective.amount).append(" "); + sb.append("Mine §a").append(objective.amount).append(" §7"); sb.append(getTargetName(objective.target)).append(" Ore"); appendLocation(sb); sb.append("."); } case SLAY -> { - sb.append("Slay ").append(objective.amount).append(" "); + sb.append("Slay §a").append(objective.amount).append(" §7"); sb.append(getTargetNamePlural(objective.target)); + sb.append("§7"); appendLocation(sb); appendEvent(sb); sb.append("."); } case DAMAGE -> { sb.append("Damage ").append(getTargetNamePlural(objective.target)); - sb.append(" ").append(objective.amount).append(" times"); + sb.append(" §7").append(objective.amount).append(" times"); appendLocation(sb); sb.append("."); } @@ -61,7 +62,7 @@ public String generateDescription() { private void appendLocation(StringBuilder sb) { if (!objective.location.isAny()) { objective.location.getRegion().ifPresent(region -> - sb.append(" in ").append(region.getName())); + sb.append(" in §b").append(region.getName())); } } @@ -88,10 +89,10 @@ private String getTargetNamePlural(Objective.BlockTarget target) { return switch (target) { case MITHRIL -> "Mithril Ore"; case TITANIUM -> "Titanium Ore"; - case GOBLIN -> "Goblins"; - case GLACITE_WALKER -> "Glacite Walkers"; - case TREASURE_HOARDER -> "Treasure Hoarders"; - case GOLDEN_GOBLIN -> "Golden Goblin"; + case GOBLIN -> "§cGoblins"; + case GLACITE_WALKER -> "§bGlacite Walkers"; + case TREASURE_HOARDER -> "§cTreasure Hoarders"; + case GOLDEN_GOBLIN -> "§6Golden Goblin"; case STAR_SENTRY -> "Star Sentrys"; case NONE -> ""; }; @@ -106,8 +107,8 @@ private String getCollectibleName(Objective.BlockTarget target) { private String getEventName(EventType event) { return switch (event) { - case GOBLIN_RAID -> "Goblin Raid Event"; - case RAFFLE -> "Raffle Event"; + case GOBLIN_RAID -> "§cGoblin Raid §7Event"; + case RAFFLE -> "§eRaffle §7Event"; case DOUBLE_POWDER -> "2x Powder Event"; case NONE -> ""; }; diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java index 22cadc379..42b1e95d8 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/gui/GUICommissionMilestones.java @@ -5,6 +5,7 @@ import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.swofty.commons.StringUtility; +import net.swofty.commons.skyblock.item.ItemType; import net.swofty.type.dwarvenmines.commission.CommissionMilestone; import net.swofty.type.dwarvenmines.commission.Commissions; import net.swofty.type.generic.gui.inventory.HypixelInventoryGUI; @@ -186,7 +187,7 @@ private void claimMilestone(SkyBlockPlayer player, CommissionMilestone milestone player.sendMessage("§7 - §b+" + milestone.getSkyBlockXpReward() + " SkyBlock XP"); if (milestone.isUnlocksEmissaries()) { - // TODO: Give Royal Compass item + player.addAndUpdateItem(ItemType.ROYAL_COMPASS); } if (milestone.isUnlocksExtraSlot()) { } @@ -194,7 +195,7 @@ private void claimMilestone(SkyBlockPlayer player, CommissionMilestone milestone // TODO: Give Travel Scroll item } if (milestone.isUnlocksRoyalPigeon()) { - // TODO: Give Royal Pigeon item + player.addAndUpdateItem(ItemType.ROYAL_PIGEON); } if (milestone.isUnlocksCrystalNucleusScroll()) { // TODO: Give Travel Scroll item diff --git a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/handlers/ability/AbilityRegistry.java b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/handlers/ability/AbilityRegistry.java index f3de83e00..47097253a 100644 --- a/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/handlers/ability/AbilityRegistry.java +++ b/type.skyblockgeneric/src/main/java/net/swofty/type/skyblockgeneric/item/handlers/ability/AbilityRegistry.java @@ -1,5 +1,7 @@ package net.swofty.type.skyblockgeneric.item.handlers.ability; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; import net.minestom.server.coordinate.BlockVec; import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Pos; @@ -53,6 +55,19 @@ public class AbilityRegistry { } )); + register(new RegisteredAbility( + "TRUE_DWARTH", + "True Dwarth", + "§7Shows the way towards the nearest §6Emissary §7while in the §2Dwarven Mines§7.", + RegisteredAbility.AbilityActivation.RIGHT_CLICK, + 20 * 3, + new RegisteredAbility.NoAbilityCost(), + (player, item, targetedBlock, blockFace) -> { + player.sendMessage(Component.text("§cThis Feature is not there yet. §aOpen a Pull request HERE to get it added quickly!") + .clickEvent(ClickEvent.openUrl("https://github.com/Swofty-Developments/HypixelSkyBlock"))); + } + )); + // register(new RegisteredAbility( // TODO: Figure out how to implement passive abiltiies // "BEJEWELED_BLADE", // "Bejeweled Blade", From 1505a7fb4cb6e18e852b1bd30017c2d713b3bdd5 Mon Sep 17 00:00:00 2001 From: ArikSquad <75741608+ArikSquad@users.noreply.github.com> Date: Wed, 31 Dec 2025 15:09:33 +0200 Subject: [PATCH 13/13] feat: name all Royal Guard in chat --- .../swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java index 9042fc0fb..c58c865c8 100644 --- a/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java +++ b/type.dwarvenmines/src/main/java/net/swofty/type/dwarvenmines/npcs/AbstractRoyalGuard.java @@ -10,6 +10,7 @@ import java.util.stream.Stream; import net.swofty.type.generic.event.custom.NPCInteractEvent; +import org.jspecify.annotations.NonNull; public class AbstractRoyalGuard extends HypixelNPC { @@ -35,6 +36,11 @@ public Pos position(HypixelPlayer player) { return position.apply(player); } + @Override + public @NonNull String chatName() { + return "§6Royal Guard"; + } + @Override public boolean looking(HypixelPlayer player) { return true;