diff --git a/src/main/java/com/alttd/playerutils/PlayerUtils.java b/src/main/java/com/alttd/playerutils/PlayerUtils.java index 7ffbfe7..06f4869 100644 --- a/src/main/java/com/alttd/playerutils/PlayerUtils.java +++ b/src/main/java/com/alttd/playerutils/PlayerUtils.java @@ -42,6 +42,7 @@ public final class PlayerUtils extends JavaPlugin { pluginManager.registerEvents(new TeleportEvent(), this); pluginManager.registerEvents(new GoatHornEvent(logger), this); pluginManager.registerEvents(new LimitArmorStands(this, logger), this); + pluginManager.registerEvents(new AprilFoolsEvent(), this); RotateBlockEvent rotateBlockEvent = new RotateBlockEvent(logger); pluginManager.registerEvents(rotateBlockEvent, this); diff --git a/src/main/java/com/alttd/playerutils/event_listeners/AprilFoolsEvent.java b/src/main/java/com/alttd/playerutils/event_listeners/AprilFoolsEvent.java new file mode 100644 index 0000000..55cbd5b --- /dev/null +++ b/src/main/java/com/alttd/playerutils/event_listeners/AprilFoolsEvent.java @@ -0,0 +1,226 @@ +package com.alttd.playerutils.event_listeners; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.minimessage.MiniMessage; +import org.bukkit.Material; +import org.bukkit.Tag; +import org.bukkit.block.Block; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Monster; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityBreedEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.player.PlayerBucketEntityEvent; +import org.bukkit.event.player.PlayerFishEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffectType; +import org.jetbrains.annotations.NotNull; + +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.util.HashMap; +import java.util.List; +import java.util.UUID; + +public class AprilFoolsEvent implements Listener { + + MiniMessage miniMessage = MiniMessage.miniMessage(); + + List happyMessages = List.of( + miniMessage.deserialize("You have a sudden urge of calmness and peace"), + miniMessage.deserialize("Mother nature is pleased and graces us with her beauty!"), + miniMessage.deserialize("The gentle breeze feels like a soothing hug from nature.") + ); + + List angryMessages = List.of( + miniMessage.deserialize("Something seems off..."), + miniMessage.deserialize("Mother nature is angry and furious with you!"), + miniMessage.deserialize("The wind picks up, carrying the anger of the earth.") + ); + + private final List badEffects = List.of(PotionEffectType.BLINDNESS, PotionEffectType.NAUSEA, + PotionEffectType.LEVITATION, PotionEffectType.DARKNESS, PotionEffectType.MINING_FATIGUE, PotionEffectType.SLOWNESS); + + private final List goodEffects = List.of(PotionEffectType.ABSORPTION, PotionEffectType.GLOWING, + PotionEffectType.HEALTH_BOOST, PotionEffectType.HERO_OF_THE_VILLAGE, PotionEffectType.LUCK, PotionEffectType.REGENERATION, + PotionEffectType.REGENERATION, PotionEffectType.RESISTANCE, PotionEffectType.SATURATION, PotionEffectType.STRENGTH); + + private final List badBlocks = List.of(Material.SHORT_GRASS, Material.TALL_GRASS, Material.SEAGRASS, + Material.TALL_SEAGRASS, Material.LILY_PAD, Material.KELP, Material.KELP_PLANT, Material.BEEHIVE, + Material.BAMBOO, Material.MOSS_BLOCK, Material.CACTUS, Material.SMALL_DRIPLEAF, Material.BIG_DRIPLEAF); + + private final List goodBlocks = List.of(Material.CACTUS, Material.AZALEA, Material.FLOWERING_AZALEA); + + private final HashMap goodActions = new HashMap<>(); + + private final HashMap badActions = new HashMap<>(); + + private boolean isFlower(Material material) { + return Tag.FLOWERS.isTagged(material); + } + + private boolean isLog(Material material) { + return Tag.LOGS.isTagged(material); + } + + private boolean isLeaves(Material material) { + return Tag.LEAVES.isTagged(material); + } + + private boolean isBadBlock(Material material) { + return badBlocks.contains(material) || isFlower(material) || isLog(material) || isLeaves(material); + } + + private boolean isGoodBlock(@NotNull Material material) { + return goodBlocks.contains(material) || isFlower(material); + } + + private boolean isNotAprilFools() { + LocalDate currentDate = LocalDate.now(ZoneOffset.UTC); + return currentDate.getMonthValue() != 4 || currentDate.getDayOfMonth() != 1; + } + + /** + * Determines whether the provided count exceeds a randomly generated limit. + * The limit is generated as a random integer between 100 and 300, inclusive. + * + * @param count the value to be compared against the generated random limit + * @return true if the count is greater than the random limit; false otherwise + */ + private boolean underLimit(int count) { + int randomValue = 100 + (int) (Math.random() * 201); + return count <= randomValue; + } + + private Component getRandomMessage(@NotNull List messages) { + return messages.get((int) (Math.random() * messages.size())); + } + + private PotionEffectType getRandomEffect(@NotNull List potionEffectTypes) { + return potionEffectTypes.get((int) (Math.random() * potionEffectTypes.size())); + } + + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + if (isNotAprilFools()) { + return; + } + if (!isGoodBlock(event.getBlock().getType())) { + return; + } + runGoodAction(event.getPlayer()); + } + + @EventHandler + public void onGrassBlockBoneMealed(PlayerInteractEvent event) { + if (isNotAprilFools()) { + return; + } + + if (!event.getAction().isRightClick()) { + return; + } + + ItemStack itemInHand = event.getPlayer().getInventory().getItemInMainHand(); + if (itemInHand.getType() != Material.BONE_MEAL) { + return; + } + + Block clickedBlock = event.getClickedBlock(); + if (clickedBlock == null || clickedBlock.getType() != Material.GRASS_BLOCK) { + return; + } + + if (event.getHand() != EquipmentSlot.HAND) { + return; + } + runGoodAction(event.getPlayer()); + } + + @EventHandler + public void onAnimalBred(EntityBreedEvent event) { + if (isNotAprilFools()) { + return; + } + if (!(event.getBreeder() instanceof Player player)) { + return; + } + + runGoodAction(player); + } + + private void runGoodAction(@NotNull Player player) { + goodActions.merge(player.getUniqueId(), 1, Integer::sum); + if (underLimit(goodActions.get(player.getUniqueId()))) { + return; + } + player.sendMessage(getRandomMessage(happyMessages)); + player.addPotionEffect(getRandomEffect(goodEffects).createEffect(60 * 20, 1)); + goodActions.put(player.getUniqueId(), 0); + } + + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { + if (isNotAprilFools()) { + return; + } + if (!isBadBlock(event.getBlock().getType())) { + return; + } + Player player = event.getPlayer(); + runBadAction(player); + } + + @EventHandler + public void onAnimalKilled(EntityDeathEvent event) { + if (isNotAprilFools()) { + return; + } + LivingEntity entity = event.getEntity(); + if (entity.getKiller() == null) { + return; + } + + if (entity instanceof Monster) { + return; + } + + Player player = entity.getKiller(); + runBadAction(player); + } + + @EventHandler + public void onFishCollected(PlayerBucketEntityEvent event) { + if (isNotAprilFools()) { + return; + } + Player player = event.getPlayer(); + runBadAction(player); + } + + @EventHandler + public void onPlayerFish(PlayerFishEvent event) { + if (isNotAprilFools()) { + return; + } + Player player = event.getPlayer(); + runBadAction(player); + } + + private void runBadAction(@NotNull Player player) { + badActions.merge(player.getUniqueId(), 1, Integer::sum); + if (underLimit(badActions.get(player.getUniqueId()))) { + return; + } + player.sendMessage(getRandomMessage(angryMessages)); + player.addPotionEffect(getRandomEffect(badEffects).createEffect(10 * 20, 1)); + badActions.put(player.getUniqueId(), 0); + } + +}