From ef791db543d25ea9e113f5d54a20e3fd248bb297 Mon Sep 17 00:00:00 2001 From: ItzKatze <136186750+ItzKatze@users.noreply.github.com> Date: Wed, 23 Jul 2025 13:35:00 +0200 Subject: [PATCH] feat: Death Datapoint --- .../types/generic/data/DataHandler.java | 1 + .../data/datapoints/DatapointBestiary.java | 10 ++- .../data/datapoints/DatapointDeaths.java | 80 +++++++++++++++++++ .../sbmenu/bestiary/GUIBestiaryMob.java | 3 +- .../types/generic/user/SkyBlockPlayer.java | 22 +++-- .../generic/utility/DeathMessageCreator.java | 36 ++++----- 6 files changed, 124 insertions(+), 28 deletions(-) create mode 100644 type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointDeaths.java diff --git a/type.generic/src/main/java/net/swofty/types/generic/data/DataHandler.java b/type.generic/src/main/java/net/swofty/types/generic/data/DataHandler.java index 7674c43e5..1d3d96f4f 100644 --- a/type.generic/src/main/java/net/swofty/types/generic/data/DataHandler.java +++ b/type.generic/src/main/java/net/swofty/types/generic/data/DataHandler.java @@ -352,6 +352,7 @@ public enum Data { SACK_OF_SACKS("sack_of_sacks", false, false, false, DatapointSackOfSacks.class, new DatapointSackOfSacks("sack_of_sacks")), ITEMS_IN_SACKS("items_in_sacks", false, false, false, DatapointItemsInSacks.class, new DatapointItemsInSacks("items_in_sacks")), BESTIARY("bestiary", false, false, false, DatapointBestiary.class, new DatapointBestiary("bestiary")), + DEATHS("deaths", false, false, false, DatapointDeaths.class, new DatapointDeaths("deaths")), SKYBLOCK_EXPERIENCE("skyblock_experience", false, false, false, DatapointSkyBlockExperience.class, new DatapointSkyBlockExperience("skyblock_experience")), BITS("bits", false, false, false, DatapointInteger.class, new DatapointInteger("bits", 0)), GEMS("gems", false, false, false, DatapointInteger.class, new DatapointInteger("gems", 0)), diff --git a/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointBestiary.java b/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointBestiary.java index 56fd501bd..cbadc07e5 100644 --- a/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointBestiary.java +++ b/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointBestiary.java @@ -11,11 +11,9 @@ import net.swofty.types.generic.event.SkyBlockEventHandler; import net.swofty.types.generic.event.custom.BestiaryUpdateEvent; import net.swofty.types.generic.gui.inventory.inventories.sbmenu.bestiary.BestiaryEntry; -import net.swofty.types.generic.skill.SkillCategories; import net.swofty.types.generic.user.SkyBlockPlayer; import org.json.JSONObject; -import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -110,6 +108,12 @@ public List getDisplay(List lore, int kills, BestiaryMob mob, Be double currentProgress = bestiaryData.getKillsToNextTier(mob, kills); double currentRequirement = bestiaryData.getTotalKillsForNextTier(bracket, tier + 1); double totalRequirement = bestiaryData.getTotalKillsForMaxTier(mob); + DatapointDeaths.PlayerDeaths playerDeaths = attachedPlayer.getDeathData(); + int deaths = 0; + + for (BestiaryMob bestiaryMob : bestiaryEntry.getMobs()) { + deaths += playerDeaths.getAmount(bestiaryMob.getMobID()); + } String baseLoadingBar = "─────────────────"; int maxBarLength = baseLoadingBar.length(); @@ -118,7 +122,7 @@ public List getDisplay(List lore, int kills, BestiaryMob mob, Be lore.add("§7" + bestiaryEntry.getDescription()); lore.add(""); lore.add("§7Kills: §a" + kills); - lore.add("§7Deaths: §a" + "TODO"); //TODO add datapoint for amount of deaths + lore.add("§7Deaths: §a" + deaths); lore.add(""); if (tier > 0) { diff --git a/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointDeaths.java b/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointDeaths.java new file mode 100644 index 000000000..4162128ef --- /dev/null +++ b/type.generic/src/main/java/net/swofty/types/generic/data/datapoints/DatapointDeaths.java @@ -0,0 +1,80 @@ +package net.swofty.types.generic.data.datapoints; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.minestom.server.entity.damage.Damage; +import net.minestom.server.entity.damage.EntityDamage; +import net.swofty.commons.protocol.Serializer; +import net.swofty.types.generic.data.Datapoint; +import net.swofty.types.generic.entity.mob.BestiaryMob; +import org.json.JSONObject; + +import java.util.HashMap; +import java.util.Map; + +public class DatapointDeaths extends Datapoint { + + public DatapointDeaths(String key, PlayerDeaths value) { + super(key, value, new Serializer<>() { + @Override + public String serialize(PlayerDeaths value) { + JSONObject jsonObject = new JSONObject(value.deaths); + return jsonObject.toString(); + } + + @Override + public PlayerDeaths deserialize(String json) { + JSONObject jsonObject = new JSONObject(json); + Map deaths = new HashMap<>(); + + for (String key : jsonObject.keySet()) { + deaths.put(key, jsonObject.getInt(key)); + } + + return new PlayerDeaths(deaths); + } + + @Override + public PlayerDeaths clone(PlayerDeaths value) { + return new PlayerDeaths(value.deaths == null ? new HashMap<>() : new HashMap<>(value.deaths)); + } + }); + } + + public DatapointDeaths(String key) { + this(key, new PlayerDeaths()); + } + + @NoArgsConstructor + @Getter + public static class PlayerDeaths { + private Map deaths = new HashMap<>(); + + public PlayerDeaths(Map mobs) { + this.deaths = mobs; + } + + private String getCauseAsString(Damage damage) { + return switch (damage.getType().name()) { + case "minecraft:mob_attack" -> ((BestiaryMob) ((EntityDamage) damage).getSource()).getMobID(); + default -> damage.getType().name(); + }; + } + + public void set(Damage deathCause, int amount) { + deaths.put(getCauseAsString(deathCause), amount); + } + + public void increase(Damage deathCause, Integer amount) { + set(deathCause, getAmount(getCauseAsString(deathCause)) + amount); + } + + public void decrease(Damage deathCause, Integer amount) { + set(deathCause, getAmount(getCauseAsString(deathCause)) - amount); + } + + public Integer getAmount(String cause) { + return deaths.getOrDefault(cause, 0); + } + } +} diff --git a/type.generic/src/main/java/net/swofty/types/generic/gui/inventory/inventories/sbmenu/bestiary/GUIBestiaryMob.java b/type.generic/src/main/java/net/swofty/types/generic/gui/inventory/inventories/sbmenu/bestiary/GUIBestiaryMob.java index 4522ce289..4398e0226 100644 --- a/type.generic/src/main/java/net/swofty/types/generic/gui/inventory/inventories/sbmenu/bestiary/GUIBestiaryMob.java +++ b/type.generic/src/main/java/net/swofty/types/generic/gui/inventory/inventories/sbmenu/bestiary/GUIBestiaryMob.java @@ -92,6 +92,7 @@ public ItemStack.Builder getItem(SkyBlockPlayer player) { public ItemStack.Builder getItem(SkyBlockPlayer player) { ArrayList lore = new ArrayList<>(); int kills = getPlayer().getBestiaryData().getAmount(mob); + int deaths = getPlayer().getDeathData().getAmount(mob.getMobID()); OtherLoot otherLoot = mob.getOtherLoot(); List commonLoot = new ArrayList<>(); @@ -116,7 +117,7 @@ public ItemStack.Builder getItem(SkyBlockPlayer player) { lore.add("§7Xp Orbs: §3" + otherLoot.getXpOrbAmount()); lore.add(""); lore.add("§7Kills: §a" + kills); - lore.add("§7Deaths: §a" + "TODO"); + lore.add("§7Deaths: §a" + deaths); lore.add(""); if (!commonLoot.isEmpty()) { diff --git a/type.generic/src/main/java/net/swofty/types/generic/user/SkyBlockPlayer.java b/type.generic/src/main/java/net/swofty/types/generic/user/SkyBlockPlayer.java index 668f47230..23c13380e 100644 --- a/type.generic/src/main/java/net/swofty/types/generic/user/SkyBlockPlayer.java +++ b/type.generic/src/main/java/net/swofty/types/generic/user/SkyBlockPlayer.java @@ -28,7 +28,6 @@ import net.swofty.types.generic.SkyBlockGenericLoader; import net.swofty.types.generic.collection.CustomCollectionAward; import net.swofty.types.generic.data.DataHandler; -import net.swofty.types.generic.data.Datapoint; import net.swofty.types.generic.data.datapoints.*; import net.swofty.types.generic.data.mongodb.CoopDatabase; import net.swofty.types.generic.event.actions.player.ActionPlayerChangeSkyBlockMenuDisplay; @@ -91,6 +90,8 @@ public class SkyBlockPlayer extends Player { @Getter private PlayerHookManager hookManager; + private static final Pattern SACK_PATTERN = Pattern.compile("^(?:(SMALL|MEDIUM|LARGE|ENCHANTED)_)?(.+?)_SACK$"); + public SkyBlockPlayer(@NotNull GameProfile gameProfile, @NotNull PlayerConnection playerConnection) { super(playerConnection, gameProfile); @@ -486,7 +487,7 @@ public int getMaxSackStorage(ItemType sack) { int maxStorage = 0; String sackCategory = ""; - Matcher matcher = Pattern.compile("^(?:(SMALL|MEDIUM|LARGE|ENCHANTED)_)?(.+?)_SACK$").matcher(sack.name()); + Matcher matcher = SACK_PATTERN.matcher(sack.name()); if (matcher.find()) { sackCategory = matcher.group(2); } else { @@ -495,7 +496,7 @@ public int getMaxSackStorage(ItemType sack) { } for (SkyBlockItem skyBlockItem : getAllSacks()) { - matcher = Pattern.compile("^(?:(SMALL|MEDIUM|LARGE|ENCHANTED)_)?(.+?)_SACK$").matcher(skyBlockItem.getAttributeHandler().getTypeAsString()); + matcher = SACK_PATTERN.matcher(skyBlockItem.getAttributeHandler().getTypeAsString()); if (matcher.find()) { String otherCategory = matcher.group(2); if (sackCategory.equals(otherCategory) && skyBlockItem.hasComponent(SackComponent.class)) { @@ -687,6 +688,10 @@ public void setBoosterCookieExpirationDate(long timestamp) { getDataHandler().get(DataHandler.Data.BOOSTER_COOKIE_EXPIRATION_DATE, DatapointLong.class).setValue(timestamp); } + public boolean isBoosterCookieActive() { + return getBoosterCookieExpirationDate() >= System.currentTimeMillis(); + } + public DatapointKat.PlayerKat getKatData() { return getDataHandler().get(DataHandler.Data.KAT, DatapointKat.class).getValue(); } @@ -742,6 +747,9 @@ public void addExperience(long value) { setExperience(getExperience() + value); } + public DatapointDeaths.PlayerDeaths getDeathData() { + return getDataHandler().get(DataHandler.Data.DEATHS, DatapointDeaths.class).getValue(); + } @Override public void kill() { @@ -754,12 +762,14 @@ public void kill() { sendMessage("§c☠ §7You " + creator.createPersonal()); - DatapointDouble coins = getDataHandler().get(DataHandler.Data.COINS, DatapointDouble.class); - coins.setValue(coins.getValue() / 2); + getDeathData().increase(this.lastDamage, 1); playSound(Sound.sound(Key.key("block.anvil.fall"), Sound.Source.PLAYER, 1.0f, 2.0f)); - sendMessage("§cYou died and lost " + StringUtility.decimalify(coins.getValue(), 1) + " coins!"); + if (!isBoosterCookieActive()) { + sendMessage("§cYou died and lost " + StringUtility.decimalify(getCoins() / 2, 1) + " coins!"); + setCoins(getCoins() / 2); + } if (!SkyBlockConst.getTypeLoader().getLoaderValues().announceDeathMessages()) return; diff --git a/type.generic/src/main/java/net/swofty/types/generic/utility/DeathMessageCreator.java b/type.generic/src/main/java/net/swofty/types/generic/utility/DeathMessageCreator.java index 5c1550f37..1cbed1eab 100644 --- a/type.generic/src/main/java/net/swofty/types/generic/utility/DeathMessageCreator.java +++ b/type.generic/src/main/java/net/swofty/types/generic/utility/DeathMessageCreator.java @@ -8,33 +8,33 @@ public record DeathMessageCreator(Damage type) { public String createPersonal() { return switch (type.getType().name()) { - case "entity_source": - yield "were slain by " + ((SkyBlockMob) ((EntityDamage) type).getSource()).getDisplayName(); - case "attack.outOfWorld": - yield "fell out of the world"; - case "attack.onFire": - yield "burned to death"; - case "attack.fall": - yield "fell from a high place"; + case "minecraft:mob_attack": + yield "were slain by " + ((SkyBlockMob) ((EntityDamage) type).getSource()).getDisplayName() + "."; + case "minecraft:out_of_world": + yield "fell out of the world."; + case "minecraft:on_fire": + yield "burned to death."; + case "minecraft:fall": + yield "fell from a high place."; default: Logger.warn("Unknown death type: " + type.getType().name()); - yield "died"; + yield "died."; }; } public String createOther() { return switch (type.getType().name()) { - case "entity_source": - yield "was slain by " + ((SkyBlockMob) ((EntityDamage) type).getSource()).getDisplayName(); - case "attack.outOfWorld": - yield "fell out of the world"; - case "attack.onFire": - yield "burned to death"; - case "attack.fall": - yield "fell from a high place"; + case "minecraft:mob_attack": + yield "was slain by " + ((SkyBlockMob) ((EntityDamage) type).getSource()).getDisplayName() + "."; + case "minecraft:out_of_world": + yield "fell out of the world."; + case "minecraft:on_fire": + yield "burned to death."; + case "minecraft:fall": + yield "fell from a high place."; default: Logger.warn("Unknown death type: " + type.getType().name()); - yield "died"; + yield "died."; }; } }