diff --git a/api/src/main/java/net/momirealms/customcrops/api/event/CropBreakEvent.java b/api/src/main/java/net/momirealms/customcrops/api/event/CropBreakEvent.java index 0159699..40a9a90 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/event/CropBreakEvent.java +++ b/api/src/main/java/net/momirealms/customcrops/api/event/CropBreakEvent.java @@ -19,29 +19,31 @@ package net.momirealms.customcrops.api.event; import net.momirealms.customcrops.api.mechanic.world.level.WorldCrop; import org.bukkit.Location; +import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.bukkit.event.player.PlayerEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** * An event that triggered when breaking a crop */ -public class CropBreakEvent extends PlayerEvent implements Cancellable { +public class CropBreakEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); private boolean cancelled; private final Location location; private final WorldCrop worldCrop; + private final Entity entity; public CropBreakEvent( - @NotNull Player player, + @Nullable Entity entity, @NotNull Location location, @Nullable WorldCrop worldCrop ) { - super(player); + this.entity = entity; this.location = location; this.worldCrop = worldCrop; } @@ -84,4 +86,17 @@ public class CropBreakEvent extends PlayerEvent implements Cancellable { public Location getLocation() { return location; } + + @Nullable + public Entity getEntity() { + return entity; + } + + @Nullable + public Player getPlayer() { + if (entity instanceof Player player) { + return player; + } + return null; + } } diff --git a/api/src/main/java/net/momirealms/customcrops/api/event/PotFillEvent.java b/api/src/main/java/net/momirealms/customcrops/api/event/PotFillEvent.java new file mode 100644 index 0000000..1319608 --- /dev/null +++ b/api/src/main/java/net/momirealms/customcrops/api/event/PotFillEvent.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.api.event; + +import net.momirealms.customcrops.api.mechanic.item.water.PassiveFillMethod; +import net.momirealms.customcrops.api.mechanic.world.level.WorldPot; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * An event that triggered when a pot is watered by the fill-methods set in each pot's config + */ +public class PotFillEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final Location location; + private final WorldPot pot; + private final ItemStack itemInHand; + private final PassiveFillMethod fillMethod; + + public PotFillEvent( + @NotNull Player player, + @NotNull ItemStack itemInHand, + @NotNull Location location, + @NotNull PassiveFillMethod fillMethod, + @NotNull WorldPot pot + ) { + super(player); + this.location = location; + this.itemInHand = itemInHand; + this.pot = pot; + this.fillMethod = fillMethod; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + /** + * Get the pot location + * @return location + */ + @NotNull + public Location getLocation() { + return location; + } + + + /** + * Get the pot's data + * @return pot + */ + @NotNull + public WorldPot getPot() { + return pot; + } + + @NotNull + public ItemStack getItemInHand() { + return itemInHand; + } + + @NotNull + public PassiveFillMethod getFillMethod() { + return fillMethod; + } +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customcrops/api/event/SprinklerFillEvent.java b/api/src/main/java/net/momirealms/customcrops/api/event/SprinklerFillEvent.java new file mode 100644 index 0000000..56db0f7 --- /dev/null +++ b/api/src/main/java/net/momirealms/customcrops/api/event/SprinklerFillEvent.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.api.event; + +import net.momirealms.customcrops.api.mechanic.item.water.PassiveFillMethod; +import net.momirealms.customcrops.api.mechanic.world.level.WorldSprinkler; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * An event that triggered when a sprinkler is watered by the fill-methods set in each sprinkler's config + */ +public class SprinklerFillEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final ItemStack itemInHand; + private final Location location; + private final PassiveFillMethod fillMethod; + private final WorldSprinkler sprinkler; + + public SprinklerFillEvent( + @NotNull Player player, + @NotNull ItemStack itemInHand, + @NotNull Location location, + @NotNull PassiveFillMethod fillMethod, + @NotNull WorldSprinkler sprinkler + ) { + super(player); + this.itemInHand = itemInHand; + this.location = location; + this.fillMethod = fillMethod; + this.sprinkler = sprinkler; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @NotNull + @Override + public HandlerList getHandlers() { + return getHandlerList(); + } + + /** + * Get the item in player's hand + * @return item in hand + */ + @NotNull + public ItemStack getItemInHand() { + return itemInHand; + } + + /** + * Get the sprinkler location + * @return location + */ + @NotNull + public Location getLocation() { + return location; + } + + @NotNull + public PassiveFillMethod getFillMethod() { + return fillMethod; + } + + @NotNull + public WorldSprinkler getSprinkler() { + return sprinkler; + } +} diff --git a/api/src/main/java/net/momirealms/customcrops/api/event/WateringCanFillEvent.java b/api/src/main/java/net/momirealms/customcrops/api/event/WateringCanFillEvent.java new file mode 100644 index 0000000..c23bf4b --- /dev/null +++ b/api/src/main/java/net/momirealms/customcrops/api/event/WateringCanFillEvent.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.api.event; + +import net.momirealms.customcrops.api.mechanic.item.WateringCan; +import net.momirealms.customcrops.api.mechanic.item.water.PositiveFillMethod; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * An event that triggered when player tries to add water to the watering-can + */ +public class WateringCanFillEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final ItemStack itemInHand; + private final WateringCan wateringCan; + private final PositiveFillMethod fillMethod; + private final Location location; + + public WateringCanFillEvent( + @NotNull Player player, + @NotNull ItemStack itemInHand, + @NotNull WateringCan wateringCan, + @NotNull Location location, + @NotNull PositiveFillMethod fillMethod + ) { + super(player); + this.cancelled = false; + this.itemInHand = itemInHand; + this.wateringCan = wateringCan; + this.location = location; + this.fillMethod = fillMethod; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlers; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @NotNull + public ItemStack getItemInHand() { + return itemInHand; + } + + @NotNull + public WateringCan getWateringCan() { + return wateringCan; + } + + @NotNull + public PositiveFillMethod getFillMethod() { + return fillMethod; + } + + @NotNull + public Location getLocation() { + return location; + } +} diff --git a/api/src/main/java/net/momirealms/customcrops/api/event/WateringCanWaterEvent.java b/api/src/main/java/net/momirealms/customcrops/api/event/WateringCanWaterEvent.java new file mode 100644 index 0000000..f810d59 --- /dev/null +++ b/api/src/main/java/net/momirealms/customcrops/api/event/WateringCanWaterEvent.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customcrops.api.event; + +import net.momirealms.customcrops.api.common.item.KeyItem; +import net.momirealms.customcrops.api.mechanic.item.WateringCan; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; + +/** + * An event that triggered when player tries to use watering-can to add water to pots/sprinklers + */ +public class WateringCanWaterEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final ItemStack itemInHand; + private final WateringCan wateringCan; + private final KeyItem potOrSprinkler; + private final Location location; + + public WateringCanWaterEvent( + @NotNull Player player, + @NotNull ItemStack itemInHand, + @NotNull WateringCan wateringCan, + @NotNull Location location, + @NotNull KeyItem potOrSprinkler + ) { + super(player); + this.cancelled = false; + this.itemInHand = itemInHand; + this.wateringCan = wateringCan; + this.location = location; + this.potOrSprinkler = potOrSprinkler; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + @Override + public @NotNull HandlerList getHandlers() { + return handlers; + } + + @NotNull + public static HandlerList getHandlerList() { + return handlers; + } + + @NotNull + public ItemStack getItemInHand() { + return itemInHand; + } + + @NotNull + public WateringCan getWateringCan() { + return wateringCan; + } + + @NotNull + public Location getLocation() { + return location; + } + + @NotNull + public KeyItem getPotOrSprinkler() { + return potOrSprinkler; + } +} diff --git a/api/src/main/java/net/momirealms/customcrops/api/mechanic/item/water/AbstractFillMethod.java b/api/src/main/java/net/momirealms/customcrops/api/mechanic/item/water/AbstractFillMethod.java index 381a3c6..6855f91 100644 --- a/api/src/main/java/net/momirealms/customcrops/api/mechanic/item/water/AbstractFillMethod.java +++ b/api/src/main/java/net/momirealms/customcrops/api/mechanic/item/water/AbstractFillMethod.java @@ -35,14 +35,30 @@ public abstract class AbstractFillMethod { this.requirements = requirements; } + /** + * Get the amount of water to add + * + * @return amount + */ public int getAmount() { return amount; } + /** + * Trigger actions related to this fill methods + * + * @param state state + */ public void trigger(State state) { ActionManager.triggerActions(state, actions); } + /** + * If player meet the requirements for this fill method + * + * @param state state + * @return meet or not + */ public boolean canFill(State state) { return RequirementManager.isRequirementMet(state, requirements); } diff --git a/build.gradle.kts b/build.gradle.kts index 59150a5..8dc3a37 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { project.group = "net.momirealms" - project.version = "3.4.0.8" + project.version = "3.4.1.0" apply() apply(plugin = "java") diff --git a/plugin/src/main/java/net/momirealms/customcrops/mechanic/action/ActionManagerImpl.java b/plugin/src/main/java/net/momirealms/customcrops/mechanic/action/ActionManagerImpl.java index 6291de2..58580d5 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/mechanic/action/ActionManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customcrops/mechanic/action/ActionManagerImpl.java @@ -64,7 +64,6 @@ import org.bukkit.block.BlockFace; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.entity.ExperienceOrb; import org.bukkit.entity.Player; -import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; diff --git a/plugin/src/main/java/net/momirealms/customcrops/mechanic/condition/ConditionManagerImpl.java b/plugin/src/main/java/net/momirealms/customcrops/mechanic/condition/ConditionManagerImpl.java index 50f790c..6ffdb02 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/mechanic/condition/ConditionManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customcrops/mechanic/condition/ConditionManagerImpl.java @@ -35,7 +35,6 @@ import net.momirealms.customcrops.compatibility.papi.ParseUtils; import net.momirealms.customcrops.mechanic.misc.CrowAttackAnimation; import net.momirealms.customcrops.utils.ClassUtils; import net.momirealms.customcrops.utils.ConfigUtils; -import org.bukkit.Location; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.data.type.Farmland; diff --git a/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/ItemManagerImpl.java b/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/ItemManagerImpl.java index 7e750d6..8aee2c8 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/ItemManagerImpl.java +++ b/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/ItemManagerImpl.java @@ -718,13 +718,14 @@ public class ItemManagerImpl implements ItemManager { return FunctionResult.PASS; } // is a pot - Pot pot = getPotByBlock(blockWrapper.getClickedBlock()); + Block block = blockWrapper.getClickedBlock(); + Pot pot = getPotByBlock(block); if (pot == null) { return FunctionResult.PASS; } final Player player = blockWrapper.getPlayer(); final ItemStack itemStack = blockWrapper.getItemInHand(); - final Location clicked = blockWrapper.getClickedBlock().getLocation(); + final Location clicked = block.getLocation(); State state = new State(player, itemStack, clicked); // check watering-can requirements if (!RequirementManager.isRequirementMet(state, wateringCan.getRequirements())) { @@ -737,8 +738,14 @@ public class ItemManagerImpl implements ItemManager { } // check amount of water int waterInCan = wateringCan.getCurrentWater(itemStack); - state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); + if (waterInCan > 0 || wateringCan.isInfinite()) { + // fire the event + WateringCanWaterEvent waterEvent = new WateringCanWaterEvent(player, itemStack, wateringCan, clicked, pot); + if (EventUtils.fireAndCheckCancel(waterEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(waterInCan - 1)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(waterInCan - 1, wateringCan.getStorage())); wateringCan.updateItem(player, itemStack, waterInCan - 1, state.getArgs()); @@ -749,6 +756,7 @@ public class ItemManagerImpl implements ItemManager { pot.trigger(ActionTrigger.ADD_WATER, new State(player, itemStack, location)); } } else { + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", "0"); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(0, wateringCan.getStorage())); wateringCan.trigger(ActionTrigger.NO_WATER, state); @@ -772,7 +780,7 @@ public class ItemManagerImpl implements ItemManager { Block potBlock = blockWrapper.getClickedBlock().getRelative(BlockFace.DOWN); Pot pot = getPotByBlock(potBlock); if (pot == null) { - LogUtils.warn("Unexpected issue: Detetced that crops are not planted on a pot: " + blockWrapper.getClickedBlock().getLocation()); + plugin.debug("Unexpected issue: Detetced that crops are not planted on a pot: " + blockWrapper.getClickedBlock().getLocation()); return FunctionResult.RETURN; } @@ -799,8 +807,14 @@ public class ItemManagerImpl implements ItemManager { } // check amount of water int waterInCan = wateringCan.getCurrentWater(itemStack); - state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); + if (waterInCan > 0 || wateringCan.isInfinite()) { + // fire the event + WateringCanWaterEvent waterEvent = new WateringCanWaterEvent(player, itemStack, wateringCan, potBlock.getLocation(), pot); + if (EventUtils.fireAndCheckCancel(waterEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(waterInCan - 1)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(waterInCan - 1, wateringCan.getStorage())); wateringCan.updateItem(player, itemStack, waterInCan - 1, state.getArgs()); @@ -811,6 +825,7 @@ public class ItemManagerImpl implements ItemManager { pot.trigger(ActionTrigger.ADD_WATER, new State(player, itemStack, location)); } } else { + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", "0"); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(0, wateringCan.getStorage())); wateringCan.trigger(ActionTrigger.NO_WATER, state); @@ -858,8 +873,14 @@ public class ItemManagerImpl implements ItemManager { } // check amount of water int waterInCan = wateringCan.getCurrentWater(itemStack); - state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); + if (waterInCan > 0 || wateringCan.isInfinite()) { + // fire the event + WateringCanWaterEvent waterEvent = new WateringCanWaterEvent(player, itemStack, wateringCan, clicked, pot); + if (EventUtils.fireAndCheckCancel(waterEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(waterInCan - 1)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(waterInCan - 1, wateringCan.getStorage())); wateringCan.updateItem(player, itemStack, waterInCan - 1, state.getArgs()); @@ -870,6 +891,7 @@ public class ItemManagerImpl implements ItemManager { pot.trigger(ActionTrigger.ADD_WATER, new State(player, itemStack, location)); } } else { + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", "0"); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(0, wateringCan.getStorage())); wateringCan.trigger(ActionTrigger.NO_WATER, state); @@ -885,12 +907,15 @@ public class ItemManagerImpl implements ItemManager { return FunctionResult.PASS; } // check watering-can requirements - State state = new State(furnitureWrapper.getPlayer(), furnitureWrapper.getItemInHand(), furnitureWrapper.getLocation()); + Player player = furnitureWrapper.getPlayer(); + ItemStack itemInHand = furnitureWrapper.getItemInHand(); + Location location = furnitureWrapper.getLocation(); + State state = new State(player, itemInHand, location); if (!RequirementManager.isRequirementMet(state, wateringCan.getRequirements())) { return FunctionResult.RETURN; } // get water in can - int waterInCan = wateringCan.getCurrentWater(furnitureWrapper.getItemInHand()); + int waterInCan = wateringCan.getCurrentWater(itemInHand); String clickedFurnitureID = furnitureWrapper.getID(); Sprinkler sprinkler = getSprinklerBy3DItemID(clickedFurnitureID); // is a sprinkler @@ -907,21 +932,27 @@ public class ItemManagerImpl implements ItemManager { // check amount of water if (waterInCan > 0 || wateringCan.isInfinite()) { // get sprinkler data - SimpleLocation location = SimpleLocation.of(furnitureWrapper.getLocation()); - Optional worldSprinkler = plugin.getWorldManager().getSprinklerAt(location); + SimpleLocation simpleLocation = SimpleLocation.of(location); + Optional worldSprinkler = plugin.getWorldManager().getSprinklerAt(simpleLocation); if (worldSprinkler.isEmpty()) { - plugin.debug("Player " + furnitureWrapper.getPlayer().getName() + " tried to interact a sprinkler which not exists in memory. Fixing the data..."); + plugin.debug("Player " + player.getName() + " tried to interact a sprinkler which not exists in memory. Fixing the data..."); } else { if (sprinkler.getStorage() <= worldSprinkler.get().getWater()) { return FunctionResult.RETURN; } } + + // fire the event + WateringCanWaterEvent waterEvent = new WateringCanWaterEvent(player, itemInHand, wateringCan, location, sprinkler); + if (EventUtils.fireAndCheckCancel(waterEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(waterInCan - 1)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(waterInCan - 1, wateringCan.getStorage())); - wateringCan.updateItem(furnitureWrapper.getPlayer(), furnitureWrapper.getItemInHand(), waterInCan - 1, state.getArgs()); + wateringCan.updateItem(player, furnitureWrapper.getItemInHand(), waterInCan - 1, state.getArgs()); wateringCan.trigger(ActionTrigger.CONSUME_WATER, state); - plugin.getWorldManager().addWaterToSprinkler(sprinkler, location, 1); + plugin.getWorldManager().addWaterToSprinkler(sprinkler, simpleLocation, 1); } else { state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", "0"); @@ -937,13 +968,18 @@ public class ItemManagerImpl implements ItemManager { for (PositiveFillMethod method : methods) { if (method.getId().equals(clickedFurnitureID)) { if (method.canFill(state)) { + // fire the event + WateringCanFillEvent fillEvent = new WateringCanFillEvent(player, itemInHand, wateringCan, location, method); + if (EventUtils.fireAndCheckCancel(fillEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + if (waterInCan < wateringCan.getStorage()) { waterInCan += method.getAmount(); waterInCan = Math.min(waterInCan, wateringCan.getStorage()); state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(waterInCan)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(waterInCan, wateringCan.getStorage())); - wateringCan.updateItem(furnitureWrapper.getPlayer(), furnitureWrapper.getItemInHand(), waterInCan, state.getArgs()); + wateringCan.updateItem(player, furnitureWrapper.getItemInHand(), waterInCan, state.getArgs()); wateringCan.trigger(ActionTrigger.ADD_WATER, state); method.trigger(state); } else { @@ -970,12 +1006,14 @@ public class ItemManagerImpl implements ItemManager { if (wateringCan.isInfinite()) { return FunctionResult.PASS; } + Player player = interactWrapper.getPlayer(); + ItemStack itemInHand = interactWrapper.getItemInHand(); // get the clicked block - Block targetBlock = interactWrapper.getPlayer().getTargetBlockExact(5, FluidCollisionMode.ALWAYS); + Block targetBlock = player.getTargetBlockExact(5, FluidCollisionMode.ALWAYS); if (targetBlock == null) return FunctionResult.PASS; // check watering-can requirements - State state = new State(interactWrapper.getPlayer(), interactWrapper.getItemInHand(), targetBlock.getLocation()); + State state = new State(player, itemInHand, targetBlock.getLocation()); if (!RequirementManager.isRequirementMet(state, wateringCan.getRequirements())) { return FunctionResult.RETURN; } @@ -984,18 +1022,23 @@ public class ItemManagerImpl implements ItemManager { if (targetBlock.getBlockData() instanceof Waterlogged waterlogged && waterlogged.isWaterlogged()) { blockID = "WATER"; } - int water = wateringCan.getCurrentWater(interactWrapper.getItemInHand()); + int water = wateringCan.getCurrentWater(itemInHand); PositiveFillMethod[] methods = wateringCan.getPositiveFillMethods(); for (PositiveFillMethod method : methods) { if (method.getId().equals(blockID)) { if (method.canFill(state)) { if (water < wateringCan.getStorage()) { + // fire the event + WateringCanFillEvent fillEvent = new WateringCanFillEvent(player, itemInHand, wateringCan, state.getLocation(), method); + if (EventUtils.fireAndCheckCancel(fillEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + water += method.getAmount(); water = Math.min(water, wateringCan.getStorage()); state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(water)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(water, wateringCan.getStorage())); - wateringCan.updateItem(interactWrapper.getPlayer(), interactWrapper.getItemInHand(), water, state.getArgs()); + wateringCan.updateItem(player, itemInHand, water, state.getArgs()); wateringCan.trigger(ActionTrigger.ADD_WATER, state); method.trigger(state); } else { @@ -1017,12 +1060,14 @@ public class ItemManagerImpl implements ItemManager { if (wateringCan.isInfinite()) { return FunctionResult.PASS; } + Player player = interactWrapper.getPlayer(); // get the clicked block - Block targetBlock = interactWrapper.getPlayer().getTargetBlockExact(5, FluidCollisionMode.ALWAYS); + Block targetBlock = player.getTargetBlockExact(5, FluidCollisionMode.ALWAYS); if (targetBlock == null) return FunctionResult.PASS; // check watering-can requirements - State state = new State(interactWrapper.getPlayer(), interactWrapper.getItemInHand(), targetBlock.getLocation()); + ItemStack itemInHand = interactWrapper.getItemInHand(); + State state = new State(player, itemInHand, targetBlock.getLocation()); if (!RequirementManager.isRequirementMet(state, wateringCan.getRequirements())) { return FunctionResult.RETURN; } @@ -1031,18 +1076,23 @@ public class ItemManagerImpl implements ItemManager { if (targetBlock.getBlockData() instanceof Waterlogged waterlogged && waterlogged.isWaterlogged()) { blockID = "WATER"; } - int water = wateringCan.getCurrentWater(interactWrapper.getItemInHand()); + int water = wateringCan.getCurrentWater(itemInHand); PositiveFillMethod[] methods = wateringCan.getPositiveFillMethods(); for (PositiveFillMethod method : methods) { if (method.getId().equals(blockID)) { if (method.canFill(state)) { if (water < wateringCan.getStorage()) { + // fire the event + WateringCanFillEvent fillEvent = new WateringCanFillEvent(player, itemInHand, wateringCan, state.getLocation(), method); + if (EventUtils.fireAndCheckCancel(fillEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + water += method.getAmount(); water = Math.min(water, wateringCan.getStorage()); state.setArg("{storage}", String.valueOf(wateringCan.getStorage())); state.setArg("{current}", String.valueOf(water)); state.setArg("{water_bar}", wateringCan.getWaterBar() == null ? "" : wateringCan.getWaterBar().getWaterBar(water, wateringCan.getStorage())); - wateringCan.updateItem(interactWrapper.getPlayer(), interactWrapper.getItemInHand(), water, state.getArgs()); + wateringCan.updateItem(player, itemInHand, water, state.getArgs()); wateringCan.trigger(ActionTrigger.ADD_WATER, state); method.trigger(state); } else { @@ -1223,14 +1273,18 @@ public class ItemManagerImpl implements ItemManager { // add water to sprinkler String itemID = getItemID(itemInHand); int itemAmount = itemInHand.getAmount(); - Optional worldSprinkler = plugin.getWorldManager().getSprinklerAt(simpleLocation); - int waterInSprinkler = worldSprinkler.map(WorldSprinkler::getWater).orElse(0); + int waterInSprinkler = optionalSprinkler.get().getWater(); // if it's not infinite if (!sprinkler.isInfinite()) { for (PassiveFillMethod method : sprinkler.getPassiveFillMethods()) { if (method.getUsed().equals(itemID) && itemAmount >= method.getUsedAmount()) { if (method.canFill(state)) { if (waterInSprinkler < sprinkler.getStorage()) { + // fire the event + SprinklerFillEvent fillEvent = new SprinklerFillEvent(player, itemInHand, location, method, optionalSprinkler.get()); + if (EventUtils.fireAndCheckCancel(fillEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + if (player.getGameMode() != GameMode.CREATIVE) { itemInHand.setAmount(itemAmount - method.getUsedAmount()); if (method.getReturned() != null) { @@ -1751,25 +1805,23 @@ public class ItemManagerImpl implements ItemManager { } // if not reached the max point, try detecting bone meals - if (optionalCrop.isPresent()) { - if (optionalCrop.get().getPoint() < crop.getMaxPoints()) { - for (BoneMeal boneMeal : crop.getBoneMeals()) { - if (boneMeal.getItem().equals(itemID)) { - if (player.getGameMode() != GameMode.CREATIVE) { - itemInHand.setAmount(itemAmount - boneMeal.getUsedAmount()); - if (boneMeal.getReturned() != null) { - ItemStack returned = getItemStack(player, boneMeal.getReturned()); - ItemUtils.giveItem(player, returned, boneMeal.getReturnedAmount()); - } + if (optionalCrop.get().getPoint() < crop.getMaxPoints()) { + for (BoneMeal boneMeal : crop.getBoneMeals()) { + if (boneMeal.getItem().equals(itemID)) { + if (player.getGameMode() != GameMode.CREATIVE) { + itemInHand.setAmount(itemAmount - boneMeal.getUsedAmount()); + if (boneMeal.getReturned() != null) { + ItemStack returned = getItemStack(player, boneMeal.getReturned()); + ItemUtils.giveItem(player, returned, boneMeal.getReturnedAmount()); } - boneMeal.trigger(cropState); - plugin.getWorldManager().addPointToCrop(crop, SimpleLocation.of(cropLocation), boneMeal.getPoint()); - return FunctionResult.RETURN; } + boneMeal.trigger(cropState); + plugin.getWorldManager().addPointToCrop(crop, SimpleLocation.of(cropLocation), boneMeal.getPoint()); + return FunctionResult.RETURN; } - } else { - crop.trigger(ActionTrigger.RIPE, cropState); } + } else { + crop.trigger(ActionTrigger.RIPE, cropState); } // trigger interact actions @@ -1900,6 +1952,11 @@ public class ItemManagerImpl implements ItemManager { if (method.getUsed().equals(itemID) && itemAmount >= method.getUsedAmount()) { if (method.canFill(state)) { if (waterInPot < pot.getStorage()) { + // fire the event + PotFillEvent waterEvent = new PotFillEvent(player, itemInHand, location, method, optionalPot.get()); + if (EventUtils.fireAndCheckCancel(waterEvent)) + return FunctionResult.CANCEL_EVENT_AND_RETURN; + if (player.getGameMode() != GameMode.CREATIVE) { itemInHand.setAmount(itemAmount - method.getUsedAmount()); if (method.getReturned() != null) { diff --git a/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/custom/AbstractCustomListener.java b/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/custom/AbstractCustomListener.java index 6ab7427..6d5745f 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/custom/AbstractCustomListener.java +++ b/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/custom/AbstractCustomListener.java @@ -22,6 +22,7 @@ import net.momirealms.customcrops.api.manager.ConfigManager; import net.momirealms.customcrops.api.manager.WorldManager; import net.momirealms.customcrops.api.mechanic.item.Pot; import net.momirealms.customcrops.api.mechanic.item.Sprinkler; +import net.momirealms.customcrops.api.mechanic.item.WateringCan; import net.momirealms.customcrops.api.mechanic.world.SimpleLocation; import net.momirealms.customcrops.mechanic.item.ItemManagerImpl; import org.bukkit.Location; @@ -38,6 +39,7 @@ import org.bukkit.event.block.*; import org.bukkit.event.entity.EntityChangeBlockEvent; import org.bukkit.event.entity.ItemSpawnEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.Nullable; @@ -177,6 +179,15 @@ public abstract class AbstractCustomListener implements Listener { } } + @EventHandler (ignoreCancelled = true) + public void onItemDamage(PlayerItemDamageEvent event) { + ItemStack itemStack = event.getItem(); + WateringCan wateringCan = this.itemManager.getWateringCanByItemStack(itemStack); + if (wateringCan != null) { + event.setCancelled(true); + } + } + public void onPlaceBlock(Player player, Block block, String blockID, Cancellable event) { this.itemManager.handlePlayerPlaceBlock(player, block, blockID, event); } diff --git a/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/impl/WateringCanConfig.java b/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/impl/WateringCanConfig.java index 5b95b3b..9a5edca 100644 --- a/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/impl/WateringCanConfig.java +++ b/plugin/src/main/java/net/momirealms/customcrops/mechanic/item/impl/WateringCanConfig.java @@ -134,6 +134,7 @@ public class WateringCanConfig extends AbstractEventItem implements WateringCan @Override public void updateItem(Player player, ItemStack itemStack, int water, Map args) { + int maxDurability = itemStack.getType().getMaxDurability(); NBTItem nbtItem = new NBTItem(itemStack); if (isInfinite()) water = storage; if (hasDynamicLore()) { @@ -159,6 +160,9 @@ public class WateringCanConfig extends AbstractEventItem implements WateringCan } nbtItem.setInteger("WaterAmount", water); + if (maxDurability != 0) { + nbtItem.setInteger("Damage", (int) (maxDurability * (((double) storage - water) / storage))); + } itemStack.setItemMeta(nbtItem.getItem().getItemMeta()); }