diff --git a/build.gradle.kts b/build.gradle.kts index 95813231..e8a122c6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -20,7 +20,7 @@ repositories { dependencies { // minecraft development api - compileOnly("io.papermc.paper:paper-api:1.21.8-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT") paperLibrary("dev.rollczi:litecommands-bukkit:3.10.6") paperLibrary("dev.rollczi:litecommands-adventure:3.10.6") @@ -109,7 +109,7 @@ tasks.withType { tasks { runServer { - minecraftVersion("1.21.8") + minecraftVersion("1.21.10") downloadPlugins.modrinth("luckperms", "v5.5.0-bukkit") } diff --git a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java index 8dcb4358..3449f798 100644 --- a/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java +++ b/src/main/java/com/eternalcode/parcellockers/ParcelLockers.java @@ -121,7 +121,7 @@ public void onEnable() { UserValidationService userValidationService = new UserValidator(); UserManager userManager = new UserManagerImpl(userRepository, userValidationService); LockerValidationService lockerValidationService = new LockerValidator(); - LockerManager lockerManager = new LockerManager(lockerRepository, lockerValidationService); + LockerManager lockerManager = new LockerManager(config, lockerRepository, lockerValidationService, parcelRepository); ParcelContentManager parcelContentManager = new ParcelContentManager(parcelContentRepository); ItemStorageManager itemStorageManager = new ItemStorageManager(itemStorageRepository); DeliveryManager deliveryManager = new DeliveryManager(deliveryRepository); @@ -131,6 +131,7 @@ public void onEnable() { GuiManager guiManager = new GuiManager( config, scheduler, + noticeService, parcelService, lockerManager, userManager, diff --git a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java index 87c96281..1ffd0ae9 100644 --- a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java +++ b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/MessageConfig.java @@ -96,6 +96,10 @@ public static class ParcelMessages extends OkaeriConfig { .chat("&4✘ &cThe parcel destination locker is not set!") .sound(Sound.ENTITY_ENDERMAN_AMBIENT.key()) .build(); + public Notice lockerFull = Notice.builder() + .chat("&4✘ &cThe destination locker is full! Please select another locker.") + .sound(Sound.ENTITY_VILLAGER_NO.key()) + .build(); public Notice illegalItem = Notice.builder() .chat("&4✘ &cThe parcel contains illegal items that cannot be sent. ({ITEMS})") .build(); diff --git a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java index 26db6c87..7818b1ae 100644 --- a/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java +++ b/src/main/java/com/eternalcode/parcellockers/configuration/implementation/PluginConfig.java @@ -58,6 +58,9 @@ public static class Settings extends OkaeriConfig { @Comment({"", "# Parcel sending duration for priority parcels"}) public Duration priorityParcelSendDuration = Duration.ofSeconds(30); + + @Comment({"", "# Maximum number of parcels that can be stored in a single locker"}) + public int maxParcelsPerLocker = 30; } public static class GuiSettings extends OkaeriConfig { diff --git a/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java b/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java index 8a870bba..ddc49245 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/GuiManager.java @@ -8,6 +8,7 @@ import com.eternalcode.parcellockers.itemstorage.ItemStorageManager; import com.eternalcode.parcellockers.locker.Locker; import com.eternalcode.parcellockers.locker.LockerManager; +import com.eternalcode.parcellockers.notification.NoticeService; import com.eternalcode.parcellockers.parcel.Parcel; import com.eternalcode.parcellockers.parcel.ParcelService; import com.eternalcode.parcellockers.parcel.task.ParcelSendTask; @@ -28,6 +29,7 @@ public class GuiManager { private final PluginConfig config; private final Scheduler scheduler; + private final NoticeService noticeService; private final ParcelService parcelService; private final LockerManager lockerManager; private final UserManager userManager; @@ -36,7 +38,7 @@ public class GuiManager { private final DeliveryManager deliveryManager; public GuiManager( - PluginConfig config, Scheduler scheduler, ParcelService parcelService, + PluginConfig config, Scheduler scheduler, NoticeService noticeService, ParcelService parcelService, LockerManager lockerManager, UserManager userManager, ItemStorageManager itemStorageManager, @@ -45,6 +47,7 @@ public GuiManager( ) { this.config = config; this.scheduler = scheduler; + this.noticeService = noticeService; this.parcelService = parcelService; this.lockerManager = lockerManager; this.userManager = userManager; @@ -54,20 +57,38 @@ public GuiManager( } public void sendParcel(Player sender, Parcel parcel, List items) { - Duration delay = parcel.priority() - ? this.config.settings.priorityParcelSendDuration - : this.config.settings.parcelSendDuration; - this.parcelService.send(sender, parcel, items); - this.deliveryManager.create(parcel.uuid(), Instant.now().plus(delay)); - this.parcelContentManager.create(parcel.uuid(), items); - - ParcelSendTask task = new ParcelSendTask( - parcel, - this.parcelService, - this.deliveryManager - ); - - this.scheduler.runLaterAsync(task, delay); + this.lockerManager.isLockerFull(parcel.destinationLocker()).thenAccept(isFull -> { + if (isFull) { + this.noticeService.create() + .notice(messages -> messages.parcel.lockerFull) + .player(sender.getUniqueId()) + .send(); + return; + } + + Duration delay = parcel.priority() + ? this.config.settings.priorityParcelSendDuration + : this.config.settings.parcelSendDuration; + + this.parcelService.send(sender, parcel, items) + .thenAccept(v -> this.deliveryManager.create(parcel.uuid(), Instant.now().plus(delay))) + .thenRun(() -> { + ParcelSendTask task = new ParcelSendTask( + parcel, + this.parcelService, + this.deliveryManager + ); + this.itemStorageManager.delete(sender.getUniqueId()); + + this.scheduler.runLaterAsync(task, delay); + }); + }).exceptionally(throwable -> { + this.noticeService.create() + .notice(messages -> messages.parcel.cannotSend) + .player(sender.getUniqueId()) + .send(); + return null; + }); } public void collectParcel(Player player, Parcel parcel) { diff --git a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/SendingGui.java b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/SendingGui.java index 7417b0a5..a6e5fa0a 100644 --- a/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/SendingGui.java +++ b/src/main/java/com/eternalcode/parcellockers/gui/implementation/locker/SendingGui.java @@ -244,8 +244,6 @@ public void show(Player player) { ); this.guiManager.sendParcel(player, parcel, result.items()); - this.guiManager.deleteItemStorage(player.getUniqueId()); - this.gui.close(player); }).orTimeout(5, TimeUnit.SECONDS)); diff --git a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java index 641547c7..a413c678 100644 --- a/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java +++ b/src/main/java/com/eternalcode/parcellockers/locker/LockerManager.java @@ -1,8 +1,10 @@ package com.eternalcode.parcellockers.locker; +import com.eternalcode.parcellockers.configuration.implementation.PluginConfig; import com.eternalcode.parcellockers.locker.repository.LockerRepository; import com.eternalcode.parcellockers.locker.validation.LockerValidationService; import com.eternalcode.parcellockers.notification.NoticeService; +import com.eternalcode.parcellockers.parcel.repository.ParcelRepository; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.PageResult; import com.eternalcode.parcellockers.shared.Position; @@ -19,15 +21,24 @@ public class LockerManager { + private final PluginConfig config; private final LockerRepository lockerRepository; private final LockerValidationService validationService; + private final ParcelRepository parcelRepository; private final Cache lockersByUUID; private final Cache lockersByPosition; - public LockerManager(LockerRepository lockerRepository, LockerValidationService validationService) { + public LockerManager( + PluginConfig config, + LockerRepository lockerRepository, + LockerValidationService validationService, + ParcelRepository parcelRepository + ) { + this.config = config; this.lockerRepository = lockerRepository; this.validationService = validationService; + this.parcelRepository = parcelRepository; this.lockersByUUID = Caffeine.newBuilder() .expireAfterAccess(Duration.ofHours(2)) @@ -148,6 +159,11 @@ public CompletableFuture deleteAll(CommandSender sender, NoticeService not }); } + public CompletableFuture isLockerFull(UUID lockerUuid) { + return this.parcelRepository.countByDestinationLocker(lockerUuid) + .thenApply(count -> count > 0 && count >= this.config.settings.maxParcelsPerLocker); + } + private void cacheAll() { this.lockerRepository.fetchAll() .thenAccept(optionalLockers -> optionalLockers.ifPresent(lockers -> lockers.forEach(locker -> { @@ -156,3 +172,4 @@ private void cacheAll() { }))); } } + diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java index 9b9243af..5249fb15 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelService.java @@ -29,6 +29,7 @@ public interface ParcelService { CompletableFuture> getByReceiver(UUID receiver, Page page); + CompletableFuture delete(UUID uuid); CompletableFuture delete(Parcel parcel); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java index a072ab1c..29129a63 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/ParcelServiceImpl.java @@ -196,6 +196,7 @@ public CompletableFuture> getByReceiver(UUID receiver, Page p }); } + private void cacheAll() { this.parcelRepository.fetchAll() .thenAccept(optional -> optional.ifPresent(parcels -> parcels.forEach(this::cache))); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java index b2813733..fccea627 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepository.java @@ -29,6 +29,8 @@ public interface ParcelRepository { CompletableFuture> fetchByReceiver(UUID receiver, Page page); + CompletableFuture countByDestinationLocker(UUID destinationLocker); + CompletableFuture delete(Parcel parcel); CompletableFuture delete(UUID uuid); diff --git a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java index 2f89fa10..d54fd677 100644 --- a/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java +++ b/src/main/java/com/eternalcode/parcellockers/parcel/repository/ParcelRepositoryOrmLite.java @@ -4,6 +4,7 @@ import com.eternalcode.parcellockers.database.DatabaseManager; import com.eternalcode.parcellockers.database.wrapper.AbstractRepositoryOrmLite; import com.eternalcode.parcellockers.parcel.Parcel; +import com.eternalcode.parcellockers.parcel.ParcelStatus; import com.eternalcode.parcellockers.shared.Page; import com.eternalcode.parcellockers.shared.PageResult; import com.j256.ormlite.table.TableUtils; @@ -18,6 +19,7 @@ public class ParcelRepositoryOrmLite extends AbstractRepositoryOrmLite implement private static final String RECEIVER_COLUMN = "receiver"; private static final String SENDER_COLUMN = "sender"; + private static final String DESTINATION_LOCKER_COLUMN = "destination_locker"; public ParcelRepositoryOrmLite(DatabaseManager databaseManager, Scheduler scheduler) { super(databaseManager, scheduler); @@ -70,6 +72,18 @@ public CompletableFuture> fetchByReceiver(UUID receiver, Page return this.fetchByPaged(receiver, page, RECEIVER_COLUMN); } + @Override + public CompletableFuture countByDestinationLocker(UUID destinationLocker) { + return this.action(ParcelTable.class, dao -> { + long count = dao.queryBuilder() + .where() + .eq(DESTINATION_LOCKER_COLUMN, destinationLocker) + .eq("status", ParcelStatus.DELIVERED) + .countOf(); + return (int) count; + }); + } + private CompletableFuture> fetchByPaged(UUID key, Page page, String column) { return this.action( ParcelTable.class, dao -> {