From 6706c98091e4a9e70e4c4b4ae979e99453d39827 Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 11 Jan 2026 22:10:22 +0100 Subject: [PATCH 1/8] Add custom event classes for lockers, parcels, users, and item storage Introduced new cancellable and non-cancellable event classes for locker creation/deletion, parcel send/deliver/collect, user creation/name change, and item storage updates. Also fixed a message key in DeliveryManager from 'deletedContents' to 'deletedDeliveries' for admin notifications. --- .../delivery/DeliveryManager.java | 2 +- .../event/ItemStorageUpdateEvent.java | 49 +++++++++++++++++++ .../locker/event/LockerCreateEvent.java | 49 +++++++++++++++++++ .../locker/event/LockerDeleteEvent.java | 49 +++++++++++++++++++ .../parcel/event/ParcelCollectEvent.java | 42 ++++++++++++++++ .../parcel/event/ParcelDeliverEvent.java | 43 ++++++++++++++++ .../parcel/event/ParcelSendEvent.java | 42 ++++++++++++++++ .../user/event/UserChangeNameEvent.java | 36 ++++++++++++++ .../user/event/UserCreateEvent.java | 30 ++++++++++++ 9 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java create mode 100644 src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java diff --git a/src/main/java/com/eternalcode/parcellockers/delivery/DeliveryManager.java b/src/main/java/com/eternalcode/parcellockers/delivery/DeliveryManager.java index 2cacfa98..ceeb8edf 100644 --- a/src/main/java/com/eternalcode/parcellockers/delivery/DeliveryManager.java +++ b/src/main/java/com/eternalcode/parcellockers/delivery/DeliveryManager.java @@ -61,7 +61,7 @@ public CompletableFuture deleteAll(CommandSender sender, NoticeService not this.deliveryCache.invalidateAll(); noticeService.create() .viewer(sender) - .notice(messages -> messages.admin.deletedContents) + .notice(messages -> messages.admin.deletedDeliveries) .placeholder("{COUNT}", deleted.toString()) .send(); }); diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java new file mode 100644 index 00000000..f1653887 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java @@ -0,0 +1,49 @@ +package com.eternalcode.parcellockers.itemstorage.event; + +import com.eternalcode.parcellockers.itemstorage.ItemStorage; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class ItemStorageUpdateEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final ItemStorage oldItemStorage; + private final ItemStorage updatedItemStorage; + + private boolean cancelled; + + public ItemStorageUpdateEvent(ItemStorage oldItemStorage, ItemStorage updatedItemStorage) { + this.oldItemStorage = oldItemStorage; + this.updatedItemStorage = updatedItemStorage; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public ItemStorage getOldItemStorage() { + return this.oldItemStorage; + } + + public ItemStorage getUpdatedItemStorage() { + return this.updatedItemStorage; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLER_LIST; + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java new file mode 100644 index 00000000..db296a1f --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java @@ -0,0 +1,49 @@ +package com.eternalcode.parcellockers.locker.event; + +import com.eternalcode.parcellockers.locker.Locker; +import java.util.UUID; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class LockerCreateEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Locker locker; + private final UUID player; + private boolean cancelled; + + public LockerCreateEvent(Locker locker, UUID player) { + this.locker = locker; + this.player = player; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public Locker getLocker() { + return this.locker; + } + + public UUID getPlayer() { + return this.player; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + +} diff --git a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java new file mode 100644 index 00000000..317b5060 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java @@ -0,0 +1,49 @@ +package com.eternalcode.parcellockers.locker.event; + +import com.eternalcode.parcellockers.locker.Locker; +import java.util.UUID; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class LockerDeleteEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Locker locker; + private final UUID player; + private boolean cancelled; + + public LockerDeleteEvent(Locker locker, UUID player) { + this.locker = locker; + this.player = player; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public Locker getLocker() { + return this.locker; + } + + public UUID getPlayer() { + return this.player; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + +} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java new file mode 100644 index 00000000..8c2a9e41 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java @@ -0,0 +1,42 @@ +package com.eternalcode.parcellockers.parcel.event; + +import com.eternalcode.parcellockers.parcel.Parcel; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jspecify.annotations.NonNull; + +public class ParcelCollectEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Parcel parcel; + private boolean cancelled; + + public ParcelCollectEvent(Parcel parcel) { + this.parcel = parcel; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public Parcel getParcel() { + return this.parcel; + } + + @Override + public @NonNull HandlerList getHandlers() { + return HANDLER_LIST; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java new file mode 100644 index 00000000..5ab340f3 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java @@ -0,0 +1,43 @@ +package com.eternalcode.parcellockers.parcel.event; + +import com.eternalcode.parcellockers.parcel.Parcel; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jspecify.annotations.NonNull; + +public class ParcelDeliverEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Parcel parcel; + private boolean cancelled; + + public ParcelDeliverEvent(Parcel parcel) { + super(true); + this.parcel = parcel; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public Parcel getParcel() { + return this.parcel; + } + + @Override + public @NonNull HandlerList getHandlers() { + return HANDLER_LIST; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java new file mode 100644 index 00000000..879fec6f --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java @@ -0,0 +1,42 @@ +package com.eternalcode.parcellockers.parcel.event; + +import com.eternalcode.parcellockers.parcel.Parcel; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jspecify.annotations.NonNull; + +public class ParcelSendEvent extends Event implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final Parcel parcel; + private boolean cancelled; + + public ParcelSendEvent(Parcel parcel) { + this.parcel = parcel; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public Parcel getParcel() { + return this.parcel; + } + + @Override + public @NonNull HandlerList getHandlers() { + return HANDLER_LIST; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java b/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java new file mode 100644 index 00000000..ef9aa198 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java @@ -0,0 +1,36 @@ +package com.eternalcode.parcellockers.user.event; + +import com.eternalcode.parcellockers.user.User; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jspecify.annotations.NonNull; + +public class UserChangeNameEvent extends Event { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final User user; + private final String oldName; + + public UserChangeNameEvent(User user, String oldName) { + this.user = user; + this.oldName = oldName; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public User getUser() { + return this.user; + } + + public String getOldName() { + return this.oldName; + } + + @Override + public @NonNull HandlerList getHandlers() { + return HANDLER_LIST; + } +} diff --git a/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java b/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java new file mode 100644 index 00000000..f2ba6978 --- /dev/null +++ b/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java @@ -0,0 +1,30 @@ +package com.eternalcode.parcellockers.user.event; + +import com.eternalcode.parcellockers.user.User; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jspecify.annotations.NonNull; + +public class UserCreateEvent extends Event { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final User user; + + public UserCreateEvent(User user) { + this.user = user; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + public User getUser() { + return this.user; + } + + @Override + public @NonNull HandlerList getHandlers() { + return HANDLER_LIST; + } +} From f29f0eaea9db5dcda776f2b4309fdd8fff99b65b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 11 Jan 2026 21:16:41 +0000 Subject: [PATCH 2/8] Initial plan From f3dc9e6692848729a8ab83c458722a11f5894376 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 11 Jan 2026 22:19:17 +0100 Subject: [PATCH 3/8] Update src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../parcellockers/locker/event/LockerCreateEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java index db296a1f..03afdbcb 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java @@ -42,7 +42,7 @@ public void setCancelled(boolean cancel) { } @Override - public HandlerList getHandlers() { + public @org.jetbrains.annotations.NotNull HandlerList getHandlers() { return HANDLER_LIST; } From 0d0a30d3afbb0e3ba043b64e663caaf6b62bccd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=99dziora?= <77227023+Jakubk15@users.noreply.github.com> Date: Sun, 11 Jan 2026 22:19:32 +0100 Subject: [PATCH 4/8] Update src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../parcellockers/locker/event/LockerDeleteEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java index 317b5060..9a642c1a 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java @@ -42,7 +42,7 @@ public void setCancelled(boolean cancel) { } @Override - public HandlerList getHandlers() { + public @org.jetbrains.annotations.NotNull HandlerList getHandlers() { return HANDLER_LIST; } From bbfc01d6db3aa092b923ca7adff731e21218aed0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 11 Jan 2026 21:27:06 +0000 Subject: [PATCH 5/8] Fire event classes in appropriate code sections Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> --- gradlew | 0 .../parcellockers/ParcelLockers.java | 9 +++-- .../itemstorage/ItemStorageManager.java | 27 +++++++++---- .../parcellockers/locker/LockerManager.java | 40 ++++++++++++++++--- .../controller/LockerBreakController.java | 2 +- .../controller/LockerPlaceController.java | 2 +- .../parcel/service/ParcelServiceImpl.java | 26 +++++++++++- .../parcel/task/ParcelSendTask.java | 11 +++++ .../parcellockers/user/UserManager.java | 2 + .../parcellockers/user/UserManagerImpl.java | 38 +++++++++++++++++- 10 files changed, 137 insertions(+), 20 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index cfb973a0..cf4c7a5c 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -126,15 +126,16 @@ public void onEnable() { parcelContentRepository, scheduler, config, - this.economy + this.economy, + server ); UserValidationService userValidationService = new UserValidator(); - UserManager userManager = new UserManagerImpl(userRepository, userValidationService); + UserManager userManager = new UserManagerImpl(userRepository, userValidationService, server); LockerValidationService lockerValidationService = new LockerValidator(); - LockerManager lockerManager = new LockerManager(config, lockerRepository, lockerValidationService, parcelRepository); + LockerManager lockerManager = new LockerManager(config, lockerRepository, lockerValidationService, parcelRepository, server); ParcelContentManager parcelContentManager = new ParcelContentManager(parcelContentRepository); - ItemStorageManager itemStorageManager = new ItemStorageManager(itemStorageRepository); + ItemStorageManager itemStorageManager = new ItemStorageManager(itemStorageRepository, server); DeliveryManager deliveryManager = new DeliveryManager(deliveryRepository); ParcelDispatchService parcelDispatchService = new ParcelDispatchService( diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java index 3ad125e1..0695e6e2 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.itemstorage; +import com.eternalcode.parcellockers.itemstorage.event.ItemStorageUpdateEvent; import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepository; import com.eternalcode.parcellockers.notification.NoticeService; import com.github.benmanes.caffeine.cache.Cache; @@ -9,6 +10,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.inventory.ItemStack; @@ -17,9 +19,11 @@ public class ItemStorageManager { private final Cache cache; private final ItemStorageRepository itemStorageRepository; + private final Server server; - public ItemStorageManager(ItemStorageRepository itemStorageRepository) { + public ItemStorageManager(ItemStorageRepository itemStorageRepository, Server server) { this.itemStorageRepository = itemStorageRepository; + this.server = server; this.cache = Caffeine.newBuilder() .expireAfterWrite(6, TimeUnit.HOURS) @@ -45,13 +49,22 @@ public ItemStorage getOrCreate(UUID owner, List items) { } public ItemStorage create(UUID owner, List items) { - ItemStorage itemStorage = new ItemStorage(owner, items); - if (this.cache.getIfPresent(owner) != null) { - throw new IllegalStateException("ItemStorage for owner " + owner + " already exists. Use ItemStorageManager#getOrCreate method instead."); + ItemStorage oldItemStorage = this.cache.getIfPresent(owner); + ItemStorage newItemStorage = new ItemStorage(owner, items); + + if (oldItemStorage != null) { + // This is an update operation - fire ItemStorageUpdateEvent + ItemStorageUpdateEvent event = new ItemStorageUpdateEvent(oldItemStorage, newItemStorage); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + throw new IllegalStateException("ItemStorage update was cancelled by event"); + } } - this.cache.put(owner, itemStorage); - this.itemStorageRepository.save(itemStorage); - return itemStorage; + + this.cache.put(owner, newItemStorage); + this.itemStorageRepository.save(newItemStorage); + return newItemStorage; } private void cacheAll() { diff --git a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java index b55b1c6c..d0143060 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java @@ -1,6 +1,8 @@ package com.eternalcode.parcellockers.locker; import com.eternalcode.parcellockers.configuration.implementation.PluginConfig; +import com.eternalcode.parcellockers.locker.event.LockerCreateEvent; +import com.eternalcode.parcellockers.locker.event.LockerDeleteEvent; import com.eternalcode.parcellockers.locker.repository.LockerRepository; import com.eternalcode.parcellockers.locker.validation.LockerValidationService; import com.eternalcode.parcellockers.notification.NoticeService; @@ -18,6 +20,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import org.bukkit.Server; import org.bukkit.command.CommandSender; public class LockerManager { @@ -26,6 +29,7 @@ public class LockerManager { private final LockerRepository lockerRepository; private final LockerValidationService validationService; private final ParcelRepository parcelRepository; + private final Server server; private final Cache lockersByUUID; private final Cache lockersByPosition; @@ -34,12 +38,14 @@ public LockerManager( PluginConfig config, LockerRepository lockerRepository, LockerValidationService validationService, - ParcelRepository parcelRepository + ParcelRepository parcelRepository, + Server server ) { this.config = config; this.lockerRepository = lockerRepository; this.validationService = validationService; this.parcelRepository = parcelRepository; + this.server = server; this.lockersByUUID = Caffeine.newBuilder() .expireAfterAccess(Duration.ofHours(2)) @@ -96,7 +102,7 @@ public CompletableFuture> get(Page page) { return this.lockerRepository.findPage(page); } - public CompletableFuture create(UUID uniqueId, String name, Position position) { + public CompletableFuture create(UUID uniqueId, String name, Position position, UUID playerUUID) { return CompletableFuture.supplyAsync(() -> { ValidationResult validation = this.validationService.validateCreateParameters(uniqueId, name, position); @@ -115,6 +121,15 @@ public CompletableFuture create(UUID uniqueId, String name, Position pos } Locker locker = new Locker(uniqueId, name, position); + + // Fire LockerCreateEvent + LockerCreateEvent event = new LockerCreateEvent(locker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + throw new ValidationException("Locker creation cancelled by event"); + } + this.lockersByUUID.put(uniqueId, locker); this.lockersByPosition.put(position, locker); @@ -122,11 +137,26 @@ public CompletableFuture create(UUID uniqueId, String name, Position pos }).thenCompose(Function.identity()); } - public CompletableFuture delete(UUID uniqueId) { + public CompletableFuture delete(UUID uniqueId, UUID playerUUID) { return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { if (deleted > 0) { - this.lockersByUUID.invalidate(uniqueId); - this.lockersByPosition.asMap().values().removeIf(locker -> locker.uuid().equals(uniqueId)); + // Get locker before deleting from cache for the event + Locker locker = this.lockersByUUID.getIfPresent(uniqueId); + + if (locker != null) { + // Fire LockerDeleteEvent + LockerDeleteEvent event = new LockerDeleteEvent(locker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (!event.isCancelled()) { + this.lockersByUUID.invalidate(uniqueId); + this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); + } + } else { + // If locker is not in cache, still delete it + this.lockersByUUID.invalidate(uniqueId); + this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); + } } }); } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java index df1daf6a..03180901 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java @@ -57,7 +57,7 @@ public void onBlockBreak(BlockBreakEvent event) { return; } - this.lockerManager.delete(locker.get().uuid()); + this.lockerManager.delete(locker.get().uuid(), player.getUniqueId()); this.noticeService.player(player.getUniqueId(), messages -> messages.locker.deleted); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java index 499ba76e..21f1206b 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java @@ -128,7 +128,7 @@ public void onBlockPlace(BlockPlaceEvent event) { location.getWorld().getBlockAt(location).setBlockData(data); }); - this.lockerManager.create(UUID.randomUUID(), description, PositionAdapter.convert(location)) + this.lockerManager.create(UUID.randomUUID(), description, PositionAdapter.convert(location), player.getUniqueId()) .thenAccept(locker -> { this.noticeService.create() .player(player.getUniqueId()) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java index bd977458..554acb1f 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java @@ -9,6 +9,8 @@ import com.eternalcode.parcellockers.content.repository.ParcelContentRepository; import com.eternalcode.parcellockers.notification.NoticeService; import com.eternalcode.parcellockers.parcel.Parcel; +import com.eternalcode.parcellockers.parcel.event.ParcelCollectEvent; +import com.eternalcode.parcellockers.parcel.event.ParcelSendEvent; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.PageResult; @@ -23,6 +25,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import net.milkbowl.vault.economy.Economy; +import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -42,6 +45,7 @@ public class ParcelServiceImpl implements ParcelService { private final Scheduler scheduler; private final PluginConfig config; private final Economy economy; + private final Server server; private final Cache parcelsByUuid; @@ -51,7 +55,8 @@ public ParcelServiceImpl( ParcelContentRepository parcelContentRepository, Scheduler scheduler, PluginConfig config, - Economy economy + Economy economy, + Server server ) { this.noticeService = noticeService; this.parcelRepository = parcelRepository; @@ -59,6 +64,7 @@ public ParcelServiceImpl( this.scheduler = scheduler; this.config = config; this.economy = economy; + this.server = server; this.parcelsByUuid = Caffeine.newBuilder() .expireAfterAccess(CACHE_EXPIRE_HOURS, TimeUnit.HOURS) @@ -73,6 +79,15 @@ public CompletableFuture send(Player sender, Parcel parcel, List messages.parcel.cannotSend); + return CompletableFuture.completedFuture(false); + } + List itemsCopy = items.stream() .map(ItemStack::clone) .toList(); @@ -158,6 +173,15 @@ public CompletableFuture collect(Player player, Parcel parcel) { Objects.requireNonNull(player, "Player cannot be null"); Objects.requireNonNull(parcel, "Parcel cannot be null"); + // Fire ParcelCollectEvent + ParcelCollectEvent event = new ParcelCollectEvent(parcel); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + this.noticeService.player(player.getUniqueId(), messages -> messages.parcel.cannotCollect); + return CompletableFuture.completedFuture(null); + } + return this.parcelContentRepository.find(parcel.uuid()).thenCompose(optional -> { if (optional.isEmpty()) { this.noticeService.player(player.getUniqueId(), messages -> messages.parcel.cannotCollect); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java b/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java index 43bbc01a..98adac43 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java @@ -3,8 +3,10 @@ import com.eternalcode.parcellockers.delivery.DeliveryManager; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelStatus; +import com.eternalcode.parcellockers.parcel.event.ParcelDeliverEvent; import com.eternalcode.parcellockers.parcel.service.ParcelService; import java.util.logging.Logger; +import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; public class ParcelSendTask extends BukkitRunnable { @@ -40,6 +42,15 @@ public void run() { ParcelStatus.DELIVERED ); + // Fire ParcelDeliverEvent + ParcelDeliverEvent event = new ParcelDeliverEvent(updated); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + LOGGER.info("ParcelDeliverEvent was cancelled for parcel " + updated.uuid()); + return; + } + this.parcelService.update(updated) .exceptionally(throwable -> { LOGGER.severe("Failed to update parcel " + updated.uuid() + " to DELIVERED status: " + throwable.getMessage()); diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserManager.java b/src/main/java/com/eternalcode/parcellockers/user/UserManager.java index e7daaaf2..fa386f12 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/UserManager.java +++ b/src/main/java/com/eternalcode/parcellockers/user/UserManager.java @@ -17,4 +17,6 @@ public interface UserManager { CompletableFuture> get(UUID uniqueId); CompletableFuture> getPage(Page page); + + CompletableFuture changeName(UUID uuid, String newName); } diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java b/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java index 8238c579..2c65ae91 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java @@ -3,6 +3,8 @@ import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.PageResult; import com.eternalcode.parcellockers.shared.validation.ValidationResult; +import com.eternalcode.parcellockers.user.event.UserChangeNameEvent; +import com.eternalcode.parcellockers.user.event.UserCreateEvent; import com.eternalcode.parcellockers.user.repository.UserRepository; import com.eternalcode.parcellockers.user.validation.UserValidationService; import com.github.benmanes.caffeine.cache.Cache; @@ -12,18 +14,21 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import org.bukkit.Server; public class UserManagerImpl implements UserManager { private final UserRepository userRepository; private final UserValidationService validationService; + private final Server server; private final Cache usersByUUID; private final Cache usersByName; - public UserManagerImpl(UserRepository userRepository, UserValidationService validationService) { + public UserManagerImpl(UserRepository userRepository, UserValidationService validationService, Server server) { this.userRepository = userRepository; this.validationService = validationService; + this.server = server; this.usersByUUID = Caffeine.newBuilder() .expireAfterAccess(2, TimeUnit.HOURS) .maximumSize(10_000) @@ -98,6 +103,11 @@ public CompletableFuture create(UUID uuid, String name) { } User user = new User(uuid, name); + + // Fire UserCreateEvent + UserCreateEvent event = new UserCreateEvent(user); + this.server.getPluginManager().callEvent(event); + this.usersByUUID.put(uuid, user); this.usersByName.put(name, user); this.userRepository.save(user); @@ -105,4 +115,30 @@ public CompletableFuture create(UUID uuid, String name) { return user; }); } + + @Override + public CompletableFuture changeName(UUID uuid, String newName) { + return CompletableFuture.supplyAsync(() -> { + User oldUser = this.usersByUUID.getIfPresent(uuid); + + if (oldUser == null) { + throw new ValidationException("User not found with UUID: " + uuid); + } + + String oldName = oldUser.name(); + + // Fire UserChangeNameEvent + UserChangeNameEvent event = new UserChangeNameEvent(oldUser, oldName); + this.server.getPluginManager().callEvent(event); + + // Update cache + User updatedUser = new User(uuid, newName); + this.usersByUUID.put(uuid, updatedUser); + this.usersByName.invalidate(oldName); + this.usersByName.put(newName, updatedUser); + + // Update in repository + return this.userRepository.changeName(uuid, newName); + }).thenCompose(future -> future); + } } From f3141bd324f912b203ca8b959a184049d41964dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 11 Jan 2026 21:28:51 +0000 Subject: [PATCH 6/8] Fix locker deletion event to fire before database deletion Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> --- .../parcellockers/locker/LockerManager.java | 57 ++++++++++++++----- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java index d0143060..430e2ccb 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java @@ -138,25 +138,52 @@ public CompletableFuture create(UUID uniqueId, String name, Position pos } public CompletableFuture delete(UUID uniqueId, UUID playerUUID) { - return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { - if (deleted > 0) { - // Get locker before deleting from cache for the event - Locker locker = this.lockersByUUID.getIfPresent(uniqueId); + // Get locker from cache first for the event + Locker locker = this.lockersByUUID.getIfPresent(uniqueId); + + // If not in cache, try to fetch from database + if (locker == null) { + return this.lockerRepository.find(uniqueId).thenCompose(optionalLocker -> { + if (optionalLocker.isEmpty()) { + // Locker doesn't exist, nothing to delete + return CompletableFuture.completedFuture(null); + } + + Locker foundLocker = optionalLocker.get(); + + // Fire LockerDeleteEvent before deletion + LockerDeleteEvent event = new LockerDeleteEvent(foundLocker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + // Event was cancelled, don't delete + return CompletableFuture.completedFuture(null); + } - if (locker != null) { - // Fire LockerDeleteEvent - LockerDeleteEvent event = new LockerDeleteEvent(locker, playerUUID); - this.server.getPluginManager().callEvent(event); - - if (!event.isCancelled()) { + // Proceed with deletion + return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { + if (deleted > 0) { this.lockersByUUID.invalidate(uniqueId); this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); } - } else { - // If locker is not in cache, still delete it - this.lockersByUUID.invalidate(uniqueId); - this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); - } + }); + }); + } + + // Fire LockerDeleteEvent before deletion + LockerDeleteEvent event = new LockerDeleteEvent(locker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + // Event was cancelled, don't delete + return CompletableFuture.completedFuture(null); + } + + // Proceed with deletion + return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { + if (deleted > 0) { + this.lockersByUUID.invalidate(uniqueId); + this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); } }); } From 2ee7f3d457e6b1cac86f29f6b8cb51e6e926b42c Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 16:56:01 +0100 Subject: [PATCH 7/8] Implement event firing for custom event classes (#161) * Initial plan * Fire event classes in appropriate code sections Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> * Fix locker deletion event to fire before database deletion Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> --- gradlew | 0 .../parcellockers/ParcelLockers.java | 9 +-- .../itemstorage/ItemStorageManager.java | 27 ++++++-- .../parcellockers/locker/LockerManager.java | 65 +++++++++++++++++-- .../controller/LockerBreakController.java | 2 +- .../controller/LockerPlaceController.java | 2 +- .../parcel/service/ParcelServiceImpl.java | 26 +++++++- .../parcel/task/ParcelSendTask.java | 11 ++++ .../parcellockers/user/UserManager.java | 2 + .../parcellockers/user/UserManagerImpl.java | 38 ++++++++++- 10 files changed, 163 insertions(+), 19 deletions(-) mode change 100644 => 100755 gradlew diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index cfb973a0..cf4c7a5c 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -126,15 +126,16 @@ public void onEnable() { parcelContentRepository, scheduler, config, - this.economy + this.economy, + server ); UserValidationService userValidationService = new UserValidator(); - UserManager userManager = new UserManagerImpl(userRepository, userValidationService); + UserManager userManager = new UserManagerImpl(userRepository, userValidationService, server); LockerValidationService lockerValidationService = new LockerValidator(); - LockerManager lockerManager = new LockerManager(config, lockerRepository, lockerValidationService, parcelRepository); + LockerManager lockerManager = new LockerManager(config, lockerRepository, lockerValidationService, parcelRepository, server); ParcelContentManager parcelContentManager = new ParcelContentManager(parcelContentRepository); - ItemStorageManager itemStorageManager = new ItemStorageManager(itemStorageRepository); + ItemStorageManager itemStorageManager = new ItemStorageManager(itemStorageRepository, server); DeliveryManager deliveryManager = new DeliveryManager(deliveryRepository); ParcelDispatchService parcelDispatchService = new ParcelDispatchService( diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java index 3ad125e1..0695e6e2 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java @@ -1,5 +1,6 @@ package com.eternalcode.parcellockers.itemstorage; +import com.eternalcode.parcellockers.itemstorage.event.ItemStorageUpdateEvent; import com.eternalcode.parcellockers.itemstorage.repository.ItemStorageRepository; import com.eternalcode.parcellockers.notification.NoticeService; import com.github.benmanes.caffeine.cache.Cache; @@ -9,6 +10,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.inventory.ItemStack; @@ -17,9 +19,11 @@ public class ItemStorageManager { private final Cache cache; private final ItemStorageRepository itemStorageRepository; + private final Server server; - public ItemStorageManager(ItemStorageRepository itemStorageRepository) { + public ItemStorageManager(ItemStorageRepository itemStorageRepository, Server server) { this.itemStorageRepository = itemStorageRepository; + this.server = server; this.cache = Caffeine.newBuilder() .expireAfterWrite(6, TimeUnit.HOURS) @@ -45,13 +49,22 @@ public ItemStorage getOrCreate(UUID owner, List items) { } public ItemStorage create(UUID owner, List items) { - ItemStorage itemStorage = new ItemStorage(owner, items); - if (this.cache.getIfPresent(owner) != null) { - throw new IllegalStateException("ItemStorage for owner " + owner + " already exists. Use ItemStorageManager#getOrCreate method instead."); + ItemStorage oldItemStorage = this.cache.getIfPresent(owner); + ItemStorage newItemStorage = new ItemStorage(owner, items); + + if (oldItemStorage != null) { + // This is an update operation - fire ItemStorageUpdateEvent + ItemStorageUpdateEvent event = new ItemStorageUpdateEvent(oldItemStorage, newItemStorage); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + throw new IllegalStateException("ItemStorage update was cancelled by event"); + } } - this.cache.put(owner, itemStorage); - this.itemStorageRepository.save(itemStorage); - return itemStorage; + + this.cache.put(owner, newItemStorage); + this.itemStorageRepository.save(newItemStorage); + return newItemStorage; } private void cacheAll() { diff --git a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java index b55b1c6c..430e2ccb 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java @@ -1,6 +1,8 @@ package com.eternalcode.parcellockers.locker; import com.eternalcode.parcellockers.configuration.implementation.PluginConfig; +import com.eternalcode.parcellockers.locker.event.LockerCreateEvent; +import com.eternalcode.parcellockers.locker.event.LockerDeleteEvent; import com.eternalcode.parcellockers.locker.repository.LockerRepository; import com.eternalcode.parcellockers.locker.validation.LockerValidationService; import com.eternalcode.parcellockers.notification.NoticeService; @@ -18,6 +20,7 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.function.Function; +import org.bukkit.Server; import org.bukkit.command.CommandSender; public class LockerManager { @@ -26,6 +29,7 @@ public class LockerManager { private final LockerRepository lockerRepository; private final LockerValidationService validationService; private final ParcelRepository parcelRepository; + private final Server server; private final Cache lockersByUUID; private final Cache lockersByPosition; @@ -34,12 +38,14 @@ public LockerManager( PluginConfig config, LockerRepository lockerRepository, LockerValidationService validationService, - ParcelRepository parcelRepository + ParcelRepository parcelRepository, + Server server ) { this.config = config; this.lockerRepository = lockerRepository; this.validationService = validationService; this.parcelRepository = parcelRepository; + this.server = server; this.lockersByUUID = Caffeine.newBuilder() .expireAfterAccess(Duration.ofHours(2)) @@ -96,7 +102,7 @@ public CompletableFuture> get(Page page) { return this.lockerRepository.findPage(page); } - public CompletableFuture create(UUID uniqueId, String name, Position position) { + public CompletableFuture create(UUID uniqueId, String name, Position position, UUID playerUUID) { return CompletableFuture.supplyAsync(() -> { ValidationResult validation = this.validationService.validateCreateParameters(uniqueId, name, position); @@ -115,6 +121,15 @@ public CompletableFuture create(UUID uniqueId, String name, Position pos } Locker locker = new Locker(uniqueId, name, position); + + // Fire LockerCreateEvent + LockerCreateEvent event = new LockerCreateEvent(locker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + throw new ValidationException("Locker creation cancelled by event"); + } + this.lockersByUUID.put(uniqueId, locker); this.lockersByPosition.put(position, locker); @@ -122,11 +137,53 @@ public CompletableFuture create(UUID uniqueId, String name, Position pos }).thenCompose(Function.identity()); } - public CompletableFuture delete(UUID uniqueId) { + public CompletableFuture delete(UUID uniqueId, UUID playerUUID) { + // Get locker from cache first for the event + Locker locker = this.lockersByUUID.getIfPresent(uniqueId); + + // If not in cache, try to fetch from database + if (locker == null) { + return this.lockerRepository.find(uniqueId).thenCompose(optionalLocker -> { + if (optionalLocker.isEmpty()) { + // Locker doesn't exist, nothing to delete + return CompletableFuture.completedFuture(null); + } + + Locker foundLocker = optionalLocker.get(); + + // Fire LockerDeleteEvent before deletion + LockerDeleteEvent event = new LockerDeleteEvent(foundLocker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + // Event was cancelled, don't delete + return CompletableFuture.completedFuture(null); + } + + // Proceed with deletion + return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { + if (deleted > 0) { + this.lockersByUUID.invalidate(uniqueId); + this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); + } + }); + }); + } + + // Fire LockerDeleteEvent before deletion + LockerDeleteEvent event = new LockerDeleteEvent(locker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + // Event was cancelled, don't delete + return CompletableFuture.completedFuture(null); + } + + // Proceed with deletion return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { if (deleted > 0) { this.lockersByUUID.invalidate(uniqueId); - this.lockersByPosition.asMap().values().removeIf(locker -> locker.uuid().equals(uniqueId)); + this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); } }); } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java index df1daf6a..03180901 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerBreakController.java @@ -57,7 +57,7 @@ public void onBlockBreak(BlockBreakEvent event) { return; } - this.lockerManager.delete(locker.get().uuid()); + this.lockerManager.delete(locker.get().uuid(), player.getUniqueId()); this.noticeService.player(player.getUniqueId(), messages -> messages.locker.deleted); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java index 499ba76e..21f1206b 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/controller/LockerPlaceController.java @@ -128,7 +128,7 @@ public void onBlockPlace(BlockPlaceEvent event) { location.getWorld().getBlockAt(location).setBlockData(data); }); - this.lockerManager.create(UUID.randomUUID(), description, PositionAdapter.convert(location)) + this.lockerManager.create(UUID.randomUUID(), description, PositionAdapter.convert(location), player.getUniqueId()) .thenAccept(locker -> { this.noticeService.create() .player(player.getUniqueId()) diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java index bd977458..554acb1f 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/service/ParcelServiceImpl.java @@ -9,6 +9,8 @@ import com.eternalcode.parcellockers.content.repository.ParcelContentRepository; import com.eternalcode.parcellockers.notification.NoticeService; import com.eternalcode.parcellockers.parcel.Parcel; +import com.eternalcode.parcellockers.parcel.event.ParcelCollectEvent; +import com.eternalcode.parcellockers.parcel.event.ParcelSendEvent; import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.PageResult; @@ -23,6 +25,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import net.milkbowl.vault.economy.Economy; +import org.bukkit.Server; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -42,6 +45,7 @@ public class ParcelServiceImpl implements ParcelService { private final Scheduler scheduler; private final PluginConfig config; private final Economy economy; + private final Server server; private final Cache parcelsByUuid; @@ -51,7 +55,8 @@ public ParcelServiceImpl( ParcelContentRepository parcelContentRepository, Scheduler scheduler, PluginConfig config, - Economy economy + Economy economy, + Server server ) { this.noticeService = noticeService; this.parcelRepository = parcelRepository; @@ -59,6 +64,7 @@ public ParcelServiceImpl( this.scheduler = scheduler; this.config = config; this.economy = economy; + this.server = server; this.parcelsByUuid = Caffeine.newBuilder() .expireAfterAccess(CACHE_EXPIRE_HOURS, TimeUnit.HOURS) @@ -73,6 +79,15 @@ public CompletableFuture send(Player sender, Parcel parcel, List messages.parcel.cannotSend); + return CompletableFuture.completedFuture(false); + } + List itemsCopy = items.stream() .map(ItemStack::clone) .toList(); @@ -158,6 +173,15 @@ public CompletableFuture collect(Player player, Parcel parcel) { Objects.requireNonNull(player, "Player cannot be null"); Objects.requireNonNull(parcel, "Parcel cannot be null"); + // Fire ParcelCollectEvent + ParcelCollectEvent event = new ParcelCollectEvent(parcel); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + this.noticeService.player(player.getUniqueId(), messages -> messages.parcel.cannotCollect); + return CompletableFuture.completedFuture(null); + } + return this.parcelContentRepository.find(parcel.uuid()).thenCompose(optional -> { if (optional.isEmpty()) { this.noticeService.player(player.getUniqueId(), messages -> messages.parcel.cannotCollect); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java b/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java index 43bbc01a..98adac43 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/task/ParcelSendTask.java @@ -3,8 +3,10 @@ import com.eternalcode.parcellockers.delivery.DeliveryManager; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelStatus; +import com.eternalcode.parcellockers.parcel.event.ParcelDeliverEvent; import com.eternalcode.parcellockers.parcel.service.ParcelService; import java.util.logging.Logger; +import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; public class ParcelSendTask extends BukkitRunnable { @@ -40,6 +42,15 @@ public void run() { ParcelStatus.DELIVERED ); + // Fire ParcelDeliverEvent + ParcelDeliverEvent event = new ParcelDeliverEvent(updated); + Bukkit.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + LOGGER.info("ParcelDeliverEvent was cancelled for parcel " + updated.uuid()); + return; + } + this.parcelService.update(updated) .exceptionally(throwable -> { LOGGER.severe("Failed to update parcel " + updated.uuid() + " to DELIVERED status: " + throwable.getMessage()); diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserManager.java b/src/main/java/com/eternalcode/parcellockers/user/UserManager.java index e7daaaf2..fa386f12 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/UserManager.java +++ b/src/main/java/com/eternalcode/parcellockers/user/UserManager.java @@ -17,4 +17,6 @@ public interface UserManager { CompletableFuture> get(UUID uniqueId); CompletableFuture> getPage(Page page); + + CompletableFuture changeName(UUID uuid, String newName); } diff --git a/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java b/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java index 8238c579..2c65ae91 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/user/UserManagerImpl.java @@ -3,6 +3,8 @@ import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.PageResult; import com.eternalcode.parcellockers.shared.validation.ValidationResult; +import com.eternalcode.parcellockers.user.event.UserChangeNameEvent; +import com.eternalcode.parcellockers.user.event.UserCreateEvent; import com.eternalcode.parcellockers.user.repository.UserRepository; import com.eternalcode.parcellockers.user.validation.UserValidationService; import com.github.benmanes.caffeine.cache.Cache; @@ -12,18 +14,21 @@ import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; +import org.bukkit.Server; public class UserManagerImpl implements UserManager { private final UserRepository userRepository; private final UserValidationService validationService; + private final Server server; private final Cache usersByUUID; private final Cache usersByName; - public UserManagerImpl(UserRepository userRepository, UserValidationService validationService) { + public UserManagerImpl(UserRepository userRepository, UserValidationService validationService, Server server) { this.userRepository = userRepository; this.validationService = validationService; + this.server = server; this.usersByUUID = Caffeine.newBuilder() .expireAfterAccess(2, TimeUnit.HOURS) .maximumSize(10_000) @@ -98,6 +103,11 @@ public CompletableFuture create(UUID uuid, String name) { } User user = new User(uuid, name); + + // Fire UserCreateEvent + UserCreateEvent event = new UserCreateEvent(user); + this.server.getPluginManager().callEvent(event); + this.usersByUUID.put(uuid, user); this.usersByName.put(name, user); this.userRepository.save(user); @@ -105,4 +115,30 @@ public CompletableFuture create(UUID uuid, String name) { return user; }); } + + @Override + public CompletableFuture changeName(UUID uuid, String newName) { + return CompletableFuture.supplyAsync(() -> { + User oldUser = this.usersByUUID.getIfPresent(uuid); + + if (oldUser == null) { + throw new ValidationException("User not found with UUID: " + uuid); + } + + String oldName = oldUser.name(); + + // Fire UserChangeNameEvent + UserChangeNameEvent event = new UserChangeNameEvent(oldUser, oldName); + this.server.getPluginManager().callEvent(event); + + // Update cache + User updatedUser = new User(uuid, newName); + this.usersByUUID.put(uuid, updatedUser); + this.usersByName.invalidate(oldName); + this.usersByName.put(newName, updatedUser); + + // Update in repository + return this.userRepository.changeName(uuid, newName); + }).thenCompose(future -> future); + } } From 63a7d130d7e22bd2d524259bd0d604d586470e3d Mon Sep 17 00:00:00 2001 From: Jakubk15 <77227023+Jakubk15@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:07:05 +0100 Subject: [PATCH 8/8] Refactor item storage and locker event handling for improved clarity and efficiency --- .../itemstorage/ItemStorageManager.java | 16 ++-- .../event/ItemStorageUpdateEvent.java | 1 + .../parcellockers/locker/LockerManager.java | 73 +++++++------------ .../locker/event/LockerCreateEvent.java | 4 +- .../locker/event/LockerDeleteEvent.java | 4 +- .../parcel/event/ParcelCollectEvent.java | 5 +- .../parcel/event/ParcelDeliverEvent.java | 4 +- .../parcel/event/ParcelSendEvent.java | 5 +- .../user/event/UserChangeNameEvent.java | 4 +- .../user/event/UserCreateEvent.java | 4 +- 10 files changed, 53 insertions(+), 67 deletions(-) diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java index 0695e6e2..0111e36e 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/ItemStorageManager.java @@ -51,15 +51,13 @@ public ItemStorage getOrCreate(UUID owner, List items) { public ItemStorage create(UUID owner, List items) { ItemStorage oldItemStorage = this.cache.getIfPresent(owner); ItemStorage newItemStorage = new ItemStorage(owner, items); - - if (oldItemStorage != null) { - // This is an update operation - fire ItemStorageUpdateEvent - ItemStorageUpdateEvent event = new ItemStorageUpdateEvent(oldItemStorage, newItemStorage); - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - throw new IllegalStateException("ItemStorage update was cancelled by event"); - } + + // This is an update operation - fire ItemStorageUpdateEvent + ItemStorageUpdateEvent event = new ItemStorageUpdateEvent(oldItemStorage, newItemStorage); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + throw new IllegalStateException("ItemStorage update was cancelled by event"); } this.cache.put(owner, newItemStorage); diff --git a/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java b/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java index f1653887..bebb56fc 100644 --- a/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/itemstorage/event/ItemStorageUpdateEvent.java @@ -16,6 +16,7 @@ public class ItemStorageUpdateEvent extends Event implements Cancellable { private boolean cancelled; public ItemStorageUpdateEvent(ItemStorage oldItemStorage, ItemStorage updatedItemStorage) { + super(true); this.oldItemStorage = oldItemStorage; this.updatedItemStorage = updatedItemStorage; } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java index 430e2ccb..dc5e30c6 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java @@ -138,53 +138,25 @@ public CompletableFuture create(UUID uniqueId, String name, Position pos } public CompletableFuture delete(UUID uniqueId, UUID playerUUID) { - // Get locker from cache first for the event - Locker locker = this.lockersByUUID.getIfPresent(uniqueId); - - // If not in cache, try to fetch from database - if (locker == null) { - return this.lockerRepository.find(uniqueId).thenCompose(optionalLocker -> { - if (optionalLocker.isEmpty()) { - // Locker doesn't exist, nothing to delete - return CompletableFuture.completedFuture(null); - } - - Locker foundLocker = optionalLocker.get(); - - // Fire LockerDeleteEvent before deletion - LockerDeleteEvent event = new LockerDeleteEvent(foundLocker, playerUUID); - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - // Event was cancelled, don't delete - return CompletableFuture.completedFuture(null); - } - - // Proceed with deletion - return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { - if (deleted > 0) { - this.lockersByUUID.invalidate(uniqueId); - this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); - } - }); - }); - } - - // Fire LockerDeleteEvent before deletion - LockerDeleteEvent event = new LockerDeleteEvent(locker, playerUUID); - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - // Event was cancelled, don't delete - return CompletableFuture.completedFuture(null); - } - - // Proceed with deletion - return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { - if (deleted > 0) { - this.lockersByUUID.invalidate(uniqueId); - this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); + Locker cachedLocker = this.lockersByUUID.getIfPresent(uniqueId); + + CompletableFuture lockerFuture = cachedLocker != null + ? CompletableFuture.completedFuture(cachedLocker) + : this.lockerRepository.find(uniqueId).thenApply(opt -> opt.orElse(null)); + + return lockerFuture.thenCompose(locker -> { + if (locker == null) { + return CompletableFuture.completedFuture(null); + } + + LockerDeleteEvent event = new LockerDeleteEvent(locker, playerUUID); + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + return CompletableFuture.completedFuture(null); } + + return this.deleteLocker(uniqueId); }); } @@ -205,4 +177,13 @@ public CompletableFuture isLockerFull(UUID uniqueId) { return this.parcelRepository.countDeliveredParcelsByDestinationLocker(uniqueId) .thenApply(count -> count > 0 && count >= this.config.settings.maxParcelsPerLocker); } + + private CompletableFuture deleteLocker(UUID uniqueId) { + return this.lockerRepository.delete(uniqueId).thenAccept(deleted -> { + if (deleted > 0) { + this.lockersByUUID.invalidate(uniqueId); + this.lockersByPosition.asMap().values().removeIf(l -> l.uuid().equals(uniqueId)); + } + }); + } } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java index 03afdbcb..cc5f5e82 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerCreateEvent.java @@ -5,6 +5,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; public class LockerCreateEvent extends Event implements Cancellable { @@ -15,6 +16,7 @@ public class LockerCreateEvent extends Event implements Cancellable { private boolean cancelled; public LockerCreateEvent(Locker locker, UUID player) { + super(true); this.locker = locker; this.player = player; } @@ -42,7 +44,7 @@ public void setCancelled(boolean cancel) { } @Override - public @org.jetbrains.annotations.NotNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } diff --git a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java index 9a642c1a..9d48601a 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/event/LockerDeleteEvent.java @@ -5,6 +5,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; public class LockerDeleteEvent extends Event implements Cancellable { @@ -15,6 +16,7 @@ public class LockerDeleteEvent extends Event implements Cancellable { private boolean cancelled; public LockerDeleteEvent(Locker locker, UUID player) { + super(true); this.locker = locker; this.player = player; } @@ -42,7 +44,7 @@ public void setCancelled(boolean cancel) { } @Override - public @org.jetbrains.annotations.NotNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java index 8c2a9e41..b6aa8569 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelCollectEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.jspecify.annotations.NonNull; +import org.jetbrains.annotations.NotNull; public class ParcelCollectEvent extends Event implements Cancellable { @@ -14,6 +14,7 @@ public class ParcelCollectEvent extends Event implements Cancellable { private boolean cancelled; public ParcelCollectEvent(Parcel parcel) { + super(true); this.parcel = parcel; } @@ -26,7 +27,7 @@ public Parcel getParcel() { } @Override - public @NonNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java index 5ab340f3..47ac5347 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelDeliverEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.jspecify.annotations.NonNull; +import org.jetbrains.annotations.NotNull; public class ParcelDeliverEvent extends Event implements Cancellable { @@ -27,7 +27,7 @@ public Parcel getParcel() { } @Override - public @NonNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java index 879fec6f..c1c83d69 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/event/ParcelSendEvent.java @@ -4,7 +4,7 @@ import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.jspecify.annotations.NonNull; +import org.jetbrains.annotations.NotNull; public class ParcelSendEvent extends Event implements Cancellable { @@ -14,6 +14,7 @@ public class ParcelSendEvent extends Event implements Cancellable { private boolean cancelled; public ParcelSendEvent(Parcel parcel) { + super(true); this.parcel = parcel; } @@ -26,7 +27,7 @@ public Parcel getParcel() { } @Override - public @NonNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } diff --git a/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java b/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java index ef9aa198..972adcb9 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/user/event/UserChangeNameEvent.java @@ -3,7 +3,7 @@ import com.eternalcode.parcellockers.user.User; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.jspecify.annotations.NonNull; +import org.jetbrains.annotations.NotNull; public class UserChangeNameEvent extends Event { @@ -30,7 +30,7 @@ public String getOldName() { } @Override - public @NonNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } } diff --git a/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java b/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java index f2ba6978..a0439fe7 100644 --- a/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java +++ b/src/main/java/com/eternalcode/parcellockers/user/event/UserCreateEvent.java @@ -3,7 +3,7 @@ import com.eternalcode.parcellockers.user.User; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; -import org.jspecify.annotations.NonNull; +import org.jetbrains.annotations.NotNull; public class UserCreateEvent extends Event { @@ -24,7 +24,7 @@ public User getUser() { } @Override - public @NonNull HandlerList getHandlers() { + public @NotNull HandlerList getHandlers() { return HANDLER_LIST; } }