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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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/50] 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 From 9b8428ccab41f99f6c6f7c7baad0939b0b5c37ef Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 13:02:20 +0200 Subject: [PATCH 21/50] fix: broadcast miraculous fishing event --- .../contents/miraculousfishing/MiraculousFishingEvent.java | 2 +- .../resources/translations/default/dailyevents.properties | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index 42cc0cec5..31aacd0a5 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -101,7 +101,7 @@ public CustomAmbient getAmbient() { @Override public Component getStartBroadcast() { return TranslationManager.translation("feature.dailyevents.miraculousfishing.broadcast.start", - Component.text(FishingAttributeManager.FISHING_SPEED_MODIFIER * 100, NamedTextColor.AQUA)); + Component.text(FishingAttributeManager.FISHING_SPEED_MODIFIER * 100 + "%", NamedTextColor.AQUA)); } @Override diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index ea139460a..093fc562c 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -33,8 +33,8 @@ feature.dailyevents.miraculousfishing.broadcast.start=
*sortez vos cannes à pêche et découvrez les mystères des lacs*\
\
Effets :\ -
+ %1$s% vitesse de pêche\ -
+ Loots spéciaux et rares\ +
+ %1$s< vitesse de pêche\ +
+ Loots spéciaux et rares\
+ Monstres des Mers\
\
From 9bb5ee5bf6cb5c66d718b39d8337343f89bd812d Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 13:10:20 +0200 Subject: [PATCH 22/50] fix: Player is either on another team or not on any team. Cannot remove from team 'omc_glow_dark_red' --- .../contents/mobs/AncientMonster.java | 2 +- .../contents/mobs/CorruptedMonster.java | 2 +- .../contents/mobs/CursedMonster.java | 2 +- .../contents/mobs/EnragedMonster.java | 2 +- .../core/utils/nms/entity/EntityGlowNMS.java | 40 +++++++++++-------- 5 files changed, 28 insertions(+), 20 deletions(-) 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 6f7def833..1b8eeffe2 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 @@ -70,6 +70,6 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.removeGlowing(entity, ChatFormatting.YELLOW); + EntityGlowNMS.removeGlowing(entity); } } 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 841715afd..6b92568ea 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 @@ -64,6 +64,6 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.removeGlowing(entity, ChatFormatting.DARK_RED); + EntityGlowNMS.removeGlowing(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 8731b66d2..3e3f24640 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.removeGlowing(entity, ChatFormatting.DARK_PURPLE); + EntityGlowNMS.removeGlowing(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 2856e4421..3069d7ed2 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 @@ -69,6 +69,6 @@ public void resetToDefault(Monster entity) { EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.removeGlowing(entity, ChatFormatting.RED); + EntityGlowNMS.removeGlowing(entity); } } \ No newline at end of file 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 93983feba..af05f44ec 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 @@ -14,10 +14,13 @@ import java.util.HashMap; import java.util.Map; +import java.util.UUID; public class EntityGlowNMS implements Listener { private static final Scoreboard NMS_SCOREBOARD = new Scoreboard(); private static final Map TEAM_MAP = new HashMap<>(); + private static final Map entitiesGlowing = new HashMap<>(); + public EntityGlowNMS() { for (ChatFormatting color : ChatFormatting.values()) { @@ -34,6 +37,17 @@ public EntityGlowNMS() { } public static void setGlowingColor(Entity entity, ChatFormatting color) { + ChatFormatting previous = entitiesGlowing.get(entity.getUniqueId()); + if (previous != null && previous != color) { + PlayerTeam previousTeam = TEAM_MAP.get(previous); + sendPacket(ClientboundSetPlayerTeamPacket.createPlayerPacket( + previousTeam, entity.getUniqueId().toString(), ClientboundSetPlayerTeamPacket.Action.REMOVE + )); + } else if (previous == color) { + entity.setGlowing(true); + return; + } + entity.setGlowing(true); PlayerTeam team = TEAM_MAP.get(color); @@ -46,33 +60,27 @@ public static void setGlowingColor(Entity entity, ChatFormatting color) { ); sendPacket(addEntityPacket); + entitiesGlowing.put(entity.getUniqueId(), color); } - public static void removeGlowing(Entity entity, ChatFormatting color) { + public static void removeGlowing(Entity entity) { entity.setGlowing(false); + ChatFormatting current = entitiesGlowing.remove(entity.getUniqueId()); - PlayerTeam team = TEAM_MAP.get(color); + if (current == null) return; + + PlayerTeam team = TEAM_MAP.get(current); String entry = entity.getUniqueId().toString(); ClientboundSetPlayerTeamPacket removeEntityPacket = ClientboundSetPlayerTeamPacket.createPlayerPacket( - team, - entry, - ClientboundSetPlayerTeamPacket.Action.REMOVE - ); + 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 bedb27354656c56fdf85a76a82043fd865fda408 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 8 Jul 2026 16:18:09 +0200 Subject: [PATCH 23/50] fix: divers --- .../bloodynight/BloodyNightManager.java | 5 +++- .../bloodynight/BloodyNightRaidManager.java | 8 +++-- .../loottable/BloodyMobLootTable.java | 14 ++++----- .../listeners/MonsterSpawnLIstener.java | 29 ++++++++----------- 4 files changed, 28 insertions(+), 28 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 5835bb5d3..07c6e2573 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 @@ -84,7 +84,7 @@ 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; CustomMob cm = OMCRegistry.CUSTOM_MOBS.getMob(monster); @@ -123,6 +123,9 @@ private static void deleteRaidMonsters(World world) { public static void applyBloodyMonster(LivingEntity entity) { double random = ThreadLocalRandom.current().nextDouble(); + System.out.println(random); + + //todo: sfx particule if (random < 0.60) { OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(entity); } else if (random < 0.90) { 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 index cbd5535f7..8a8802357 100644 --- 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 @@ -4,9 +4,9 @@ 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.event.entity.CreatureSpawnEvent; import org.bukkit.persistence.PersistentDataType; import java.util.List; @@ -56,8 +56,10 @@ private static void spawnRaidAroundPlayer(Player player) { 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); + location.getWorld().spawnEntity(location, type, CreatureSpawnEvent.SpawnReason.CUSTOM,s -> + s.getPersistentDataContainer().set( + BloodyNightManager.RAID_MONSTER_KEY, PersistentDataType.BOOLEAN, true)); + } private static EntityType getRandomRaidMonsterType() { 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 index bff68b171..fc68bd18f 100644 --- 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 @@ -25,13 +25,13 @@ public String getNamespace() { @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) + new ItemLoot(Material.IRON_INGOT,0.3, 1, 4), + new ItemLoot(Material.GOLD_INGOT,0.2, 1, 3), + new ItemLoot(Material.DIAMOND,0.07, 1, 2), + new ItemLoot(Material.IRON_BLOCK,0.08, 1), + new ItemLoot(Material.GOLD_BLOCK,0.06, 1), + new ItemLoot(Material.DIAMOND_BLOCK,0.01, 1), + new ItemLoot(Material.NETHERITE_SCRAP,0.004, 1) )); } } 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 3afbdb48f..275247b2a 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 @@ -21,23 +21,18 @@ 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); - - 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); + System.out.println("e"); + if (monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { + System.out.println("b"); + BloodyNightManager.applyBloodyMonster(monster); + } else { + System.out.println("a"); + ParticleUtils.spawnDispersingParticles(event.getLocation(), + Particle.DAMAGE_INDICATOR, + 10, 35, 0.1D, null); + + OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(monster); + } } @EventHandler From 45e200f14589df5860608eb6bf4a2b3cea6682b1 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 11 Jul 2026 15:30:57 +0200 Subject: [PATCH 24/50] change: blood moon texture --- .../contents/ambient/BloodyAmbient.java | 2 ++ .../environment/celestial/moon/full_moon.png | Bin 6954 -> 0 bytes 2 files changed, 2 insertions(+) delete mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/full_moon.png 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 cb8a4492f..38939c305 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 @@ -37,6 +37,8 @@ public AmbientBuilder getAmbientBuilder() { obj.addProperty("visual/cloud_height", 65); obj.addProperty("visual/cloud_color", "#7e8c2b2b"); + // c'est ceci qui va permet de detecter au shader que l'ambience est activé et qu'il faut mettre la blood moon + obj.addProperty("visual/cloud_fog_end_distance", 2040.0067); obj.addProperty("visual/water_fog_color", "#330505"); }) diff --git a/src/main/resources/contents/omc_daily_events_rp/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 deleted file mode 100644 index a97e7272f6574ae896d030768da88c6d103a3813..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6954 zcmeI1ZBSEJ8pm(aKq=HE6s)flYCDoGR-m=Q3M6Su>q`|_hefcJptOjq11w@g0^~*4 zm(?zIhZa%5gsBd#P@uk)LV|(D6BSfmVw#6<`ZFoXbkyUE?>p3HvtLuYo~$*1Jx zK67&JbAQkO`JZ$DlAO4CiSJ5Z48xXe-IA~q!>I6;iuriM$9&O0?HIPwv^C+~lp@NE zChAI!eyLYqu~t^F*Yt@u?Wj-xCBNls=#Bl~sY2g6{$ki`TgrFV?70*0`-dx*e{zda znc};CpTV&9&tK?RM`x5721Rjix`R7<`>$#RKEKFci5m;rR>*rTxliBYIDpLt&f z);=t&CI_dzf<*tCtw|KYpq=W=&Rbj`#uj1XeH1TgOi5i}C|ksC5>flA+Phz%hq9$< zYzpHyS_9389@-Z!#pbh(1u!F>@p3YDTFKq?t4^QaTAdxN>nxCUPvh2wbK}JC>{a8A z2twW3rO+CvEi&Tpypp)!NXc`#w}foim1uU+set6i$ql2 zD)@l=JP!A{cQSD;8u*Ix$lqu_L6DW>wXx^XfPvj4f1`&cGo)D1i6@_;ffTcPdnSIC zQjyP#jI&>rzlWRr6(PPwiJ46u^~;(p>j`a-BwpCYClt6rU2hTM!^%O2(6(4N=#Vf~ z_c<a6gWNph$q{#h8W%b~TP)cyGB#is zJTp|k;^KonsYYV*jCz-mn6?cJI`TL!lSVlc)-XyGTyyyUa^$C*!snXp<{NQHYGT$( zvDJsor;+|NfS#sy?dPFd%iqqX#7s;qMPX@xU_+UD4za1L6jAe4J>e*L!5x8p7j!bJWOF-7gNf#%R)wbg|A!vqU(mW3f*I3 zRp~2@MlE(JaDxPKNdrQ#w!a~&LV?6ffsvjIo|J^LpB9GoEqZg#^sFuC$F918a+%)= zDcO*Z4d}lqWgS-DjgaGuJ&#&j-WQvD!jzmlOht{;#s3LVwO>AT7KD zmMvX4fCP`7z^0sPUbPMB&{gQW_qByc7U==W*qZ4RFCkHD5K+Heh^|2_CjiSnvRXIG z;AKB`?(qD@|8t^x6|Ig(o6eV{XS^zKOx}BhTSxY*CAYab89K6KtAz#J^mbx#TtT=( zMv~In368L&g-=*QvZo>lbA0URK?GFa8&d50T4OFb_!j!~l`$@Ac-Mi(@9)a0NVu** zi+pSiM$Pkkfbrnm6LPyDhIT96B|t( z@q;yj*ka}dXVfdKV%K~YzI{4+w8XjN(2t$}QNC{?nEr{9vx3>dZrfR!@F8?x?>hBn z&PgFLu}UR)D6m?F6qHI^G1^SfQUS2=tZN&P_Emx-dz;ndHhbH^#eH_D!o8z?8wL~l zcie9Ax8N4P=;=oymkAD2h0EPh;XvruKcrtkQm6tcJTGzYcQP-7S$u2bM{cutUPO&F zo83_jL10R6XCFXS5DC67Tae+7`Wn3AKYm%~US>87RBCsvH17mYx}xf`dzs*4D{VZ_ z&5#L9`>#J4T|vBL^BLjt_Fk4tzbnH0(Tf|cBQ1H}P3EK!ZM-UC@39+H{|dtF=w~VJ zCGthe6-I4+gS(N)a!fgxqe*;bBx!_5O5B(`&5SyD=rTI0g z_H|8kg=4z>u5Gl!4|j4{jV~9KSn?NK6=9J9*14Iaa=od=$Wo=Ic@Aelv^_^lprTK8 z?goG{0kG9X=A3o^?BZ29bx&?D>$$&=g+HkNP@*+;h8V_e@)6>-s9S;wzQ*airDOK% z9OF1~lh{J9mGGjgWw=^9%U8QM8sEX;-Aeg2}u6?;P7TLl!Xu41EJ;)Yb23vSwwwLV2;#{zWvBDu_3q8{V-OqY*&ROdG zl>_Ivrwq3D+YRO^p51TQqCfb#tI$4EKp30`3wlw*vpip@h!b%Q{zWlDyQSF1G1gwx zBeNz=fj2EnMu*8kADpxl>WzF7Ee0GrZ#%}_NTO8;?N(!xp@X<>fL6b*2AL}jpv84H zl5JSL6VTdFv>&0>0y~Zx#S|j<*P32TU~z8<`VO5rwGZBbVOu{)OlW*B^XR_;KIN5F From d0331ea908886bc6a4b2719039bf74acacfa8ba2 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 11 Jul 2026 15:42:00 +0200 Subject: [PATCH 25/50] update nms code to 26.2 --- .../core/utils/nms/entity/EntityGlowNMS.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 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 af05f44ec..60abf88b6 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 @@ -1,9 +1,9 @@ package fr.openmc.core.utils.nms.entity; -import net.minecraft.ChatFormatting; import net.minecraft.network.protocol.game.ClientboundSetPlayerTeamPacket; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Scoreboard; +import net.minecraft.world.scores.TeamColor; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.entity.Entity; @@ -14,21 +14,20 @@ import java.util.HashMap; import java.util.Map; +import java.util.Optional; import java.util.UUID; public class EntityGlowNMS implements Listener { private static final Scoreboard NMS_SCOREBOARD = new Scoreboard(); - private static final Map TEAM_MAP = new HashMap<>(); - private static final Map entitiesGlowing = new HashMap<>(); + private static final Map TEAM_MAP = new HashMap<>(); + private static final Map entitiesGlowing = new HashMap<>(); public EntityGlowNMS() { - for (ChatFormatting color : ChatFormatting.values()) { - if (!color.isColor()) continue; + for (TeamColor color : TeamColor.values()) { + PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, "omc_glow_" + color.getSerializedName()); - PlayerTeam team = new PlayerTeam(NMS_SCOREBOARD, "omc_glow_" + color.getName()); - - team.setColor(color); + team.setColor(Optional.of(color)); team.setSeeFriendlyInvisibles(false); team.setNameTagVisibility(PlayerTeam.Visibility.NEVER); @@ -36,8 +35,8 @@ public EntityGlowNMS() { } } - public static void setGlowingColor(Entity entity, ChatFormatting color) { - ChatFormatting previous = entitiesGlowing.get(entity.getUniqueId()); + public static void setGlowingColor(Entity entity, TeamColor color) { + TeamColor previous = entitiesGlowing.get(entity.getUniqueId()); if (previous != null && previous != color) { PlayerTeam previousTeam = TEAM_MAP.get(previous); sendPacket(ClientboundSetPlayerTeamPacket.createPlayerPacket( @@ -65,7 +64,7 @@ public static void setGlowingColor(Entity entity, ChatFormatting color) { public static void removeGlowing(Entity entity) { entity.setGlowing(false); - ChatFormatting current = entitiesGlowing.remove(entity.getUniqueId()); + TeamColor current = entitiesGlowing.remove(entity.getUniqueId()); if (current == null) return; @@ -89,9 +88,7 @@ private static void sendPacket(ClientboundSetPlayerTeamPacket packet) { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { - for (ChatFormatting color : ChatFormatting.values()) { - if (!color.isColor()) continue; - + for (TeamColor color : TeamColor.values()) { PlayerTeam team = TEAM_MAP.get(color); if (team == null) continue; From dbf6c944d1f6bb028ad68b7d35a46ec11e4d2dce Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 11 Jul 2026 15:46:23 +0200 Subject: [PATCH 26/50] fix: ChatFormatting color to TeamColor --- .../contents/bloodynight/contents/mobs/AncientMonster.java | 4 ++-- .../contents/bloodynight/contents/mobs/CorruptedMonster.java | 4 ++-- .../contents/bloodynight/contents/mobs/CursedMonster.java | 4 ++-- .../contents/bloodynight/contents/mobs/EnragedMonster.java | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) 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 1b8eeffe2..c81eb8131 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 @@ -4,7 +4,7 @@ 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 net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -57,7 +57,7 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.setGlowingColor(entity, ChatFormatting.YELLOW); + EntityGlowNMS.setGlowingColor(entity, TeamColor.YELLOW); } public void resetToDefault(Monster entity) { 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 6b92568ea..bd573ae63 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 @@ -4,7 +4,7 @@ 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 net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -53,7 +53,7 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_RED); + EntityGlowNMS.setGlowingColor(entity, TeamColor.DARK_RED); } 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 3e3f24640..1a49cc010 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 @@ -4,7 +4,7 @@ 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 net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -63,7 +63,7 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); - EntityGlowNMS.setGlowingColor(entity, ChatFormatting.DARK_PURPLE); + EntityGlowNMS.setGlowingColor(entity, TeamColor.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 3069d7ed2..1f6c8bf19 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 @@ -4,7 +4,7 @@ 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 net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeModifier; @@ -56,7 +56,7 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); - EntityGlowNMS.setGlowingColor(entity, ChatFormatting.RED); + EntityGlowNMS.setGlowingColor(entity, TeamColor.RED); } public void resetToDefault(Monster entity) { From 750a33062d6582020d52d075a92c3f6766f7a4ef Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 11 Jul 2026 19:29:53 +0200 Subject: [PATCH 27/50] revert: back texture blood moon (with shader it bugged) --- .../environment/celestial/moon/full_moon.png | Bin 0 -> 6954 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/full_moon.png diff --git a/src/main/resources/contents/omc_daily_events_rp/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 new file mode 100644 index 0000000000000000000000000000000000000000..a97e7272f6574ae896d030768da88c6d103a3813 GIT binary patch literal 6954 zcmeI1ZBSEJ8pm(aKq=HE6s)flYCDoGR-m=Q3M6Su>q`|_hefcJptOjq11w@g0^~*4 zm(?zIhZa%5gsBd#P@uk)LV|(D6BSfmVw#6<`ZFoXbkyUE?>p3HvtLuYo~$*1Jx zK67&JbAQkO`JZ$DlAO4CiSJ5Z48xXe-IA~q!>I6;iuriM$9&O0?HIPwv^C+~lp@NE zChAI!eyLYqu~t^F*Yt@u?Wj-xCBNls=#Bl~sY2g6{$ki`TgrFV?70*0`-dx*e{zda znc};CpTV&9&tK?RM`x5721Rjix`R7<`>$#RKEKFci5m;rR>*rTxliBYIDpLt&f z);=t&CI_dzf<*tCtw|KYpq=W=&Rbj`#uj1XeH1TgOi5i}C|ksC5>flA+Phz%hq9$< zYzpHyS_9389@-Z!#pbh(1u!F>@p3YDTFKq?t4^QaTAdxN>nxCUPvh2wbK}JC>{a8A z2twW3rO+CvEi&Tpypp)!NXc`#w}foim1uU+set6i$ql2 zD)@l=JP!A{cQSD;8u*Ix$lqu_L6DW>wXx^XfPvj4f1`&cGo)D1i6@_;ffTcPdnSIC zQjyP#jI&>rzlWRr6(PPwiJ46u^~;(p>j`a-BwpCYClt6rU2hTM!^%O2(6(4N=#Vf~ z_c<a6gWNph$q{#h8W%b~TP)cyGB#is zJTp|k;^KonsYYV*jCz-mn6?cJI`TL!lSVlc)-XyGTyyyUa^$C*!snXp<{NQHYGT$( zvDJsor;+|NfS#sy?dPFd%iqqX#7s;qMPX@xU_+UD4za1L6jAe4J>e*L!5x8p7j!bJWOF-7gNf#%R)wbg|A!vqU(mW3f*I3 zRp~2@MlE(JaDxPKNdrQ#w!a~&LV?6ffsvjIo|J^LpB9GoEqZg#^sFuC$F918a+%)= zDcO*Z4d}lqWgS-DjgaGuJ&#&j-WQvD!jzmlOht{;#s3LVwO>AT7KD zmMvX4fCP`7z^0sPUbPMB&{gQW_qByc7U==W*qZ4RFCkHD5K+Heh^|2_CjiSnvRXIG z;AKB`?(qD@|8t^x6|Ig(o6eV{XS^zKOx}BhTSxY*CAYab89K6KtAz#J^mbx#TtT=( zMv~In368L&g-=*QvZo>lbA0URK?GFa8&d50T4OFb_!j!~l`$@Ac-Mi(@9)a0NVu** zi+pSiM$Pkkfbrnm6LPyDhIT96B|t( z@q;yj*ka}dXVfdKV%K~YzI{4+w8XjN(2t$}QNC{?nEr{9vx3>dZrfR!@F8?x?>hBn z&PgFLu}UR)D6m?F6qHI^G1^SfQUS2=tZN&P_Emx-dz;ndHhbH^#eH_D!o8z?8wL~l zcie9Ax8N4P=;=oymkAD2h0EPh;XvruKcrtkQm6tcJTGzYcQP-7S$u2bM{cutUPO&F zo83_jL10R6XCFXS5DC67Tae+7`Wn3AKYm%~US>87RBCsvH17mYx}xf`dzs*4D{VZ_ z&5#L9`>#J4T|vBL^BLjt_Fk4tzbnH0(Tf|cBQ1H}P3EK!ZM-UC@39+H{|dtF=w~VJ zCGthe6-I4+gS(N)a!fgxqe*;bBx!_5O5B(`&5SyD=rTI0g z_H|8kg=4z>u5Gl!4|j4{jV~9KSn?NK6=9J9*14Iaa=od=$Wo=Ic@Aelv^_^lprTK8 z?goG{0kG9X=A3o^?BZ29bx&?D>$$&=g+HkNP@*+;h8V_e@)6>-s9S;wzQ*airDOK% z9OF1~lh{J9mGGjgWw=^9%U8QM8sEX;-Aeg2}u6?;P7TLl!Xu41EJ;)Yb23vSwwwLV2;#{zWvBDu_3q8{V-OqY*&ROdG zl>_Ivrwq3D+YRO^p51TQqCfb#tI$4EKp30`3wlw*vpip@h!b%Q{zWlDyQSF1G1gwx zBeNz=fj2EnMu*8kADpxl>WzF7Ee0GrZ#%}_NTO8;?N(!xp@X<>fL6b*2AL}jpv84H zl5JSL6VTdFv>&0>0y~Zx#S|j<*P32TU~z8<`VO5rwGZBbVOu{)OlW*B^XR_;KIN5F literal 0 HcmV?d00001 From b6b9b783201873b316c49f158bfcb420fb1eb72b Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Sat, 11 Jul 2026 20:16:48 +0200 Subject: [PATCH 28/50] fix: Player is either on another team or not on any team. Cannot remove from team 'omc_glow_dark_red'. --- .../core/utils/nms/entity/EntityGlowNMS.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 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 60abf88b6..1baf276b4 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 @@ -16,11 +16,12 @@ import java.util.Map; import java.util.Optional; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; public class EntityGlowNMS implements Listener { private static final Scoreboard NMS_SCOREBOARD = new Scoreboard(); private static final Map TEAM_MAP = new HashMap<>(); - private static final Map entitiesGlowing = new HashMap<>(); + private static final Map entitiesGlowing = new ConcurrentHashMap<>(); public EntityGlowNMS() { @@ -86,13 +87,26 @@ private static void sendPacket(ClientboundSetPlayerTeamPacket packet) { } } + private static void sendPacketTo(Player player, ClientboundSetPlayerTeamPacket packet) { + ((CraftPlayer) player).getHandle().connection.send(packet); + } + @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { + Player joined = event.getPlayer(); for (TeamColor color : TeamColor.values()) { PlayerTeam team = TEAM_MAP.get(color); if (team == null) continue; - sendPacket(ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); + sendPacketTo(joined, ClientboundSetPlayerTeamPacket.createAddOrModifyPacket(team, true)); + } + + for (Map.Entry entry : entitiesGlowing.entrySet()) { + PlayerTeam team = TEAM_MAP.get(entry.getValue()); + if (team == null) continue; + sendPacketTo(joined, ClientboundSetPlayerTeamPacket.createPlayerPacket( + team, entry.getKey().toString(), ClientboundSetPlayerTeamPacket.Action.ADD + )); } } } From 7f7868cd6bcfa48e55c0418034b97ed5ba4d72e8 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 13 Jul 2026 21:53:47 +0200 Subject: [PATCH 29/50] feat add shader for Blood Moon without deleting any moon textures. (just waning_gibbous bugged) --- .../contents/ambient/BloodyAmbient.java | 6 +- .../minecraft/shaders/core/position_tex.fsh | 31 ++++++ .../minecraft/shaders/core/position_tex.vsh | 101 ++++++++++++++++++ .../celestial/moon/first_quarter.png | Bin 0 -> 1620 bytes .../environment/celestial/moon/full_moon.png | Bin 6954 -> 1653 bytes .../environment/celestial/moon/new_moon.png | Bin 0 -> 1530 bytes .../celestial/moon/third_quarter.png | Bin 0 -> 1620 bytes .../celestial/moon/waning_crescent.png | Bin 0 -> 1551 bytes .../celestial/moon/waning_gibbous.png | Bin 0 -> 1647 bytes .../celestial/moon/waxing_crescent.png | Bin 0 -> 1569 bytes .../celestial/moon/waxing_gibbous.png | Bin 0 -> 1635 bytes .../shaders/include/compare_float.glsl | 7 ++ .../shaders/include/get_dimension.glsl | 5 + .../shaders/include/shift_texture.glsl | 48 +++++++++ 14 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.fsh create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.vsh create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/first_quarter.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/new_moon.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/third_quarter.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waning_crescent.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waning_gibbous.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waxing_crescent.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waxing_gibbous.png create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/compare_float.glsl create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/get_dimension.glsl create mode 100644 src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/shift_texture.glsl 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 38939c305..1de17d4ac 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 @@ -35,10 +35,11 @@ public AmbientBuilder getAmbientBuilder() { obj.addProperty("visual/moon_angle", 67); obj.addProperty("visual/star_brightness", 0.7); + + obj.addProperty("visual/cloud_fog_end_distance", 512.0032); + obj.addProperty("visual/cloud_height", 65); obj.addProperty("visual/cloud_color", "#7e8c2b2b"); - // c'est ceci qui va permet de detecter au shader que l'ambience est activé et qu'il faut mettre la blood moon - obj.addProperty("visual/cloud_fog_end_distance", 2040.0067); obj.addProperty("visual/water_fog_color", "#330505"); }) @@ -69,6 +70,7 @@ public AmbientBuilder getAmbientBuilder() { .defaultClock("overworld") .timelines("#minecraft:in_overworld") + .hasFixedTime(true, 21000) .hasPrecipitation(false, WeatherType.NONE); } diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.fsh b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.fsh new file mode 100644 index 000000000..9ab716101 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.fsh @@ -0,0 +1,31 @@ +#version 330 +#moj_import +#moj_import + +#moj_import + +in vec2 texCoord0; +flat in int isCelestial; +flat in float textureShift; +flat in float frames; +flat in float textureHeight; +flat in vec2 atlasSize; + +uniform sampler2D Sampler0; + +out vec4 fragColor; + +void main() { + vec4 color = texture(Sampler0, texCoord0); + + if (isCelestial == 1) + { + vec2 uv = texCoord0 * atlasSize; + + uv = shiftTextureUV(uv, textureHeight, frames, textureShift); + + color = texture(Sampler0, uv / atlasSize); + } + + fragColor = color * ColorModulator; +} diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.vsh b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.vsh new file mode 100644 index 000000000..1edefabe5 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/shaders/core/position_tex.vsh @@ -0,0 +1,101 @@ +#version 330 +#moj_import +#moj_import +#moj_import +#moj_import +#moj_import + +in vec3 Position; +in vec2 UV0; +in vec4 Color; + +uniform sampler2D Sampler0; + +out vec2 texCoord0; +flat out int isCelestial; +flat out float frames; +flat out float textureShift; +flat out float textureHeight; +flat out vec2 atlasSize; + +bool isMarker(vec4 color, vec4 compareColor) { + return all(lessThan(abs(color.rgb - compareColor.rgb), vec3(0.004))); +} + +int detectMarker(vec2 uv) { + ivec2 texelCoord = ivec2(uv * atlasSize); + vec4 c = texelFetch(Sampler0, texelCoord, 0); + + if (isMarker(c, vec4(1.0, 1.0, 1.0, 1.0) / 255.0)) return 1; // Sun + else if (isMarker(c, vec4(3.0, 3.0, 3.0, 1.0) / 255.0)) return 2; // Moon + return 0; +} + +mat3 rotateX(float a) { + float s = sin(a); + float c = cos(a); + return mat3( + 1.0, 0.0, 0.0, + 0.0, c, -s, + 0.0, s, c + ); +} + +mat3 rotateZ(float a) { + float s = sin(a); + float c = cos(a); + return mat3( + c, -s, 0.0, + s, c, 0.0, + 0.0, 0.0, 1.0 + ); +} + +mat3 rotateY(float a) { + float s = sin(a); + float c = cos(a); + return mat3( + c, 0.0, s, + 0.0, 1.0, 0.0, + -s, 0.0, c + ); +} + +void main() { + texCoord0 = UV0; + atlasSize = vec2(textureSize(Sampler0, 0)); + float size = 1.0; + float tilt = 0.0; + float SunOffset = 0.0; + + switch (detectMarker(UV0)) + { // Sun + case 1: { + isCelestial = 1; + frames = 1.0; + textureHeight = 64.0; + switch (getDimension(FogColor.rgb, FogCloudsEnd)) + { + default: textureShift = 0.0; size = 1.0; + } break; + } // Moon + case 2: { + isCelestial = 1; + frames = 2.0; + textureHeight = 64.0; + switch (getDimension(FogColor.rgb, FogCloudsEnd)) + { + case 1: textureShift = 1.0; size = 3.0; break; // texture de blood moon + default: textureShift = 0.0; size = 1.0; + } break; + } + default: { + isCelestial = 0; + } + } + vec3 rotated = rotateY(radians(tilt)) * Position; + vec4 pos = vec4(rotated, size); + pos.x += SunOffset; + + gl_Position = ProjMat * ModelViewMat * pos; +} diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/first_quarter.png b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/first_quarter.png new file mode 100644 index 0000000000000000000000000000000000000000..a123cac38487f8dfe6d97aeb75338815d14d12b6 GIT binary patch literal 1620 zcmV-a2CMmrP)iXbQiF+{{wKF~MQ)g|ZLy4BTRnR%a+14GqR_v`b!r>d)alB_5S@0^px%3^Oh z`Pds$Q53vt&zS>e*}!;PzUPuucf1AAG6;rQXmMTZ56OEUInfUtZKLY%2|#k;#JD!i z;&(fi%FHmVeIH@^LBjbRfUGt$V>9RXhA}%|jkT#1AO)!^sUnEB{QwqmFyn{j+BU}wvQ}zn zAew--Hl`p3(E>=#^P-66d0vPZ03nLTID@VGq<0LB)-nb4F;jM&FGE@pb@ z!KplY@^N|Of)%W(qN8UlSOKE4Lc} zFT8k${q^-zY|o#2mBuht!+DZIDXv5T0{}MfRxQngu>t|$KN>**c=DO&3O z<(Hp-kn`uxC_peIh?^&=gtf5{AXE<1Vl<8r<^11Xfa4F`%dv|WFD2EY`Z|dN1AsPO zdYSEo&9nOiu)`^+*T5d8U^k1<03bl@X%X(`Hnb@)efr6VNwqt;4fnngp;L)-Gc|+h z(i;&jx4Nx(W?0JktF#RXST`s{+XhLEb*z@{ z1<|N&tS4zph4X6wsCm&81gc?%Wv12-9c`oP?=1k+fXM>$sE(njJD%O8KhL`gH{R0H zcizS7oq{2=Y-nm)^4&{PeNYX6wy_!3ZM6^q7xUpt2GRyfK_WnEo*J7eKfI;FIW3ZO z9DM~*m_87L=m4l`)0pGB2T2h&qKw;WEuZDQ?Ho6u8mJ9o5DkDnbBtM)qg+jMK%w=m z@`I{OHy`{p+OkqJz`(E%q62_a>^q)ABm6o}j0+~A0O&)`s$~LAkdhB0J&p#s_5xV# zFv~;SW?tZBH5fAuJjE=YAQc4$Gaexf^)6a!)z=XIm}@S^D+O06L*2<9RYFWXPG$XWiAQ<7(f7EE|?MkXbLU> zKm@S(b)H2gxy0(n=mRDzXigA7CF_6*g!zXtAm-kwDN+e3%=BeR7iyS>2vCIABg79A zRL^w)AQ72x0gAl;`UXu+-+u9(oO=Fg`Rs#_<@k|%v zj5KDeek~Y}^IXQ6$a`C-X?o(wNT%ygM3C=4`kd|8x8^d3X{FP!?R`uE$;`@X7=YCx z;!NY86d3_5dK`OqYoh^h{mPGQ|M}{&T>bloT)8!4)HW3Wm^s~)O0Uzv1-b}e4R-<{ zL}V?`bvze&=fY{4LRW8=5d>2J{gF>}3Q&DjaT;9ZWg8It0r1px$~lKD3Fz9jzu10r zd%iyacbWoAz_f2uu*@QS?cw|6^6%HV;!P)x9gSmqT7=8ohR+_wH`SjvZ#O`oUEhX# z-H0G;Fxzey8xj6^Wn1yeA4UdX)3CC~F#r@|MK2^!ngZ7a7hHHxIOtb0$Wl1;mr|Jb zL4Yn4$=eg319>e+#{eMMTYG3fOrR73NM`t01#wlLPthLGd4j(H84a%H#jyiL^2c3 S4)*{6002ovPDHLkV1fV#tmPp9 literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events_rp/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 index a97e7272f6574ae896d030768da88c6d103a3813..ca795ad8ec0b042e0137d2ca0c5499527f9daec9 100644 GIT binary patch literal 1653 zcmV-*28#KKP)HF;pDn(E$ue)YW7)jdg86oq%r z$#iA0H=BIy^{FTdUbW-Q9G{1!k~8JV$}^LuhURW$NyY!EGw_=h!sF7rGBWO>rh za&_wxjmv22%cSqiPKXvjG?7el80XqIV+F&Qov+5)lnRi7l%{1MDsi^L=1osMQt5ew7ztek;lwkgeYBdET)hE*vw!G zb2F;Un`4%kn&X0MXhtr9&@n&&hAD)yVCtMlj62MphL|a5tETpy05LTZ@M6)dblUgT zcl0dl%(0CZ6rL>PV?9Y*Dx6;dK=q5JAW#L< zFEh1%=x7^NeQyAmdQ7I6N3{%1?eXjy{dwM2xbbF|zVl93X9@buvcA$Zaf$NZN1%wgzT<`^4rOjr&}fuOxvqi+2#=lTx1hD9F?D<0nYXEB} z&#=9C{Dhpla7j*H88K=r1pr1)H>HW!GH`)T16ahJ00q`|_hefcJptOjq11w@g0^~*4 zm(?zIhZa%5gsBd#P@uk)LV|(D6BSfmVw#6<`ZFoXbkyUE?>p3HvtLuYo~$*1Jx zK67&JbAQkO`JZ$DlAO4CiSJ5Z48xXe-IA~q!>I6;iuriM$9&O0?HIPwv^C+~lp@NE zChAI!eyLYqu~t^F*Yt@u?Wj-xCBNls=#Bl~sY2g6{$ki`TgrFV?70*0`-dx*e{zda znc};CpTV&9&tK?RM`x5721Rjix`R7<`>$#RKEKFci5m;rR>*rTxliBYIDpLt&f z);=t&CI_dzf<*tCtw|KYpq=W=&Rbj`#uj1XeH1TgOi5i}C|ksC5>flA+Phz%hq9$< zYzpHyS_9389@-Z!#pbh(1u!F>@p3YDTFKq?t4^QaTAdxN>nxCUPvh2wbK}JC>{a8A z2twW3rO+CvEi&Tpypp)!NXc`#w}foim1uU+set6i$ql2 zD)@l=JP!A{cQSD;8u*Ix$lqu_L6DW>wXx^XfPvj4f1`&cGo)D1i6@_;ffTcPdnSIC zQjyP#jI&>rzlWRr6(PPwiJ46u^~;(p>j`a-BwpCYClt6rU2hTM!^%O2(6(4N=#Vf~ z_c<a6gWNph$q{#h8W%b~TP)cyGB#is zJTp|k;^KonsYYV*jCz-mn6?cJI`TL!lSVlc)-XyGTyyyUa^$C*!snXp<{NQHYGT$( zvDJsor;+|NfS#sy?dPFd%iqqX#7s;qMPX@xU_+UD4za1L6jAe4J>e*L!5x8p7j!bJWOF-7gNf#%R)wbg|A!vqU(mW3f*I3 zRp~2@MlE(JaDxPKNdrQ#w!a~&LV?6ffsvjIo|J^LpB9GoEqZg#^sFuC$F918a+%)= zDcO*Z4d}lqWgS-DjgaGuJ&#&j-WQvD!jzmlOht{;#s3LVwO>AT7KD zmMvX4fCP`7z^0sPUbPMB&{gQW_qByc7U==W*qZ4RFCkHD5K+Heh^|2_CjiSnvRXIG z;AKB`?(qD@|8t^x6|Ig(o6eV{XS^zKOx}BhTSxY*CAYab89K6KtAz#J^mbx#TtT=( zMv~In368L&g-=*QvZo>lbA0URK?GFa8&d50T4OFb_!j!~l`$@Ac-Mi(@9)a0NVu** zi+pSiM$Pkkfbrnm6LPyDhIT96B|t( z@q;yj*ka}dXVfdKV%K~YzI{4+w8XjN(2t$}QNC{?nEr{9vx3>dZrfR!@F8?x?>hBn z&PgFLu}UR)D6m?F6qHI^G1^SfQUS2=tZN&P_Emx-dz;ndHhbH^#eH_D!o8z?8wL~l zcie9Ax8N4P=;=oymkAD2h0EPh;XvruKcrtkQm6tcJTGzYcQP-7S$u2bM{cutUPO&F zo83_jL10R6XCFXS5DC67Tae+7`Wn3AKYm%~US>87RBCsvH17mYx}xf`dzs*4D{VZ_ z&5#L9`>#J4T|vBL^BLjt_Fk4tzbnH0(Tf|cBQ1H}P3EK!ZM-UC@39+H{|dtF=w~VJ zCGthe6-I4+gS(N)a!fgxqe*;bBx!_5O5B(`&5SyD=rTI0g z_H|8kg=4z>u5Gl!4|j4{jV~9KSn?NK6=9J9*14Iaa=od=$Wo=Ic@Aelv^_^lprTK8 z?goG{0kG9X=A3o^?BZ29bx&?D>$$&=g+HkNP@*+;h8V_e@)6>-s9S;wzQ*airDOK% z9OF1~lh{J9mGGjgWw=^9%U8QM8sEX;-Aeg2}u6?;P7TLl!Xu41EJ;)Yb23vSwwwLV2;#{zWvBDu_3q8{V-OqY*&ROdG zl>_Ivrwq3D+YRO^p51TQqCfb#tI$4EKp30`3wlw*vpip@h!b%Q{zWlDyQSF1G1gwx zBeNz=fj2EnMu*8kADpxl>WzF7Ee0GrZ#%}_NTO8;?N(!xp@X<>fL6b*2AL}jpv84H zl5JSL6VTdFv>&0>0y~Zx#S|j<*P32TU~z8<`VO5rwGZBbVOu{)OlW*B^XR_;KIN5F diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/new_moon.png b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/new_moon.png new file mode 100644 index 0000000000000000000000000000000000000000..9e36bdae954b10c1c6c531c6c61322f0bcd823cc GIT binary patch literal 1530 zcmVzY@c zICI7<%#06}CN4>h#|Hod12YWP;=10SQ%WgwqHi5-v%2pEKyl&1xHAp;yB{m%W*F9f z$}rO)cK!$;bVhFM=KNk9FO`jw8au=YB>!O#V9LD80HG@Sp;EUg(YVc~sV(}corD+x zWD^Ne!MM`C8!H&b{CqXmrd5Cvq-~|mAlgm?c*JJL56!jhk2z$g($GOP0d0LuK^$TL zP?}eDoz1JN7I6SV)V+1!(WW+bMhTV24AI8oSWck;@XBBcb2sYDhhv_Yn&X0M=ti-C z&@n&&hAG&zpmf%eqX1?|khm#Qv9+-kz$%Any;x?5ORvB9M1X_){}$Dv`Ywt88Ne>4 zVCRc)r?=tBHzIUeiE*vB-BWEuxZLix;+;Q?o|DJ1Zbtf0(oIR<1^9$KmlqN)gbqL# zr9;?Q-Z3%e=W`WW)9vwWpX!wivJ`M!jST4QUrOmd0ighzfPTv3rEtjKjQD!S6ZC_A zd0eHfCE#6?MLPs3jdiS(?*-XtXsjn`OWFAy0Mx%|2?BL6^Kw(~TSwch?)w11HDj{H zJZog=8jpwP^ym3lcH`aIs`pa*!cV z36cRy^U~N&`Qa^P=L|^7ar6~LVWvPFVg#V3ePfR69wfDGM1k9CrxYsQc9EM<2Q&n6 zh#tU{ImW!oMWv<{pwOm4`KC7L=7YaR+q7y17#L1Li~w+of5&rZfnUdkam^$Y0DUNW zwM?K7((qxV$I&3yNdT`MW|hV5<~4pXnK9GAQ_SNr!4S_jRP7)UKg$h*DKLpHg%N;P zk83aM&K#xyP_Q5?o`dItR^t7&fxrj=fN_XTG>9UF9sukZwZI&PX=IME1;>Qb;VIBG zV9rGvX(gsGg231&YWM&G76Gb!7gSPnuC;oYEkz@TIZR=`7Fku2t6!oIm{8N4Ab={?0TZzKhcO^FDXJ+_u@u(& zvZM>urXd5=_IiZ)VS?(p4ge$~D=t8h&px_AQ`e8*{3P#Qdq=+d{7bof;RX5j!I}_j zTN6kDl_Leh*)+sCfYm}{_UiY{cv)4l3?iT2yiU`r7Z$Sr-dh>u=P$ly`~9PhY+%~z zG#sUrQ$RB7rkw|1wTL)q{Hr<;z@x{pPj24m0UX}`h3#M8-I68n{5W0qo&U0ECF_Rh5ocA|HQvou<&8hfM~-6hOaME1d#V-?p5F*d{pw#AyJ$ zy}!>nhdc@B;NU*nA0BT`2jEFl;0d@+Z3>RF2tRo96}k26Ay>TX>T4JC*ohY5ac;x+ zFXEf(-owW|5a^k2!;@}A5H^^j_zW8n{&;6w@y;Jc4&c+Uv&S(26kngXGQY%#OF+2%h7QF2=?Bd+Yb|{gn&vAZ8eoA$*a}AR_m>+ z%q}NTY6#+TkZl?oy84r*I`+R0%t6g*%4{h7_x*q39^9IB3-Npa000nVWkN?pIW;mf gH$gKtH8?mlH$*ZwaUf*?0000b`w`->K^Ao+K-Z!aL_=v9j1( zPCoX=R1^iTI&kKQSvE4>l^?hy)gSKwbPR%F7Ft}_`eX9mM^5xZN8708djgPLI5BQa zv-sVPr7|-NYu`thVUTcs4Jn3h-x($iO zbu{&L()aZsL=PaENG3UqbM2e4f?>?gS7U8z1xP{aTIvX*?J$5v9L)Hkxwh>wgKU%< z8i*#Kt&J&&L3998^Smgcd7c*{20)0SwGJ#=U%ST0qjDD^YL^^~DI@?^8BAerMvZxQ z%o0;`Tu=?o$R!Xu1_;0~g)l8Bopr>xL-jO7rL0y>?K=TtY9!#rqFL><@0;)FTM9NU z^d&%upC%SDjmid~(7ui7bR`L}Di~MVx+((Ln1X033?8?q0l?VeHxrsNiIRPce{=o< zP2YO+b+%`|`b2*JbCZ1t=fIEvFlOZeisL#BOkxP2C}FN<3Nc|{6DZ~MxefXF!*}G{ z^FPwC3s976G=`}f&XW`>aaA=AVDoO((mWU|5CDEz0C1ZE1Ve(jd6G(48w&wK7uoSUf` zOqbq>aJkiO#Vdap-6D@;U5L6C^p@0j0X`x3<%NU`p#jiEX%Jy7?iU!d^SKH`)2wc` zH}pydg%ogHjRMf#zm(E_073yY0sW-MQ{j-k8S(XuC+G+L^tejfkbrfALbP3w)L6$F z*UO+larW?W`!{m{`is`=glFpZcjFpugPn)>6}E&B7kuW;in zEq&)*tidT5Gt0)NrX%0KBsB!p0_Yl>Vbj(N5pXddu4EuxpcEtmq~@uynexM1DxA|H zNypJw5QP~6F^C?3nzoHOu6vLaVI#`8tv2#m&fCs$6Ka6EAO_I_7&6D0Raxe0nga^0 z@01@@XS(^|uhCYungIreLl8XxoMPYc94hhaI594mgaV)sIjfclv_UF9jPy7fcM?&SyOcjLn^f z4Adh!JE(PaWtB2V{G;)~36y_8D3n%UZ&pQI*%Fi-!&dXdB0x*C8z+5mT0MHa% z0DuT!@#{Q`Omm6VPtXTUR?wUvfJ)W@6A1GUV?fNkQ&Xf8Qkdz>k}lLR4H2LSuSbX< zCa9k406-!#_vF3pI@8H9HzBS!Tv*8 zi-c)hR&rb;}Mt>+76z$dZ6AUHY5t z7uV;z1F+o`SOTV9n}TH);j{POEhm55Py7yol+tDIi<~DrvAik;ox_Z3@0^Rg& zxYLaY!UnVDZek(jy1bb`u?S~1JLO>~qwwlUzvTC)j)mm#xvx^C&>VlXIWRbdt zruL+%mj3sFF{m*OnRSK#zW*Pz1`Me@Rx=p@000nVWkN?YFfcMgGB`CiI5J>U&3#WFrUzE`mQnP!Pe7ox7PB!IcYxYsG~>$3LJOSK>+q6BP+A+yxP0 zVi=Ktn2*KW+tnrKy!BRBf6bj_K5h#>~x(4;3daNsY$`00V<$=u(U8T7OP4#>|O+>S&wQ9Txz_g$v`()a7IQu9TT! zSo<-r*2WaX zAO--XdF6dJuPQHM0EF$yk8^aAmS`ldqpqfMiIJur5+bYhxoosvM@iUSx>3-h5-WdZ=DJ zTU3kcyChBpU~m83BNI41fNe~{))(PcZ^M&sMCh~R&)E8TdC87Ph~ zNliiZ0EWh9*tP9O1Y9hpD;dZTs07IXrFm&=ru^`hO6Lqn%5n4+L}8{t3}OVJrhQ|M z>mDRNZA6aSYNzNb-gbeTPzN*wF^C?(lsU$%%DPh13Q%a{p!}rP>E?sKM%%P%1{fGl zL5u)!iXG!QRO8oiVeFZN0-z5CtCk7$K^i`c^m{bObrQg8hgp^4Hgk_(Ov#vO;3;PD zB*75RHdJjO0YA$V1XExVT?!)rs~*>0_|6=r08lU|OP+)0f>vVvRRVz#003hU>yRLd z6nX%#W7Gn37{-w~#%hiUr^8a9sl%L$G}20lZUlj`b@rt>C2KX)HDqlz^B(E#19ix&vgJG5m|BpihTCbK21$O zee;XF_Rg#F)#qQzix-}g@9wV%u}W(KDWGzsK)5swVGdwfYs^;tPBLCpl`Nddr&srA zdg($fyRW~TL2i8UHQOH^u4N6=R;S@G#+(9@SvBoE0INmBPUByCM*xc+-+gj*zXxz| z{a3d4zP~27{<$yLAFdd+O$7i}K{ur)>NIeHZUWfBod5_C*{LcWuS7onaF3?Ytp`m8 z!4yEZtEEl>s&89PLujKM0^&3PUfJE{oI{obbocJxY=3;TJ{^Fgroa*~o!S%}XAyqz z((`idj{~lF)1?aPcndLYmf--ajMh#+h*hv5k}BK+~zw&JZn zj10i0VQY_L04T(kUPz!a1+EJ&xb&WI)~{rcrEu;qr7)j@09`7Qw-6L0YI>~ z_S}A$KqUlJf@rI$93`t(`&zBFrZT&nK&c^!$v`$~XlUwBn(Em9J}?J0rzx|c@Zb0U z1AOu5nhJv9+W-In5M*USM@2z5I5t8xMm0h-G&eXnMVQUe2LJ#707*qoM6N<$f&g@& B###UX literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waning_gibbous.png b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waning_gibbous.png new file mode 100644 index 0000000000000000000000000000000000000000..2058eef562a0ef0e4a653e6a7322e3249a7fb607 GIT binary patch literal 1647 zcmV-#29WuQP)e*E!5mAH%!RSR0Pl|$g@}>t##DgGsFeo{xD2N9U0)l^ppy0)WUIals znTUxWF$togE=Ek$up$95ABUZp>XPUEsILCnnPg`(d0?oT>fU~S?^D&)J&E()#}ER| zmP@_)6jN_V-g~}k&zS>eZeYBv*mFr%cf1AAGEhUOEv{?*A;lOIC;HlvHmUxe0c01> zjB8VuzT2@}W`<$u#{|<4qUU!2Ty12=X3pQU3j0Lg?L6)-NOZ^i09F}HVQxmX zd3($f6LVZp49zHH5Hbb`z;FsWEhwGqNO5cRY=}y^S~0cn43JV|0=`%>tAg}n{T+Qv z!KQ_M89?J_6N{LQ${N5+-^OIRvIMv)7*C}Q(*$5+0wSq!@VGq<0LB)-nXoA*QF0&S z-+p(BO`$j6c#V#K{TZG4b0dx692hbHjJa}!;&GV+zimr{B09rXreK|@H-<Zz^|d2y zQvJOJU>Y!)VV=}6GHQH$f48hDCXJSrIC*@mhOB;aSc zLU0P4M4dthz^cc!N4_?PDF6h_(F&h~=YmvX{jq|;2mpXFh)Gb0EQJOD>^N$IISgaR z9AhPq5l@Guz@`p!PBf*8LUbJnj7@@s4jpY>e#{VKT@y$Fl_Ld)(`g7p04t@$Y}K!-@u(?&#Pp?ed^ z@%KOG_KS-Xn!vP@Y1oW0rGR9{(`p!it3||4;$QKO0W5kPdvX812EfMAliZ#=e1uN_ zbDoY~9COq*6#y6q*_5VHrhymeEPz$q34kD?)uNE`g6M^3_OdB-`oc7UU<#l=iWQjx zR9{s*4WWv(35Z1i+`qQQa}HS&(Al$pbNl6`$zlMungUC}w6H0dXAwSq=goBFw+&wL zraiarPGj3zg!9~n5AVh|(O(xXH9(*%z74m#5kc5sHp3NcMEK*SZN*D}7#V;~!_pqd z01${Jy^uh83cN0O!RdR#PQQ{tmcmtkDTR3-1n9I#zCH2Tk=Jr`3;=??wO8$j36w)X zIf%59%2u*!r7zW5Ys#}r3FK;nm<(i=+J>g)q>1MK_kkg(A@!NHh5x?)AC(&nsRi$r tq5uE@5M*USM@2X|H8eOeK`=o?LPSP0LOQCO0000007*qoM6N<$f&lF&@Ol6M literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waxing_crescent.png b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/minecraft/textures/environment/celestial/moon/waxing_crescent.png new file mode 100644 index 0000000000000000000000000000000000000000..ea4599f243224b11c6c02ef3fbd62a5118667365 GIT binary patch literal 1569 zcmV++2HyFJP)9z;d)q$h957w};4ta$L__yPPAcfE)=qb3nV{02f0 zLqq~%{-8VE)g{mK)>~cuFEj4!?&N`?YN~tt`Mpn7b@wE$EX&}%m-TX~x0yof&8aL) zUUlNk88bICK2(^vBsCr%01OPGp^Gi9YyCNe5E3W)v7>EL_dNs1E}R*6rY?QAW4X)> z!`crCW*Q`(KLT)_kr|sgzh}pDC8MCm1~CFjf7k<T)NM*MZj)(fvwmnN zAw~enM4S{bF0^mP3WhN|UyZeC6(9#`TWJ%Bw$lI>aWvzH=Gykh46;*hXds$^wl=09 z1~CB0&5N>3=0#D87yu#4-a4>oL+d-EfXaP>Xnl4prH}zwWiW-g8Fl8vF-uI%aX~dS zBcDO&7$5+{6ymg?bk>pLj@8o;m9knjweJK-sgZyeOJ=Rte(1iVZzzf2%V+x|FFnDZF1Awu`ZzeQl5*7Ox$Hj6z_w2sB^7`BI z_g{D9@h6^=gDao%90I_Yl}9L!>ohQlDS)zqxtb}&f_+V(65kvpbCW?phX-HK7^Z4i zXDKw|8x$}DVDoO((mWa~5CHy-wtX4I;lULJh=v65b(Tt88*2e#v=bK|epP(l#bw-KZGt5F|I& zu}*d`NJc|rJxNCNu9nYZ(zm7BGl1V54`jEG3nLr<;;loIeqd~5d z09HH9iWs+5EuafFa}Zk2$7}G1ArZ)7MQ~@jLb1saZETJmI6&3=3JzaR(xFopSo|H6q~5V#{Cu6*aj`yjO_1YiIGfLbsm0MHbC z1b_%&@#{Q`EDK51FVF{!D``#;KxONI3B>t_F(B&T)fB136ju7Oqzg4pLjow{>k;CI z399Eh0Fa0*xd25ze*Y3pO+S9~lf3cHYjXI>=km0)D?+T|nm`Ju94QbkPJ^EV zSXLUdRlgUF7eyfpC-Twdi!{A(u9E#XUrr!DfA%%oAMV#u!?e|DI0_-9fMixpI}gBW z5wX+wm!%_sMUP`2UcS@=xPAQ>ws)>xlbe6umFxFcjM}CG04uLIr6%Y!aDlD^*uzc$ zgox}Fg^m{@AG~*wrqIoMO#;CbK))4BodQ(fwwwmv1~~%6NdUaMzt1^`ED7k=tv}e_ zcu=1Vz{94%5-^?E6l}5x-+lf`x%TUAu6Wahr_ZOctrp=X+wiUP_@?^(-h&x8DuG(`AaFx zryxKVi{$pi=Tu(H(J=rB_ST-+4-+VdfN~IRHI;|Ss@1+$Ypp5IE+vp_2x2mjbs8F) z`je*G_}>TSpyo7XHWdE*{y&H2<(k~VLrDMt01#wlLPt0>FhepzHZw#FSc_dF!pN{>sem&hF%ap=zpo`}w_3Raf_HRuqMI&dF?L zu{WQ5>Z_#ht6qo>Ks1p|av0~@H)93En4Pc2+EfaVf>f1M5k%X50E;-7@k4WMn_~u9 zD>XC_O+Z^4QxJn_0i@=6QAG1RFGLK05Jh7hShT)!wUI~VE<#i;ITlk$0IV{Y!rY8% z^Y)k}rslYy8k&(yAao26fME(@T2MOch;fJNX^2W$t(w|*0>sovz>7t*%4y%%-_f@e zY+C3`fDk`TEMgjsYJfufHm1{+B*3a*Tx#pe2w-ChqNy-=+@1yiV~gKRXv!o;>|-1k zGabHbO&)smNqO_FcjU8A-jl<3-z)1Up5-|NfH5l%P#o83U=n=*#R%qVrVwNHHGz@1 zax0oY{mgOpUwru$`T3{s**|siIU2)M4W~&8rMMCW3;@`?TeUO~#tH<0|6=8L99omV zE^jgc2oR@E9#?>1NDwzoQVDBgCP1hhrp0I+A3Chw_&QY zAHSbeyN%m$_Zty9l{hz1Gnmf35#e&n+lrU|FuFw^$GQ-8E$A(&?*e>6?#l}a7eWo7 zi_##%Slll#X6JJihNfQKY`67F289%GT#W+I-oKR6y$3=8Gy(mj$5Y{uy&3WKj3?*^ z{q(p>+mL{DgF>`zkknYmYS~^8joQX~lD1ShzXpJs7fnH+8fI8#YW>jBHmd&K0x%7j z%rKAY7@E4{*)96>ysL2I%`JWBovq#}7&6O-rluv|y(HBK)c|N4n_=BnGZAnxAFgB| zZJ-n+0;J}tv6=G2TPmE>B1y;5R}h8i12KpWfSNXqIj(z<6k#LExUJUmSVZQ4ErED064|I<2f|Kuj9nHU=j*| zKIE)gCeQ>a`7qMsXpn0!fYlDOJj8A01zuKzG1I_P%;E`xA)alh+CUtBmInx?z$EGv zIsjHZu01YlbC?1^!7^FlIe0E;CDxw=5EuafFa|Mo0U}AE0RTHjEii|n@0eq3#4+J? zSPC@FFy|trRN{Qrfxy_*Y4`vF76I~j7vxfKuC;oYjYT7eIZRnhtOv0K#3aA_@5H3uE8vxr{TB*Ef#R^vHpctUdlf1o`fRPuYHT zeJWF!Ryqw^-p3S>%%rS_0az^}&NTj&A|rrBk7KWG9BTkWT zwg9mRfQQ%CIOmWh0bRQEC)=-YOcw)ivnj9yObeTWc^2XG_uMY$f7|4WHyt^2FplkN z5zccPK5-D=RDWE%(Ex#Vd>ig|BZ9EOY`Gn5MEK*SZN*D}7#V;~!_pqd08oe}y^ug@ z3S1XlaN#{+uV2X^OJUz%N@3my0lH8mZ%=&o%41<_VhxtXk5 z?Q6Bxn$qlI0;$>{CIgwJwxOvxX{ug;J`F()sn4uW{{!V&`jLbp+Ft+w01#wlLPs(* hLNqi%MKVD$GBHClH$~ukl8FES002ovPDHLkV1f*L>0tl> literal 0 HcmV?d00001 diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/compare_float.glsl b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/compare_float.glsl new file mode 100644 index 000000000..51156beee --- /dev/null +++ b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/compare_float.glsl @@ -0,0 +1,7 @@ +bool approxEqualsVec3(vec3 v1, vec3 v2, float eps) { + return all(greaterThan(vec3(eps), abs(v1 - v2))); +} + +bool approxEquals(float f1, float f2, float eps) { + return eps >= abs(f1 - f2); +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/get_dimension.glsl b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/get_dimension.glsl new file mode 100644 index 000000000..5764ba775 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/get_dimension.glsl @@ -0,0 +1,5 @@ +int getDimension(vec3 biomeFog, float cloudFogDistance) { + float bloodyCFD = 512.0032; + if (approxEquals(cloudFogDistance, bloodyCFD, 0.00001)) return 1; // Bloody Ambient + return 0; +} \ No newline at end of file diff --git a/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/shift_texture.glsl b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/shift_texture.glsl new file mode 100644 index 000000000..6f1f8bf78 --- /dev/null +++ b/src/main/resources/contents/omc_daily_events_rp/resourcepack/assets/omc_daily_events_rp/shaders/include/shift_texture.glsl @@ -0,0 +1,48 @@ +vec2 shiftTextureUV(vec2 uv, float texHeight, float frameCount, float shiftAmount) +{ + // +1 because the atlas seems to adds a row of pixels around the image (not sure why +2 doesn't seem correct then tho) + float realHeight = texHeight + 1.0; + + // Calculate the static corner UV for the texture in the atlas. + // This is done by flooring the division of the current pixel coordinate with the total texture height. + // This gets the rounded amount of times the texture would fit between the current pixel and the (0,0). + // Multiply this by the height of the texture to get the corner of each fragment in the texture. + vec2 origin = vec2(0.0, (floor(uv.y / (realHeight)) * realHeight)); + + // Shift the texture to the correct frame + float shiftBy = shiftAmount * realHeight / frameCount; + + // normalize the texture coordinate, apply the transformations, move it back + uv -= origin; + uv *= vec2(1.0, 1.0 / frameCount); + uv += vec2(0.0, shiftBy); + uv += origin; + + return uv; +} + +vec2 shiftTextureUV_special(vec2 uv, float texHeight, float frameCount, float shiftAmount) +{ + // +1 because the atlas seems to adds a row of pixels around the image (not sure why +2 doesn't seem correct then tho) + float realHeight = texHeight + 1.0; + + // height of the sun texture (+1) that must be accounted for when the moon phase texture is on the same column as the sun texture on the celestial atlas + float sunHeight = 513.0; + + // Calculate the static corner UV for the texture in the atlas. + // This is done by flooring the division of the current pixel coordinate with the total texture height. + // This gets the rounded amount of times the texture would fit between the current pixel and the (0,0). + // Multiply this by the height of the texture to get the corner of each fragment in the texture. + vec2 origin = vec2(0.0, (floor((uv.y - sunHeight) / (realHeight)) * realHeight) + sunHeight); + + // Shift the texture to the correct frame + float shiftBy = shiftAmount * realHeight / frameCount; + + // normalize the texture coordinate, apply the transformations, move it back + uv -= origin; + uv *= vec2(1.0, 1.0 / frameCount); + uv += vec2(0.0, shiftBy); + uv += origin; + + return uv; +} \ No newline at end of file From 79dc540c98f6d8b5c2cffa4b0c8ca0a51184298f Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Mon, 13 Jul 2026 22:04:15 +0200 Subject: [PATCH 30/50] change: balances --- .../contents/bloodynight/BloodyNightRaidManager.java | 2 +- .../contents/loottable/BloodyMobLootTable.java | 2 +- .../bloodynight/listeners/MonsterSpawnLIstener.java | 8 ++++---- .../bloodynight/listeners/PlayerKillMonsterListener.java | 4 +--- 4 files changed, 7 insertions(+), 9 deletions(-) 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 index 8a8802357..5ea1905f6 100644 --- 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 @@ -17,7 +17,7 @@ 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 int MAX_SPAWN_RADIUS = 15; private static final List BLOODY_MONSTERS_AVAILABLE = List.of( EntityType.ZOMBIE, 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 index fc68bd18f..5e6e1a37b 100644 --- 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 @@ -25,7 +25,7 @@ public String getNamespace() { @Override public Set getLoots() { return new LinkedHashSet<>(List.of( - new ItemLoot(Material.IRON_INGOT,0.3, 1, 4), + new ItemLoot(Material.IRON_INGOT,0.4, 1, 4), new ItemLoot(Material.GOLD_INGOT,0.2, 1, 3), new ItemLoot(Material.DIAMOND,0.07, 1, 2), new ItemLoot(Material.IRON_BLOCK,0.08, 1), 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 275247b2a..597ae0333 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 @@ -19,14 +19,13 @@ public class MonsterSpawnLIstener implements Listener { @EventHandler public void onNormalMonsterSpawn(EntitySpawnEvent event) { if (!DailyEventsManager.isActiveDailyEvent() - || !(DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent)) return; + || !(DailyEventsManager.getActiveDailyEvent() instanceof BloodyNightEvent bloodyEvent)) return; + if (!event.getLocation().getWorld().getName().equals(bloodyEvent.getWorldEvent())) return; + if (!(event.getEntity() instanceof Monster monster)) return; - System.out.println("e"); if (monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { - System.out.println("b"); BloodyNightManager.applyBloodyMonster(monster); } else { - System.out.println("a"); ParticleUtils.spawnDispersingParticles(event.getLocation(), Particle.DAMAGE_INDICATOR, 10, 35, 0.1D, null); @@ -39,6 +38,7 @@ public void onNormalMonsterSpawn(EntitySpawnEvent event) { 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)) { 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 index 7685dd897..08d95c4b9 100644 --- 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 @@ -5,7 +5,6 @@ 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; @@ -27,8 +26,7 @@ public void onPlayerKill(EntityDeathEvent event) { event.getDrops().clear(); - List loots = OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLootsWithAmount( - player, RandomUtils.randomBetween(1, 2)); + List loots = OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots(player); event.getDrops().clear(); for (CustomLoot loot : loots) { From 0a3f5a74e1a3d966495182f4515443d6aef3a868 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:27:58 +0200 Subject: [PATCH 31/50] fix: chunk loading --- .../core/registry/ambient/CustomAmbient.java | 3 +- .../core/utils/nms/PlayerRespawnNMS.java | 28 ++++++------------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index 2b54f46ce..cc54a2de1 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -86,6 +86,7 @@ public void apply(Collection receivers) { */ public void reset(Player player) { ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); + ACTIVE_AMBIENTS.remove(player.getUniqueId()); // * On envoie le packet respawn qui remets tout a la normale PlayerRespawnNMS.sendPacket( @@ -93,8 +94,6 @@ public void reset(Player player) { nmsPlayer.createCommonSpawnInfo(nmsPlayer.level()), getTransitionDimensionForPlayer(nmsPlayer) ); - - ACTIVE_AMBIENTS.remove(player.getUniqueId()); } /** diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java index 0cec2d3e0..42361619d 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java @@ -2,14 +2,15 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.registry.ambient.CustomAmbient; -import net.minecraft.network.protocol.game.*; +import net.minecraft.network.protocol.game.ClientboundChangeDifficultyPacket; +import net.minecraft.network.protocol.game.ClientboundPlayerAbilitiesPacket; +import net.minecraft.network.protocol.game.ClientboundRespawnPacket; +import net.minecraft.network.protocol.game.CommonPlayerSpawnInfo; import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.players.PlayerList; -import net.minecraft.world.level.ChunkPos; import net.minecraft.world.level.Level; -import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.storage.LevelData; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.CraftServer; @@ -113,23 +114,10 @@ private static void sendPostRespawnPackets(ServerPlayer nmsPlayer) { PlayerPositionNMS.sendPos(nmsPlayer, nmsPlayer.position()); - nmsPlayer.connection.send(new ClientboundSetChunkCacheCenterPacket( - nmsPlayer.chunkPosition().x(), - nmsPlayer.chunkPosition().z() - )); - - int viewDistance = nmsWorld.getServer().getPlayerList().getViewDistance(); - ChunkPos center = nmsPlayer.chunkPosition(); - for (int cx = center.x() - viewDistance; cx <= center.x() + viewDistance; cx++) { - for (int cz = center.z() - viewDistance; cz <= center.z() + viewDistance; cz++) { - LevelChunk chunk = nmsWorld.getChunkIfLoaded(cx, cz); - if (chunk != null) { - nmsPlayer.connection.send( - new ClientboundLevelChunkWithLightPacket(chunk, nmsWorld.getLightEngine(), null, null, false) - ); - } - } - } + // Utilisation d'une méthode trouvé via l'utilisation de ClientboundSetChunkCacheCenterPacket. + // Refait tout simplement le systeme de chargement des chunks pour un joueur, sans avoir de défaillance + nmsWorld.moonrise$getPlayerChunkLoader().removePlayer(nmsPlayer); + nmsWorld.moonrise$getPlayerChunkLoader().addPlayer(nmsPlayer); } /** From 51249eabd54641892e7f6451988c5aab8df546b9 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 14 Jul 2026 12:34:49 +0200 Subject: [PATCH 32/50] tested --- .../dailyevents/contents/bloodynight/BloodyNightManager.java | 2 -- 1 file changed, 2 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 07c6e2573..c0e89e8b5 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 @@ -18,8 +18,6 @@ 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 { public static final NamespacedKey RAID_MONSTER_KEY = new NamespacedKey("omc_daily_events", "raid_monster"); From a95c76675f0c836eae4ffb6d31952c0ccd17868f Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 14 Jul 2026 14:35:04 +0200 Subject: [PATCH 33/50] change: buff bloody monsters --- .../contents/mobs/AncientMonster.java | 13 +++++++++---- .../contents/mobs/CorruptedMonster.java | 16 ++++++++++++---- .../bloodynight/contents/mobs/CursedMonster.java | 15 ++++++++++----- .../contents/mobs/EnragedMonster.java | 13 +++++++++---- 4 files changed, 40 insertions(+), 17 deletions(-) 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 c81eb8131..a142eaf62 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 @@ -7,31 +7,32 @@ import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; 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, + 5.00, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "ancient_attack"), - 0.60, + 1.50, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "ancient_speed"), - 0.20, + 0.35, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "ancient_follow"), - 0.60, + 1.00, AttributeModifier.Operation.ADD_SCALAR ); @@ -53,6 +54,10 @@ public void apply(Monster entity) { entity.setCustomNameVisible(false); EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + AttributeInstance attrInst = entity.getAttribute(Attribute.MAX_HEALTH); + if (attrInst == null) return; + entity.setHealth(attrInst.getValue()); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(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 index bd573ae63..f14bd378a 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 @@ -7,28 +7,32 @@ import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; 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, + 1, AttributeModifier.Operation.ADD_SCALAR ); + private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "corrupted_attack"), - 0.10, + 0.25, AttributeModifier.Operation.ADD_SCALAR ); + private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "corrupted_speed"), - 0.10, + 0.15, AttributeModifier.Operation.ADD_SCALAR ); + private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "corrupted_follow"), - 0.10, + 0.25, AttributeModifier.Operation.ADD_SCALAR ); @@ -49,6 +53,10 @@ public void apply(Monster entity) { entity.setCustomNameVisible(false); EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + AttributeInstance attrInst = entity.getAttribute(Attribute.MAX_HEALTH); + if (attrInst == null) return; + entity.setHealth(attrInst.getValue()); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(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 index 1a49cc010..aad135729 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 @@ -7,37 +7,38 @@ import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; 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, + 3, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "cursed_attack"), - 0.25, + 0.90, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "cursed_speed"), - -0.15, + -0.10, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "cursed_follow"), - 0.20, + 0.70, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier SCALE_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "cursed_scale"), - 0.40, + 1, AttributeModifier.Operation.ADD_SCALAR ); @@ -72,6 +73,10 @@ public void resetToDefault(Monster entity) { entity.setCustomNameVisible(true); EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + AttributeInstance attrInst = entity.getAttribute(Attribute.MAX_HEALTH); + if (attrInst == null) return; + entity.setHealth(attrInst.getValue()); + 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/EnragedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java index 1f6c8bf19..d233e1850 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 @@ -7,31 +7,32 @@ import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; 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, + 1.75, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier ATTACK_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "enraged_attack"), - 0.35, + 0.55, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier SPEED_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "enraged_speed"), - 0.35, + 0.30, AttributeModifier.Operation.ADD_SCALAR ); private static final AttributeModifier FOLLOW_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "enraged_follow"), - 0.30, + 0.45, AttributeModifier.Operation.ADD_SCALAR ); @@ -65,6 +66,10 @@ public void resetToDefault(Monster entity) { entity.setCustomNameVisible(true); EntityUtils.removeModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + AttributeInstance attrInst = entity.getAttribute(Attribute.MAX_HEALTH); + if (attrInst == null) return; + entity.setHealth(attrInst.getValue()); + EntityUtils.removeModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.removeModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); From f4677bb6bad96d294d0bf2a3f3129bb044f9e7d7 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 14 Jul 2026 19:04:51 +0200 Subject: [PATCH 34/50] feat: add base of Vampire Boss (summoning, support bossbar for CustomMob) --- .../java/fr/openmc/core/ListenersManager.java | 6 +- .../loottable/BloodyMobLootTable.java | 2 + .../contents/mobs/vampire/VampireBoss.java | 131 ++++++++++++++++++ .../vampire/tasks/SummoningEffectTask.java | 112 +++++++++++++++ .../openmc/core/registry/mobs/CustomMob.java | 2 + .../core/registry/mobs/CustomMobRegistry.java | 22 +++ .../listeners/CustomMobBossbarListener.java | 44 ++++++ .../mobs/listeners/CustomMobLoadListener.java | 21 +++ .../registry/mobs/options/MobBossbarImpl.java | 109 +++++++++++++++ .../registry/mobs/task/MobBossbarUpdater.java | 39 ++++++ .../default/dailyevents.properties | 10 +- 11 files changed, 496 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/SummoningEffectTask.java create mode 100644 src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobBossbarListener.java create mode 100644 src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobLoadListener.java create mode 100644 src/main/java/fr/openmc/core/registry/mobs/options/MobBossbarImpl.java create mode 100644 src/main/java/fr/openmc/core/registry/mobs/task/MobBossbarUpdater.java diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index aac51507c..0f9c1f642 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -9,7 +9,9 @@ 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.CustomMobBossbarListener; import fr.openmc.core.registry.mobs.listeners.CustomMobDeathListener; +import fr.openmc.core.registry.mobs.listeners.CustomMobLoadListener; import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import org.bukkit.Bukkit; import org.bukkit.Server; @@ -46,7 +48,9 @@ public static void init() { new BiomesOnChunkLoad(), new AmbientWeatherListener(), new AmbientFixedTimeListener(), - new EntityGlowNMS() + new EntityGlowNMS(), + new CustomMobBossbarListener(), + new CustomMobLoadListener() ); if (!OMCPlugin.isUnitTestVersion()) { 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 index 5e6e1a37b..2815ae587 100644 --- 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 @@ -1,5 +1,6 @@ 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; @@ -27,6 +28,7 @@ public Set getLoots() { return new LinkedHashSet<>(List.of( new ItemLoot(Material.IRON_INGOT,0.4, 1, 4), new ItemLoot(Material.GOLD_INGOT,0.2, 1, 3), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE,0.2, 1, 3), new ItemLoot(Material.DIAMOND,0.07, 1, 2), new ItemLoot(Material.IRON_BLOCK,0.08, 1), new ItemLoot(Material.GOLD_BLOCK,0.06, 1), diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java new file mode 100644 index 000000000..18afa8fda --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -0,0 +1,131 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.registry.mobs.CustomMobAttribute; +import fr.openmc.core.registry.mobs.options.MobBossbarImpl; +import fr.openmc.core.utils.bukkit.ParticleUtils; +import fr.openmc.core.utils.text.messages.TranslationManager; +import io.papermc.paper.datacomponent.item.ResolvableProfile; +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.*; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Mannequin; +import org.bukkit.entity.Player; + +import java.util.UUID; + +import static fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask.SUMMON_EFFECT_INTERVAL_TICKS; + +@SuppressWarnings("UnstableApiUsage") +public class VampireBoss extends CustomMob implements MobBossbarImpl { + public VampireBoss(String id) { + super(id, + "Vampire", + Mannequin.class, + 1000, + 20, + 0.1, + new CustomMobAttribute(Attribute.SCALE, 20), + new CustomMobAttribute(Attribute.KNOCKBACK_RESISTANCE, 1) + ); + } + + @Override + public Mannequin spawn(Location spawnLocation) { + startSummoning(spawnLocation); + return null; + } + + private void startSummoning(Location at) { + World world = at.getWorld(); + for (Player player : world.getPlayers()) { + player.sendMessage(TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.coming" + )); + } + + new SummoningEffectTask(this, at).runTaskTimer( + OMCPlugin.getInstance(), + 0L, + SUMMON_EFFECT_INTERVAL_TICKS + ); + } + + public void summon(Location at) { + Mannequin mannequin = this.getPreBuildMob(at); + mannequin.setDescription(Component.empty()); + mannequin.setProfile(ResolvableProfile.resolvableProfile() + .uuid(UUID.fromString("2add34b4-2d09-4204-a458-6251b0d24661")) + .build() + ); + + World world = at.getWorld(); + + ParticleUtils.spawnCubeParticles( + at.clone().add(0, 2, 0), + Particle.EXPLOSION_EMITTER, + 1.0, + 2.0, + 1.0, + 10, + 100, + null + ); + + ParticleUtils.spawnCubeParticles( + at.clone().add(0, 2, 0), + Particle.LAVA, + 3.0, + 5.0, + 3.0, + 200, + 100, + null + ); + + world.playSound( + at, + Sound.ENTITY_WITHER_SPAWN, + SoundCategory.HOSTILE, + 5.0F, + 0.6F + ); + + for (Player player : world.getPlayers()) { + player.sendMessage( + TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.summoned", + Component.text(at.getX(), NamedTextColor.RED), + Component.text(at.getY(), NamedTextColor.RED), + Component.text(at.getZ(), NamedTextColor.RED) + ) + ); + } + } + + @Override + public Component getBossBarName(LivingEntity entity) { + return TranslationManager.translation("feature.dailyevents.bloody_night.vampire_boss.name"); + } + + @Override + public BossBar.Color getBossBarColor() { + return BossBar.Color.RED; + } + + @Override + public BossBar.Overlay getBossBarOverlay() { + return BossBar.Overlay.NOTCHED_6; + } + + @Override + public double getBossBarViewRadius() { + return 60; + } +} + diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/SummoningEffectTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/SummoningEffectTask.java new file mode 100644 index 000000000..ad77cad52 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/SummoningEffectTask.java @@ -0,0 +1,112 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks; + +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.*; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.concurrent.ThreadLocalRandom; + +public class SummoningEffectTask extends BukkitRunnable { + private final VampireBoss boss; + private final Location spawnLocation; + private long elapsedTicks = 0; + + public static final long SUMMON_DURATION_TICKS = 20L * 60L; // 60 sec + public static final long SUMMON_EFFECT_INTERVAL_TICKS = 20L * 5L; // 5 sec + + public SummoningEffectTask(VampireBoss boss, Location spawnLocation) { + this.boss = boss; + this.spawnLocation = spawnLocation; + } + + @Override + public void run() { + if (elapsedTicks >= SUMMON_DURATION_TICKS) { + cancel(); + boss.summon(spawnLocation); + return; + } + + playSummoningEffects(spawnLocation); + + elapsedTicks += SUMMON_EFFECT_INTERVAL_TICKS; + } + + private void playSummoningEffects(Location center) { + World world = center.getWorld(); + + if (world == null) { + return; + } + + ThreadLocalRandom random = ThreadLocalRandom.current(); + + for (int i = 0; i < 12; i++) { + double angle = random.nextDouble(0, Math.PI * 2); + double distance = random.nextDouble(3.0, 12.0); + + double offsetX = Math.cos(angle) * distance; + double offsetZ = Math.sin(angle) * distance; + + Location lightningLocation = center.clone().add( + offsetX, + 0, + offsetZ + ); + + lightningLocation.setY(world.getHighestBlockYAt(lightningLocation) + 1); + + world.strikeLightningEffect(lightningLocation); + } + + ParticleUtils.spawnCubeParticles( + center, + Particle.EXPLOSION, + 3.0, + 3.0, + 3.0, + 15, + 20, + null + ); + + ParticleUtils.spawnCubeParticles( + center, + Particle.RAID_OMEN, + 5.0, + 6.0, + 5.0, + 200, + 40, + null + ); + + ParticleUtils.spawnCubeParticles( + center, + Particle.LARGE_SMOKE, + 4.0, + 4.0, + 4.0, + 100, + 50, + null + ); + + world.playSound( + center, + Sound.ENTITY_WITHER_AMBIENT, + SoundCategory.HOSTILE, + 10.0F, + 0.5F + ); + + world.playSound( + center, + Sound.ENTITY_LIGHTNING_BOLT_THUNDER, + SoundCategory.WEATHER, + 4.0F, + 0.3F + ); + } +} \ 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 efa1493c3..ddabaafa3 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMob.java @@ -93,6 +93,8 @@ public EntitySnapshot getMobSnapshot(Object... objects) { public T getPreBuildMob(Location spawnLocation) { T livingEntity = spawnLocation.getWorld().spawn(spawnLocation.add(0, 1, 0), entityClass, null, CreatureSpawnEvent.SpawnReason.CUSTOM); applyStats(livingEntity); + + CustomMobRegistry.HAS_BOSSBAR.add(livingEntity.getUniqueId()); return livingEntity; } 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 455b441d5..8c3bab42f 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java @@ -7,14 +7,20 @@ 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.bloodynight.contents.mobs.vampire.VampireBoss; 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 fr.openmc.core.registry.mobs.task.MobBossbarUpdater; import org.bukkit.NamespacedKey; import org.bukkit.entity.Entity; import org.bukkit.event.Listener; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + public class CustomMobRegistry extends Registry implements KeyedRegistry { public static final NamespacedKey CUSTOM_MOB_KEY = @@ -81,6 +87,22 @@ public class CustomMobRegistry extends Registry implemen CorruptedMonster::new )); + public final CustomMobEntry VAMPIRE_BOSS = register(new CustomMobEntry( + "omc_daily_events:vampire_boss", + VampireBoss::new + )); + + public final static Set HAS_BOSSBAR = new HashSet<>(); + + @Override + public void postInit() { + new MobBossbarUpdater().runTaskTimer( + OMCPlugin.getInstance(), + 0L, + 20L + ); + } + @Override public String key(CustomMobEntry registryObject) { return registryObject.id(); diff --git a/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobBossbarListener.java b/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobBossbarListener.java new file mode 100644 index 000000000..24f05aebb --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobBossbarListener.java @@ -0,0 +1,44 @@ +package fr.openmc.core.registry.mobs.listeners; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.registry.mobs.options.MobBossbarImpl; +import org.bukkit.Bukkit; +import org.bukkit.entity.LivingEntity; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDeathEvent; + +public class CustomMobBossbarListener implements Listener { + @EventHandler(ignoreCancelled = true) + public void onCustomMobDamage(EntityDamageEvent event) { + if (!(event.getEntity() instanceof LivingEntity entity)) return; + + CustomMob customMob = OMCRegistry.CUSTOM_MOBS.getMob(entity); + + if (!(customMob instanceof MobBossbarImpl bossBarMob)) return; + + Bukkit.getScheduler().runTask(OMCPlugin.getInstance(), () -> { + if (!entity.isValid() || entity.isDead()) { + bossBarMob.removeBossBar(entity); + return; + } + + bossBarMob.updateBossBar(entity); + bossBarMob.updateBossBarViewers(entity); + }); + } + + @EventHandler + public void onCustomMobDeath(EntityDeathEvent event) { + LivingEntity entity = event.getEntity(); + + CustomMob customMob = OMCRegistry.CUSTOM_MOBS.getMob(entity); + + if (customMob instanceof MobBossbarImpl bossBarMob) { + bossBarMob.removeBossBar(entity); + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobLoadListener.java b/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobLoadListener.java new file mode 100644 index 000000000..28b26f5b8 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/mobs/listeners/CustomMobLoadListener.java @@ -0,0 +1,21 @@ +package fr.openmc.core.registry.mobs.listeners; + +import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.registry.mobs.CustomMobRegistry; +import fr.openmc.core.registry.mobs.options.MobBossbarImpl; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class CustomMobLoadListener implements Listener { + @EventHandler + public void onEntityLoad(EntityAddToWorldEvent event) { + CustomMob customMob = OMCRegistry.CUSTOM_MOBS.getMob(event.getEntity()); + if (customMob == null) return; + if (!(customMob instanceof MobBossbarImpl)) return; + if (!(event.getEntity() instanceof MobBossbarImpl)) return; + + CustomMobRegistry.HAS_BOSSBAR.add(event.getEntity().getUniqueId()); + } +} diff --git a/src/main/java/fr/openmc/core/registry/mobs/options/MobBossbarImpl.java b/src/main/java/fr/openmc/core/registry/mobs/options/MobBossbarImpl.java new file mode 100644 index 000000000..6a10462dd --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/mobs/options/MobBossbarImpl.java @@ -0,0 +1,109 @@ +package fr.openmc.core.registry.mobs.options; + +import net.kyori.adventure.bossbar.BossBar; +import net.kyori.adventure.text.Component; +import org.bukkit.attribute.Attribute; +import org.bukkit.attribute.AttributeInstance; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; + +import java.util.Collection; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public interface MobBossbarImpl { + Map ACTIVE_BOSS_BARS = new ConcurrentHashMap<>(); + + default Component getBossBarName(LivingEntity entity) { + return entity.customName() != null + ? entity.customName() + : Component.text(entity.getName()); + } + + BossBar.Color getBossBarColor(); + + BossBar.Overlay getBossBarOverlay(); + + double getBossBarViewRadius(); + + default BossBar createBossBar(LivingEntity entity) { + BossBar bossBar = BossBar.bossBar( + getBossBarName(entity), + getHealthProgress(entity), + getBossBarColor(), + getBossBarOverlay() + ); + + ACTIVE_BOSS_BARS.put(entity.getUniqueId(), bossBar); + + return bossBar; + } + + default BossBar getBossBar(LivingEntity entity) { + return ACTIVE_BOSS_BARS.get(entity.getUniqueId()); + } + + default BossBar getOrCreateBossBar(LivingEntity entity) { + BossBar bossBar = getBossBar(entity); + + if (bossBar != null) { + return bossBar; + } + + return createBossBar(entity); + } + + default void updateBossBar(LivingEntity entity) { + BossBar bossBar = getOrCreateBossBar(entity); + + bossBar.name(getBossBarName(entity)); + bossBar.progress(getHealthProgress(entity)); + } + + default void updateBossBarViewers(LivingEntity entity) { + BossBar bossBar = getOrCreateBossBar(entity); + + double radius = getBossBarViewRadius(); + double radiusSquared = radius * radius; + + Collection players = entity.getWorld().getPlayers(); + + for (Player player : players) { + boolean shouldSee = + player.getLocation().distanceSquared(entity.getLocation()) + <= radiusSquared; + + if (shouldSee) { + player.showBossBar(bossBar); + } else { + player.hideBossBar(bossBar); + } + } + } + + default void removeBossBar(LivingEntity entity) { + BossBar bossBar = ACTIVE_BOSS_BARS.remove(entity.getUniqueId()); + + if (bossBar == null) { + return; + } + + for (Player player : entity.getWorld().getPlayers()) { + player.hideBossBar(bossBar); + } + } + + private float getHealthProgress(LivingEntity entity) { + AttributeInstance maxHealthAttribute = entity.getAttribute(Attribute.MAX_HEALTH); + if (maxHealthAttribute == null) return 0; + + if (maxHealthAttribute.getValue() <= 0) { + return 0.0F; + } + + double progress = entity.getHealth() / maxHealthAttribute.getValue(); + + return (float) Math.clamp(progress, 0.0, 1.0); + } +} diff --git a/src/main/java/fr/openmc/core/registry/mobs/task/MobBossbarUpdater.java b/src/main/java/fr/openmc/core/registry/mobs/task/MobBossbarUpdater.java new file mode 100644 index 000000000..0dcf78015 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/mobs/task/MobBossbarUpdater.java @@ -0,0 +1,39 @@ +package fr.openmc.core.registry.mobs.task; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.registry.mobs.CustomMobRegistry; +import fr.openmc.core.registry.mobs.options.MobBossbarImpl; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Iterator; +import java.util.UUID; + +public class MobBossbarUpdater extends BukkitRunnable { + + @Override + public void run() { + Iterator iterator = CustomMobRegistry.HAS_BOSSBAR.iterator(); + + while (iterator.hasNext()) { + UUID uuid = iterator.next(); + Entity entity = Bukkit.getEntity(uuid); + + if (!(entity instanceof LivingEntity livingEntity)) return; + CustomMob customMob = OMCRegistry.CUSTOM_MOBS.getMob(entity); + if (customMob == null) return; + if (!(customMob instanceof MobBossbarImpl bossBarMob)) return; + + if (!livingEntity.isValid() || livingEntity.isDead()) { + bossBarMob.removeBossBar(livingEntity); + iterator.remove(); + continue; + } + + bossBarMob.updateBossBarViewers(livingEntity); + } + } +} diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 093fc562c..5eddf5f8c 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -105,4 +105,12 @@ feature.dailyevents.miraculousfishing.menu.info.loot_table.lore=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 +feature.dailyevents.bloody_night.enchantment.vampirism.name=Vampirisme +feature.dailyevents.bloody_night.vampire_boss.name=Vampire +feature.dailyevents.bloody_night.vampire_boss.coming=Une anomalie commence à se rapprocher du sol +feature.dailyevents.bloody_night.vampire_boss.summoned= \ +
\ +
BOSS VAMPIRE ! un boss vient attérir en %1$s %2$s %3$s \ +
*unissez vous afin de le battre tous ensemble !*\ +
\ +
\ No newline at end of file From bbfb309b217a481b19c6ae59c09097fe4e177506 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Tue, 14 Jul 2026 20:17:50 +0200 Subject: [PATCH 35/50] feat: add BloodExplosionAttack --- .../contents/mobs/vampire/VampireBoss.java | 33 ++++ .../vampire/attacks/BloodExplosionAttack.java | 161 ++++++++++++++++++ .../mobs/vampire/tasks/VampireAttackTask.java | 38 +++++ .../openmc/core/registry/mobs/MobAttack.java | 9 + 4 files changed, 241 insertions(+) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java create mode 100644 src/main/java/fr/openmc/core/registry/mobs/MobAttack.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java index 18afa8fda..b3af5d158 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -1,13 +1,17 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire; import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks.BloodExplosionAttack; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.VampireAttackTask; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.registry.mobs.CustomMobAttribute; +import fr.openmc.core.registry.mobs.MobAttack; import fr.openmc.core.registry.mobs.options.MobBossbarImpl; import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.text.messages.TranslationManager; import io.papermc.paper.datacomponent.item.ResolvableProfile; +import lombok.Getter; import net.kyori.adventure.bossbar.BossBar; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -17,12 +21,25 @@ import org.bukkit.entity.Mannequin; import org.bukkit.entity.Player; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; import static fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask.SUMMON_EFFECT_INTERVAL_TICKS; +//todo: attack (blood explosion, explosive bat, mini vempire defender) +//todo: death (sfx, rewards mailbox en fonction des dégats mis (plus de dégat plus de chance) @SuppressWarnings("UnstableApiUsage") +@Getter public class VampireBoss extends CustomMob implements MobBossbarImpl { + private final Random random = ThreadLocalRandom.current(); + private final List attacks = new ArrayList<>(List.of( + new BloodExplosionAttack(this) + )); + private Mannequin mannequin; + public VampireBoss(String id) { super(id, "Vampire", @@ -64,6 +81,12 @@ public void summon(Location at) { .build() ); + + new VampireAttackTask(this).runTaskLater( + OMCPlugin.getInstance(), + 20L * 10 // 10 sex + ); + World world = at.getWorld(); ParticleUtils.spawnCubeParticles( @@ -106,6 +129,8 @@ public void summon(Location at) { ) ); } + + this.mannequin = mannequin; } @Override @@ -127,5 +152,13 @@ public BossBar.Overlay getBossBarOverlay() { public double getBossBarViewRadius() { return 60; } + + public void pickRandomAttack() { + if (attacks.isEmpty()) { + return; + } + + attacks.get(random.nextInt(attacks.size())).execute(); + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java new file mode 100644 index 000000000..d46bf6727 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java @@ -0,0 +1,161 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks; + +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import fr.openmc.core.registry.mobs.MobAttack; +import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.*; +import org.bukkit.entity.Mannequin; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public class BloodExplosionAttack implements MobAttack { + + private final VampireBoss boss; + + public BloodExplosionAttack(VampireBoss boss) { + this.boss = boss; + } + + @Override + public void execute() { + Mannequin mannequin = boss.getMannequin(); + + if (mannequin == null || !mannequin.isValid() || mannequin.isDead()) return; + + Location center = mannequin.getLocation() + .clone() + .add(0, mannequin.getHeight() / 3.0, 0); + + spawnRadialParticles(center); + damageNearbyPlayers(mannequin); + + World world = mannequin.getWorld(); + + world.playSound( + center, + Sound.ENTITY_GENERIC_EXPLODE, + SoundCategory.HOSTILE, + 3.0F, + 0.6F + ); + + world.playSound( + center, + Sound.ENTITY_WITHER_HURT, + SoundCategory.HOSTILE, + 2.0F, + 0.5F + ); + } + + private void damageNearbyPlayers(Mannequin mannequin) { + Collection players = mannequin.getWorld().getNearbyPlayers( + mannequin.getLocation(), + 20 + ); + + for (Player player : players) { + if (!canDamage(player)) { + continue; + } + + double newHealth = player.getHealth() * 0.7; + + player.setHealth(Math.max(1.0, newHealth)); + + player.playSound( + player.getLocation(), + Sound.ENTITY_PLAYER_HURT, + SoundCategory.PLAYERS, + 1.0F, + 0.7F + ); + } + } + + private boolean canDamage(Player player) { + return player.isValid() + && !player.isDead() + && player.getGameMode() != GameMode.CREATIVE + && player.getGameMode() != GameMode.SPECTATOR; + } + + /** + * Fait apparaitre des particules de sorte qui partent dans toutes les directions d'un cercle en 2D + * Math + * @param center le mob + */ + private void spawnRadialParticles(Location center) { + Collection receivers = + center.getNearbyEntitiesByType( + Player.class, + 50 + ); + + if (receivers.isEmpty()) return; + + int directions = 64; + double particleSpeed = 1.2; + + double[] heightOffsets = { + -2.0, + -1.0, + 0.0, + 1.0, + 2.0 + }; + + for (double heightOffset : heightOffsets) { + Location particleOrigin = center.clone().add( + 0, + heightOffset, + 0 + ); + + for (int i = 0; i < directions; i++) { + double angle = (Math.PI * 2 * i) / directions; + + double directionX = Math.cos(angle); + double directionZ = Math.sin(angle); + + for (Player player : receivers) { + ParticleUtils.sendParticlePacket( + player, + Particle.DUST, + particleOrigin, + 0, + directionX, + 0.0, + directionZ, + particleSpeed, + new Particle.DustOptions(Color.RED, 1.0f) + ); + + ParticleUtils.sendParticlePacket( + player, + Particle.LARGE_SMOKE, + particleOrigin, + 0, + directionX, + 0.0, + directionZ, + particleSpeed * 0.7, + null + ); + } + } + } + + ParticleUtils.spawnCubeParticles( + center, + Particle.EXPLOSION, + 1.5, + 2.5, + 1.5, + 20, + 50, + null + ); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java new file mode 100644 index 000000000..107748df1 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java @@ -0,0 +1,38 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; + +public class VampireAttackTask extends BukkitRunnable { + private final VampireBoss boss; + private final Random random = ThreadLocalRandom.current(); + + public static final long MIN_ATTACK_DELAY = 20L * 10; // 10 sec + public static final long MAX_ATTACK_DELAY = 20L * 17; // 17 sec + + public VampireAttackTask(VampireBoss boss) { + this.boss = boss; + } + + @Override + public void run() { + if (!boss.getMannequin().isValid()) { + cancel(); + return; + } + + boss.pickRandomAttack(); + + long nextDelay = random.nextLong( + MIN_ATTACK_DELAY, + MAX_ATTACK_DELAY + 1 + ); + + this.cancel(); + this.runTaskLater(OMCPlugin.getInstance(), nextDelay); + } +} diff --git a/src/main/java/fr/openmc/core/registry/mobs/MobAttack.java b/src/main/java/fr/openmc/core/registry/mobs/MobAttack.java new file mode 100644 index 000000000..e85cc3803 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/mobs/MobAttack.java @@ -0,0 +1,9 @@ +package fr.openmc.core.registry.mobs; + +/** + * Une interface représentant des attaques custom de mob. + */ +public interface MobAttack { + + void execute(); +} From 2aa3cec37bf8d257b0128f003c8a7a51d2bfc2bc Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:26:07 +0200 Subject: [PATCH 36/50] feat: add VampireBatAttack --- .../bloodynight/BloodyNightManager.java | 8 +- .../contents/mobs/bat/AbstractVampireBat.java | 157 ++++++++++++++++++ .../mobs/bat/ExplosiveVampireBat.java | 62 +++++++ .../mobs/bat/LevitationVampireBat.java | 74 +++++++++ .../contents/mobs/bat/PoisonVampireBat.java | 77 +++++++++ .../{ => bloodytypes}/AncientMonster.java | 2 +- .../{ => bloodytypes}/CorruptedMonster.java | 2 +- .../mobs/{ => bloodytypes}/CursedMonster.java | 2 +- .../{ => bloodytypes}/EnragedMonster.java | 2 +- .../contents/mobs/vampire/VampireBoss.java | 15 +- .../vampire/attacks/BloodExplosionAttack.java | 4 +- .../vampire/attacks/VampireBatAttack.java | 98 +++++++++++ .../mobs/vampire/tasks/VampireAttackTask.java | 27 ++- .../core/registry/mobs/CustomMobRegistry.java | 26 ++- 14 files changed, 519 insertions(+), 37 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/AbstractVampireBat.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/ExplosiveVampireBat.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/LevitationVampireBat.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/PoisonVampireBat.java rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/{ => bloodytypes}/AncientMonster.java (98%) rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/{ => bloodytypes}/CorruptedMonster.java (98%) rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/{ => bloodytypes}/CursedMonster.java (98%) rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/{ => bloodytypes}/EnragedMonster.java (98%) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/VampireBatAttack.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 c0e89e8b5..c14e00d70 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 @@ -2,10 +2,10 @@ 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 fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.AncientMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CorruptedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CursedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.EnragedMonster; import fr.openmc.core.registry.mobs.CustomMob; import org.bukkit.Bukkit; import org.bukkit.GameRules; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/AbstractVampireBat.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/AbstractVampireBat.java new file mode 100644 index 000000000..278f0cbfc --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/AbstractVampireBat.java @@ -0,0 +1,157 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.registry.mobs.CustomMobAttribute; +import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Bat; +import org.bukkit.entity.Player; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.BoundingBox; +import org.bukkit.util.Vector; + +import java.util.Comparator; + +public abstract class AbstractVampireBat extends CustomMob { + + private static final double SPEED = 0.55; + private static final double SEARCH_RADIUS = 30.0; + + private static final int MAX_LIFETIME_TICKS = 20 * 15; + + public AbstractVampireBat(String id, String name) { + super( + id, + name, + Bat.class, + 10.0, + 0.0, + new CustomMobAttribute(Attribute.KNOCKBACK_RESISTANCE, 1.0) + ); + } + + public Bat spawn(Location location, Player target) { + Bat bat = getPreBuildMob(location.clone()); + + bat.setAwake(true); + bat.setPersistent(false); + + startTargeting(bat, target); + + return bat; + } + + @Override + public void onDeath(CustomMob thisMob, EntityDeathEvent event) { + if (!(event.getEntity() instanceof Bat bat)) return; + + impactAndRemoveBat(bat, null); + } + + // * a override + public void onImpact(Bat bat, Player target, Location impactLocation) {} + + private void impactAndRemoveBat(Bat bat, Player target) { + Location impactLocation = bat.getLocation().clone(); + + onImpact(bat, target, impactLocation); + removeBat(bat); + } + + private void startTargeting(Bat bat, Player initialTarget) { + new BukkitRunnable() { + private Player target = initialTarget; + private int elapsedTicks; + + @Override + public void run() { + if (!isBatAlive(bat)) { + cancel(); + return; + } + + elapsedTicks += 2; + + if (elapsedTicks >= MAX_LIFETIME_TICKS) { + removeBat(bat); + cancel(); + return; + } + + if (!isValidTarget(bat, target)) { + target = findNearestTarget(bat); + + if (target == null) { + removeBat(bat); + cancel(); + return; + } + } + + Location targetLocation = target.getEyeLocation(); + Location batLocation = bat.getLocation(); + + BoundingBox impactBox = target.getBoundingBox().expand(0.2); + + if (impactBox.contains(batLocation.toVector())) { + impactAndRemoveBat(bat, target); + cancel(); + return; + } + + Vector direction = targetLocation.toVector() + .subtract(batLocation.toVector()); + + if (direction.lengthSquared() > 0.001) { + bat.setVelocity(direction.normalize().multiply(SPEED)); + } + + playTravelParticles(bat); + } + }.runTaskTimer(OMCPlugin.getInstance(), 0L, 2L); + } + + public void playTravelParticles(Bat bat) { + ParticleUtils.sendParticlePacket( + Particle.SMOKE, + bat.getLocation(), + 32 + ); + } + + private Player findNearestTarget(Bat bat) { + return bat.getWorld() + .getNearbyPlayers(bat.getLocation(), SEARCH_RADIUS) + .stream() + .filter(player -> isValidTarget(bat, player)) + .min(Comparator.comparingDouble(player -> + player.getLocation().distanceSquared(bat.getLocation()) + )) + .orElse(null); + } + + private boolean isValidTarget(Bat bat, Player player) { + return player != null + && player.isValid() + && !player.isDead() + && player.getWorld().equals(bat.getWorld()) + && player.getGameMode() != GameMode.CREATIVE + && player.getGameMode() != GameMode.SPECTATOR; + } + + private boolean isBatAlive(Bat bat) { + return bat != null + && bat.isValid() + && !bat.isDead(); + } + + private void removeBat(Bat bat) { + unregisterAsCustomMob(bat); + bat.remove(); + } +} \ No newline at end of file diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/ExplosiveVampireBat.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/ExplosiveVampireBat.java new file mode 100644 index 000000000..967d47678 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/ExplosiveVampireBat.java @@ -0,0 +1,62 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat; + +import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.*; +import org.bukkit.entity.Bat; +import org.bukkit.entity.Player; + +public class ExplosiveVampireBat extends AbstractVampireBat { + + public ExplosiveVampireBat(String id) { + super(id, + "Chauve-souris explosive" + ); + } + + @Override + public void playTravelParticles(Bat bat) { + ParticleUtils.sendParticlePacket( + Particle.FLAME, + bat.getLocation(), + 32 + ); + + ParticleUtils.sendParticlePacket( + Particle.SMOKE, + bat.getLocation(), + 32 + ); + } + + @Override + public void onImpact(Bat bat, Player target, Location impactLocation) { + World world = impactLocation.getWorld(); + + Particle.EXPLOSION.builder() + .location(impactLocation) + .count(5) + .offset(0.5, 0.5, 0.5) + .receivers(40, true) + .spawn(); + + world.playSound( + impactLocation, + Sound.ENTITY_GENERIC_EXPLODE, + SoundCategory.HOSTILE, + 2.0F, + 0.8F + ); + + for (Player player : world.getNearbyPlayers(impactLocation, 3.0)) { + if (!canDamage(player)) continue; + + player.damage(4, bat); + } + } + + private boolean canDamage(Player player) { + return !player.isDead() + && player.getGameMode() != GameMode.CREATIVE + && player.getGameMode() != GameMode.SPECTATOR; + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/LevitationVampireBat.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/LevitationVampireBat.java new file mode 100644 index 000000000..ab8de5d95 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/LevitationVampireBat.java @@ -0,0 +1,74 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat; + +import fr.openmc.core.utils.bukkit.ParticleUtils; +import org.bukkit.*; +import org.bukkit.entity.AreaEffectCloud; +import org.bukkit.entity.Bat; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class LevitationVampireBat extends AbstractVampireBat { + + public LevitationVampireBat(String id) { + super(id, + "Chauve-souris de lévitation" + ); + } + + @Override + public void playTravelParticles(Bat bat) { + ParticleUtils.sendParticlePacket( + Particle.END_ROD, + bat.getLocation(), + 32 + ); + } + + @Override + public void onImpact(Bat bat, Player target, Location impactLocation) { + impactLocation.getWorld().spawn( + impactLocation, + AreaEffectCloud.class, + c -> { + c.setRadius(4.0F); + c.setDuration(20 * 5); + c.setWaitTime(0); + + c.setRadiusPerTick(-c.getRadius() / c.getDuration()); + + c.setParticle(Particle.ENTITY_EFFECT, Color.fromRGB(60, 160, 40)); + + c.addCustomEffect( + new PotionEffect( + PotionEffectType.LEVITATION, + 20 * 5, + 1, + false, + true, + true + ), + true + ); + } + ); + + + if (target != null) + target.getWorld().playSound( + target.getLocation(), + Sound.ENTITY_SHULKER_SHOOT, + SoundCategory.HOSTILE, + 1.5F, + 0.8F + ); + + Particle.END_ROD.builder() + .location(impactLocation) + .count(40) + .offset(1.0, 1.5, 1.0) + .extra(0.1) + .receivers(40, true) + .spawn(); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/PoisonVampireBat.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/PoisonVampireBat.java new file mode 100644 index 000000000..1c017f147 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bat/PoisonVampireBat.java @@ -0,0 +1,77 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat; + +import org.bukkit.*; +import org.bukkit.entity.AreaEffectCloud; +import org.bukkit.entity.Bat; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +public class PoisonVampireBat extends AbstractVampireBat { + + public PoisonVampireBat(String id) { + super(id, + "Chauve-souris empoisonneuse" + ); + } + + @Override + public void playTravelParticles(Bat bat) { + Particle.ENTITY_EFFECT.builder() + .location(bat.getLocation()) + .count(4) + .offset(0.2, 0.2, 0.2) + .extra(0.01) + .data(Color.fromRGB(60, 160, 40)) + .receivers(32, true) + .spawn(); + } + + @Override + public void onImpact(Bat bat, Player target, Location impactLocation) { + World world = impactLocation.getWorld(); + + world.spawn( + impactLocation, + AreaEffectCloud.class, + c -> { + c.setRadius(4.0F); + c.setDuration(20 * 5); + c.setWaitTime(0); + + c.setRadiusPerTick(-c.getRadius() / c.getDuration()); + + c.setParticle(Particle.ENTITY_EFFECT, Color.fromRGB(60, 160, 40)); + + c.addCustomEffect( + new PotionEffect( + PotionEffectType.POISON, + 20 * 4, + 1, + false, + true, + true + ), + true + ); + } + ); + + world.playSound( + impactLocation, + Sound.ENTITY_SPLASH_POTION_BREAK, + SoundCategory.HOSTILE, + 1.5F, + 0.6F + ); + + Particle.ENTITY_EFFECT.builder() + .location(impactLocation) + .count(50) + .offset(2.0, 1.0, 2.0) + .extra(0.05) + .data(Color.fromRGB(60, 160, 40)) + .receivers(40, true) + .spawn(); + } +} 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/bloodytypes/AncientMonster.java similarity index 98% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/AncientMonster.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/AncientMonster.java index a142eaf62..7b427f169 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/bloodytypes/AncientMonster.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; 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/bloodytypes/CorruptedMonster.java similarity index 98% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CorruptedMonster.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CorruptedMonster.java index f14bd378a..9522b60ef 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/bloodytypes/CorruptedMonster.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; 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/bloodytypes/CursedMonster.java similarity index 98% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/CursedMonster.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java index aad135729..bba3aa415 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/bloodytypes/CursedMonster.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; 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/bloodytypes/EnragedMonster.java similarity index 98% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/EnragedMonster.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java index d233e1850..225837541 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/bloodytypes/EnragedMonster.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs; +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java index b3af5d158..c3ef49b9e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -2,6 +2,7 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks.BloodExplosionAttack; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks.VampireBatAttack; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.VampireAttackTask; import fr.openmc.core.registry.mobs.CustomMob; @@ -35,9 +36,7 @@ @Getter public class VampireBoss extends CustomMob implements MobBossbarImpl { private final Random random = ThreadLocalRandom.current(); - private final List attacks = new ArrayList<>(List.of( - new BloodExplosionAttack(this) - )); + private final List attacks; private Mannequin mannequin; public VampireBoss(String id) { @@ -50,6 +49,11 @@ public VampireBoss(String id) { new CustomMobAttribute(Attribute.SCALE, 20), new CustomMobAttribute(Attribute.KNOCKBACK_RESISTANCE, 1) ); + + this.attacks = new ArrayList<>(List.of( + new BloodExplosionAttack(this), + new VampireBatAttack(this) + )); } @Override @@ -82,9 +86,10 @@ public void summon(Location at) { ); - new VampireAttackTask(this).runTaskLater( + new VampireAttackTask(this).runTaskTimer( OMCPlugin.getInstance(), - 20L * 10 // 10 sex + 20L, + 20L ); World world = at.getWorld(); diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java index d46bf6727..32e075c25 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/BloodExplosionAttack.java @@ -56,9 +56,7 @@ private void damageNearbyPlayers(Mannequin mannequin) { ); for (Player player : players) { - if (!canDamage(player)) { - continue; - } + if (!canDamage(player)) continue; double newHealth = player.getHealth() * 0.7; diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/VampireBatAttack.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/VampireBatAttack.java new file mode 100644 index 000000000..c2e52a6f4 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/attacks/VampireBatAttack.java @@ -0,0 +1,98 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat.AbstractVampireBat; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import fr.openmc.core.registry.mobs.CustomMobEntry; +import fr.openmc.core.registry.mobs.MobAttack; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.SoundCategory; +import org.bukkit.entity.Mannequin; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +public class VampireBatAttack implements MobAttack { + + private static final double TARGET_RADIUS = 25.0; + + private final VampireBoss boss; + + private final List BATS = new ArrayList<>(); + + public VampireBatAttack(VampireBoss boss) { + this.boss = boss; + } + + @Override + public void execute() { + if (BATS.isEmpty()) { + BATS.addAll(List.of( + OMCRegistry.CUSTOM_MOBS.EXPLOSIVE_VAMPIRE_BAT, + OMCRegistry.CUSTOM_MOBS.POISON_VAMPIRE_BAT, + OMCRegistry.CUSTOM_MOBS.LEVITATION_VAMPIRE_BAT + )); + } + + Mannequin mannequin = boss.getMannequin(); + + if (mannequin == null || !mannequin.isValid() || mannequin.isDead()) return; + + List targets = mannequin.getWorld() + .getNearbyPlayers( + mannequin.getLocation(), + TARGET_RADIUS + ) + .stream() + .filter(this::canTarget) + .toList(); + + if (targets.isEmpty()) return; + + int amount = ThreadLocalRandom.current().nextInt(3, 7); + + mannequin.getWorld().playSound( + mannequin.getLocation(), + Sound.ENTITY_BAT_TAKEOFF, + SoundCategory.HOSTILE, + 3.0F, + 0.5F + ); + + for (int i = 0; i < amount; i++) { + Player target = targets.get(ThreadLocalRandom.current().nextInt(targets.size())); + + Location spawnLocation = getRandomSpawnLocation(mannequin); + CustomMobEntry batType = BATS.get(ThreadLocalRandom.current().nextInt(BATS.size())); + + if (!(batType.getMob() instanceof AbstractVampireBat batVampire)) return; + batVampire.spawn(spawnLocation, target); + } + } + + private Location getRandomSpawnLocation(Mannequin mannequin) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + + double angle = random.nextDouble(0, Math.PI * 2); + double radius = random.nextDouble(1.0, 3.0); + + return mannequin.getLocation() + .clone() + .add( + Math.cos(angle) * radius, + mannequin.getHeight() * 0.5, + Math.sin(angle) * radius + ); + } + + private boolean canTarget(Player player) { + return player.isValid() + && !player.isDead() + && player.getGameMode() != GameMode.CREATIVE + && player.getGameMode() != GameMode.SPECTATOR; + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java index 107748df1..dd529b741 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/tasks/VampireAttackTask.java @@ -1,38 +1,31 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks; -import fr.openmc.core.OMCPlugin; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import fr.openmc.core.utils.RandomUtils; import org.bukkit.scheduler.BukkitRunnable; -import java.util.Random; -import java.util.concurrent.ThreadLocalRandom; - public class VampireAttackTask extends BukkitRunnable { private final VampireBoss boss; - private final Random random = ThreadLocalRandom.current(); - public static final long MIN_ATTACK_DELAY = 20L * 10; // 10 sec - public static final long MAX_ATTACK_DELAY = 20L * 17; // 17 sec + private static final int MIN_ATTACK_DELAY_SECONDS = 8; + private static final int MAX_ATTACK_DELAY_SECONDS = 16; public VampireAttackTask(VampireBoss boss) { this.boss = boss; } + private int cooldown = RandomUtils.randomBetween(MIN_ATTACK_DELAY_SECONDS, MAX_ATTACK_DELAY_SECONDS); + @Override public void run() { if (!boss.getMannequin().isValid()) { cancel(); return; } - - boss.pickRandomAttack(); - - long nextDelay = random.nextLong( - MIN_ATTACK_DELAY, - MAX_ATTACK_DELAY + 1 - ); - - this.cancel(); - this.runTaskLater(OMCPlugin.getInstance(), nextDelay); + cooldown--; + if (cooldown <= 0) { + boss.pickRandomAttack(); + cooldown = RandomUtils.randomBetween(MIN_ATTACK_DELAY_SECONDS, MAX_ATTACK_DELAY_SECONDS); + } } } 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 8c3bab42f..ea11e3fa6 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java @@ -3,10 +3,13 @@ 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.bloodynight.contents.mobs.bat.ExplosiveVampireBat; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat.LevitationVampireBat; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bat.PoisonVampireBat; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.AncientMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CorruptedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CursedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.EnragedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; 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; @@ -87,6 +90,21 @@ public class CustomMobRegistry extends Registry implemen CorruptedMonster::new )); + public final CustomMobEntry EXPLOSIVE_VAMPIRE_BAT = register(new CustomMobEntry( + "omc_daily_events:explosive_vampire_bat", + ExplosiveVampireBat::new + )); + + public final CustomMobEntry POISON_VAMPIRE_BAT = register(new CustomMobEntry( + "omc_daily_events:poison_vampire_bat", + PoisonVampireBat::new + )); + + public final CustomMobEntry LEVITATION_VAMPIRE_BAT = register(new CustomMobEntry( + "omc_daily_events:levitation_vampire_bat", + LevitationVampireBat::new + )); + public final CustomMobEntry VAMPIRE_BOSS = register(new CustomMobEntry( "omc_daily_events:vampire_boss", VampireBoss::new From 3a6604109038776c45ef068186d54b2eb1cce45e Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:42:32 +0200 Subject: [PATCH 37/50] feat: add VampireSlave, spawn when VampireBoss was hit --- .../contents/mobs/vampire/VampireBoss.java | 29 ++++++++++++++++++- .../contents/mobs/vampire/VampireSlave.java | 29 +++++++++++++++++++ .../core/registry/mobs/CustomMobRegistry.java | 6 ++++ .../omc_daily_events/nbt/head/vampire.json | 2 +- 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java index c3ef49b9e..f6e2229fd 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -1,6 +1,7 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire; import fr.openmc.core.OMCPlugin; +import fr.openmc.core.OMCRegistry; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks.BloodExplosionAttack; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.attacks.VampireBatAttack; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask; @@ -11,6 +12,7 @@ import fr.openmc.core.registry.mobs.options.MobBossbarImpl; import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.text.messages.TranslationManager; +import fr.openmc.core.utils.world.LocationUtils; import io.papermc.paper.datacomponent.item.ResolvableProfile; import lombok.Getter; import net.kyori.adventure.bossbar.BossBar; @@ -18,9 +20,13 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.*; import org.bukkit.attribute.Attribute; +import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Mannequin; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; import java.util.ArrayList; import java.util.List; @@ -34,7 +40,7 @@ //todo: death (sfx, rewards mailbox en fonction des dégats mis (plus de dégat plus de chance) @SuppressWarnings("UnstableApiUsage") @Getter -public class VampireBoss extends CustomMob implements MobBossbarImpl { +public class VampireBoss extends CustomMob implements MobBossbarImpl, Listener { private final Random random = ThreadLocalRandom.current(); private final List attacks; private Mannequin mannequin; @@ -138,6 +144,27 @@ public void summon(Location at) { this.mannequin = mannequin; } + @EventHandler(ignoreCancelled = true) + public void onVampireDamageByPlayer(EntityDamageByEntityEvent event) { + Entity victim = event.getEntity(); + + CustomMob mob = OMCRegistry.CUSTOM_MOBS.getMob(victim); + if (mob == null) return; + if (!mob.getId().equals(this.getId())) return; + + Entity damager = event.getDamager(); + + if (!(damager instanceof Player player)) { + event.setCancelled(true); + return; + } + + if (ThreadLocalRandom.current().nextDouble() < 0.25) { + OMCRegistry.CUSTOM_MOBS.VAMPIRE_SLAVE.spawn( + LocationUtils.randomLocation(player.getLocation(), 3.0)); + } + } + @Override public Component getBossBarName(LivingEntity entity) { return TranslationManager.translation("feature.dailyevents.bloody_night.vampire_boss.name"); diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java new file mode 100644 index 000000000..7631a2176 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java @@ -0,0 +1,29 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.utils.RandomUtils; +import org.bukkit.Location; +import org.bukkit.entity.Zombie; + +public class VampireSlave extends CustomMob { + public VampireSlave(String id) { + super(id, + "Esclave du Vampire", + Zombie.class, + 16, + 5, + RandomUtils.randomBetween(0.1, 0.2) + ); + } + + @Override + public Zombie spawn(Location spawnLocation) { + Zombie zombie = this.getPreBuildMob(spawnLocation); + + zombie.getEquipment().setHelmet(OMCRegistry.CUSTOM_ITEMS.VAMPIRE_HEAD.getBest()); + zombie.getEquipment().setHelmetDropChance(0); + + return zombie; + } +} \ No newline at end of file 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 ea11e3fa6..495a9fee0 100644 --- a/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java +++ b/src/main/java/fr/openmc/core/registry/mobs/CustomMobRegistry.java @@ -11,6 +11,7 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CursedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.EnragedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireSlave; 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 fr.openmc.core.registry.mobs.task.MobBossbarUpdater; @@ -110,6 +111,11 @@ public class CustomMobRegistry extends Registry implemen VampireBoss::new )); + public final CustomMobEntry VAMPIRE_SLAVE = register(new CustomMobEntry( + "omc_daily_events:vampire_slave", + VampireSlave::new + )); + public final static Set HAS_BOSSBAR = new HashSet<>(); @Override 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 index 616087460..9a07e7681 100644 --- a/src/main/resources/contents/omc_daily_events/nbt/head/vampire.json +++ b/src/main/resources/contents/omc_daily_events/nbt/head/vampire.json @@ -4,7 +4,7 @@ "properties": [ { "name": "textures", - "value": "e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTdkOWFkNzk1NzdkYTBkMjY3MTlmNTljNGY0NDlkOTBjZGVhYjM5ZTcwMDk1ZTQ2NWI5ZWNhYWJmMjZjYmY3MSJ9fX0=\"}]},minecraft:lore=['{\"text\":\"https://namemc.com/skin/efaad3c14fefec0c" + "value": "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWFhMjllYTk2MTc1N2RjM2M5MGJmYWJmMzAyYzVhYmU5ZDMwOGZiNGE3ZDM4NjRlNTc4OGFkMmNjOTE2MGFhMiJ9fX0=" } ] } From e44e288047dcaf7d8b2987b64605c14d8f5f2bb0 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 15 Jul 2026 11:55:00 +0200 Subject: [PATCH 38/50] change: buff slave --- .../bloodynight/contents/mobs/vampire/VampireBoss.java | 9 ++++----- .../bloodynight/contents/mobs/vampire/VampireSlave.java | 6 ++++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java index f6e2229fd..da4baea09 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -20,10 +20,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.*; import org.bukkit.attribute.Attribute; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Mannequin; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; @@ -160,8 +157,10 @@ public void onVampireDamageByPlayer(EntityDamageByEntityEvent event) { } if (ThreadLocalRandom.current().nextDouble() < 0.25) { - OMCRegistry.CUSTOM_MOBS.VAMPIRE_SLAVE.spawn( + Entity spawned = OMCRegistry.CUSTOM_MOBS.VAMPIRE_SLAVE.spawn( LocationUtils.randomLocation(player.getLocation(), 3.0)); + if (spawned instanceof Zombie zombie) + zombie.setTarget(player); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java index 7631a2176..50e89968e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireSlave.java @@ -12,8 +12,8 @@ public VampireSlave(String id) { "Esclave du Vampire", Zombie.class, 16, - 5, - RandomUtils.randomBetween(0.1, 0.2) + 8, + RandomUtils.randomBetween(0.2, 0.35) ); } @@ -24,6 +24,8 @@ public Zombie spawn(Location spawnLocation) { zombie.getEquipment().setHelmet(OMCRegistry.CUSTOM_ITEMS.VAMPIRE_HEAD.getBest()); zombie.getEquipment().setHelmetDropChance(0); + zombie.setAggressive(true); + return zombie; } } \ No newline at end of file From f16cae3a94e7d944d12cf0b29fe0d5cc2bc34743 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 15 Jul 2026 14:19:27 +0200 Subject: [PATCH 39/50] feat: boss rewards manager --- .../bloodynight/BloodyNightManager.java | 21 ++- .../contents/mobs/vampire/VampireBoss.java | 57 ++++++- .../mobs/vampire/VampireBossLootManager.java | 161 ++++++++++++++++++ .../MiraculousFishingManager.java | 27 +-- .../models/dailyevent/DailyEvent.java | 5 + .../features/mailboxes/MailboxManager.java | 21 +-- .../registry/loottable/loots/CustomLoot.java | 21 +++ .../default/dailyevents.properties | 21 ++- 8 files changed, 286 insertions(+), 48 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.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 c14e00d70..7f6ae7b6a 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 @@ -7,10 +7,8 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CursedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.EnragedMonster; import fr.openmc.core.registry.mobs.CustomMob; -import org.bukkit.Bukkit; -import org.bukkit.GameRules; -import org.bukkit.NamespacedKey; -import org.bukkit.World; +import fr.openmc.core.utils.world.LocationUtils; +import org.bukkit.*; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Monster; @@ -22,6 +20,7 @@ public class BloodyNightManager { public static final NamespacedKey RAID_MONSTER_KEY = new NamespacedKey("omc_daily_events", "raid_monster"); private static BukkitTask raidTask; + private static BukkitTask vampireTask; private static long lastTime; public static void start(BloodyNightEvent event) { @@ -36,6 +35,14 @@ public static void start(BloodyNightEvent event) { 20L * 60L * 2 // 2 min ); + // * Programmation du boss Vampire + Location vampireSpawnLocation = LocationUtils.randomLocation(world.getSpawnLocation(), world.getWorldBorder().getSize() / 2.0); + vampireTask = Bukkit.getScheduler().runTaskLater( + OMCPlugin.getInstance(), + () -> OMCRegistry.CUSTOM_MOBS.VAMPIRE_BOSS.spawn(vampireSpawnLocation), + 20L * 60L * 15 // 15 min + ); + // * Modification des monstres déjà présent dans le monde (uniquement ceux chargé) applyCorruptedMonsters(world); @@ -56,6 +63,12 @@ public static void stop(BloodyNightEvent event) { raidTask = null; } + // * Fin des raids + if (vampireTask != null) { + vampireTask.cancel(); + vampireTask = null; + } + // * Supression des monstres devant etre supprimé (ex ceux qui vient des raids) deleteRaidMonsters(world); diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java index da4baea09..12fdfe810 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -24,6 +24,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDeathEvent; import java.util.ArrayList; import java.util.List; @@ -33,8 +34,6 @@ import static fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.tasks.SummoningEffectTask.SUMMON_EFFECT_INTERVAL_TICKS; -//todo: attack (blood explosion, explosive bat, mini vempire defender) -//todo: death (sfx, rewards mailbox en fonction des dégats mis (plus de dégat plus de chance) @SuppressWarnings("UnstableApiUsage") @Getter public class VampireBoss extends CustomMob implements MobBossbarImpl, Listener { @@ -65,6 +64,34 @@ public Mannequin spawn(Location spawnLocation) { return null; } + @Override + public void onDeath(CustomMob thisMob, EntityDeathEvent event) { + LivingEntity entity = event.getEntity(); + if (mannequin == null || + !entity.getUniqueId().equals(mannequin.getUniqueId())) return; + + event.getDrops().clear(); + event.setDroppedExp(0); + + Location deathLocation = entity.getLocation().clone(); + + ParticleUtils.spawnCubeParticles( + deathLocation.clone().add(0, 4, 0), + Particle.EXPLOSION_EMITTER, + 5.0, + 6.0, + 5.0, + 25, + 100, + null + ); + + VampireBossLootManager.giveContributions(thisMob); + + VampireBossLootManager.damageContributions.clear(); + mannequin = null; + } + private void startSummoning(Location at) { World world = at.getWorld(); for (Player player : world.getPlayers()) { @@ -146,14 +173,15 @@ public void onVampireDamageByPlayer(EntityDamageByEntityEvent event) { Entity victim = event.getEntity(); CustomMob mob = OMCRegistry.CUSTOM_MOBS.getMob(victim); - if (mob == null) return; - if (!mob.getId().equals(this.getId())) return; + if (mob == null || !mob.getId().equals(this.getId())) return; - Entity damager = event.getDamager(); + Player player = getDamagerPlayer(event); + if (player == null) return; - if (!(damager instanceof Player player)) { - event.setCancelled(true); - return; + double effectiveDamage = event.getFinalDamage(); + if (effectiveDamage > 0) { + double actualDamage = VampireBossLootManager.damageContributions.remove(player.getUniqueId()); + VampireBossLootManager.damageContributions.put(player.getUniqueId(), actualDamage + effectiveDamage); } if (ThreadLocalRandom.current().nextDouble() < 0.25) { @@ -191,5 +219,18 @@ public void pickRandomAttack() { attacks.get(random.nextInt(attacks.size())).execute(); } + + private Player getDamagerPlayer(EntityDamageByEntityEvent event) { + Entity damager = event.getDamager(); + if (damager instanceof Player player) { + event.setCancelled(true); + return player; + } + + if (damager instanceof Projectile projectile && projectile.getShooter() instanceof Player player) + return player; + + return null; + } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java new file mode 100644 index 000000000..441f040ac --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java @@ -0,0 +1,161 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire; + +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.economy.EconomyManager; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.leaderboards.LeaderboardManager; +import fr.openmc.core.features.mailboxes.MailboxManager; +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.registry.loottable.loots.MoneyLoot; +import fr.openmc.core.registry.mobs.CustomMob; +import fr.openmc.core.utils.cache.CacheOfflinePlayer; +import fr.openmc.core.utils.cache.PlayerNameCache; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +public class VampireBossLootManager { + + public static final Map damageContributions = new HashMap<>(); + private static final CustomLootTable VAMPIRE_BOSS_LOOT_TABLE = OMCRegistry.CUSTOM_LOOT_TABLES.VAMPIRE; + + public static void giveContributions(CustomMob mob) { + double totalHealth = mob.getHealth(); + + Map orderedMap = damageContributions.entrySet() + .stream() + .sorted((entry1, entry2) -> Double.compare( + entry2.getValue(), + entry1.getValue() + )) + .collect(Collectors.toMap( + Map.Entry::getKey, + Map.Entry::getValue, + (e1, e2) -> e1, + LinkedHashMap::new + )); + + + World world = DailyEventsManager.BLOODY_NIGHT.getWorld(); + if (world == null) return; + + if (orderedMap.isEmpty()) { + broadcastToWorld(world, TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.defeated.no_body" + )); + return; + } + + int rankInt = 0; + + + broadcastToWorld(world, TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.defeated.start" + )); + + for (Map.Entry entry : orderedMap.entrySet()) { + if (rankInt == 1 || rankInt == 2 || rankInt == 3) { + broadcastToWorld(world, TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.defeated.rank", + Component.text(rankInt + 1, LeaderboardManager.getRankColor(rankInt + 1)), + PlayerNameCache.name(entry.getKey()).color(NamedTextColor.GOLD), + Component.text(String.format("%.1f", entry.getValue()), NamedTextColor.RED) + )); + } else { + OfflinePlayer offlinePlayer = CacheOfflinePlayer.getOfflinePlayer(entry.getKey()); + if (offlinePlayer == null) continue; + if (!offlinePlayer.isOnline()) continue; + Player player = offlinePlayer.getPlayer(); + if (player == null) continue; + + player.sendMessage(TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.defeated.midle", + Component.text(rankInt + 1, LeaderboardManager.getRankColor(rankInt + 1)), + PlayerNameCache.name(entry.getKey()).color(NamedTextColor.GOLD), + Component.text(String.format("%.1f", entry.getValue()), NamedTextColor.RED) + )); + } + + UUID playerUUID = entry.getKey(); + double damage = entry.getValue(); + double participation = damage / totalHealth; + + if (participation < 0.01) continue; + + double chanceMultiplier = getChanceMultiplier(participation); + giveLootToContributor(playerUUID, chanceMultiplier); + + rankInt++; + } + + broadcastToWorld(world, TranslationManager.translation( + "feature.dailyevents.bloody_night.vampire_boss.defeated.end")); + } + + private static void giveLootToContributor(UUID playerUUID, double chanceMultiplier) { + ThreadLocalRandom random = ThreadLocalRandom.current(); + OfflinePlayer offlinePlayer = CacheOfflinePlayer.getOfflinePlayer(playerUUID); + + Player player = offlinePlayer.getPlayer(); + + + for (CustomLoot loot : VAMPIRE_BOSS_LOOT_TABLE.getLoots()) { + if (!(loot instanceof ItemLoot) && !(loot instanceof MoneyLoot)) continue; + + double finalChance = loot.getChance() * chanceMultiplier; + + if (finalChance > 1.0) { + finalChance = 1.0; + } else if (finalChance < 0.0) { + finalChance = 0.0; + } + + if (random.nextDouble() > finalChance) continue; + + int amount = -1; + if (loot instanceof ItemLoot itemLoot) { + amount = itemLoot.getRepresentativeItem().getAmount(); + MailboxManager.sendItemsToOfflinePlayer(offlinePlayer, itemLoot.getItems().toArray(new ItemStack[0])); + } else if (loot instanceof MoneyLoot moneyLoot) { + EconomyManager.addBalance(playerUUID, moneyLoot.getMoney()); + } + + if (player != null && offlinePlayer.isOnline()) { + loot.sendLootMessage(player, amount); + } + } + } + + private static double getChanceMultiplier(double participation) { + if (participation >= 0.75) { + return 1.0; + } else if (participation >= 0.50) { + return 0.80; + } else if (participation >= 0.25) { + return 0.60; + } else if (participation >= 0.10) { + return 0.40; + } else { + return 0.25; + } + } + + private static void broadcastToWorld(World world, Component component) { + for (Player player : world.getPlayers()) { + player.sendMessage(component); + } + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index d4cae35fa..6d4f659bc 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -6,8 +6,6 @@ import fr.openmc.core.registry.loottable.loots.MoneyLoot; import fr.openmc.core.registry.loottable.loots.RepresentedItem; import fr.openmc.core.registry.loottable.loots.TableLoot; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.entity.Entity; @@ -22,27 +20,6 @@ public class MiraculousFishingManager { public static final NamespacedKey NOT_PICKUP_KEY = new NamespacedKey(OMCPlugin.getInstance(), "not_pickup"); - /** - * Envoie le message de loot contenant, le nom du loot et la chance du loot - * @param player le joueur a qui envoyé le message - * @param loot le loot obtenu - * @param amount le nombre de loot - */ - public static void sendLootMessage(Player player, CustomLoot loot, int amount) { - Component base = Component.text(" - ", NamedTextColor.GRAY); - - if (amount != -1) - base = base.append(Component.text(amount + "x ")); - - if (loot.getDisplayText() != null && - !(loot instanceof TableLoot)) { - base = base.append(loot.getDisplayText()) - .append(Component.text(" ("+ Math.round(loot.getChance() * 100.0) +"% ★)", NamedTextColor.AQUA)); - - player.sendMessage(base); - } - } - /** * Simule un item qui est lancé du bouchon de pêche jusqu'au joueur, via un CustomLoot. * @param player le joueur visé @@ -53,7 +30,7 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust // * Gestion spécial pour les Sea Creature if (loot instanceof SeaCreatureLoot seaCreatureLoot) { // * On envoie le message de loot - sendLootMessage(player, loot, -1); + loot.sendLootMessage(player, -1); Entity entity = seaCreatureLoot.getSeaCreatureMob().spawn(hookLocation); @@ -81,7 +58,7 @@ public static void simulateLaunchLoot(Player player, Location hookLocation, Cust itemEntity.setGlowing(true); // * On envoie le message de loot - sendLootMessage(player, loot, itemEntity.getItemStack().getAmount()); + loot.sendLootMessage(player, itemEntity.getItemStack().getAmount()); applyVelocity(hookLocation, player.getEyeLocation(), itemEntity, 0.1); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java index e94afdf00..e979d26ed 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/DailyEvent.java @@ -5,6 +5,7 @@ import fr.openmc.core.features.events.contents.dailyevents.tasks.EndEventTask; import fr.openmc.core.features.events.models.Event; import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Player; import java.util.Collection; @@ -104,4 +105,8 @@ public void end() { toast.getEndToastData().send(receivers); } } + + public World getWorld() { + return Bukkit.getWorld(this.getWorldEvent()); + } } diff --git a/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java b/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java index 2ea40f10b..9335b26e6 100644 --- a/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java +++ b/src/main/java/fr/openmc/core/features/mailboxes/MailboxManager.java @@ -116,19 +116,20 @@ private static boolean sendLetter(Player sender, OfflinePlayer receiver, ItemSta } public static void sendItemsToAOfflinePlayerBatch(Map playerItemsMap) { - try { - for (Map.Entry entry : playerItemsMap.entrySet()) { - OfflinePlayer player = entry.getKey(); - ItemStack[] items = entry.getValue(); + for (Map.Entry entry : playerItemsMap.entrySet()) { + sendItemsToOfflinePlayer(entry.getKey(), entry.getValue()); + } + } - int numItems = Arrays.stream(items).mapToInt(ItemStack::getAmount).sum(); + public static void sendItemsToOfflinePlayer(OfflinePlayer player, ItemStack[] items) { + try { + int numItems = Arrays.stream(items).mapToInt(ItemStack::getAmount).sum(); - byte[] itemsBytes = BukkitSerializer.serializeItemStacks(changeStackItem(items)); + byte[] itemsBytes = BukkitSerializer.serializeItemStacks(changeStackItem(items)); - Letter letter = new Letter(nextLetterId++, player.getUniqueId(), player.getUniqueId(), itemsBytes, numItems, - Timestamp.valueOf(DateUtils.getLocalDateTime()), false); - letters.add(letter); - } + Letter letter = new Letter(nextLetterId++, player.getUniqueId(), player.getUniqueId(), itemsBytes, numItems, + Timestamp.valueOf(DateUtils.getLocalDateTime()), false); + letters.add(letter); } catch (IOException e) { OMCLogger.warn("Error while sending items to offline players: {}", e.getMessage(), e); } diff --git a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java index 7722cbd8e..55d6dae7c 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java +++ b/src/main/java/fr/openmc/core/registry/loottable/loots/CustomLoot.java @@ -1,6 +1,7 @@ package fr.openmc.core.registry.loottable.loots; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -18,4 +19,24 @@ default ItemStack getRepresentativeItem() { } return null; } + + /** + * Envoie le message de loot contenant, le nom du loot et la chance du loot + * @param player le joueur a qui envoyé le message + * @param amount le nombre de loot + */ + default void sendLootMessage(Player player, int amount) { + Component base = Component.text(" - ", NamedTextColor.GRAY); + + if (amount != -1) + base = base.append(Component.text(amount + "x ")); + + if (this.getDisplayText() != null && + !(this instanceof TableLoot)) { + base = base.append(this.getDisplayText()) + .append(Component.text(" ("+ Math.round(this.getChance() * 100.0) +"% ★)", NamedTextColor.AQUA)); + + player.sendMessage(base); + } + } } \ 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 5eddf5f8c..baae3c480 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -113,4 +113,23 @@ feature.dailyevents.bloody_night.vampire_boss.summoned=BOSS VAMPIRE ! un boss vient attérir en %1$s %2$s %3$s \
*unissez vous afin de le battre tous ensemble !*\
\ -
\ No newline at end of file +
+ +feature.dailyevents.bloody_night.vampire_boss.defeated.no_body= \ +
\ +
BOSS VAMPIRE ! Le Vampire est parti \ +
*aucune personne à participer à l'événement, dommage!*\ +
\ +
+ + +feature.dailyevents.bloody_night.vampire_boss.defeated.start= \ +
\ +
BOSS VAMPIRE ! Le boss vient d'être térrasé ! \ +
Voici le classement : + +feature.dailyevents.bloody_night.vampire_boss.defeated.midle=
(vous) %1$s %2$s - %3$s dégats \ +
\ +
Vos récompenses : +feature.dailyevents.bloody_night.vampire_boss.defeated.rank=- %1$s %2$s - %3$s dégats +feature.dailyevents.bloody_night.vampire_boss.defeated.end= \ No newline at end of file From 5d8f837954f31047cb34a96152487a46a554e1ce Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Wed, 15 Jul 2026 20:46:14 +0200 Subject: [PATCH 40/50] change: buff/nerf/fix big commit ahah --- .../bloodynight/BloodyNightManager.java | 16 +++++++++++ .../contents/loottable/VampireLootTable.java | 9 ++++-- .../contents/mobs/vampire/VampireBoss.java | 24 ++++++++-------- .../mobs/vampire/VampireBossLootManager.java | 28 +++++++++++++------ .../listeners/DailyEventAmbientListeners.java | 2 +- .../models/dailyevent/HasAmbient.java | 6 +++- .../core/registry/ambient/CustomAmbient.java | 17 +++++++++-- .../registry/loottable/loots/ItemLoot.java | 8 ++++++ .../core/utils/nms/PlayerRespawnNMS.java | 20 ++++++++----- .../default/dailyevents.properties | 9 ++++-- 10 files changed, 103 insertions(+), 36 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 7f6ae7b6a..02b86eaf1 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,8 @@ import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CorruptedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.CursedMonster; import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.bloodytypes.EnragedMonster; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireBoss; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.mobs.vampire.VampireSlave; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.world.LocationUtils; import org.bukkit.*; @@ -71,6 +73,7 @@ public static void stop(BloodyNightEvent event) { // * Supression des monstres devant etre supprimé (ex ceux qui vient des raids) deleteRaidMonsters(world); + deleteVampireMonsters(world); // * Modification des monstres déjà présent dans le monde (uniquement ceux chargé) desactivateCorruptedMonsters(world); @@ -123,6 +126,19 @@ private static void deleteRaidMonsters(World world) { } } + /** + * Supprime tout les monstres spawné par le vampire + * @param world le monde ciblé par la nuit sanglante + */ + private static void deleteVampireMonsters(World world) { + for (Entity entity : world.getEntities()) { + CustomMob customMob = OMCRegistry.CUSTOM_MOBS.getMob(entity); + if (customMob == null) continue; + if (customMob instanceof VampireBoss || customMob instanceof VampireSlave) + entity.remove(); + } + } + /** * Applique l'effet bloody sur un monstre * - Corrompu - 60% 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 index 427ba492f..924f380fb 100644 --- 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 @@ -6,6 +6,7 @@ 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.inventory.ItemType; import java.util.LinkedHashSet; import java.util.List; @@ -26,10 +27,12 @@ public String getNamespace() { 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(ItemType.OMINOUS_BOTTLE.createItemStack( + o -> o.setAmplifier(6)),0.6, 1), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.VAMPIRE_HEAD,0.50, 1), new ItemLoot( - OMCRegistry.CUSTOM_ENCHANTS.VAMPIRISM.getEnchantedBookItem(1, 3), - 0.1, + OMCRegistry.CUSTOM_ENCHANTS.VAMPIRISM.getEnchantedBookItem(1, 2), + 0.25, 1 ) )); diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java index 12fdfe810..4f18a812f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBoss.java @@ -67,8 +67,6 @@ public Mannequin spawn(Location spawnLocation) { @Override public void onDeath(CustomMob thisMob, EntityDeathEvent event) { LivingEntity entity = event.getEntity(); - if (mannequin == null || - !entity.getUniqueId().equals(mannequin.getUniqueId())) return; event.getDrops().clear(); event.setDroppedExp(0); @@ -158,9 +156,9 @@ public void summon(Location at) { player.sendMessage( TranslationManager.translation( "feature.dailyevents.bloody_night.vampire_boss.summoned", - Component.text(at.getX(), NamedTextColor.RED), - Component.text(at.getY(), NamedTextColor.RED), - Component.text(at.getZ(), NamedTextColor.RED) + Component.text(Math.round(at.getX()), NamedTextColor.RED), + Component.text(Math.round(at.getY()), NamedTextColor.RED), + Component.text(Math.round(at.getZ()), NamedTextColor.RED) ) ); } @@ -173,14 +171,20 @@ public void onVampireDamageByPlayer(EntityDamageByEntityEvent event) { Entity victim = event.getEntity(); CustomMob mob = OMCRegistry.CUSTOM_MOBS.getMob(victim); + if (!(victim instanceof LivingEntity livingVictim)) return; if (mob == null || !mob.getId().equals(this.getId())) return; Player player = getDamagerPlayer(event); if (player == null) return; - double effectiveDamage = event.getFinalDamage(); + double effectiveDamage = Math.min(event.getFinalDamage(), livingVictim.getHealth()); if (effectiveDamage > 0) { - double actualDamage = VampireBossLootManager.damageContributions.remove(player.getUniqueId()); + double actualDamage = 0; + + if (VampireBossLootManager.damageContributions.containsKey(player.getUniqueId())) { + actualDamage = VampireBossLootManager.damageContributions.get(player.getUniqueId()); + } + VampireBossLootManager.damageContributions.put(player.getUniqueId(), actualDamage + effectiveDamage); } @@ -222,14 +226,12 @@ public void pickRandomAttack() { private Player getDamagerPlayer(EntityDamageByEntityEvent event) { Entity damager = event.getDamager(); - if (damager instanceof Player player) { - event.setCancelled(true); - return player; - } + if (damager instanceof Player player) return player; if (damager instanceof Projectile projectile && projectile.getShooter() instanceof Player player) return player; + event.setCancelled(true); return null; } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java index 441f040ac..fba8687de 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/vampire/VampireBossLootManager.java @@ -14,19 +14,19 @@ import fr.openmc.core.utils.cache.PlayerNameCache; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; +import static fr.openmc.core.features.mailboxes.utils.MailboxUtils.getHoverEvent; + public class VampireBossLootManager { public static final Map damageContributions = new HashMap<>(); @@ -70,7 +70,7 @@ public static void giveContributions(CustomMob mob) { if (rankInt == 1 || rankInt == 2 || rankInt == 3) { broadcastToWorld(world, TranslationManager.translation( "feature.dailyevents.bloody_night.vampire_boss.defeated.rank", - Component.text(rankInt + 1, LeaderboardManager.getRankColor(rankInt + 1)), + Component.text("#"+ rankInt + 1, LeaderboardManager.getRankColor(rankInt + 1)), PlayerNameCache.name(entry.getKey()).color(NamedTextColor.GOLD), Component.text(String.format("%.1f", entry.getValue()), NamedTextColor.RED) )); @@ -103,6 +103,15 @@ public static void giveContributions(CustomMob mob) { broadcastToWorld(world, TranslationManager.translation( "feature.dailyevents.bloody_night.vampire_boss.defeated.end")); + + Component messageMail = TranslationManager.translation("feature.dailyevents.bloody_night.vampire_boss.mail.received") + .appendNewline() + .append(TranslationManager.translation("feature.dailyevents.bloody_night.vampire_boss.mail.click")) + .clickEvent(ClickEvent.runCommand("mailbox")) + .hoverEvent(getHoverEvent(TranslationManager.translationString("feature.dailyevents.bloody_night.vampire_boss.mail.hover"))) + .append(TranslationManager.translation("feature.dailyevents.bloody_night.vampire_boss.mail.open_mailbox")); + + broadcastToWorld(world, messageMail); } private static void giveLootToContributor(UUID playerUUID, double chanceMultiplier) { @@ -110,7 +119,7 @@ private static void giveLootToContributor(UUID playerUUID, double chanceMultipli OfflinePlayer offlinePlayer = CacheOfflinePlayer.getOfflinePlayer(playerUUID); Player player = offlinePlayer.getPlayer(); - + List rewards = new ArrayList<>(); for (CustomLoot loot : VAMPIRE_BOSS_LOOT_TABLE.getLoots()) { if (!(loot instanceof ItemLoot) && !(loot instanceof MoneyLoot)) continue; @@ -127,8 +136,9 @@ private static void giveLootToContributor(UUID playerUUID, double chanceMultipli int amount = -1; if (loot instanceof ItemLoot itemLoot) { - amount = itemLoot.getRepresentativeItem().getAmount(); - MailboxManager.sendItemsToOfflinePlayer(offlinePlayer, itemLoot.getItems().toArray(new ItemStack[0])); + ItemStack itemReward = itemLoot.getRepresentativeItem(); + amount = itemReward.getAmount(); + rewards.add(itemReward); } else if (loot instanceof MoneyLoot moneyLoot) { EconomyManager.addBalance(playerUUID, moneyLoot.getMoney()); } @@ -137,6 +147,8 @@ private static void giveLootToContributor(UUID playerUUID, double chanceMultipli loot.sendLootMessage(player, amount); } } + + MailboxManager.sendItemsToOfflinePlayer(offlinePlayer, rewards.toArray(ItemStack[]::new)); } private static double getChanceMultiplier(double participation) { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java index e19c7b359..658a1f47c 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/listeners/DailyEventAmbientListeners.java @@ -21,7 +21,7 @@ public void onJoin(PlayerJoinEvent event) { if (!(dailyEvent instanceof HasAmbient hasAmbient)) return; - hasAmbient.apply(event.getPlayer()); + hasAmbient.apply(event.getPlayer(), true); } @EventHandler diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java index 6f93a2c09..d391885be 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/models/dailyevent/HasAmbient.java @@ -12,7 +12,11 @@ public interface HasAmbient { CustomAmbient getAmbient(); default void apply(Player player) { - this.getAmbient().apply(player); + apply(player, false); + } + + default void apply(Player player, boolean isJoining) { + this.getAmbient().apply(player, isJoining); } default void apply(Collection receivers) { diff --git a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java index cc54a2de1..8e6ad10ed 100644 --- a/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java +++ b/src/main/java/fr/openmc/core/registry/ambient/CustomAmbient.java @@ -46,13 +46,23 @@ public abstract class CustomAmbient { * @param player Le joueur concerné */ public void apply(Player player) { + apply(player, false); + } + + /** + * Applique l'ambience sur un Joueur + * @param player Le joueur concerné + * @param isJoining Si le joueur est rejoint ou non + */ + public void apply(Player player, boolean isJoining) { ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); // * On envoie le packet respawn qui applique l'ambience PlayerRespawnNMS.sendPacket( nmsPlayer, getPlayerAmbientSpawnInfo(nmsPlayer), - getTransitionDimensionForPlayer(nmsPlayer) + getTransitionDimensionForPlayer(nmsPlayer), + isJoining ); if (this.getAmbientBuilder().utilizeBiome()) { @@ -76,7 +86,7 @@ public void apply(Player player) { */ public void apply(Collection receivers) { for (Player receiver : receivers) { - apply(receiver); + apply(receiver, false); } } @@ -92,7 +102,8 @@ public void reset(Player player) { PlayerRespawnNMS.sendPacket( nmsPlayer, nmsPlayer.createCommonSpawnInfo(nmsPlayer.level()), - getTransitionDimensionForPlayer(nmsPlayer) + getTransitionDimensionForPlayer(nmsPlayer), + false ); } 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 04bd03a5e..3f60524f8 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 @@ -53,6 +53,14 @@ public ItemLoot(ItemStack item, double chance, int minAmount, int maxAmount) { maxAmount); } + public ItemLoot(ItemStack item, double chance, int amount) { + this(Collections.singleton(item), + null, + chance, + amount, + amount); + } + public ItemLoot(Material item, double chance, int minAmount, int maxAmount) { this(ItemStack.of(item), chance, diff --git a/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java b/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java index 42361619d..d70000e21 100644 --- a/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java +++ b/src/main/java/fr/openmc/core/utils/nms/PlayerRespawnNMS.java @@ -44,12 +44,12 @@ private static void sendSimplePacket(ServerPlayer nmsPlayer, CommonPlayerSpawnIn * @param nmsPlayer le joueur en NMS * @param spawnInfo Les informations de la dimension ou il est envoyé */ - public static void sendPacket(ServerPlayer nmsPlayer, CommonPlayerSpawnInfo spawnInfo) { + public static void sendPacket(ServerPlayer nmsPlayer, CommonPlayerSpawnInfo spawnInfo, boolean isJoining) { // ** Envoie de l'entete du packet respawn sendSimplePacket(nmsPlayer, spawnInfo); // ** Procédure afin que le packet respawn soit valide - sendPostRespawnPackets(nmsPlayer); + sendPostRespawnPackets(nmsPlayer, isJoining); resyncEntities(nmsPlayer.getBukkitEntity().getPlayer()); } @@ -63,11 +63,15 @@ public static void sendPacket(ServerPlayer nmsPlayer, CommonPlayerSpawnInfo spaw * Note : Assurer vous que le pivot ne pointe pas vers une dimension ou le joueur est déja * {@code nmsPlayer.createCommonSpawnInfo(nmsPlayer.level()).dimension().equals(Level.OVERWORLD) ? Level.END : Level.OVERWORLD;} */ - public static void sendPacket(ServerPlayer nmsPlayer, CommonPlayerSpawnInfo targetSpawnInfo, ResourceKey pivotDimension) { + public static void sendPacket( + ServerPlayer nmsPlayer, + CommonPlayerSpawnInfo targetSpawnInfo, + ResourceKey pivotDimension, + boolean isJoining) { // changement de dimension car sinon l'ambience de la dimension n'est pas affiché // l'unique packet de repsawn pour simuler un changement de dimension + envoie du dimension type = plus rapide sendSimplePacket(nmsPlayer, createPlayerSpawnInfoWithDimension(nmsPlayer, pivotDimension)); - sendPacket(nmsPlayer, targetSpawnInfo); + sendPacket(nmsPlayer, targetSpawnInfo, isJoining); } /** @@ -95,7 +99,7 @@ public void run() { * Procédure basée sur {@link ServerPlayer#teleport} afin de corriger que le packet RESPAWN invalide * @param nmsPlayer le joueur (NMS) */ - private static void sendPostRespawnPackets(ServerPlayer nmsPlayer) { + private static void sendPostRespawnPackets(ServerPlayer nmsPlayer, boolean isJoining) { ServerLevel nmsWorld = nmsPlayer.level(); LevelData levelData = nmsWorld.getLevelData(); @@ -116,8 +120,10 @@ private static void sendPostRespawnPackets(ServerPlayer nmsPlayer) { // Utilisation d'une méthode trouvé via l'utilisation de ClientboundSetChunkCacheCenterPacket. // Refait tout simplement le systeme de chargement des chunks pour un joueur, sans avoir de défaillance - nmsWorld.moonrise$getPlayerChunkLoader().removePlayer(nmsPlayer); - nmsWorld.moonrise$getPlayerChunkLoader().addPlayer(nmsPlayer); + if (!isJoining) { + nmsWorld.moonrise$getPlayerChunkLoader().removePlayer(nmsPlayer); + nmsWorld.moonrise$getPlayerChunkLoader().addPlayer(nmsPlayer); + } } /** diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index baae3c480..349518007 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -33,7 +33,7 @@ feature.dailyevents.miraculousfishing.broadcast.start=
*sortez vos cannes à pêche et découvrez les mystères des lacs*\
\
Effets :\ -
+ %1$s< vitesse de pêche\ +
+ %1$s vitesse de pêche\
+ Loots spéciaux et rares\
+ Monstres des Mers\
\ @@ -132,4 +132,9 @@ feature.dailyevents.bloody_night.vampire_boss.defeated.midle=
(vou
\
Vos récompenses : feature.dailyevents.bloody_night.vampire_boss.defeated.rank=- %1$s %2$s - %3$s dégats -feature.dailyevents.bloody_night.vampire_boss.defeated.end= \ No newline at end of file +feature.dailyevents.bloody_night.vampire_boss.defeated.end= + +feature.dailyevents.bloody_night.vampire_boss.mail.received=Vous avez reçu la lettre des récompenses +feature.dailyevents.bloody_night.vampire_boss.mail.click=Cliquez ici +feature.dailyevents.bloody_night.vampire_boss.mail.hover=Ouvrir la mailbox +feature.dailyevents.bloody_night.vampire_boss.mail.open_mailbox= pour ouvrir la mailbox \ No newline at end of file From cb659bc3393aa69f06f66b9dee559828e9a454c9 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:25:13 +0200 Subject: [PATCH 41/50] fix: review of louty --- .../java/fr/openmc/core/ListenersManager.java | 2 ++ .../MiraculousFishingManager.java | 10 ++++++-- .../core/listeners/InteractListener.java | 5 ++++ .../DesactivateFireworkDamageListener.java | 23 +++++++++++++++++++ .../lootboxes/menu/LootboxOpenMenu.java | 4 ++++ 5 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/main/java/fr/openmc/core/registry/lootboxes/listener/DesactivateFireworkDamageListener.java diff --git a/src/main/java/fr/openmc/core/ListenersManager.java b/src/main/java/fr/openmc/core/ListenersManager.java index 0f9c1f642..44212fd70 100644 --- a/src/main/java/fr/openmc/core/ListenersManager.java +++ b/src/main/java/fr/openmc/core/ListenersManager.java @@ -9,6 +9,7 @@ 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.lootboxes.listener.DesactivateFireworkDamageListener; import fr.openmc.core.registry.mobs.listeners.CustomMobBossbarListener; import fr.openmc.core.registry.mobs.listeners.CustomMobDeathListener; import fr.openmc.core.registry.mobs.listeners.CustomMobLoadListener; @@ -38,6 +39,7 @@ public static void init() { new PlayerDeathListener(), new AsyncChatListener(OMCPlugin.getInstance()), new InteractListener(), + new DesactivateFireworkDamageListener(), new BlockPlaceListener(), new EquipableItemListener(), new NoMoreRabbit(), diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java index 6d4f659bc..5573b4483 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingManager.java @@ -95,8 +95,14 @@ private static void applyVelocity(Location origin, Location destination, Entity // * Revient à faire le vecteur vitesse entre 2 vecteur (xp - xh, yp - yh, zp - zh) Vector velocity = destination.toVector().subtract(origin.toVector()); velocity.multiply(force); - velocity.setY(velocity.getY() + Math.sqrt(Math.sqrt( - velocity.getX()*2 + velocity.getY()*2 + velocity.getZ()*2)) * 0.08); + + double m = Math.sqrt( + velocity.getX() * velocity.getX() + + velocity.getY() * velocity.getY() + + velocity.getZ() * velocity.getZ() + ); + + velocity.setY(velocity.getY() + m * 0.08); entity.setVelocity(velocity); } } diff --git a/src/main/java/fr/openmc/core/listeners/InteractListener.java b/src/main/java/fr/openmc/core/listeners/InteractListener.java index c28899705..a4fb92b0c 100644 --- a/src/main/java/fr/openmc/core/listeners/InteractListener.java +++ b/src/main/java/fr/openmc/core/listeners/InteractListener.java @@ -2,7 +2,9 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.items.CustomItem; +import fr.openmc.core.registry.items.options.LootboxBlock; import fr.openmc.core.registry.items.options.UsableItem; +import fr.openmc.core.utils.bukkit.ItemUtils; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; @@ -30,6 +32,9 @@ void onInteract(PlayerInteractEvent event) { if (player.isSneaking()) usable.onSneakClick(player, event); else if (action.isLeftClick()) usable.onLeftClick(player, event); else if (action.isRightClick()) usable.onRightClick(player, event); + } else if (item.get() instanceof LootboxBlock lootbox) { + ItemUtils.removeItemsFromPlayerInventory(player, item.get().getBest(), 1); + lootbox.getLootbox().open(player); } } diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/listener/DesactivateFireworkDamageListener.java b/src/main/java/fr/openmc/core/registry/lootboxes/listener/DesactivateFireworkDamageListener.java new file mode 100644 index 000000000..d6f374253 --- /dev/null +++ b/src/main/java/fr/openmc/core/registry/lootboxes/listener/DesactivateFireworkDamageListener.java @@ -0,0 +1,23 @@ +package fr.openmc.core.registry.lootboxes.listener; + +import fr.openmc.core.OMCPlugin; +import org.bukkit.NamespacedKey; +import org.bukkit.entity.Firework; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.persistence.PersistentDataType; + +public class DesactivateFireworkDamageListener implements Listener { + public static final NamespacedKey NO_DAMAGE_KEY = new NamespacedKey(OMCPlugin.getInstance(), "no_damage_firework"); + + @EventHandler + public void onFireworkDamage(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Firework firework)) return; + + if (firework.getPersistentDataContainer().has(NO_DAMAGE_KEY, PersistentDataType.BOOLEAN)) { + event.setCancelled(true); + + } + } +} diff --git a/src/main/java/fr/openmc/core/registry/lootboxes/menu/LootboxOpenMenu.java b/src/main/java/fr/openmc/core/registry/lootboxes/menu/LootboxOpenMenu.java index e7742c53a..01f81eaef 100644 --- a/src/main/java/fr/openmc/core/registry/lootboxes/menu/LootboxOpenMenu.java +++ b/src/main/java/fr/openmc/core/registry/lootboxes/menu/LootboxOpenMenu.java @@ -29,6 +29,7 @@ import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.persistence.PersistentDataType; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; @@ -37,6 +38,8 @@ import java.util.List; import java.util.Map; +import static fr.openmc.core.registry.lootboxes.listener.DesactivateFireworkDamageListener.NO_DAMAGE_KEY; + public class LootboxOpenMenu extends Menu { // ** Animation @@ -234,6 +237,7 @@ public void run() { meta.setPower(2); firework.setFireworkMeta(meta); firework.detonate(); + firework.getPersistentDataContainer().set(NO_DAMAGE_KEY, PersistentDataType.BOOLEAN, true); }); MessagesManager.broadcastMessage(TranslationManager.translation("feature.tickets.loot.broadcast", From 71b590d180c0e8ae5280823488659a6f4b38beeb Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:32:30 +0200 Subject: [PATCH 42/50] fix: sfx on water --- .../listeners/PlayerFishListener.java | 73 ++++++++++++------- .../core/utils/bukkit/ParticleUtils.java | 6 ++ 2 files changed, 52 insertions(+), 27 deletions(-) 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 a9e7edc79..71bc55016 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 @@ -16,10 +16,12 @@ import fr.openmc.core.utils.text.messages.MessagesManager; import fr.openmc.core.utils.text.messages.Prefix; import fr.openmc.core.utils.text.messages.TranslationManager; +import io.papermc.paper.event.entity.FishHookStateChangeEvent; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Particle; import org.bukkit.Sound; +import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.FishHook; import org.bukkit.entity.Item; @@ -44,43 +46,60 @@ public void onStartFishing(PlayerFishEvent event) { FishingAttributeManager.applyFishingSpeedModifier(player, hook); - switch (event.getState()) { - case FISHING -> { - // * SFX - ParticleUtils.sendParticlePacket(player, Particle.POOF, hook.getLocation(), 5, 0.1, 0.1, 0.1, 0.01, null); - player.playSound(player.getLocation(), Sound.ENTITY_FISHING_BOBBER_SPLASH, 1f, 0.7f); + if (event.getState().equals(PlayerFishEvent.State.CAUGHT_FISH)) { + Entity caughtEntity = event.getCaught(); + if (caughtEntity instanceof Item caughtItem) { + caughtItem.remove(); } - case CAUGHT_FISH -> { - Entity caughtEntity = event.getCaught(); - if (caughtEntity instanceof Item caughtItem) { - caughtItem.remove(); - } + CustomLootTable fishingLootTable = OMCRegistry.CUSTOM_LOOT_TABLES.MIRACULOUS_FISHING; - CustomLootTable fishingLootTable = OMCRegistry.CUSTOM_LOOT_TABLES.MIRACULOUS_FISHING; + List loots = fishingLootTable.rollLoots(); - List loots = fishingLootTable.rollLoots(); + List finalLoots = FishingAttributeManager.applyDoubleHookChance(player, loots); - List finalLoots = FishingAttributeManager.applyDoubleHookChance(player, loots); + // * SFX + ParticleUtils.spawnDispersingParticles(player, + Particle.CLOUD, + hook.getLocation(), + 35, 0.1D, null); - // * SFX - ParticleUtils.spawnDispersingParticles(player, - Particle.CLOUD, - hook.getLocation(), - 35, 0.1D, null); + MessagesManager.sendMessage(player, TranslationManager.translation( + "feature.dailyevents.miraculousfishing.loot_table.get", + Component.text(finalLoots.size()).color(NamedTextColor.YELLOW) + ), Prefix.MIRACULOUS_FISHING, MessageType.INFO, false); - MessagesManager.sendMessage(player, TranslationManager.translation( - "feature.dailyevents.miraculousfishing.loot_table.get", - Component.text(finalLoots.size()).color(NamedTextColor.YELLOW) - ), Prefix.MIRACULOUS_FISHING, MessageType.INFO, false); + if (loots.size() * 2 == finalLoots.size()) { + player.sendMessage(TranslationManager.translation("feature.dailyevents.miraculousfishing.loot_table.get.double_hook")); + } - if (loots.size()*2 == finalLoots.size()) { - player.sendMessage(TranslationManager.translation("feature.dailyevents.miraculousfishing.loot_table.get.double_hook")); - } + sendLoot(player, hook, finalLoots); + } + } - sendLoot(player, hook, finalLoots); - } + @EventHandler + public void onHookOnWater(FishHookStateChangeEvent event) { + if (!DailyEventsManager.isActiveDailyEvent() + || !(DailyEventsManager.getActiveDailyEvent() instanceof MiraculousFishingEvent)) return; + + Entity hook = event.getEntity(); + World world = hook.getWorld(); + + if (event.getNewHookState().equals(FishHook.HookState.BOBBING)) { + // * SFX + ParticleUtils.sendParticlePacket( + hook.getLocation().getNearbyEntitiesByType(Player.class, 30), + Particle.POOF, hook.getLocation(), + 5, + 0.1, + 0.1, + 0.1, + 0.01, + null + ); + world.playSound(hook.getLocation(), Sound.ENTITY_FISHING_BOBBER_SPLASH, 2f, 0.7f); } + } /** diff --git a/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java b/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java index 0d919c5a4..1f693ae36 100644 --- a/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java +++ b/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java @@ -128,6 +128,12 @@ public static void sendParticlePacket(Player player, Particle particle, Location sendParticlePacket(player, particle, loc, 3, 0.2f, 0.2f, 0.2f, 0.01f, null); } + public static void sendParticlePacket(Collection receivers, Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double speed, T data) { + for (Player player : receivers) { + sendParticlePacket(player, particle, location, count, offsetX, offsetY, offsetZ, speed, data); + } + } + public static void sendParticlePacket(Player player, Particle particle, Location location, int count, double offsetX, double offsetY, double offsetZ, double speed, T data) { ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); From 0140aea8044e225f084f03572ba9e242fd917bbd Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 11:51:15 +0200 Subject: [PATCH 43/50] fix: sfx on water --- src/main/java/fr/openmc/core/listeners/InteractListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/fr/openmc/core/listeners/InteractListener.java b/src/main/java/fr/openmc/core/listeners/InteractListener.java index a4fb92b0c..631c0f2cf 100644 --- a/src/main/java/fr/openmc/core/listeners/InteractListener.java +++ b/src/main/java/fr/openmc/core/listeners/InteractListener.java @@ -32,7 +32,8 @@ void onInteract(PlayerInteractEvent event) { if (player.isSneaking()) usable.onSneakClick(player, event); else if (action.isLeftClick()) usable.onLeftClick(player, event); else if (action.isRightClick()) usable.onRightClick(player, event); - } else if (item.get() instanceof LootboxBlock lootbox) { + } else if (item.get() instanceof LootboxBlock lootbox + && event.getAction() == Action.RIGHT_CLICK_AIR) { ItemUtils.removeItemsFromPlayerInventory(player, item.get().getBest(), 1); lootbox.getLootbox().open(player); } From f45b94a7a89249a9ba309879b569cdbfd1876bc6 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:33:49 +0200 Subject: [PATCH 44/50] change: ia placeholder for attribute with ancient fisher armor --- .../FishingAttributeManager.java | 7 +++++-- .../placeholder/DoubleHookChancePlaceholder.java | 16 ++++++++++++++++ .../placeholder/FishingSpeedPlaceholder.java | 15 +++++++++++++++ .../placeholders/IAPlaceholderRegistry.java | 6 +++++- .../core/registry/items/CustomItemRegistry.java | 5 ++--- .../contents/omc_daily_events/armor.yml | 8 ++++++++ 6 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/DoubleHookChancePlaceholder.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/FishingSpeedPlaceholder.java diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/FishingAttributeManager.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/FishingAttributeManager.java index a135b58b2..6972efa95 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/FishingAttributeManager.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/FishingAttributeManager.java @@ -18,6 +18,9 @@ public class FishingAttributeManager { public static final double FISHING_SPEED_MODIFIER = 0.4; public static final double DOUBLE_HOOK_MODIFIER = 0; + public static final double ARMOR_FISHING_SPEED_MODIFIER = 0.05; + public static final double ARMOR_DOUBLE_HOOK_MODIFIER = 0.03; + private static final Set FISHER_ARMOR = Set.of( OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_HELMET, OMCRegistry.CUSTOM_ITEMS.ANCIENT_FISHER_CHESTPLATE, @@ -56,7 +59,7 @@ public static double getFishingSpped(Player player) { Optional ci = OMCRegistry.CUSTOM_ITEMS.get(item); if (ci.isPresent() && FISHER_ARMOR.contains(ci.get())) { - base += 0.05; + base += ARMOR_FISHING_SPEED_MODIFIER; } } @@ -84,7 +87,7 @@ public static double getDoubleHookChance(Player player) { Optional ci = OMCRegistry.CUSTOM_ITEMS.get(item); if (ci.isPresent() && FISHER_ARMOR.contains(ci.get())) { - base += 0.03; + base += ARMOR_DOUBLE_HOOK_MODIFIER; } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/DoubleHookChancePlaceholder.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/DoubleHookChancePlaceholder.java new file mode 100644 index 000000000..a3e1eee3c --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/DoubleHookChancePlaceholder.java @@ -0,0 +1,16 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.placeholder; + +import fr.openmc.core.hooks.itemsadder.placeholders.IAPlaceholder; + +import static fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.FishingAttributeManager.ARMOR_DOUBLE_HOOK_MODIFIER; + +public class DoubleHookChancePlaceholder implements IAPlaceholder { + + public String name() { + return "armor_double_hook_chance"; + } + + public String resolve(String idItem) { + return String.valueOf(ARMOR_DOUBLE_HOOK_MODIFIER * 100); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/FishingSpeedPlaceholder.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/FishingSpeedPlaceholder.java new file mode 100644 index 000000000..9e5d38ecf --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/contents/placeholder/FishingSpeedPlaceholder.java @@ -0,0 +1,15 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.placeholder; + +import fr.openmc.core.hooks.itemsadder.placeholders.IAPlaceholder; + +import static fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.FishingAttributeManager.ARMOR_FISHING_SPEED_MODIFIER; + +public class FishingSpeedPlaceholder implements IAPlaceholder { + public String name() { + return "armor_fishing_speed"; + } + + public String resolve(String idItem) { + return String.valueOf(ARMOR_FISHING_SPEED_MODIFIER * 100); + } +} diff --git a/src/main/java/fr/openmc/core/hooks/itemsadder/placeholders/IAPlaceholderRegistry.java b/src/main/java/fr/openmc/core/hooks/itemsadder/placeholders/IAPlaceholderRegistry.java index bbe1c1da3..6cdad7580 100644 --- a/src/main/java/fr/openmc/core/hooks/itemsadder/placeholders/IAPlaceholderRegistry.java +++ b/src/main/java/fr/openmc/core/hooks/itemsadder/placeholders/IAPlaceholderRegistry.java @@ -4,6 +4,8 @@ import fr.openmc.core.features.dream.placeholders.DreamItemMaterialPlaceholder; import fr.openmc.core.features.dream.placeholders.DreamItemNamePlaceholder; import fr.openmc.core.features.dream.placeholders.DreamItemTooltipPlaceholder; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.placeholder.DoubleHookChancePlaceholder; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.contents.placeholder.FishingSpeedPlaceholder; import java.util.HashMap; import java.util.Map; @@ -25,7 +27,9 @@ public static IAPlaceholderRegistry loadDefault() { registry.register( new DreamItemTooltipPlaceholder(), new DreamItemMaterialPlaceholder(), - new DreamItemNamePlaceholder() + new DreamItemNamePlaceholder(), + new FishingSpeedPlaceholder(), + new DoubleHookChancePlaceholder() ); return registry; } 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 a2e9eab53..7e9e9f23e 100644 --- a/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java +++ b/src/main/java/fr/openmc/core/registry/items/CustomItemRegistry.java @@ -23,7 +23,8 @@ import java.util.Optional; -public class CustomItemRegistry extends Registry implements KeyedRegistry { +public class CustomItemRegistry extends Registry + implements KeyedRegistry { public static final NamespacedKey CUSTOM_ITEM_KEY = new NamespacedKey("openmc", "custom_item"); @@ -131,8 +132,6 @@ public class CustomItemRegistry extends Registry implements 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 public void postInit() { CommandsManager.getHandler().register(new CustomItemsDebugCommand()); diff --git a/src/main/resources/contents/omc_daily_events/armor.yml b/src/main/resources/contents/omc_daily_events/armor.yml index c8dfa6db4..3b915496f 100644 --- a/src/main/resources/contents/omc_daily_events/armor.yml +++ b/src/main/resources/contents/omc_daily_events/armor.yml @@ -15,6 +15,8 @@ items: - armor/ancient_fishing/ancient_helmet material: LEATHER_HELMET lore: + - "§8+ §b{armor_fishing_speed:a}% §7de §bvitesse de pêche" + - "§8+ §1{armor_double_hook_chance:a}% §7de chance de §1double prise" - "§7§oUn casque trouvé dans les abysses des mers" durability: unbreakable: true @@ -31,6 +33,8 @@ items: - armor/ancient_fishing/ancient_chestplate material: LEATHER_CHESTPLATE lore: + - "§8+ §b{armor_fishing_speed:a}% §7de §bvitesse de pêche" + - "§8+ §1{armor_double_hook_chance:a}% §7de chance de §1double prise" - "§7§oUn plastron trouvé dans les abysses des mers" durability: unbreakable: true @@ -46,6 +50,8 @@ items: - armor/ancient_fishing/ancient_leggings material: LEATHER_LEGGINGS lore: + - "§8+ §b{armor_fishing_speed:a}% §7de §bvitesse de pêche" + - "§8+ §1{armor_double_hook_chance:a}% §7de chance de §1double prise" - "§7§oUne jambière trouvé dans les abysses des mers" durability: unbreakable: true @@ -62,6 +68,8 @@ items: - armor/ancient_fishing/ancient_boots material: LEATHER_BOOTS lore: + - "§8+ §b{armor_fishing_speed:a}% §7de §bvitesse de pêche" + - "§8+ §1{armor_double_hook_chance:a}% §7de chance de §1double prise" - "§7§oDes bottes trouvées dans les abysses des mers" durability: unbreakable: true From c2d94efc33f126f803372d448fa1dbdc7f52cef2 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:41:47 +0200 Subject: [PATCH 45/50] change: improve spawn raid and vampire --- .../contents/bloodynight/BloodyNightManager.java | 7 ++++++- .../contents/bloodynight/BloodyNightRaidManager.java | 7 ++++++- .../java/fr/openmc/core/utils/world/LocationUtils.java | 6 ++++++ 3 files changed, 18 insertions(+), 2 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 02b86eaf1..bd0f22396 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 @@ -38,7 +38,12 @@ public static void start(BloodyNightEvent event) { ); // * Programmation du boss Vampire - Location vampireSpawnLocation = LocationUtils.randomLocation(world.getSpawnLocation(), world.getWorldBorder().getSize() / 2.0); + Location vampireSpawnLocation = LocationUtils.getSafeNearbySurface( + LocationUtils.randomLocation( + world.getSpawnLocation(), + world.getWorldBorder().getSize() / 2.0, 10000 + ), + 50); vampireTask = Bukkit.getScheduler().runTaskLater( OMCPlugin.getInstance(), () -> OMCRegistry.CUSTOM_MOBS.VAMPIRE_BOSS.spawn(vampireSpawnLocation), 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 index 5ea1905f6..5235d3e08 100644 --- 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 @@ -47,7 +47,12 @@ private static void spawnRaidAroundPlayer(Player player) { ); for (int i = 0; i < mobAmount; i++) { - Location spawnLocation = LocationUtils.getSafeNearbySurface(player.getLocation(), MAX_SPAWN_RADIUS); + Location spawnLocation = LocationUtils.getSafeNearbySurface( + LocationUtils.randomLocation( + player.getLocation(), + MAX_SPAWN_RADIUS + ), + 20); world.strikeLightningEffect(spawnLocation); spawnRandomMonster(spawnLocation); diff --git a/src/main/java/fr/openmc/core/utils/world/LocationUtils.java b/src/main/java/fr/openmc/core/utils/world/LocationUtils.java index 8d8fc52c0..7faf407fa 100644 --- a/src/main/java/fr/openmc/core/utils/world/LocationUtils.java +++ b/src/main/java/fr/openmc/core/utils/world/LocationUtils.java @@ -19,6 +19,12 @@ public static Location randomLocation(Location origin, double distance) { return target.getWorld().getHighestBlockAt(target).getLocation().add(0, 1, 0); } + public static Location randomLocation(Location origin, double minDistance, double maxDistance) { + double distance = minDistance + Math.random() * (maxDistance - minDistance); + + return randomLocation(origin, distance); + } + public static Location getSafeNearbySurface(Location location, int radius) { World world = location.getWorld(); int baseY = location.getBlockY(); From 37e19d6018c3f276e417efa9eff5edd1c5c3e050 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 12:44:22 +0200 Subject: [PATCH 46/50] change: improve spawn raid and vampire --- .../dailyevents/contents/bloodynight/BloodyNightManager.java | 1 + 1 file changed, 1 insertion(+) 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 bd0f22396..2ff6a1adb 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 @@ -44,6 +44,7 @@ public static void start(BloodyNightEvent event) { world.getWorldBorder().getSize() / 2.0, 10000 ), 50); + vampireTask = Bukkit.getScheduler().runTaskLater( OMCPlugin.getInstance(), () -> OMCRegistry.CUSTOM_MOBS.VAMPIRE_BOSS.spawn(vampireSpawnLocation), From 5b45537820e5ce796da7db4268a94d82786dc3e3 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:03:20 +0200 Subject: [PATCH 47/50] change: improve loot table for difficulty of each mob --- .../bloodynight/BloodyNightManager.java | 4 -- .../bloodymob/AncientMobLootTable.java | 36 ++++++++++++++++ .../CorruptedMobLootTable.java} | 13 +++--- .../bloodymob/CursedMobLootTable.java | 43 +++++++++++++++++++ .../bloodymob/EnragedMobLootTable.java | 38 ++++++++++++++++ .../mobs/bloodytypes/AncientMonster.java | 8 +++- .../mobs/bloodytypes/CorruptedMonster.java | 10 ++++- .../mobs/bloodytypes/CursedMonster.java | 12 +++++- .../mobs/bloodytypes/EnragedMonster.java | 12 +++++- .../listeners/MonsterSpawnLIstener.java | 6 --- .../loottable/CustomLootTableRegistry.java | 10 ++++- .../default/dailyevents.properties | 6 ++- 12 files changed, 172 insertions(+), 26 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/AncientMobLootTable.java rename src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/{BloodyMobLootTable.java => bloodymob/CorruptedMobLootTable.java} (70%) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.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 2ff6a1adb..9d736930e 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 @@ -155,10 +155,6 @@ private static void deleteVampireMonsters(World world) { */ public static void applyBloodyMonster(LivingEntity entity) { double random = ThreadLocalRandom.current().nextDouble(); - - System.out.println(random); - - //todo: sfx particule if (random < 0.60) { OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(entity); } else if (random < 0.90) { diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/AncientMobLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/AncientMobLootTable.java new file mode 100644 index 000000000..795ea93b1 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/AncientMobLootTable.java @@ -0,0 +1,36 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob; + +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 org.bukkit.Material; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public class AncientMobLootTable extends CustomLootTable { + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.ancient_mob"); + } + + @Override + public String getNamespace() { + return "omc_daily_events:ancient_mobs"; + } + + @Override + public Set getLoots() { + return new LinkedHashSet<>(List.of( + new ItemLoot(Material.IRON_BLOCK,0.3, 3, 6), + new ItemLoot(Material.GOLD_BLOCK,0.2, 1, 2), + new ItemLoot(Material.DIAMOND_BLOCK,0.13, 1), + new ItemLoot(Material.NETHERITE_SCRAP,0.1, 2), + new ItemLoot(OMCRegistry.CUSTOM_ENCHANTS.VAMPIRISM.getEnchantedBookItem(1),0.02, 1) + )); + } +} 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/bloodymob/CorruptedMobLootTable.java similarity index 70% rename from src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/BloodyMobLootTable.java rename to src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CorruptedMobLootTable.java index 2815ae587..3f3ba45b6 100644 --- 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/bloodymob/CorruptedMobLootTable.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable; +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.loottable.CustomLootTable; @@ -12,15 +12,15 @@ import java.util.List; import java.util.Set; -public class BloodyMobLootTable extends CustomLootTable { +public class CorruptedMobLootTable extends CustomLootTable { @Override public Component getName() { - return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.bloody_mob"); + return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.corrupted_mob"); } @Override public String getNamespace() { - return "omc_daily_events:bloody_mobs"; + return "omc_daily_events:corrupted_mobs"; } @Override @@ -30,10 +30,7 @@ public Set getLoots() { new ItemLoot(Material.GOLD_INGOT,0.2, 1, 3), new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE,0.2, 1, 3), new ItemLoot(Material.DIAMOND,0.07, 1, 2), - new ItemLoot(Material.IRON_BLOCK,0.08, 1), - new ItemLoot(Material.GOLD_BLOCK,0.06, 1), - new ItemLoot(Material.DIAMOND_BLOCK,0.01, 1), - new ItemLoot(Material.NETHERITE_SCRAP,0.004, 1) + new ItemLoot(Material.GOLDEN_APPLE,0.06, 1, 3) )); } } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java new file mode 100644 index 000000000..424073370 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java @@ -0,0 +1,43 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob; + +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 org.bukkit.Material; +import org.bukkit.inventory.ItemType; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public class CursedMobLootTable extends CustomLootTable { + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.cursed_mob"); + } + + @Override + public String getNamespace() { + return "omc_daily_events:cursed_mobs"; + } + + @Override + public Set getLoots() { + return new LinkedHashSet<>(List.of( + new ItemLoot(Material.IRON_BLOCK,0.3, 1, 2), + new ItemLoot(Material.GOLD_BLOCK,0.2, 1, 2), + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK,0.2, 2, 4), + new ItemLoot(Material.DIAMOND,0.2, 1, 2), + new ItemLoot(ItemType.SPLASH_POTION.createItemStack(p -> { + p.addCustomEffect(new PotionEffect(PotionEffectType.INSTANT_HEALTH, 5, 1), true); + }),0.13, 1), + new ItemLoot(Material.DIAMOND_BLOCK,0.1, 1), + new ItemLoot(Material.NETHERITE_SCRAP,0.04, 1) + )); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java new file mode 100644 index 000000000..c6d0f56f5 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java @@ -0,0 +1,38 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob; + +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 org.bukkit.Material; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +public class EnragedMobLootTable extends CustomLootTable { + @Override + public Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.enraged_mob"); + } + + @Override + public String getNamespace() { + return "omc_daily_events:enraged_mobs"; + } + + @Override + public Set getLoots() { + return new LinkedHashSet<>(List.of( + new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE,0.4, 4, 8), + new ItemLoot(Material.IRON_BLOCK,0.23, 1), + new ItemLoot(Material.GOLDEN_APPLE,0.2, 1, 2), + new ItemLoot(Material.GOLD_BLOCK,0.16, 1), + new ItemLoot(Material.DIAMOND,0.1, 1, 2), + new ItemLoot(Material.DIAMOND_BLOCK,0.01, 1), + new ItemLoot(Material.NETHERITE_SCRAP,0.004, 1) + )); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/AncientMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/AncientMonster.java index 7b427f169..abbf10087 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/AncientMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/AncientMonster.java @@ -3,9 +3,11 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; +import org.bukkit.Particle; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; @@ -43,7 +45,7 @@ public AncientMonster(String id) { Monster.class, 3, 1, - OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + OMCRegistry.CUSTOM_LOOT_TABLES.ANCIENT_MOB.rollLoots() ); } @@ -62,6 +64,10 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + // * SFX + ParticleUtils.spawnDispersingParticles(entity.getLocation(), + Particle.EXPLOSION_EMITTER, + 5, 35, 0.1D, null); EntityGlowNMS.setGlowingColor(entity, TeamColor.YELLOW); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CorruptedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CorruptedMonster.java index 9522b60ef..18593c7da 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CorruptedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CorruptedMonster.java @@ -3,9 +3,11 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; +import org.bukkit.Particle; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; @@ -14,7 +16,7 @@ public class CorruptedMonster extends CustomMob { private static final AttributeModifier HEALTH_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "corrupted_health"), - 1, + 0.75, AttributeModifier.Operation.ADD_SCALAR ); @@ -42,7 +44,7 @@ public CorruptedMonster(String id) { Monster.class, 1, 1, - OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + OMCRegistry.CUSTOM_LOOT_TABLES.CORRUPTED_MOB.rollLoots() ); } @@ -61,6 +63,10 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + // * SFX + ParticleUtils.spawnDispersingParticles(entity.getLocation(), + Particle.TRIAL_SPAWNER_DETECTION, + 10, 35, 0.1D, null); EntityGlowNMS.setGlowingColor(entity, TeamColor.DARK_RED); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java index bba3aa415..1532b8baa 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java @@ -3,9 +3,11 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; +import org.bukkit.Particle; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; @@ -48,7 +50,7 @@ public CursedMonster(String id) { Monster.class, 1, 1, - OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + OMCRegistry.CUSTOM_LOOT_TABLES.CURSED_MOB.rollLoots() ); } @@ -59,11 +61,19 @@ public void apply(Monster entity) { entity.setCustomNameVisible(false); EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + AttributeInstance attrInst = entity.getAttribute(Attribute.MAX_HEALTH); + if (attrInst == null) return; + entity.setHealth(attrInst.getValue()); + 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); + // * SFX + ParticleUtils.spawnDispersingParticles(entity.getLocation(), + Particle.REVERSE_PORTAL, + 10, 35, 0.1D, null); EntityGlowNMS.setGlowingColor(entity, TeamColor.DARK_PURPLE); } diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java index 225837541..af1603cd5 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java @@ -3,9 +3,11 @@ import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.mobs.CustomMob; import fr.openmc.core.utils.bukkit.EntityUtils; +import fr.openmc.core.utils.bukkit.ParticleUtils; import fr.openmc.core.utils.nms.entity.EntityGlowNMS; import net.minecraft.world.scores.TeamColor; import org.bukkit.NamespacedKey; +import org.bukkit.Particle; import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; @@ -42,7 +44,7 @@ public EnragedMonster(String id) { Monster.class, 1, 1, - OMCRegistry.CUSTOM_LOOT_TABLES.BLOODY_MOB.rollLoots() + OMCRegistry.CUSTOM_LOOT_TABLES.ENRAGED_MOB.rollLoots() ); } @@ -53,10 +55,18 @@ public void apply(Monster entity) { entity.setCustomNameVisible(false); EntityUtils.addModifierIfPresent(entity, Attribute.MAX_HEALTH, HEALTH_MODIFIER); + AttributeInstance attrInst = entity.getAttribute(Attribute.MAX_HEALTH); + if (attrInst == null) return; + entity.setHealth(attrInst.getValue()); + EntityUtils.addModifierIfPresent(entity, Attribute.ATTACK_DAMAGE, ATTACK_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + // * SFX + ParticleUtils.spawnDispersingParticles(entity.getLocation(), + Particle.ANGRY_VILLAGER, + 10, 35, 0.1D, null); EntityGlowNMS.setGlowingColor(entity, TeamColor.RED); } 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 597ae0333..17567a63e 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 @@ -7,9 +7,7 @@ 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; import org.bukkit.event.Listener; @@ -26,10 +24,6 @@ public void onNormalMonsterSpawn(EntitySpawnEvent event) { if (monster.getPersistentDataContainer().has(BloodyNightManager.RAID_MONSTER_KEY)) { BloodyNightManager.applyBloodyMonster(monster); } else { - ParticleUtils.spawnDispersingParticles(event.getLocation(), - Particle.DAMAGE_INDICATOR, - 10, 35, 0.1D, null); - OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(monster); } } 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 092e79273..5f4b07877 100644 --- a/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java +++ b/src/main/java/fr/openmc/core/registry/loottable/CustomLootTableRegistry.java @@ -2,8 +2,11 @@ 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.bloodynight.contents.loottable.bloodymob.AncientMobLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob.CorruptedMobLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob.CursedMobLootTable; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.contents.loottable.bloodymob.EnragedMobLootTable; 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; @@ -27,7 +30,10 @@ public class CustomLootTableRegistry extends Registry i public final CustomLootTable LEGENDARY_FISHING_TREASURE = register(new LegendaryFishingTreasureLootTable()); public final CustomLootTable VAMPIRE = register(new VampireLootTable()); - public final CustomLootTable BLOODY_MOB = register(new BloodyMobLootTable()); + public final CustomLootTable CORRUPTED_MOB = register(new CorruptedMobLootTable()); + public final CustomLootTable CURSED_MOB = register(new CursedMobLootTable()); + public final CustomLootTable ENRAGED_MOB = register(new EnragedMobLootTable()); + public final CustomLootTable ANCIENT_MOB = register(new AncientMobLootTable()); @Override public String key(CustomLootTable registryObject) { diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 349518007..57798e387 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -102,7 +102,11 @@ 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 +feature.dailyevents.bloody_night.loot_table.corrupted_mob=Loots des monstres corrompus +feature.dailyevents.bloody_night.loot_table.cursed_mob=Loots des monstres maudits +feature.dailyevents.bloody_night.loot_table.enraged_mob=Loots des monstres enragés +feature.dailyevents.bloody_night.loot_table.ancient_mob=Loots des monstres anciens + feature.dailyevents.bloody_night.loot_table.vampire_boss=Loots du Vampire feature.dailyevents.bloody_night.enchantment.vampirism.name=Vampirisme From 337d9fc308aab583f9dc0260d93ed5e4e5651acb Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 13:06:16 +0200 Subject: [PATCH 48/50] change: improve creeper set Enraged --- .../contents/mobs/bloodytypes/CursedMonster.java | 6 ++++++ .../contents/mobs/bloodytypes/EnragedMonster.java | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java index 1532b8baa..f4eb13915 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/CursedMonster.java @@ -11,8 +11,11 @@ import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Creeper; import org.bukkit.entity.Monster; +import java.util.concurrent.ThreadLocalRandom; + public class CursedMonster extends CustomMob { private static final AttributeModifier HEALTH_MODIFIER = new AttributeModifier( new NamespacedKey("omc_daily_events", "cursed_health"), @@ -70,6 +73,9 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.SCALE, SCALE_MODIFIER); + if (ThreadLocalRandom.current().nextBoolean() && entity instanceof Creeper) + entity.getWorld().strikeLightningEffect(entity.getLocation()); + // * SFX ParticleUtils.spawnDispersingParticles(entity.getLocation(), Particle.REVERSE_PORTAL, diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java index af1603cd5..9afd39834 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/mobs/bloodytypes/EnragedMonster.java @@ -11,6 +11,7 @@ import org.bukkit.attribute.Attribute; import org.bukkit.attribute.AttributeInstance; import org.bukkit.attribute.AttributeModifier; +import org.bukkit.entity.Creeper; import org.bukkit.entity.Monster; public class EnragedMonster extends CustomMob { @@ -63,6 +64,9 @@ public void apply(Monster entity) { EntityUtils.addModifierIfPresent(entity, Attribute.MOVEMENT_SPEED, SPEED_MODIFIER); EntityUtils.addModifierIfPresent(entity, Attribute.FOLLOW_RANGE, FOLLOW_MODIFIER); + if (entity instanceof Creeper) + entity.getWorld().strikeLightningEffect(entity.getLocation()); + // * SFX ParticleUtils.spawnDispersingParticles(entity.getLocation(), Particle.ANGRY_VILLAGER, From a44e8fb8707bddd350147428dc442ccd64732843 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 18:49:06 +0200 Subject: [PATCH 49/50] feat: add info menu bloody event --- .../bloodynight/BloodyNightEvent.java | 12 ++- .../bloodynight/BloodyNightManager.java | 21 ++-- .../bloodynight/BloodyNightRaidManager.java | 4 +- .../contents/loottable/VampireLootTable.java | 2 +- .../bloodymob/CursedMobLootTable.java | 5 +- .../bloodymob/EnragedMobLootTable.java | 3 + .../listeners/PlayerKillMonsterListener.java | 54 ++++------- .../bloodynight/menu/BloodyMonsterMenu.java | 97 +++++++++++++++++++ .../bloodynight/menu/BloodyNightMenu.java | 93 ++++++++++++++++++ .../MiraculousFishingEvent.java | 3 +- .../listeners/AmbientWeatherListener.java | 2 +- .../default/dailyevents.properties | 21 +++- 12 files changed, 269 insertions(+), 48 deletions(-) create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyMonsterMenu.java create mode 100644 src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyNightMenu.java 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 19b56c982..b92042544 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,26 +1,31 @@ package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight; +import fr.openmc.api.menulib.Menu; 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.contents.bloodynight.menu.BloodyNightMenu; 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; import fr.openmc.core.features.events.contents.dailyevents.models.dailyevent.HasToast; +import fr.openmc.core.features.events.models.HasMenu; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.toast.CustomToastData; import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; import net.minecraft.advancements.AdvancementType; import org.bukkit.Material; +import org.bukkit.entity.Player; 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, HasListeners { +public class BloodyNightEvent extends DailyEvent + implements HasToast, HasAmbient, HasBroadcast, HasListeners, HasMenu { @Override public String getEventId() { return "bloody_night"; @@ -101,4 +106,9 @@ public Set getListeners() { new MonsterSpawnLIstener() ); } + + @Override + public Menu getInfoMenu(Player player) { + return new BloodyNightMenu(player); + } } 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 9d736930e..5f65cffc5 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 @@ -18,9 +18,13 @@ import java.util.concurrent.ThreadLocalRandom; -// todo: faire boss vampire (abilité chauve souris explosante, empoissonante, ...) public class BloodyNightManager { + // * CONSTANTES public static final NamespacedKey RAID_MONSTER_KEY = new NamespacedKey("omc_daily_events", "raid_monster"); + + public static final long VAMPIRE_SPAWN_TIME = 20L * 60L * 15; // 15 min + public static final long RAID_INTERVAL = 20L * 60L * 2; // 2 min + private static BukkitTask raidTask; private static BukkitTask vampireTask; private static long lastTime; @@ -34,7 +38,7 @@ public static void start(BloodyNightEvent event) { OMCPlugin.getInstance(), () -> BloodyNightRaidManager.startRaid(world), 20L * 10, - 20L * 60L * 2 // 2 min + RAID_INTERVAL ); // * Programmation du boss Vampire @@ -48,7 +52,7 @@ public static void start(BloodyNightEvent event) { vampireTask = Bukkit.getScheduler().runTaskLater( OMCPlugin.getInstance(), () -> OMCRegistry.CUSTOM_MOBS.VAMPIRE_BOSS.spawn(vampireSpawnLocation), - 20L * 60L * 15 // 15 min + VAMPIRE_SPAWN_TIME ); // * Modification des monstres déjà présent dans le monde (uniquement ceux chargé) @@ -145,6 +149,11 @@ private static void deleteVampireMonsters(World world) { } } + public static final double CORRUPTED_CHANCE = 0.5; + public static final double ENRAGED_CHANCE = 0.3; + public static final double CURSED_CHANCE = 0.15; + public static final double ANCIENT_CHANCE = 0.05; + /** * Applique l'effet bloody sur un monstre * - Corrompu - 60% @@ -155,11 +164,11 @@ private static void deleteVampireMonsters(World world) { */ public static void applyBloodyMonster(LivingEntity entity) { double random = ThreadLocalRandom.current().nextDouble(); - if (random < 0.60) { + if (random < CORRUPTED_CHANCE) { OMCRegistry.CUSTOM_MOBS.CORRUPTED_MONSTER.apply(entity); - } else if (random < 0.90) { + } else if (random < CORRUPTED_CHANCE + ENRAGED_CHANCE) { OMCRegistry.CUSTOM_MOBS.ENRAGED_MONSTER.apply(entity); - } else if (random < 0.95) { + } else if (random < CORRUPTED_CHANCE + ENRAGED_CHANCE + CURSED_CHANCE) { OMCRegistry.CUSTOM_MOBS.CURSED_MONSTER.apply(entity); } else { OMCRegistry.CUSTOM_MOBS.ANCIENT_MONSTER.apply(entity); 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 index 5235d3e08..d02f15743 100644 --- 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 @@ -25,7 +25,9 @@ public class BloodyNightRaidManager { EntityType.SPIDER, EntityType.CREEPER, EntityType.HUSK, - EntityType.STRAY + EntityType.STRAY, + EntityType.PARCHED, + EntityType.BOGGED ); public static void startRaid(World world) { 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 index 924f380fb..41b6579d0 100644 --- 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 @@ -28,7 +28,7 @@ public Set getLoots() { return new LinkedHashSet<>(List.of( new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK,1, 1, 5), new ItemLoot(ItemType.OMINOUS_BOTTLE.createItemStack( - o -> o.setAmplifier(6)),0.6, 1), + o -> o.setAmplifier(4)),0.6, 1), new ItemLoot(OMCRegistry.CUSTOM_ITEMS.VAMPIRE_HEAD,0.50, 1), new ItemLoot( OMCRegistry.CUSTOM_ENCHANTS.VAMPIRISM.getEnchantedBookItem(1, 2), diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java index 424073370..1ac954395 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/CursedMobLootTable.java @@ -33,9 +33,8 @@ public Set getLoots() { new ItemLoot(Material.GOLD_BLOCK,0.2, 1, 2), new ItemLoot(OMCRegistry.CUSTOM_ITEMS.AYWENITE_BLOCK,0.2, 2, 4), new ItemLoot(Material.DIAMOND,0.2, 1, 2), - new ItemLoot(ItemType.SPLASH_POTION.createItemStack(p -> { - p.addCustomEffect(new PotionEffect(PotionEffectType.INSTANT_HEALTH, 5, 1), true); - }),0.13, 1), + new ItemLoot(ItemType.SPLASH_POTION.createItemStack(p -> + p.addCustomEffect(new PotionEffect(PotionEffectType.INSTANT_HEALTH, 5, 1), true)),0.13, 1), new ItemLoot(Material.DIAMOND_BLOCK,0.1, 1), new ItemLoot(Material.NETHERITE_SCRAP,0.04, 1) )); diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java index c6d0f56f5..7768ce85e 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/contents/loottable/bloodymob/EnragedMobLootTable.java @@ -7,6 +7,7 @@ import fr.openmc.core.utils.text.messages.TranslationManager; import net.kyori.adventure.text.Component; import org.bukkit.Material; +import org.bukkit.inventory.ItemType; import java.util.LinkedHashSet; import java.util.List; @@ -30,6 +31,8 @@ public Set getLoots() { new ItemLoot(Material.IRON_BLOCK,0.23, 1), new ItemLoot(Material.GOLDEN_APPLE,0.2, 1, 2), new ItemLoot(Material.GOLD_BLOCK,0.16, 1), + new ItemLoot(ItemType.OMINOUS_BOTTLE.createItemStack(o -> + o.setAmplifier(4)),0.13, 1, 2), new ItemLoot(Material.DIAMOND,0.1, 1, 2), new ItemLoot(Material.DIAMOND_BLOCK,0.01, 1), new ItemLoot(Material.NETHERITE_SCRAP,0.004, 1) 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 index 08d95c4b9..074e0c030 100644 --- 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 @@ -1,40 +1,28 @@ 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 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.rollLoots(player); - - event.getDrops().clear(); - for (CustomLoot loot : loots) { - if (!(loot instanceof ItemLoot itemLoot)) continue; - - for (ItemStack item : itemLoot.getItems()) { - event.getDrops().add(item); - } - } - } +// @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.CORRUPTED_MOB.rollLoots(player); +// +// 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/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyMonsterMenu.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyMonsterMenu.java new file mode 100644 index 000000000..e471bf56f --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyMonsterMenu.java @@ -0,0 +1,97 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.menu; + +import fr.openmc.api.menulib.Menu; +import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.api.menulib.utils.ItemMenuBuilder; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightManager; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BloodyMonsterMenu extends Menu { + + public BloodyMonsterMenu(Player owner) { + super(owner); + } + + @Override + public @NotNull Component getName() { + return TranslationManager.translation("feature.dailyevents.bloody_night.menu.info.bloody_monster.name"); + } + + @Override + public String getTexture() { + return null; + } + + @Override + public @NotNull InventorySize getInventorySize() { + return InventorySize.NORMAL; + } + + @Override + public void onInventoryClick(InventoryClickEvent click) { + //empty + } + + @Override + public @NotNull Map getContent() { + Map inventory = new HashMap<>(); + + inventory.put(11, new ItemMenuBuilder(this, Material.CRIMSON_NYLIUM, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.corrupted_mob")); + itemMeta.lore(TranslationManager.translationLore( + "feature.dailyevents.bloody_night.menu.info.bloody_monster.lore", + Component.text(BloodyNightManager.CORRUPTED_CHANCE * 100 + "%", NamedTextColor.DARK_RED))); + }).setOnClick(_ -> + OMCRegistry.CUSTOM_LOOT_TABLES.CORRUPTED_MOB.openMenu(getOwner()))); + + inventory.put(12, new ItemMenuBuilder(this, Material.RED_DYE, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.cursed_mob")); + itemMeta.lore(TranslationManager.translationLore( + "feature.dailyevents.bloody_night.menu.info.bloody_monster.lore", + Component.text(BloodyNightManager.CURSED_CHANCE * 100 + "%", NamedTextColor.RED))); + }).setOnClick(_ -> + OMCRegistry.CUSTOM_LOOT_TABLES.CURSED_MOB.openMenu(getOwner()))); + + inventory.put(14, new ItemMenuBuilder(this, Material.PURPLE_DYE, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.enraged_mob")); + itemMeta.lore(TranslationManager.translationLore( + "feature.dailyevents.bloody_night.menu.info.bloody_monster.lore", + Component.text(BloodyNightManager.ENRAGED_CHANCE * 100 + "%", NamedTextColor.DARK_PURPLE))); + }).setOnClick(_ -> + OMCRegistry.CUSTOM_LOOT_TABLES.ENRAGED_MOB.openMenu(getOwner()))); + + inventory.put(15, new ItemMenuBuilder(this, Material.YELLOW_DYE, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.loot_table.ancient_mob")); + itemMeta.lore(TranslationManager.translationLore( + "feature.dailyevents.bloody_night.menu.info.bloody_monster.lore", + Component.text(BloodyNightManager.ANCIENT_CHANCE * 100 + "%", NamedTextColor.YELLOW))); + }).setOnClick(_ -> + OMCRegistry.CUSTOM_LOOT_TABLES.ANCIENT_MOB.openMenu(getOwner()))); + + inventory.put(18, new ItemMenuBuilder(this, Material.ARROW, true)); + + return inventory; + } + + @Override + public void onClose(InventoryCloseEvent event) { + //empty + } + + @Override + public List getTakableSlot() { + return List.of(); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyNightMenu.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyNightMenu.java new file mode 100644 index 000000000..0e740f1cc --- /dev/null +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/bloodynight/menu/BloodyNightMenu.java @@ -0,0 +1,93 @@ +package fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.menu; + +import fr.openmc.api.menulib.Menu; +import fr.openmc.api.menulib.utils.InventorySize; +import fr.openmc.api.menulib.utils.ItemMenuBuilder; +import fr.openmc.core.OMCRegistry; +import fr.openmc.core.features.events.contents.dailyevents.DailyEventsManager; +import fr.openmc.core.features.events.contents.dailyevents.contents.bloodynight.BloodyNightManager; +import fr.openmc.core.features.events.contents.dailyevents.contents.miraculousfishing.MiraculousFishingEvent; +import fr.openmc.core.utils.text.messages.TranslationManager; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BloodyNightMenu extends Menu { + + public BloodyNightMenu(Player owner) { + super(owner); + } + + @Override + public @NotNull Component getName() { + return DailyEventsManager.BLOODY_NIGHT.getName(); + } + + @Override + public String getTexture() { + return null; + } + + @Override + public @NotNull InventorySize getInventorySize() { + return InventorySize.NORMAL; + } + + @Override + public void onInventoryClick(InventoryClickEvent click) { + //empty + } + + @Override + public @NotNull Map getContent() { + Map inventory = new HashMap<>(); + + boolean isActived = DailyEventsManager.isActiveDailyEvent() + && DailyEventsManager.getActiveDailyEvent() instanceof MiraculousFishingEvent; + + inventory.put(11, new ItemMenuBuilder(this, Material.STRIDER_SPAWN_EGG, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.menu.info.bloody_monster.name")); + itemMeta.lore(TranslationManager.translationLore( + "feature.dailyevents.bloody_night.menu.info.bloody_monster.lore")); + itemMeta.setEnchantmentGlintOverride(isActived); + }).setOnClick(_ -> new BloodyMonsterMenu(getOwner()).open())); + + inventory.put(13, new ItemMenuBuilder(this, OMCRegistry.CUSTOM_ITEMS.VAMPIRE_HEAD, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.menu.info.vampire_boss.name")); + itemMeta.lore(TranslationManager.translationLore( + "feature.dailyevents.bloody_night.menu.info.vampire_boss.lore", + Component.text(BloodyNightManager.VAMPIRE_SPAWN_TIME / 60 / 20, NamedTextColor.RED))); + itemMeta.setEnchantmentGlintOverride(isActived); + }).setOnClick(_ -> + OMCRegistry.CUSTOM_LOOT_TABLES.VAMPIRE.openMenu(getOwner()))); + + inventory.put(15, new ItemMenuBuilder(this, Material.NETHERITE_SPEAR, itemMeta -> { + itemMeta.displayName(TranslationManager.translation("feature.dailyevents.bloody_night.menu.info.bloody_raid.name")); + itemMeta.lore(TranslationManager.translationLore("feature.dailyevents.bloody_night.menu.info.bloody_raid.lore", + Component.text(BloodyNightManager.RAID_INTERVAL / 60 / 20, NamedTextColor.RED))); + itemMeta.setEnchantmentGlintOverride(isActived); + })); + + inventory.put(18, new ItemMenuBuilder(this, Material.ARROW, true)); + + return inventory; + } + + @Override + public void onClose(InventoryCloseEvent event) { + //empty + } + + @Override + public List getTakableSlot() { + return List.of(); + } +} diff --git a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java index 31aacd0a5..ca0f13d1f 100644 --- a/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java +++ b/src/main/java/fr/openmc/core/features/events/contents/dailyevents/contents/miraculousfishing/MiraculousFishingEvent.java @@ -28,7 +28,8 @@ import java.util.List; import java.util.Set; -public class MiraculousFishingEvent extends DailyEvent implements HasToast, HasAmbient, HasBroadcast, HasListeners, HasMenu { +public class MiraculousFishingEvent extends DailyEvent + implements HasToast, HasAmbient, HasBroadcast, HasListeners, HasMenu { @Override public String getEventId() { return "miraculous_fishing"; 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 57e7f14ef..9641f8298 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 @@ -25,7 +25,7 @@ public void onPlayerRespawn(PlayerRespawnEvent event) { } @EventHandler - public void onTimeChange(WeatherChangeEvent event) { + public void onWeatherChange(WeatherChangeEvent event) { for (Player player : event.getWorld().getPlayers()) { reapplyWeather(player); } diff --git a/src/main/resources/translations/default/dailyevents.properties b/src/main/resources/translations/default/dailyevents.properties index 57798e387..be13f2dca 100644 --- a/src/main/resources/translations/default/dailyevents.properties +++ b/src/main/resources/translations/default/dailyevents.properties @@ -50,6 +50,12 @@ feature.dailyevents.bloodynight.broadcast.start=
NUIT SANGLANTE ! Le bain de sang commence !\
*sortez vos armes et combattez les vagues de monstres*\
\ +
Effets :\ +
+ Type de monstres sanglants\ +
+ Raid de monstres\ +
+ Boss Vampire\ +
+ Régénération naturelle désactivée\ +
\
feature.dailyevents.bloodynight.broadcast.end= \
\ @@ -141,4 +147,17 @@ feature.dailyevents.bloody_night.vampire_boss.defeated.end=Vous avez reçu la lettre des récompenses feature.dailyevents.bloody_night.vampire_boss.mail.click=Cliquez ici feature.dailyevents.bloody_night.vampire_boss.mail.hover=Ouvrir la mailbox -feature.dailyevents.bloody_night.vampire_boss.mail.open_mailbox= pour ouvrir la mailbox \ No newline at end of file +feature.dailyevents.bloody_night.vampire_boss.mail.open_mailbox= pour ouvrir la mailbox + +feature.dailyevents.bloody_night.menu.info.bloody_monster.name=Types de monstres sanglant +feature.dailyevents.bloody_night.menu.info.bloody_monster.lore=Vous avez %1$s de l'avoir pendant un raid \ +
CLIQUEZ ICI POUR VOIR LES LOOTS + +feature.dailyevents.bloody_night.menu.info.vampire_boss.name=Le boss Vampire +feature.dailyevents.bloody_night.menu.info.vampire_boss.lore=Le boss arrive après %1$s minutes que la nuit sanglante \ +
soit arrivée. Faites place à un combat original à plusieurs \ +
CLIQUEZ ICI POUR VOIR LES LOOTS DU BOSS + +feature.dailyevents.bloody_night.menu.info.bloody_raid.name=Les raids +feature.dailyevents.bloody_night.menu.info.bloody_raid.lore=Les raids se passent toutes les %1$s minutes. \ +
C'est ici où il y a de multiples variétés de mob qui peuvent spawn ! \ No newline at end of file From 40b7d40015517183361a0c618e627b2339f74913 Mon Sep 17 00:00:00 2001 From: iambibi_ <89582596+iambibi@users.noreply.github.com> Date: Thu, 16 Jul 2026 18:59:59 +0200 Subject: [PATCH 50/50] fix; weather when weather fixe at none --- .../ambient/listeners/AmbientWeatherListener.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 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 9641f8298..07121e81c 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 @@ -1,8 +1,10 @@ package fr.openmc.core.registry.ambient.listeners; +import fr.openmc.core.OMCPlugin; import fr.openmc.core.OMCRegistry; import fr.openmc.core.registry.ambient.CustomAmbient; import fr.openmc.core.utils.nms.PlayerWeatherNMS; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -26,9 +28,11 @@ public void onPlayerRespawn(PlayerRespawnEvent event) { @EventHandler public void onWeatherChange(WeatherChangeEvent event) { - for (Player player : event.getWorld().getPlayers()) { - reapplyWeather(player); - } + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> { + for (Player player : event.getWorld().getPlayers()) { + reapplyWeather(player); + } + }, 1L); } /**