From d662d6031f0ea67702f29045a94ad84900f033bd Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 4 Jul 2026 20:55:00 +0200 Subject: [PATCH 01/20] fix: ortho --- .../resources/translations/default/dailyevents.properties | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index a9a60699d..958976f58 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -30,7 +30,7 @@ feature.dailyevents.broadcast.soon=*un évènement commence feature.dailyevents.miraculousfishing.broadcast.start= \
\
PËCHE MIRACLEUSE ! La grande session a commencé !\ -
*sortez vous canne à pêche et découvrez les mystères des lacs*\ +
*sortez vos cannes à pêche et découvrez les mystères des lacs*\
\
Effets :\
+ %1$s% vitesse de pêche\ @@ -99,4 +99,7 @@ feature.dailyevents.miraculousfishing.menu.info.sea_creature.lore=Des loots uniques et spéciaux feature.dailyevents.miraculousfishing.menu.info.loot_table.lore=Bénéficiez d'une bénédiction miraculeuse \
vous laissant des récompenses et des loots nouveaux\ -
CLIQUEZ ICI POUR VOIR LES ITEMS PECHABLE \ No newline at end of file +
CLIQUEZ ICI POUR VOIR LES ITEMS PECHABLE + +# ** Nuit sanglante ** +feature.dailyevents.bloody_night.loot_table.bloody_mob=Loots des monstres sanglants \ No newline at end of file From e5396b1506075b2cd0bf430f2773e849ccf97e66 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 4 Jul 2026 22:49:06 +0200 Subject: [PATCH 02/20] feat: add Vampirism enchantment --- .../contents/enchantments/Vampirism.java | 148 ++++++++++++++++++ .../enchantments/CustomEnchantment.java | 6 + .../CustomEnchantmentRegistry.java | 3 + 3 files changed, 157 insertions(+) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java new file mode 100644 index 000000000..83ff1f7d2 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java @@ -0,0 +1,148 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.enchantments; + +import fr.openmc.core.features.dream.models.registry.DreamEnchantment; +import fr.openmc.core.utils.text.messages.TranslationManager; +import io.papermc.paper.registry.data.EnchantmentRegistryEntry; +import io.papermc.paper.registry.keys.tags.ItemTypeTagKeys; +import io.papermc.paper.registry.tag.TagKey; +import net.kyori.adventure.key.Key; +import net.kyori.adventure.text.Component; +import org.bukkit.NamespacedKey; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.ItemType; + +@SuppressWarnings("UnstableApiUsage") +public class Vampirism extends DreamEnchantment implements Listener { + private static final NamespacedKey MAX_HEALTH_MODIFIER_KEY = + new NamespacedKey("omc_daily_events", "vampirism_max_health"); + + @Override + public Key getKey() { + return Key.key("omc_daily_events:vampirism"); + } + + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.enchantment.vampirism.name"); + } + + @Override + public TagKey getSupportedItems() { + return ItemTypeTagKeys.SWORDS; + } + + @Override + public int getMaxLevel() { + return 3; + } + + @Override + public int getWeight() { + return 1; + } + + @Override + public int getAnvilCost() { + return 4; + } + + @Override + public EnchantmentRegistryEntry.EnchantmentCost getMinimumCost() { + return EnchantmentRegistryEntry.EnchantmentCost.of(1, 2); + } + + @Override + public EnchantmentRegistryEntry.EnchantmentCost getMaximalmCost() { + return EnchantmentRegistryEntry.EnchantmentCost.of(4, 5); + } + + @EventHandler + public void onAttack(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Player player)) return; + if (!(event.getEntity() instanceof LivingEntity)) return; + + Enchantment enchant = this.getEnchantment(); + if (enchant == null) return; + + ItemStack item = player.getInventory().getItemInMainHand(); + if (!item.getEnchantments().containsKey(enchant)) return; + int level = item.getEnchantmentLevel(enchant); + + double damageDealt = event.getFinalDamage(); + if (damageDealt <= 0) return; + + healPlayer(player, damageDealt); + + if (level >= 2) { + double max = getMaxHealthForLevel(level); + + AttributeInstance maxHealthAttr = player.getAttribute(Attribute.MAX_HEALTH); + if (maxHealthAttr == null) return; + + maxHealthAttr.addModifier(new AttributeModifier( + MAX_HEALTH_MODIFIER_KEY, + max - maxHealthAttr.getValue(), + AttributeModifier.Operation.ADD_NUMBER + )); + } + } + + @EventHandler + public void onItemHeldChange(PlayerItemHeldEvent event) { + Player player = event.getPlayer(); + + Enchantment enchant = this.getEnchantment(); + if (enchant == null) return; + + ItemStack item = player.getInventory().getItem(event.getPreviousSlot()); + if (item == null) return; + if (!item.getEnchantments().containsKey(enchant)) return; + + int level = item.getEnchantmentLevel(enchant); + + if (level < 2) return; + + AttributeInstance maxHealthAttr = player.getAttribute(Attribute.MAX_HEALTH); + if (maxHealthAttr == null) return; + maxHealthAttr.removeModifier(MAX_HEALTH_MODIFIER_KEY); + } + + /** + * Donne 1/8 de vie en fonction des dégâts infligés à l'attaquant. + * @param player le joueur ciblé + * @param damageDealt le nombre de dégats mis + */ + private void healPlayer(Player player, double damageDealt) { + AttributeInstance maxHealthAttr = player.getAttribute(Attribute.MAX_HEALTH); + if (maxHealthAttr == null) return; + + double maxHealth = maxHealthAttr.getValue(); + double heal = damageDealt * 0.125; + double newHealth = Math.min(maxHealth, player.getHealth() + heal); + + player.setHealth(newHealth); + } + + /** + * Donne la vie maximale que le joueur peut avoir en fonction du niveau de l'enchantement. + * @param level le niveau de l'enchantement + * @return la vie maximale + */ + private double getMaxHealthForLevel(int level) { + return switch (level) { + case 2 -> 25.0; + case 3 -> 30.0; + default -> 0.0; + }; + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantment.java b/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantment.java index 13f6d7097..694e83e10 100644 --- a/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantment.java +++ b/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantment.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.enchantments; import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.utils.RandomUtils; import io.papermc.paper.registry.RegistryAccess; import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; @@ -54,6 +55,11 @@ public ItemStack getVanilla() { }; } + public CustomItem getEnchantedBookItem(int minLevel, int maxLevel) { + int level = RandomUtils.randomBetween(minLevel, maxLevel); + return getEnchantedBookItem(level); + } + public Enchantment getEnchantment() { Registry<@NotNull Enchantment> enchantmentRegistry = RegistryAccess .registryAccess() diff --git a/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantmentRegistry.java b/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantmentRegistry.java index b632fdb78..d6a65d4a9 100644 --- a/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantmentRegistry.java +++ b/src/main/java/fr/openmc/core/registry/enchantments/CustomEnchantmentRegistry.java @@ -7,6 +7,7 @@ import fr.openmc.core.features.dream.registries.enchantements.DreamSleeper; import fr.openmc.core.features.dream.registries.enchantements.Experientastic; import fr.openmc.core.features.dream.registries.enchantements.Soulbound; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.enchantments.Vampirism; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import io.papermc.paper.registry.data.EnchantmentRegistryEntry; import io.papermc.paper.registry.event.RegistryComposeEvent; @@ -30,6 +31,8 @@ public Key key(CustomEnchantment registryObject) { public final CustomEnchantment EXPERIENTASTIC = register(new Experientastic()); public final CustomEnchantment DREAM_SLEEPER = register(new DreamSleeper()); + public final CustomEnchantment VAMPIRISM = register(new Vampirism()); + @Override public void bootstrap(BootstrapContext context) { context.getLifecycleManager().registerEventHandler(RegistryEvents.ENCHANTMENT.compose() From 7ce14351d2f52efa59e42d0d4315280bd9000fab Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 4 Jul 2026 22:51:23 +0200 Subject: [PATCH 03/20] feat: add Loot Tables --- .../loottable/BloodyMobLootTable.java | 37 +++++++++++++++++++ .../contents/loottable/VampireLootTable.java | 37 +++++++++++++++++++ .../registry/items/CustomItemRegistry.java | 2 + .../loottable/CustomLootTableRegistry.java | 6 ++- .../registry/loottable/loots/ItemLoot.java | 10 +++++ .../contents/omc_daily_events/head.yml | 5 +++ .../omc_daily_events/nbt/head/vampire.json | 12 ++++++ .../default/dailyevents.properties | 5 ++- 8 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/BloodyMobLootTable.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/VampireLootTable.java create mode 100644 src/main/resources/contents/omc_daily_events/nbt/head/vampire.json diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/BloodyMobLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/BloodyMobLootTable.java new file mode 100644 index 000000000..bff68b171 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/BloodyMobLootTable.java @@ -0,0 +1,37 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable; + +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import org.bukkit.Material; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public class BloodyMobLootTable extends CustomLootTable { + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.bloody_mob"); + } + + @Override + public String getNamespace() { + return "omc_daily_events:bloody_mobs"; + } + + @Override + public Set getLoots() { + return new LinkedHashSet<>(List.of( + new ItemLoot(Material.IRON_INGOT,0.3, 1, 5), + new ItemLoot(Material.GOLD_INGOT,0.2, 2, 4), + new ItemLoot(Material.DIAMOND,0.1, 1, 2), + new ItemLoot(Material.IRON_BLOCK,0.08, 1, 2), + new ItemLoot(Material.GOLD_BLOCK,0.06, 1, 2), + new ItemLoot(Material.DIAMOND_BLOCK,0.03, 1), + new ItemLoot(Material.NETHERITE_INGOT,0.004, 1) + )); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/VampireLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/VampireLootTable.java new file mode 100644 index 000000000..427ba492f --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/VampireLootTable.java @@ -0,0 +1,37 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.loottable.CustomLootTable; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public class VampireLootTable extends CustomLootTable { + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.vampire_boss"); + } + + @Override + public String getNamespace() { + return "omc_daily_events.vampire_boss"; + } + + @Override + public Set getLoots() { + return new LinkedHashSet<>(List.of( + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK,1, 1, 5), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.VAMPIRE_HEAD,0.25, 1), + new ItemLoot( + OMCRegistry.CUSTOM_ENCHANTS.VAMPIRISM.getEnchantedBookItem(1, 3), + 0.1, + 1 + ) + )); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java index f96d58213..200175764 100644 --- a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java +++ b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java @@ -127,6 +127,8 @@ public class CustomItemRegistry extends Registry implements public final CustomItem POISSON_STEVE_HEAD = register("omc_daily_events:poisson_steve_head", Material.PLAYER_HEAD); public final CustomItem KRAKEN_HEAD = register("omc_daily_events:kraken_head", Material.PLAYER_HEAD); public final CustomItem LEVIATHAN_HEAD = register("omc_daily_events:leviathan_head", Material.PLAYER_HEAD); + public final CustomItem VAMPIRE_HEAD = register("omc_daily_events:vampire_head", Material.PLAYER_HEAD); + @Override diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java index 2b6797b86..092e79273 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java @@ -2,6 +2,8 @@ import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.BloodyMobLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.VampireLootTable; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing.BasicFishLootTable; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing.MiraculousFishLootTable; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.loottable.fishing.SeaCreatureLootTable; @@ -19,12 +21,14 @@ public class CustomLootTableRegistry extends Registry i public final CustomLootTable MIRACULOUS_FISHING = register(new MiraculousFishLootTable()); public final CustomLootTable BASIC_FISHING = register(new BasicFishLootTable()); public final CustomLootTable SEA_CREATURE = register(new SeaCreatureLootTable()); - public final CustomLootTable FISHING_FURNITURE = register(new FishingFurnitureLootTable()); public final CustomLootTable RARE_FISHING_TREASURE = register(new RareFishingTreasureLootTable()); public final CustomLootTable EPIC_FISHING_TREASURE = register(new EpicFishingTreasureLootTable()); public final CustomLootTable LEGENDARY_FISHING_TREASURE = register(new LegendaryFishingTreasureLootTable()); + public final CustomLootTable VAMPIRE = register(new VampireLootTable()); + public final CustomLootTable BLOODY_MOB = register(new BloodyMobLootTable()); + @Override public String key(CustomLootTable registryObject) { return registryObject.getNamespace(); diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java index 014003291..04bd03a5e 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/ItemLoot.java @@ -60,6 +60,16 @@ public ItemLoot(Material item, double chance, int minAmount, int maxAmount) { maxAmount); } + public ItemLoot(Material item, double chance, int amount) { + if (item == null) { + throw new IllegalArgumentException("CustomItem cannot be null"); + } + this(Collections.singleton(ItemStack.of(item)), + null, + chance, + amount, + amount); + } public ItemLoot(CustomItem item, double chance, int amount) { if (item == null) { throw new IllegalArgumentException("CustomItem cannot be null"); diff --git a/src/main/resources/contents/omc_daily_events/head.yml b/src/main/resources/contents/omc_daily_events/head.yml index 53b204b82..90d141995 100644 --- a/src/main/resources/contents/omc_daily_events/head.yml +++ b/src/main/resources/contents/omc_daily_events/head.yml @@ -41,4 +41,9 @@ items: leviathan_head: display_name: "Tete de Léviathan" components_nbt_file: "nbt/head/leviathan.json" + material: PLAYER_HEAD + + vampire_head: + display_name: "Tete de Vampire" + components_nbt_file: "nbt/head/vampire.json" material: PLAYER_HEAD \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events/nbt/head/vampire.json b/src/main/resources/contents/omc_daily_events/nbt/head/vampire.json new file mode 100644 index 000000000..616087460 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events/nbt/head/vampire.json @@ -0,0 +1,12 @@ +{ + "components": { + "profile": { + "properties": [ + { + "name": "textures", + "value": "e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTdkOWFkNzk1NzdkYTBkMjY3MTlmNTljNGY0NDlkOTBjZGVhYjM5ZTcwMDk1ZTQ2NWI5ZWNhYWJmMjZjYmY3MSJ9fX0=\"}]},minecraft:lore=['{\"text\":\"https://namemc.com/skin/efaad3c14fefec0c" + } + ] + } + } +} \ No newline at end of file diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 958976f58..ea139460a 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -102,4 +102,7 @@ feature.dailyevents.miraculousfishing.menu.info.loot_table.lore=CLIQUEZ ICI POUR VOIR LES ITEMS PECHABLE # ** Nuit sanglante ** -feature.dailyevents.bloody_night.loot_table.bloody_mob=Loots des monstres sanglants \ No newline at end of file +feature.dailyevents.bloody_night.loot_table.bloody_mob=Loots des monstres sanglants +feature.dailyevents.bloody_night.loot_table.vampire_boss=Loots du Vampire + +feature.dailyevents.bloody_night.enchantment.vampirism.name=Vampirisme \ No newline at end of file From 76dfb853102f0f47dea2bc6cb753d63e6f62295f Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sun, 5 Jul 2026 11:46:58 +0200 Subject: [PATCH 04/20] fix: modifier already applied --- .../contents/bloodynight/contents/enchantments/Vampirism.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java index 83ff1f7d2..cb9631ec3 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java @@ -89,6 +89,8 @@ public void onAttack(EntityDamageByEntityEvent event) { AttributeInstance maxHealthAttr = player.getAttribute(Attribute.MAX_HEALTH); if (maxHealthAttr == null) return; + if (maxHealthAttr.getModifier(MAX_HEALTH_MODIFIER_KEY) != null) return; + maxHealthAttr.addModifier(new AttributeModifier( MAX_HEALTH_MODIFIER_KEY, max - maxHealthAttr.getValue(), From ecd11ff01f3e677d007e292e7229e187684fb13e Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sun, 5 Jul 2026 16:50:29 +0200 Subject: [PATCH 05/20] feat: commit, a commit, move ambient, add base of bloody night --- .../dailyevents/DailyEventsManager.java | 13 +++ .../bloodynight/BloodyNightEvent.java | 23 +++-- .../bloodynight/BloodyNightManager.java | 89 +++++++++++++++++++ .../contents/ambient}/BloodyAmbient.java | 3 +- .../listeners/MonsterSpawnLIstener.java | 26 ++++++ .../listeners/PlayerKillMonsterListener.java | 42 +++++++++ .../contents/ambient}/GoldenAmbient.java | 2 +- .../contents/ambient}/BlessedAmbient.java | 2 +- .../ambient/CustomAmbientRegistry.java | 6 +- .../openmc/core/utils/bukkit/EntityUtils.java | 45 +++++++++- 10 files changed, 239 insertions(+), 12 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java rename src/main/java/fr/openmc/core/{registry/ambient/contents => features/events/contents/dailyevents/contents/bloodynight/contents/ambient}/BloodyAmbient.java (95%) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/PlayerKillMonsterListener.java rename src/main/java/fr/openmc/core/{registry/ambient/contents => features/events/contents/dailyevents/contents/goldenharvest/contents/ambient}/GoldenAmbient.java (96%) rename src/main/java/fr/openmc/core/{registry/ambient/contents => features/events/contents/dailyevents/contents/miraculousfishing/contents/ambient}/BlessedAmbient.java (96%) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 4d687a83f..2f74bef2b 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -29,6 +29,7 @@ import java.sql.SQLException; import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -231,4 +232,16 @@ public static DailyEvent getDailyEvent(String id) { .findFirst() .orElse(null); } + + /** + * Permet d'obtenir le temps restant d'un evenement journalier en secondes + * @param event l'event + * @return le temps restant en secondes + */ + public static double getRemainingTime(DailyEvent event) { + if (!isActiveDailyEvent()) return -1; + if (getActiveDailyEvent() != event) return -1; + + return outgoingEvent.getScheduledStartDate().until(DateUtils.getLocalDateTime(), ChronoUnit.SECONDS); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java index c246af449..19b56c982 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightEvent.java @@ -1,6 +1,9 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; import fr.openmc.core.OMCRegistry; +import fr.openmc.core.bootstrap.features.types.HasListeners; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners.MonsterSpawnLIstener; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners.PlayerKillMonsterListener; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.DailyEvent; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasAmbient; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasBroadcast; @@ -11,11 +14,13 @@ import net.kyori.adventure.text.Component; import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; +import org.bukkit.event.Listener; import org.bukkit.inventory.ItemStack; import java.util.List; +import java.util.Set; -public class BloodyNightEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast { +public class BloodyNightEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast, HasListeners { @Override public String getEventId() { return "bloody_night"; @@ -33,16 +38,12 @@ public int getDuration() { @Override public Runnable onStart() { - return () -> { - System.out.println("BLOODY NIGHT START"); - }; + return () -> BloodyNightManager.start(this); } @Override public Runnable onEnd() { - return () -> { - System.out.println("BLOODY NIGHT END"); - }; + return () -> BloodyNightManager.stop(this); } @Override @@ -92,4 +93,12 @@ public Component getStartBroadcast() { public Component getEndBroadcast() { return TranslationManager.translation("feature.dailyevents.bloodynight.broadcast.end"); } + + @Override + public Set getListeners() { + return Set.of( + new PlayerKillMonsterListener(), + new MonsterSpawnLIstener() + ); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java new file mode 100644 index 000000000..a49ced1ff --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java @@ -0,0 +1,89 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; + +import fr.openmc.core.utils.bukkit.EntityUtils; +import org.bukkit.Bukkit; +import org.bukkit.GameRules; +import org.bukkit.NamespacedKey; +import org.bukkit.World; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; + +public class BloodyNightManager { + private static final AttributeModifier BLOODY_HEALTH_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "bloody_health"), + 0.75, + AttributeModifier.Operation.ADD_SCALAR + ); + private static final AttributeModifier BLOODY_ATTACK_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "bloody_attack"), + 0.10, + AttributeModifier.Operation.ADD_SCALAR + ); + private static final AttributeModifier BLOODY_SPEED_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "bloody_speed"), + 0.10, + AttributeModifier.Operation.ADD_SCALAR + ); + private static final AttributeModifier BLOODY_FOLLOW_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "bloody_follow"), + 0.10, + AttributeModifier.Operation.ADD_SCALAR + ); + + public static void start(BloodyNightEvent event) { + World world = Bukkit.getWorld(event.getWorldEvent()); + if (world == null) return; + + boostMonsters(world); + world.setGameRule(GameRules.NATURAL_HEALTH_REGENERATION, false); + } + + public static void stop(BloodyNightEvent event) { + World world = Bukkit.getWorld(event.getWorldEvent()); + if (world == null) return; + + desactivateBloodyMonsters(world); + world.setGameRule(GameRules.NATURAL_HEALTH_REGENERATION, true); + } + + /** + * Boost touts les monstres présent dans le monde + * @param world le monde où se passe la blood moon + */ + private static void boostMonsters(World world) { + for (Entity entity : world.getEntities()) { + if (!(entity instanceof Monster monster)) continue; + + boostMonster(monster); + } + } + + /** + * Boost le monstre + * - Vie x1.75 + * - Dégâts +10 % + * - Vitesse +10 % + * - Détection +30 % + * @param entity l'entité à boost + */ + public static void boostMonster(LivingEntity entity) { + EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, BLOODY_HEALTH_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, BLOODY_ATTACK_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, BLOODY_SPEED_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, BLOODY_FOLLOW_MODIFIER); + } + + private static void desactivateBloodyMonsters(World world) { + for (Entity entity : world.getEntities()) { + if (!(entity instanceof Monster monster)) continue; + + EntityUtils.removeModifierIfPresent(monster, Attribute.MAX_HEALTH, BLOODY_HEALTH_MODIFIER); + EntityUtils.removeModifierIfPresent(monster, Attribute.ATTACK_DAMAGE, BLOODY_ATTACK_MODIFIER); + EntityUtils.removeModifierIfPresent(monster, Attribute.MOVEMENT_SPEED, BLOODY_SPEED_MODIFIER); + EntityUtils.removeModifierIfPresent(monster, Attribute.FOLLOW_RANGE, BLOODY_FOLLOW_MODIFIER); + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java similarity index 95% rename from src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java index dde6dc0e4..baa589a98 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BloodyAmbient.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java @@ -1,4 +1,4 @@ -package fr.openmc.core.registry.ambient.contents; +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.ambient; import fr.openmc.api.datapacks.builders.BiomeBuilder; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; @@ -12,6 +12,7 @@ import net.minecraft.world.level.dimension.DimensionType; import org.bukkit.Particle; +// todo: tester fixed time qd on dort / qd on change de time public class BloodyAmbient extends CustomAmbient { @Override public String getId() { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java new file mode 100644 index 000000000..e11f59ae2 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java @@ -0,0 +1,26 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners; + +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightManager; +import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.Particle; +import org.bukkit.entity.Monster; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntitySpawnEvent; + +public class MonsterSpawnLIstener implements Listener { + @EventHandler + public void onMonsterSpawn(EntitySpawnEvent event) { + if (!DailyEventsManager.isActiveDailyEvent() + || !(DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent)) return; + if (!(event.getEntity() instanceof Monster monster)) return; + + ParticleUtils.spawnDispersingParticles(event.getLocation(), + Particle.DAMAGE_INDICATOR, + 10, 35, 0.1D, null); + + BloodyNightManager.boostMonster(monster); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/PlayerKillMonsterListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/PlayerKillMonsterListener.java new file mode 100644 index 000000000..7685dd897 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/PlayerKillMonsterListener.java @@ -0,0 +1,42 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; +import fr.openmc.core.registry.loottable.loots.CustomLoot; +import fr.openmc.core.registry.loottable.loots.ItemLoot; +import fr.openmc.core.utils.RandomUtils; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class PlayerKillMonsterListener implements Listener { + + @EventHandler + public void onPlayerKill(EntityDeathEvent event) { + if (!DailyEventsManager.isActiveDailyEvent() + || !(DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent)) return; + if (event.getEntity().getKiller() == null) return; + if (!(event.getEntity() instanceof Monster)) return; + if (!(event.getDamageSource().getDirectEntity() instanceof Player player)) return; + + event.getDrops().clear(); + + List loots = OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLootsWithAmount( + player, RandomUtils.randomBetween(1, 2)); + + event.getDrops().clear(); + for (CustomLoot loot : loots) { + if (!(loot instanceof ItemLoot itemLoot)) continue; + + for (ItemStack item : itemLoot.getItems()) { + event.getDrops().add(item); + } + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/contents/ambient/GoldenAmbient.java similarity index 96% rename from src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/contents/ambient/GoldenAmbient.java index 72173ff22..acfdf967c 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/GoldenAmbient.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/goldenharvest/contents/ambient/GoldenAmbient.java @@ -1,4 +1,4 @@ -package fr.openmc.core.registry.ambient.contents; +package fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.contents.ambient; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.api.datapacks.builders.sounds.AmbientSoundBuilder; diff --git a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/ambient/BlessedAmbient.java similarity index 96% rename from src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/ambient/BlessedAmbient.java index 017d0899a..3e218cb47 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/contents/BlessedAmbient.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/ambient/BlessedAmbient.java @@ -1,4 +1,4 @@ -package fr.openmc.core.registry.ambient.contents; +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.ambient; import fr.openmc.api.datapacks.builders.EnvironnementAttributeBuilder; import fr.openmc.api.datapacks.builders.sounds.AmbientSoundBuilder; diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java index 01243c4fa..0eaeafc1d 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbientRegistry.java @@ -5,7 +5,11 @@ import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; -import fr.openmc.core.registry.ambient.contents.*; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.ambient.BloodyAmbient; +import fr.openmc.core.features.events.contents.dailyevents.contents.goldenharvest.contents.ambient.GoldenAmbient; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.ambient.BlessedAmbient; +import fr.openmc.core.registry.ambient.contents.DarkAmbient; +import fr.openmc.core.registry.ambient.contents.HellAmbient; import io.papermc.paper.plugin.bootstrap.BootstrapContext; import net.minecraft.core.registries.Registries; import net.minecraft.server.MinecraftServer; diff --git a/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java b/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java index c32354f7f..5e0eb7838 100644 --- a/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java +++ b/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java @@ -1,13 +1,15 @@ package fr.openmc.core.utils.bukkit; +import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; +import org.bukkit.attribute.AttributeModifier; import org.bukkit.entity.LivingEntity; public class EntityUtils { /** * Ajoute un attribut si l'AttributeInstance n'est pas nulle - * @param entity l'entity + * @param entity l'entité * @param attribute l'attribut qui veut etre mis * @param value la valeur appliquée a l'attribut */ @@ -17,4 +19,45 @@ public static void setAttributeIfPresent(LivingEntity entity, Attribute attribut attr.setBaseValue(value); } } + + /** + * Ajoute un attribut si l'AttributeInstance n'est pas nulle + * @param entity l'entité + * @param attribute l'attribut qui veut etre mis + * @param modifier le modifier appliqué sur la stats de l'entité + */ + public static void addModifierIfPresent(LivingEntity entity, Attribute attribute, AttributeModifier modifier) { + AttributeInstance attr = entity.getAttribute(attribute); + if (attr == null) return; + attr.addModifier(modifier); + } + + /** + * Supprime un modifier si l'AttributeInstance n'est pas nulle et que le modifier est présent + * @param entity l'entité + * @param attribute l'attribut qui est ciblé + * @param modifier le modifier + */ + public static void removeModifierIfPresent(LivingEntity entity, Attribute attribute, AttributeModifier modifier) { + AttributeInstance attr = entity.getAttribute(attribute); + if (attr == null) return; + NamespacedKey modifierKey = modifier.getKey(); + if (attr.getModifier(modifierKey) == null) return; + + attr.removeModifier(modifierKey); + } + + /** + * Supprime un modifier si l'AttributeInstance n'est pas nulle et que le modifier est présent + * @param entity l'entité + * @param attribute l'attribut qui est ciblé + * @param modifierKey la cle du modifier + */ + public static void removeModifierIfPresent(LivingEntity entity, Attribute attribute, NamespacedKey modifierKey) { + AttributeInstance attr = entity.getAttribute(attribute); + if (attr == null) return; + if (attr.getModifier(modifierKey) == null) return; + + attr.removeModifier(modifierKey); + } } From cb38abcf29d484a03edd3a2d5c3840d852f4a66b Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:51:42 +0200 Subject: [PATCH 06/20] feat: base of raids and types of bloody mobs --- .../bloodynight/BloodyNightManager.java | 131 ++++++++++++------ .../bloodynight/BloodyNightRaidManager.java | 66 +++++++++ .../contents/mobs/AncientMonster.java | 69 +++++++++ .../contents/mobs/CorruptedMonster.java | 69 +++++++++ .../contents/mobs/CursedMonster.java | 76 ++++++++++ .../contents/mobs/EnragedMonster.java | 68 +++++++++ .../listeners/MonsterSpawnLIstener.java | 16 ++- .../listeners/PlayerFishListener.java | 2 +- .../registry/loottable/CustomLootTable.java | 34 ++++- .../registry/loottable/loots/TableLoot.java | 5 +- .../openmc/core/registry/mobs/CustomMob.java | 22 ++- .../core/registry/mobs/CustomMobRegistry.java | 24 ++++ .../openmc/core/utils/nms/EntityGlowNMS.java | 74 ++++++++++ 13 files changed, 594 insertions(+), 62 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightRaidManager.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java create mode 100644 src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java index a49ced1ff..b968c284c 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java @@ -1,43 +1,45 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; -import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.AncientMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.CorruptedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.CursedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.EnragedMonster; import org.bukkit.Bukkit; import org.bukkit.GameRules; import org.bukkit.NamespacedKey; import org.bukkit.World; -import org.bukkit.attribute.Attribute; -import org.bukkit.attribute.AttributeModifier; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Monster; +import org.bukkit.scheduler.BukkitTask; +import java.util.concurrent.ThreadLocalRandom; + +// todo: tester si les mobs non chargé sont bien converti en monstre buffé +// todo: inverse aussi si les buffé disparaiseent bien +// todo: faire boss vampire (abilité chauve souris explosante, empoissonante, ...) public class BloodyNightManager { - private static final AttributeModifier BLOODY_HEALTH_MODIFIER = new AttributeModifier( - new NamespacedKey("omc_daily_events", "bloody_health"), - 0.75, - AttributeModifier.Operation.ADD_SCALAR - ); - private static final AttributeModifier BLOODY_ATTACK_MODIFIER = new AttributeModifier( - new NamespacedKey("omc_daily_events", "bloody_attack"), - 0.10, - AttributeModifier.Operation.ADD_SCALAR - ); - private static final AttributeModifier BLOODY_SPEED_MODIFIER = new AttributeModifier( - new NamespacedKey("omc_daily_events", "bloody_speed"), - 0.10, - AttributeModifier.Operation.ADD_SCALAR - ); - private static final AttributeModifier BLOODY_FOLLOW_MODIFIER = new AttributeModifier( - new NamespacedKey("omc_daily_events", "bloody_follow"), - 0.10, - AttributeModifier.Operation.ADD_SCALAR - ); + public static final NamespacedKey RAID_MONSTER_KEY = new NamespacedKey("omc_daily_events", "raid_monster"); + private static BukkitTask raidTask; public static void start(BloodyNightEvent event) { World world = Bukkit.getWorld(event.getWorldEvent()); if (world == null) return; - boostMonsters(world); + // * Programmation des raids + raidTask = Bukkit.getScheduler().runTaskTimer( + OMCPlugin.getInstance(), + () -> BloodyNightRaidManager.startRaid(world), + 20L * 10, + 20L * 60L * 2 // 2 min + ); + + // * Modification des monstres déjà présent dans le monde (uniquement ceux chargé) + applyCorruptedMonsters(world); + + // * Gamerules personalisée world.setGameRule(GameRules.NATURAL_HEALTH_REGENERATION, false); } @@ -45,45 +47,86 @@ public static void stop(BloodyNightEvent event) { World world = Bukkit.getWorld(event.getWorldEvent()); if (world == null) return; - desactivateBloodyMonsters(world); + // * Fin des raids + if (raidTask != null) { + raidTask.cancel(); + raidTask = null; + } + + // * Supression des monstres devant etre supprimé (ex ceux qui vient des raids) + deleteMonstersToRemove(world); + + // * Modification des monstres déjà présent dans le monde (uniquement ceux chargé) + desactivateCorruptedMonsters(world); + + // * Gamerules personalisée world.setGameRule(GameRules.NATURAL_HEALTH_REGENERATION, true); } /** - * Boost touts les monstres présent dans le monde - * @param world le monde où se passe la blood moon + * Désactive les mobs chargé dans le monde et les remet à leur état normal + * @param world le monde ciblé par la nuit sanglante */ - private static void boostMonsters(World world) { + private static void desactivateCorruptedMonsters(World world) { for (Entity entity : world.getEntities()) { if (!(entity instanceof Monster monster)) continue; - boostMonster(monster); + if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CorruptedMonster corruptedMonster) { + corruptedMonster.resetToDefault(monster); + } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CursedMonster cursedMonster) { + cursedMonster.resetToDefault(monster); + } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof EnragedMonster enragedMonster) { + enragedMonster.resetToDefault(monster); + } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof AncientMonster ancientMonster) { + ancientMonster.resetToDefault(monster); + } } } /** - * Boost le monstre - * - Vie x1.75 - * - Dégâts +10 % - * - Vitesse +10 % - * - Détection +30 % + * Supprime tout les monstres spawné par les raids + * @param world le monde ciblé par la nuit sanglante + */ + private static void deleteMonstersToRemove(World world) { + for (Entity entity : world.getEntities()) { + if (!(entity instanceof Monster monster)) continue; + if (!(entity.getPersistentDataContainer().has(RAID_MONSTER_KEY))) continue; + + monster.remove(); + } + } + + /** + * Applique l'effet bloody sur un monstre + * - Corrompu - 60% + * - Enragé - 30% + * - Maudit - 15% + * - Ancien - 5% * @param entity l'entité à boost */ - public static void boostMonster(LivingEntity entity) { - EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, BLOODY_HEALTH_MODIFIER); - EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, BLOODY_ATTACK_MODIFIER); - EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, BLOODY_SPEED_MODIFIER); - EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, BLOODY_FOLLOW_MODIFIER); + public static void applyBloodyMonster(LivingEntity entity) { + double random = ThreadLocalRandom.current().nextDouble(); + + if (random < 0.60) { + OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(entity); + } else if (random < 0.90) { + OMCRegistry.CUSTOM_MOBS.ENRAGED_MONSTER.apply(entity); + } else if (random < 0.95) { + OMCRegistry.CUSTOM_MOBS.CURSED_MONSTER.apply(entity); + } else { + OMCRegistry.CUSTOM_MOBS.ANCIENT_MONSTER.apply(entity); + } } - private static void desactivateBloodyMonsters(World world) { + /** + * Boost touts les monstres présent dans le monde + * @param world le monde où se passe la blood moon + */ + private static void applyCorruptedMonsters(World world) { for (Entity entity : world.getEntities()) { if (!(entity instanceof Monster monster)) continue; - EntityUtils.removeModifierIfPresent(monster, Attribute.MAX_HEALTH, BLOODY_HEALTH_MODIFIER); - EntityUtils.removeModifierIfPresent(monster, Attribute.ATTACK_DAMAGE, BLOODY_ATTACK_MODIFIER); - EntityUtils.removeModifierIfPresent(monster, Attribute.MOVEMENT_SPEED, BLOODY_SPEED_MODIFIER); - EntityUtils.removeModifierIfPresent(monster, Attribute.FOLLOW_RANGE, BLOODY_FOLLOW_MODIFIER); + OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(monster); } } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightRaidManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightRaidManager.java new file mode 100644 index 000000000..cbd5535f7 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightRaidManager.java @@ -0,0 +1,66 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; + +import fr.openmc.core.utils.world.LocationUtils; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.persistence.PersistentDataType; + +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class BloodyNightRaidManager { + + private static final int MIN_MOBS_PER_RAID = 7; + private static final int MAX_MOBS_PER_RAID = 14; + + private static final int MAX_SPAWN_RADIUS = 20; + + private static final List BLOODY_MONSTERS_AVAILABLE = List.of( + EntityType.ZOMBIE, + EntityType.SKELETON, + EntityType.SPIDER, + EntityType.CREEPER, + EntityType.HUSK, + EntityType.STRAY + ); + + public static void startRaid(World world) { + for (Player player : world.getPlayers()) { + if (player.getGameMode() == GameMode.SPECTATOR || + player.getGameMode() == GameMode.CREATIVE) continue; + if (player.isDead()) continue; + + spawnRaidAroundPlayer(player); + } + } + + private static void spawnRaidAroundPlayer(Player player) { + World world = player.getWorld(); + + int mobAmount = ThreadLocalRandom.current().nextInt( + MIN_MOBS_PER_RAID, + MAX_MOBS_PER_RAID + 1 + ); + + for (int i = 0; i < mobAmount; i++) { + Location spawnLocation = LocationUtils.getSafeNearbySurface(player.getLocation(), MAX_SPAWN_RADIUS); + + world.strikeLightningEffect(spawnLocation); + spawnRandomMonster(spawnLocation); + } + } + + private static void spawnRandomMonster(Location location) { + EntityType type = getRandomRaidMonsterType(); + Entity entity = location.getWorld().spawnEntity(location, type); + entity.getPersistentDataContainer().set(BloodyNightManager.RAID_MONSTER_KEY, PersistentDataType.BOOLEAN, true); + } + + private static EntityType getRandomRaidMonsterType() { + return BLOODY_MONSTERS_AVAILABLE.get(ThreadLocalRandom.current().nextInt(BLOODY_MONSTERS_AVAILABLE.size())); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java new file mode 100644 index 000000000..3f161509b --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java @@ -0,0 +1,69 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.utils.bukkit.EntityUtils; +import org.bukkit.NamespacedKey; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Monster; + +public class AncientMonster extends CustomMob { + private static final AttributeModifier HEALTH_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "ancient_health"), + 3.00, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "ancient_attack"), + 0.60, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "ancient_speed"), + 0.20, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "ancient_follow"), + 0.60, + AttributeModifier.Operation.ADD_SCALAR + ); + + public AncientMonster(String id) { + super( + id, + "Ancient", + Monster.class, + 3, + 1, + OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + ); + } + + @Override + public void apply(Monster entity) { + registerAsCustomMob(entity); + + entity.setCustomNameVisible(false); + + EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + } + + public void resetToDefault(Monster entity) { + unregisterAsCustomMob(entity); + + entity.setCustomNameVisible(true); + + EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java new file mode 100644 index 000000000..17b27e4ea --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java @@ -0,0 +1,69 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.nms.EntityGlowNMS; +import net.minecraft.ChatFormatting; +import org.bukkit.NamespacedKey; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Monster; + +public class CorruptedMonster extends CustomMob { + private static final AttributeModifier HEALTH_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "corrupted_health"), + 0.75, + AttributeModifier.Operation.ADD_SCALAR + ); + private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "corrupted_attack"), + 0.10, + AttributeModifier.Operation.ADD_SCALAR + ); + private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "corrupted_speed"), + 0.10, + AttributeModifier.Operation.ADD_SCALAR + ); + private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "corrupted_follow"), + 0.10, + AttributeModifier.Operation.ADD_SCALAR + ); + + public CorruptedMonster(String id) { + super(id, + "Corrupted", + Monster.class, + 1, + 1, + OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + ); + } + + @Override + public void apply(Monster entity) { + registerAsCustomMob(entity); + + entity.setCustomNameVisible(false); + + EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + + EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_RED); + } + + public void resetToDefault(Monster entity) { + unregisterAsCustomMob(entity); + + entity.setCustomNameVisible(true); + + EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java new file mode 100644 index 000000000..295e6a01e --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java @@ -0,0 +1,76 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.utils.bukkit.EntityUtils; +import org.bukkit.NamespacedKey; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Monster; + +public class CursedMonster extends CustomMob { + private static final AttributeModifier HEALTH_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "cursed_health"), + 1.75, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "cursed_attack"), + 0.25, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "cursed_speed"), + -0.15, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "cursed_follow"), + 0.20, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier SCALE_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "cursed_scale"), + 0.40, + AttributeModifier.Operation.ADD_SCALAR + ); + + public CursedMonster(String id) { + super(id, + "Cursed", + Monster.class, + 1, + 1, + OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + ); + } + + @Override + public void apply(Monster entity) { + registerAsCustomMob(entity); + + entity.setCustomNameVisible(false); + + EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); + } + + public void resetToDefault(Monster entity) { + unregisterAsCustomMob(entity); + + entity.setCustomNameVisible(true); + + EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java new file mode 100644 index 000000000..f7041d90e --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java @@ -0,0 +1,68 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.utils.bukkit.EntityUtils; +import org.bukkit.NamespacedKey; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Monster; + +public class EnragedMonster extends CustomMob { + private static final AttributeModifier HEALTH_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "enraged_health"), + 0.25, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "enraged_attack"), + 0.35, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "enraged_speed"), + 0.35, + AttributeModifier.Operation.ADD_SCALAR + ); + + private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( + new NamespacedKey("omc_daily_events", "enraged_follow"), + 0.30, + AttributeModifier.Operation.ADD_SCALAR + ); + + public EnragedMonster(String id) { + super(id, + "Enraged", + Monster.class, + 1, + 1, + OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + ); + } + + @Override + public void apply(Monster entity) { + registerAsCustomMob(entity); + + entity.setCustomNameVisible(false); + + EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + } + + public void resetToDefault(Monster entity) { + unregisterAsCustomMob(entity); + + entity.setCustomNameVisible(true); + + EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); + EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java index e11f59ae2..4ce3a9e8e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java @@ -1,5 +1,6 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightManager; @@ -12,15 +13,26 @@ public class MonsterSpawnLIstener implements Listener { @EventHandler - public void onMonsterSpawn(EntitySpawnEvent event) { + public void onNormalMonsterSpawn(EntitySpawnEvent event) { if (!DailyEventsManager.isActiveDailyEvent() || !(DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent)) return; if (!(event.getEntity() instanceof Monster monster)) return; + if (monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) return; ParticleUtils.spawnDispersingParticles(event.getLocation(), Particle.DAMAGE_INDICATOR, 10, 35, 0.1D, null); - BloodyNightManager.boostMonster(monster); + OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(monster); + } + + @EventHandler + public void onRaidMonsterSpawn(EntitySpawnEvent event) { + if (!DailyEventsManager.isActiveDailyEvent() + || !(DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent)) return; + if (!(event.getEntity() instanceof Monster monster)) return; + if (!(monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY))) return; + + BloodyNightManager.applyBloodyMonster(monster); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java index 8d42c7a71..a9e7edc79 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/listeners/PlayerFishListener.java @@ -59,7 +59,7 @@ public void onStartFishing(PlayerFishEvent event) { CustomLootTable fishingLootTable = OMCRegistry.CUSTOM_LOOT_TABLES.MIRACULOUS_FISHING; - List loots = fishingLootTable.rollLoots(player, false); + List loots = fishingLootTable.rollLoots(); List finalLoots = FishingAttributeManager.applyDoubleHookChance(player, loots); diff --git a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java index cb042adf0..fc9ea0db9 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTable.java @@ -29,7 +29,7 @@ public double getChanceOf(ItemStack item) { .sum(); } - public List rollLoots(Player receiver, boolean giveLoots) { + public List rollLoots(Player receiver) { List result = new ArrayList<>(); double totalChance = this.getLoots().stream() @@ -42,8 +42,7 @@ public List rollLoots(Player receiver, boolean giveLoots) { for (CustomLoot loot : this.getLoots()) { sumChance += loot.getChance(); if (roll <= sumChance) { - if (giveLoots) - loot.run(receiver); + loot.run(receiver); result.add(loot); break; } @@ -51,16 +50,37 @@ public List rollLoots(Player receiver, boolean giveLoots) { if (result.isEmpty()) { CustomLoot next = this.getLoots().iterator().next(); - if (giveLoots) - next.run(receiver); + next.run(receiver); result.add(next); } return result; } - public List rollLoots(Player receiver) { - return rollLoots(receiver, true); + public List rollLoots() { + List result = new ArrayList<>(); + + double totalChance = this.getLoots().stream() + .mapToDouble(CustomLoot::getChance) + .sum(); + + double roll = Math.random() * totalChance; + double sumChance = 0.0; + + for (CustomLoot loot : this.getLoots()) { + sumChance += loot.getChance(); + if (roll <= sumChance) { + result.add(loot); + break; + } + } + + if (result.isEmpty()) { + CustomLoot next = this.getLoots().iterator().next(); + result.add(next); + } + + return result; } public List rollLootsWithAmount(Player receiver, int amountRoll) { diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java index f5d80c55d..983fd9dc6 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/TableLoot.java @@ -53,6 +53,9 @@ public Component getDisplayText() { @Override public Set run(Player receiver) { - return Set.copyOf(lootTable.rollLoots(receiver, this.giveRewards)); + if (this.giveRewards) + return Set.copyOf(lootTable.rollLoots(receiver)); + else + return Set.copyOf(lootTable.rollLoots()); } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java b/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java index 02e8f72f2..efa1493c3 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java @@ -69,8 +69,8 @@ public T spawn(Location location) { } // * peut etre Override - public void apply(LivingEntity livingEntity) { - applyStats(livingEntity); + public void apply(T entity) { + applyStats(entity); } // * peut etre Override @@ -113,11 +113,7 @@ public void applyStats(LivingEntity livingEntity) { .orElse(livingEntity.getHealth()) ); - livingEntity.getPersistentDataContainer().set( - CustomMobRegistry.CUSTOM_MOB_KEY, - PersistentDataType.STRING, - this.getId() - ); + registerAsCustomMob(livingEntity); } public double getHealth() { @@ -127,4 +123,16 @@ public double getHealth() { .map(CustomMobAttribute::value) .orElse(20.0); } + + public void registerAsCustomMob(LivingEntity entity) { + entity.getPersistentDataContainer().set( + CustomMobRegistry.CUSTOM_MOB_KEY, + PersistentDataType.STRING, + this.getId() + ); + } + + public void unregisterAsCustomMob(LivingEntity entity) { + entity.getPersistentDataContainer().remove(CustomMobRegistry.CUSTOM_MOB_KEY); + } } diff --git a/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java b/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java index 6806d3d08..455b441d5 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java @@ -3,6 +3,10 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.bootstrap.registries.KeyedRegistry; import fr.openmc.core.bootstrap.registries.Registry; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.AncientMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.CorruptedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.CursedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.EnragedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.mobs.*; import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.mobs.kraken.Kraken; import org.bukkit.NamespacedKey; @@ -57,6 +61,26 @@ public class CustomMobRegistry extends Registry implemen GiantElderGuardian::new )); + public final CustomMobEntry ANCIENT_MONSTER = register(new CustomMobEntry( + "omc_daily_events:ancient_monster", + AncientMonster::new + )); + + public final CustomMobEntry CURSED_MONSTER = register(new CustomMobEntry( + "omc_daily_events:cursed_monster", + CursedMonster::new + )); + + public final CustomMobEntry ENRAGED_MONSTER = register(new CustomMobEntry( + "omc_daily_events:enraged_monster", + EnragedMonster::new + )); + + public final CustomMobEntry CORRUPTED_MONSTER = register(new CustomMobEntry( + "omc_daily_events:corrupted_monster", + CorruptedMonster::new + )); + @Override public String key(CustomMobEntry registryObject) { return registryObject.id(); diff --git a/src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java b/src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java new file mode 100644 index 000000000..5da609a34 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java @@ -0,0 +1,74 @@ +package fr.openmc.core.utils.nms; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; +import net.minecraft.world.scores.PlayerTeam; +import net.minecraft.world.scores.Scoreboard; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +public class EntityGlowNMS { + private static final Scoreboard NMS_SCOREBOARD = new Scoreboard(); + + public static void setGlowingColor(Entity entity, ChatFormatting color) { + removeGlowing(entity); + + entity.setGlowing(true); + + String teamName = "omc_glow_" + color.getName(); + PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, teamName); + + team.setColor(color); + team.setSeeFriendlyInvisibles(false); + team.setNameTagVisibility(PlayerTeam.Visibility.NEVER); + + String entry = entity.getUniqueId().toString(); + + ClientboundSetPlayerTeamPacket createPacket = ClientboundSetPlayerTeamPacket.createAddOrModifyPacket( + team, true); + + ClientboundSetPlayerTeamPacket addEntityPacket = ClientboundSetPlayerTeamPacket.createPlayerPacket( + team, + entry, + ClientboundSetPlayerTeamPacket.Action.ADD + ); + + sendPacket(createPacket); + sendPacket(addEntityPacket); + } + + public static void removeGlowing(Entity entity, ChatFormatting color) { + entity.setGlowing(false); + + String teamName = "omc_glow_" + color.getName(); + PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, teamName); + + String entry = entity.getUniqueId().toString(); + + ClientboundSetPlayerTeamPacket removeEntityPacket = ClientboundSetPlayerTeamPacket.createPlayerPacket( + team, + entry, + ClientboundSetPlayerTeamPacket.Action.REMOVE + ); + + sendPacket(removeEntityPacket); + } + + public static void removeGlowing(Entity entity) { + entity.setGlowing(false); + + for (ChatFormatting color : ChatFormatting.values()) { + if (!color.isColor()) continue; + + removeGlowing(entity, color); + } + } + + private static void sendPacket(ClientboundSetPlayerTeamPacket packet) { + for (Player player : Bukkit.getOnlinePlayers()) { + ((CraftPlayer) player).getHandle().connection.send(packet); + } + } +} From a9f995835ac91b4b108ca5102a286e460b576f4d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:57:39 +0200 Subject: [PATCH 07/20] build: fix --- src/main/java/fr/openmc/core/registry/mobs/CustomMobEntry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/registry/mobs/CustomMobEntry.java b/src/main/java/fr/openmc/core/registry/mobs/CustomMobEntry.java index 4d7676298..09e31e030 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMobEntry.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMobEntry.java @@ -16,7 +16,7 @@ public CustomMob getMob() { } public void apply(LivingEntity entity) { - getMob().apply(entity); + ((CustomMob) getMob()).apply(entity); } public Entity spawn(Location spawningLocation) { From a593a8a18c229d0dce7ece098902540f25792f06 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 19:54:18 +0200 Subject: [PATCH 08/20] fix: bug when stop all registry with acces in CustomMobsRegistry --- src/main/java/fr/openmc/core/OMCRegistry.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/fr/openmc/core/OMCRegistry.java b/src/main/java/fr/openmc/core/OMCRegistry.java index 9b439d59e..bd583d680 100644 --- a/src/main/java/fr/openmc/core/OMCRegistry.java +++ b/src/main/java/fr/openmc/core/OMCRegistry.java @@ -13,6 +13,7 @@ import io.papermc.paper.plugin.bootstrap.BootstrapContext; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -26,6 +27,7 @@ public final class OMCRegistry { public static CustomAmbientRegistry CUSTOM_AMBIENTS; public static CustomLootboxRegistry CUSTOM_LOOTBOXES; + private static final List LOADED = new ArrayList<>(); private static final List ALL = List.of( new RegistryContext( @@ -54,7 +56,7 @@ public static void bootstrapAll(BootstrapContext context) { if (Arrays.stream(ctx.loadingTypes()) .noneMatch(t -> t == RegistryLoadingType.BOOTSTRAP)) continue; - LifecycleRegistry r = ctx.registry().get(); + LifecycleRegistry r = load(ctx); try { r.bootstrap(context); } catch (IOException e) { @@ -70,7 +72,7 @@ public static void initAll() { if (Arrays.stream(ctx.loadingTypes()) .noneMatch(t -> t == RegistryLoadingType.RUNTIME)) continue; - LifecycleRegistry r = ctx.registry().get(); + LifecycleRegistry r = load(ctx); r.init(); OMCLogger.successFormatted("Registre {} chargé pendant le runtime", r.getClass().getSimpleName()); } @@ -81,17 +83,23 @@ public static void postInitAll() { if (Arrays.stream(ctx.loadingTypes()) .noneMatch(t -> t == RegistryLoadingType.AFTER_IA)) continue; - LifecycleRegistry r = ctx.registry().get(); + LifecycleRegistry r = load(ctx); r.postInit(); OMCLogger.successFormatted("Registre {} chargé après ItemsAdder", r.getClass().getSimpleName()); } } public static void stopAll() { - for (RegistryContext ctx : OMCRegistry.ALL) { - LifecycleRegistry r = ctx.registry().get(); + for (LifecycleRegistry r : LOADED) { r.stop(); OMCLogger.successFormatted("Registre {} stoppé", r.getClass().getSimpleName()); } + LOADED.clear(); + } + + private static LifecycleRegistry load(RegistryContext ctx) { + LifecycleRegistry registry = ctx.registry().get(); + LOADED.add(registry); + return registry; } -} \ No newline at end of file +} From 7459d76a1443eb611b618bca8e45736e6a9ddb43 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 19:56:14 +0200 Subject: [PATCH 09/20] fix: modifier stay when reload --- .../bloodynight/contents/enchantments/Vampirism.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java index cb9631ec3..44a421113 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/enchantments/Vampirism.java @@ -18,6 +18,7 @@ import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemType; @@ -119,6 +120,16 @@ public void onItemHeldChange(PlayerItemHeldEvent event) { maxHealthAttr.removeModifier(MAX_HEALTH_MODIFIER_KEY); } + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + + AttributeInstance maxHealthAttr = player.getAttribute(Attribute.MAX_HEALTH); + if (maxHealthAttr == null) return; + maxHealthAttr.removeModifier(MAX_HEALTH_MODIFIER_KEY); + + } + /** * Donne 1/8 de vie en fonction des dégâts infligés à l'attaquant. * @param player le joueur ciblé From 3ec7cee9c5f6daf54542ce5678bb93cac3da706a Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 22:35:53 +0200 Subject: [PATCH 10/20] fix: modifier already applied --- .../bloodynight/contents/mobs/CorruptedMonster.java | 2 +- src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java | 6 ++++++ .../openmc/core/utils/nms/{ => entity}/EntityGlowNMS.java | 4 +--- 3 files changed, 8 insertions(+), 4 deletions(-) rename src/main/java/fr/openmc/core/utils/nms/{ => entity}/EntityGlowNMS.java (97%) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java index 17b27e4ea..afde562c9 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java @@ -3,7 +3,7 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; -import fr.openmc.core.utils.nms.EntityGlowNMS; +import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import net.minecraft.ChatFormatting; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; diff --git a/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java b/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java index 5e0eb7838..e2fb0b4ed 100644 --- a/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java +++ b/src/main/java/fr/openmc/core/utils/bukkit/EntityUtils.java @@ -29,6 +29,12 @@ public static void setAttributeIfPresent(LivingEntity entity, Attribute attribut public static void addModifierIfPresent(LivingEntity entity, Attribute attribute, AttributeModifier modifier) { AttributeInstance attr = entity.getAttribute(attribute); if (attr == null) return; + + NamespacedKey modifierKey = modifier.getKey(); + if (attr.getModifier(modifierKey) != null) { + attr.removeModifier(modifierKey); + } + attr.addModifier(modifier); } diff --git a/src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java similarity index 97% rename from src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java rename to src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java index 5da609a34..268fd01d7 100644 --- a/src/main/java/fr/openmc/core/utils/nms/EntityGlowNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java @@ -1,4 +1,4 @@ -package fr.openmc.core.utils.nms; +package fr.openmc.core.utils.nms.entity; import net.minecraft.ChatFormatting; import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; @@ -13,8 +13,6 @@ public class EntityGlowNMS { private static final Scoreboard NMS_SCOREBOARD = new Scoreboard(); public static void setGlowingColor(Entity entity, ChatFormatting color) { - removeGlowing(entity); - entity.setGlowing(true); String teamName = "omc_glow_" + color.getName(); From ce66e6114e5a2ffc0873ee5d4a7cc68b3e0f6b01 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 22:37:41 +0200 Subject: [PATCH 11/20] fix: forget glow color --- .../contents/bloodynight/contents/mobs/AncientMonster.java | 4 ++++ .../contents/bloodynight/contents/mobs/CursedMonster.java | 4 ++++ .../contents/bloodynight/contents/mobs/EnragedMonster.java | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java index 3f161509b..68e849413 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java @@ -3,6 +3,8 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.nms.entity.EntityGlowNMS; +import net.minecraft.ChatFormatting; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -54,6 +56,8 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + + EntityGlowNMS.setGlowingColor(entity, ChatFormatting.YELLOW); } public void resetToDefault(Monster entity) { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java index 295e6a01e..3351464a8 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java @@ -3,6 +3,8 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.nms.entity.EntityGlowNMS; +import net.minecraft.ChatFormatting; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -72,5 +74,7 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); + + EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_PURPLE); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java index f7041d90e..4c9814b60 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java @@ -3,6 +3,8 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.nms.entity.EntityGlowNMS; +import net.minecraft.ChatFormatting; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -53,6 +55,8 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + + EntityGlowNMS.setGlowingColor(entity, ChatFormatting.RED); } public void resetToDefault(Monster entity) { From 549be1adef3186cee6e08c1aa0083a6e53cab99a Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 23:00:32 +0200 Subject: [PATCH 12/20] fix: spam client log "Requested creation of existing team 'omc_glow_dark_red'" --- .../core/utils/nms/entity/EntityGlowNMS.java | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java index 268fd01d7..93983feba 100644 --- a/src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/entity/EntityGlowNMS.java @@ -8,41 +8,50 @@ import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; -public class EntityGlowNMS { +import java.util.HashMap; +import java.util.Map; + +public class EntityGlowNMS implements Listener { private static final Scoreboard NMS_SCOREBOARD = new Scoreboard(); + private static final Map TEAM_MAP = new HashMap<>(); - public static void setGlowingColor(Entity entity, ChatFormatting color) { - entity.setGlowing(true); + public EntityGlowNMS() { + for (ChatFormatting color : ChatFormatting.values()) { + if (!color.isColor()) continue; - String teamName = "omc_glow_" + color.getName(); - PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, teamName); + PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, "omc_glow_" + color.getName()); - team.setColor(color); - team.setSeeFriendlyInvisibles(false); - team.setNameTagVisibility(PlayerTeam.Visibility.NEVER); + team.setColor(color); + team.setSeeFriendlyInvisibles(false); + team.setNameTagVisibility(PlayerTeam.Visibility.NEVER); - String entry = entity.getUniqueId().toString(); + TEAM_MAP.put(color, team); + } + } - ClientboundSetPlayerTeamPacket createPacket = ClientboundSetPlayerTeamPacket.createAddOrModifyPacket( - team, true); + public static void setGlowingColor(Entity entity, ChatFormatting color) { + entity.setGlowing(true); + + PlayerTeam team = TEAM_MAP.get(color); + String entry = entity.getUniqueId().toString(); ClientboundSetPlayerTeamPacket addEntityPacket = ClientboundSetPlayerTeamPacket.createPlayerPacket( team, entry, ClientboundSetPlayerTeamPacket.Action.ADD - ); + ); - sendPacket(createPacket); sendPacket(addEntityPacket); } public static void removeGlowing(Entity entity, ChatFormatting color) { entity.setGlowing(false); - String teamName = "omc_glow_" + color.getName(); - PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, teamName); - + PlayerTeam team = TEAM_MAP.get(color); String entry = entity.getUniqueId().toString(); ClientboundSetPlayerTeamPacket removeEntityPacket = ClientboundSetPlayerTeamPacket.createPlayerPacket( @@ -69,4 +78,16 @@ private static void sendPacket(ClientboundSetPlayerTeamPacket packet) { ((CraftPlayer) player).getHandle().connection.send(packet); } } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + for (ChatFormatting color : ChatFormatting.values()) { + if (!color.isColor()) continue; + + PlayerTeam team = TEAM_MAP.get(color); + if (team == null) continue; + + sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); + } + } } From 31db82c23dc9ab7775aacdd2d422ca6f5e7c8857 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 23:18:15 +0200 Subject: [PATCH 13/20] fix: bloody ambient time bugged when death or time change --- .../contents/ambient/BloodyAmbient.java | 1 - .../listeners/AmbientFixedTimeListener.java | 39 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java index baa589a98..cb8a4492f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/ambient/BloodyAmbient.java @@ -12,7 +12,6 @@ import net.minecraft.world.level.dimension.DimensionType; import org.bukkit.Particle; -// todo: tester fixed time qd on dort / qd on change de time public class BloodyAmbient extends CustomAmbient { @Override public String getId() { diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java new file mode 100644 index 000000000..5fe946f02 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java @@ -0,0 +1,39 @@ +package fr.openmc.core.registry.ambient.listeners; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.ambient.CustomAmbient; +import fr.openmc.core.utils.nms.PlayerSetTimeNMS; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.world.TimeSkipEvent; + +public class AmbientFixedTimeListener implements Listener { + @EventHandler + public void onPlayerKill(PlayerDeathEvent event) { + Player player = event.getPlayer(); + reapplyTime(player); + } + + @EventHandler + public void onTimeChange(TimeSkipEvent event) { + for (Player player : event.getWorld().getPlayers()) { + reapplyTime(player); + } + } + + /** + * Réapplique le temps sur un joueur + * @param player le joueur ciblé + */ + private void reapplyTime(Player player) { + if (!CustomAmbient.ACTIVE_AMBIENTS.containsKey(player.getUniqueId())) return; + + CustomAmbient ambientApplied = OMCRegistry.CUSTOM_AMBIENTS.getOrThrow( + CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId())); + if (ambientApplied.getAmbientBuilder().getTimeFixed() != null) { + PlayerSetTimeNMS.sendPacketSetTime(player, ambientApplied.getAmbientBuilder().getTimeFixed()); + } + } +} From 617f6e9f1ffa84a255ef5ecbdf03e51e9f10fc2d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 7 Jul 2026 23:45:31 +0200 Subject: [PATCH 14/20] fix: blood moon --- .../environment/celestial/moon}/full_moon.png | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/resources/contents/{omc_daily_events/resourcepack.assets.minecraft.textures.environment.celestial.moon => omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon}/full_moon.png (100%) diff --git a/src/main/resources/contents/omc_daily_events/resourcepack.assets.minecraft.textures.environment.celestial.moon/full_moon.png b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/full_moon.png similarity index 100% rename from src/main/resources/contents/omc_daily_events/resourcepack.assets.minecraft.textures.environment.celestial.moon/full_moon.png rename to src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/full_moon.png From 5e2422b7ad2caec3f9c4abeef3304d88a83f6d46 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:27:30 +0200 Subject: [PATCH 15/20] fix: missing listeners --- src/main/java/fr/openmc/core/ListenersManager.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index 2f1db18cc..aac51507c 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -5,10 +5,12 @@ import fr.openmc.core.features.itemsadder.SpawnerExtractorListener; import fr.openmc.core.hooks.itemsadder.ItemsAdderHook; import fr.openmc.core.listeners.*; +import fr.openmc.core.registry.ambient.listeners.AmbientFixedTimeListener; import fr.openmc.core.registry.ambient.listeners.AmbientWeatherListener; import fr.openmc.core.registry.ambient.listeners.BiomesOnChunkLoad; import fr.openmc.core.registry.ambient.listeners.CustomAmbientListener; import fr.openmc.core.registry.mobs.listeners.CustomMobDeathListener; +import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import org.bukkit.Bukkit; import org.bukkit.Server; import org.bukkit.event.Listener; @@ -42,7 +44,9 @@ public static void init() { new BlockBreakListener(), new CustomAmbientListener(), new BiomesOnChunkLoad(), - new AmbientWeatherListener() + new AmbientWeatherListener(), + new AmbientFixedTimeListener(), + new EntityGlowNMS() ); if (!OMCPlugin.isUnitTestVersion()) { From dc09a7aa1d5850e372974a52ea740516c12c44a4 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:07:46 +0200 Subject: [PATCH 16/20] fix: end event on stop server, (+ protection when entities load if bloody night not activate) --- .../dailyevents/DailyEventsManager.java | 4 ++ .../commands/DailyEventCommand.java | 11 ++++++ .../bloodynight/BloodyNightManager.java | 38 +++++++++++++------ .../contents/mobs/AncientMonster.java | 2 + .../contents/mobs/CorruptedMonster.java | 2 + .../contents/mobs/CursedMonster.java | 2 + .../contents/mobs/EnragedMonster.java | 2 + .../listeners/MonsterSpawnLIstener.java | 15 ++++++++ 8 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java index 2f74bef2b..f4e8e88f3 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/DailyEventsManager.java @@ -71,6 +71,10 @@ public void init() { @Override public void save() { + if (outgoingEvent != null) { + outgoingEvent.getDailyEvent().end(); + } + saveIncomingEventsDB(new IncomingEventsDB(incomingEvents)); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java index 655fa44b3..94ae60761 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/commands/DailyEventCommand.java @@ -30,4 +30,15 @@ public static void forceStartCommand(Player player, DailyEventsManager.getDailyEvent(dailyEvent), DateUtils.getLocalDateTime()); DailyEventsManager.outgoingEvent.getDailyEvent().start(); } + + @Subcommand("forceEnd") + @CommandPermission("omc.admins.commands.dailyevent.forceend") + public static void forceEndCommand(Player player) { + if (DailyEventsManager.outgoingEvent != null) { + // * On arrete l'evenement en cours + DailyEventsManager.endEventTask.cancel(); + DailyEventsManager.endEventTask = null; + DailyEventsManager.outgoingEvent.getDailyEvent().end(); + } + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java index b968c284c..04f191e86 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java @@ -23,6 +23,7 @@ public class BloodyNightManager { public static final NamespacedKey RAID_MONSTER_KEY = new NamespacedKey("omc_daily_events", "raid_monster"); private static BukkitTask raidTask; + private static long lastTime; public static void start(BloodyNightEvent event) { World world = Bukkit.getWorld(event.getWorldEvent()); @@ -40,6 +41,9 @@ public static void start(BloodyNightEvent event) { applyCorruptedMonsters(world); // * Gamerules personalisée + lastTime = world.getTime(); + world.setTime(21000); + world.setGameRule(GameRules.ADVANCE_TIME, false); world.setGameRule(GameRules.NATURAL_HEALTH_REGENERATION, false); } @@ -54,12 +58,14 @@ public static void stop(BloodyNightEvent event) { } // * Supression des monstres devant etre supprimé (ex ceux qui vient des raids) - deleteMonstersToRemove(world); + deleteRaidMonsters(world); // * Modification des monstres déjà présent dans le monde (uniquement ceux chargé) desactivateCorruptedMonsters(world); // * Gamerules personalisée + world.setTime(lastTime); + world.setGameRule(GameRules.ADVANCE_TIME, true); world.setGameRule(GameRules.NATURAL_HEALTH_REGENERATION, true); } @@ -69,17 +75,25 @@ public static void stop(BloodyNightEvent event) { */ private static void desactivateCorruptedMonsters(World world) { for (Entity entity : world.getEntities()) { - if (!(entity instanceof Monster monster)) continue; + desactivateCorruptedMonster(entity); + } + } - if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CorruptedMonster corruptedMonster) { - corruptedMonster.resetToDefault(monster); - } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CursedMonster cursedMonster) { - cursedMonster.resetToDefault(monster); - } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof EnragedMonster enragedMonster) { - enragedMonster.resetToDefault(monster); - } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof AncientMonster ancientMonster) { - ancientMonster.resetToDefault(monster); - } + /** + * Désactive le mob et le remet à son état normal + * @param entity l'entité ciblé à désactiver + */ + public static void desactivateCorruptedMonster(Entity entity) { + if (!(entity instanceof Monster monster)) return; + + if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CorruptedMonster corruptedMonster) { + corruptedMonster.resetToDefault(monster); + } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CursedMonster cursedMonster) { + cursedMonster.resetToDefault(monster); + } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof EnragedMonster enragedMonster) { + enragedMonster.resetToDefault(monster); + } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof AncientMonster ancientMonster) { + ancientMonster.resetToDefault(monster); } } @@ -87,7 +101,7 @@ private static void desactivateCorruptedMonsters(World world) { * Supprime tout les monstres spawné par les raids * @param world le monde ciblé par la nuit sanglante */ - private static void deleteMonstersToRemove(World world) { + private static void deleteRaidMonsters(World world) { for (Entity entity : world.getEntities()) { if (!(entity instanceof Monster monster)) continue; if (!(entity.getPersistentDataContainer().has(RAID_MONSTER_KEY))) continue; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java index 68e849413..6f7def833 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java @@ -69,5 +69,7 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + + EntityGlowNMS.removeGlowing(entity, ChatFormatting.YELLOW); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java index afde562c9..64dc51dfe 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java @@ -65,5 +65,7 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + + EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_RED); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java index 3351464a8..8f66f9e9f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java @@ -62,6 +62,8 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); + + EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_PURPLE); } public void resetToDefault(Monster entity) { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java index 4c9814b60..2856e4421 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java @@ -68,5 +68,7 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + + EntityGlowNMS.removeGlowing(entity, ChatFormatting.RED); } } \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java index 4ce3a9e8e..d87978b67 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java @@ -1,5 +1,6 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners; +import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; @@ -35,4 +36,18 @@ public void onRaidMonsterSpawn(EntitySpawnEvent event) { BloodyNightManager.applyBloodyMonster(monster); } + + @EventHandler + public void onMonsterLoaded(EntityAddToWorldEvent event) { + if (DailyEventsManager.isActiveDailyEvent() + && DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent) return; + if (!(event.getEntity() instanceof Monster monster)) return; + + if (!monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { + monster.remove(); + } + + BloodyNightManager.desactivateCorruptedMonster(monster); + + } } From c23b214aa2bb9e14f71cbbd544c5e9c6f0d4a88d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:12:52 +0200 Subject: [PATCH 17/20] fix: condition --- .../contents/bloodynight/listeners/MonsterSpawnLIstener.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java index d87978b67..72900dae4 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java @@ -43,11 +43,10 @@ public void onMonsterLoaded(EntityAddToWorldEvent event) { && DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent) return; if (!(event.getEntity() instanceof Monster monster)) return; - if (!monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { + if (monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { monster.remove(); } BloodyNightManager.desactivateCorruptedMonster(monster); - } } From 478e26b69e990dd0abccbc060f538633d2254856 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:23:58 +0200 Subject: [PATCH 18/20] fix: Entity is currently prevented from being removed from the world since it is processing section status updates --- .../bloodynight/listeners/MonsterSpawnLIstener.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java index 72900dae4..3afbdb48f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/listeners/MonsterSpawnLIstener.java @@ -1,11 +1,14 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.listeners; import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; +import fr.openmc.core.OMCPlugin; import fr.openmc.core.OMCRegistry; +import fr.openmc.core.bootstrap.integration.OMCLogger; import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightEvent; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightManager; import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.Bukkit; import org.bukkit.Particle; import org.bukkit.entity.Monster; import org.bukkit.event.EventHandler; @@ -44,7 +47,14 @@ public void onMonsterLoaded(EntityAddToWorldEvent event) { if (!(event.getEntity() instanceof Monster monster)) return; if (monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { - monster.remove(); + Bukkit.getScheduler().runTask(OMCPlugin.getInstance(), () -> { + if (monster.isValid()) { + monster.remove(); + } else { + OMCLogger.error("Impossible de supprimer le monstre (mort, delete, non chargé) " + monster.getName()); + } + }); + return; } BloodyNightManager.desactivateCorruptedMonster(monster); From f425cb89c8b692928102a9e83831238010247bc6 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:34:42 +0200 Subject: [PATCH 19/20] fix: glowing and fixed time --- .../contents/bloodynight/BloodyNightManager.java | 12 +++++++----- .../bloodynight/contents/mobs/CorruptedMonster.java | 4 +--- .../bloodynight/contents/mobs/CursedMonster.java | 2 +- .../ambient/listeners/AmbientFixedTimeListener.java | 7 +++++++ 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java index 04f191e86..5835bb5d3 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/BloodyNightManager.java @@ -6,6 +6,7 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.CorruptedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.CursedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.EnragedMonster; +import fr.openmc.core.registry.mobs.CustomMob; import org.bukkit.Bukkit; import org.bukkit.GameRules; import org.bukkit.NamespacedKey; @@ -83,16 +84,17 @@ private static void desactivateCorruptedMonsters(World world) { * Désactive le mob et le remet à son état normal * @param entity l'entité ciblé à désactiver */ - public static void desactivateCorruptedMonster(Entity entity) { + public static void desactivateCorruptedMonster(Entity entity) { if (!(entity instanceof Monster monster)) return; - if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CorruptedMonster corruptedMonster) { + CustomMob cm = OMCRegistry.CUSTOM_MOBS.getMob(monster); + if (cm instanceof CorruptedMonster corruptedMonster) { corruptedMonster.resetToDefault(monster); - } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof CursedMonster cursedMonster) { + } else if (cm instanceof CursedMonster cursedMonster) { cursedMonster.resetToDefault(monster); - } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof EnragedMonster enragedMonster) { + } else if (cm instanceof EnragedMonster enragedMonster) { enragedMonster.resetToDefault(monster); - } else if (OMCRegistry.CUSTOM_MOBS.getMob(monster) instanceof AncientMonster ancientMonster) { + } else if (cm instanceof AncientMonster ancientMonster) { ancientMonster.resetToDefault(monster); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java index 64dc51dfe..841715afd 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java @@ -59,13 +59,11 @@ public void apply(Monster entity) { public void resetToDefault(Monster entity) { unregisterAsCustomMob(entity); - entity.setCustomNameVisible(true); - EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_RED); + EntityGlowNMS.removeGlowing(entity, ChatFormatting.DARK_RED); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java index 8f66f9e9f..8731b66d2 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java @@ -77,6 +77,6 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); - EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_PURPLE); + EntityGlowNMS.removeGlowing(entity, ChatFormatting.DARK_PURPLE); } } diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java index 5fe946f02..a9e141236 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientFixedTimeListener.java @@ -7,6 +7,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.world.TimeSkipEvent; public class AmbientFixedTimeListener implements Listener { @@ -16,6 +17,12 @@ public void onPlayerKill(PlayerDeathEvent event) { reapplyTime(player); } + @EventHandler + public void onPlayerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + reapplyTime(player); + } + @EventHandler public void onTimeChange(TimeSkipEvent event) { for (Player player : event.getWorld().getPlayers()) { From e9f190b11837dd6125e40b2830da5fa7a5db1a0b Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 12:41:30 +0200 Subject: [PATCH 20/20] fix: fixed weather ambient --- .../listeners/AmbientWeatherListener.java | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java index d79e483e7..57e7f14ef 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java +++ b/src/main/java/fr/openmc/core/registry/ambient/listeners/AmbientWeatherListener.java @@ -6,22 +6,43 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.event.weather.WeatherChangeEvent; public class AmbientWeatherListener implements Listener { @EventHandler - public void onWeatherChange(WeatherChangeEvent event) { + public void onPlayerKill(PlayerDeathEvent event) { + Player player = event.getPlayer(); + reapplyWeather(player); + } + + @EventHandler + public void onPlayerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + reapplyWeather(player); + } + + @EventHandler + public void onTimeChange(WeatherChangeEvent event) { for (Player player : event.getWorld().getPlayers()) { - if (!CustomAmbient.ACTIVE_AMBIENTS.containsKey(player.getUniqueId())) continue; + reapplyWeather(player); + } + } - CustomAmbient ambientApplied = OMCRegistry.CUSTOM_AMBIENTS.getOrThrow( - CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId()) - ); + /** + * Réapplique la pluie/orage/temps sur un joueur + * @param player le joueur ciblé + */ + private void reapplyWeather(Player player) { + if (!CustomAmbient.ACTIVE_AMBIENTS.containsKey(player.getUniqueId())) return; - if (ambientApplied.getAmbientBuilder().getWeatherFixed() == null) continue; + CustomAmbient ambientApplied = OMCRegistry.CUSTOM_AMBIENTS.getOrThrow( + CustomAmbient.ACTIVE_AMBIENTS.get(player.getUniqueId())); - PlayerWeatherNMS.setWeather(player, ambientApplied.getAmbientBuilder().getWeatherFixed()); - } + if (ambientApplied.getAmbientBuilder().getWeatherFixed() == null) return; + + PlayerWeatherNMS.setWeather(player, ambientApplied.getAmbientBuilder().getWeatherFixed()); } } \ No newline at end of file