From 11981d3a81f482f425e0ea8af7a66d90e75bd397 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 3 Dec 2021 19:18:01 +0900 Subject: [PATCH 01/65] version: version 4.3.0-SNAPSHOT --- README.md | 8 ++++---- gradle.properties | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9f098f6bfa..a1fa0ff401 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Box v4.2.1 +# Box v4.3.0-SNAPSHOT ![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/okocraft/Box) ![GitHub Workflow Status](https://img.shields.io/github/workflow/status/okocraft/Box/Maven%20Build) @@ -85,19 +85,19 @@ For snapshot version, use https://okocraft.github.io/Box/maven-snapshot/ net.okocraft.box api - 4.2.1 + 4.3.0-SNAPSHOT provided ``` ```gradle dependencies { - compileOnly 'net.okocraft.box:api:4.2.1' + compileOnly 'net.okocraft.box:api:4.3.0-SNAPSHOT' } ``` ```kotlin dependencies { - compileOnly("net.okocraft.box:api:4.2.1") + compileOnly("net.okocraft.box:api:4.3.0-SNAPSHOT") } ``` diff --git a/gradle.properties b/gradle.properties index cbc8bdb009..7ff07f79ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,4 +3,4 @@ org.gradle.caching=true org.gradle.parallel=true group=net.okocraft.box -version=4.2.1 +version=4.3.0-SNAPSHOT From 698c743d45145ac24af54769e6e448482db56692 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Dec 2021 11:18:59 +0000 Subject: [PATCH 02/65] build(deps): bump actions/setup-java from 2.3.1 to 2.4.0 Bumps [actions/setup-java](https://github.com/actions/setup-java) from 2.3.1 to 2.4.0. - [Release notes](https://github.com/actions/setup-java/releases) - [Commits](https://github.com/actions/setup-java/compare/v2.3.1...v2.4.0) --- updated-dependencies: - dependency-name: actions/setup-java dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/deployment.yml | 2 +- .github/workflows/gradle.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deployment.yml b/.github/workflows/deployment.yml index 64d8fb653b..89d56e1fcf 100644 --- a/.github/workflows/deployment.yml +++ b/.github/workflows/deployment.yml @@ -11,7 +11,7 @@ jobs: steps: - uses: actions/checkout@v2.4.0 - name: Set up JDK 16 - uses: actions/setup-java@v2.3.1 + uses: actions/setup-java@v2.4.0 with: distribution: 'temurin' java-version: '16' diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 35c6e52a1d..06d759ba27 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v2.4.0 - name: Set up JDK 16 - uses: actions/setup-java@v2.3.1 + uses: actions/setup-java@v2.4.0 with: distribution: 'temurin' java-version: '16' From e744906676bad8115a1e06778c32c1976fab203b Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 02:02:56 +0900 Subject: [PATCH 03/65] build: update gradle to 7.3.1 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102e09..84d1f85fd6 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From c365020613ab0e10c9c008abcabc7dfb58a8c56c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 Dec 2021 11:17:54 +0000 Subject: [PATCH 04/65] build(deps): bump actions/upload-artifact from 2.2.4 to 2.3.0 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2.2.4 to 2.3.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2.2.4...v2.3.0) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 06d759ba27..d605563078 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -32,7 +32,7 @@ jobs: mv features/gui/build staging/features/gui mv features/notifier/build staging/features/notifier mv features/stick/build staging/features/stick - - uses: actions/upload-artifact@v2.2.4 + - uses: actions/upload-artifact@v2.3.0 with: name: Package path: staging From 9ce83a89c0f71eb66fadaec14b553cbe3db3d6e9 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 14:50:08 +0900 Subject: [PATCH 05/65] chore(bundle): add /ba reset permission --- bundle/src/main/resources/plugin.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bundle/src/main/resources/plugin.yml b/bundle/src/main/resources/plugin.yml index e3252e0d42..ac135a2a1e 100644 --- a/bundle/src/main/resources/plugin.yml +++ b/bundle/src/main/resources/plugin.yml @@ -93,6 +93,7 @@ permissions: - box.admin.command.register - box.admin.command.reload - box.admin.command.rename + - box.admin.command.reset - box.admin.command.give - box.admin.command.set - box.admin.command.take @@ -107,6 +108,8 @@ permissions: default: op box.admin.command.rename: default: op + box.admin.command.reset: + default: op box.admin.command.give: default: op box.admin.command.set: From d1269cbcef0d49a0f28d675862c832f74ccf9641 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 14:47:05 +0900 Subject: [PATCH 06/65] feat(command): implements /ba stock --- .../box/feature/command/CommandFeature.java | 6 +- .../command/boxadmin/stock/StockCommand.java | 88 +++++++ .../boxadmin/stock/StockInfoCommand.java | 66 +++++ .../boxadmin/stock/StockListCommand.java | 239 ++++++++++++++++++ .../command/message/BoxAdminMessage.java | 81 ++++++ .../command/util/UserStockHolderOperator.java | 2 +- 6 files changed, 479 insertions(+), 3 deletions(-) create mode 100644 features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockCommand.java create mode 100644 features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java create mode 100644 features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/CommandFeature.java b/features/command/src/main/java/net/okocraft/box/feature/command/CommandFeature.java index f2b5f33ae7..67abc5a93b 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/CommandFeature.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/CommandFeature.java @@ -14,6 +14,7 @@ import net.okocraft.box.feature.command.boxadmin.ResetCommand; import net.okocraft.box.feature.command.boxadmin.StockModifyCommands; import net.okocraft.box.feature.command.boxadmin.VersionCommand; +import net.okocraft.box.feature.command.boxadmin.stock.StockCommand; import java.util.List; @@ -25,8 +26,9 @@ public class CommandFeature extends AbstractBoxFeature { public final List boxAdminSubCommands = List.of(StockModifyCommands.give(), StockModifyCommands.set(), StockModifyCommands.take(), - new InfinityCommand(), new RegisterCommand(), new RenameCommand(), - new ReloadCommand(), new ResetCommand(), new VersionCommand()); + new StockCommand(), new InfinityCommand(), new RegisterCommand(), + new RenameCommand(), new ReloadCommand(), new ResetCommand(), + new VersionCommand()); public CommandFeature() { super("command"); diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockCommand.java new file mode 100644 index 0000000000..c6e6524bdb --- /dev/null +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockCommand.java @@ -0,0 +1,88 @@ +package net.okocraft.box.feature.command.boxadmin.stock; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; +import net.okocraft.box.api.command.AbstractCommand; +import net.okocraft.box.api.command.Command; +import net.okocraft.box.api.command.SubCommandHoldable; +import net.okocraft.box.api.message.GeneralMessage; +import net.okocraft.box.feature.command.message.BoxAdminMessage; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +public class StockCommand extends AbstractCommand implements SubCommandHoldable { + + private final SubCommandHolder subCommandHolder = new SubCommandHolder(); + + public StockCommand() { + // The alias should be "s", but it is already used, so we use "st". + super("stock", "box.admin.command.stock", Set.of("st")); + subCommandHolder.register(new StockInfoCommand()); + subCommandHolder.register(new StockListCommand()); + } + + @Override + public @NotNull Component getHelp() { + return BoxAdminMessage.STOCK_HELP + .append(Component.newline()) + .append( + Component.join( + JoinConfiguration.separator(Component.newline()), + subCommandHolder.getSubCommands().stream().map(Command::getHelp).toList() + ) + ); + } + + @Override + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length < 2) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_NOT_ENOUGH_ARGUMENT); + sender.sendMessage(getHelp()); + return; + } + + var optionalSubCommand = subCommandHolder.search(args[1]); + + if (optionalSubCommand.isEmpty()) { + if (!args[1].equalsIgnoreCase("help")) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_SUBCOMMAND_NOT_FOUND); + } + sender.sendMessage(getHelp()); + return; + } + + var subCommand = optionalSubCommand.get(); + + if (sender.hasPermission(subCommand.getPermissionNode())) { + subCommand.onCommand(sender, args); + } else { + sender.sendMessage(GeneralMessage.ERROR_NO_PERMISSION.apply(subCommand.getPermissionNode())); + } + } + + @Override + public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length == 2) { + return subCommandHolder.getSubCommands().stream() + .filter(cmd -> sender.hasPermission(cmd.getPermissionNode())) + .map(Command::getName) + .filter(cmdName -> cmdName.startsWith(args[1].toLowerCase(Locale.ROOT))) + .toList(); + } else { + return subCommandHolder.search(args[1]) + .filter(cmd -> sender.hasPermission(cmd.getPermissionNode())) + .map(cmd -> cmd.onTabComplete(sender, args)) + .orElse(Collections.emptyList()); + } + } + + @Override + public @NotNull SubCommandHolder getSubCommandHolder() { + return subCommandHolder; + } +} diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java new file mode 100644 index 0000000000..94357ee121 --- /dev/null +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java @@ -0,0 +1,66 @@ +package net.okocraft.box.feature.command.boxadmin.stock; + +import net.kyori.adventure.text.Component; +import net.okocraft.box.api.BoxProvider; +import net.okocraft.box.api.command.AbstractCommand; +import net.okocraft.box.api.message.GeneralMessage; +import net.okocraft.box.feature.command.message.BoxAdminMessage; +import net.okocraft.box.feature.command.util.TabCompleter; +import net.okocraft.box.feature.command.util.UserStockHolderOperator; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +public class StockInfoCommand extends AbstractCommand { + + public StockInfoCommand() { + super("info", "box.admin.command.stock.info", Set.of("i")); + } + + @Override + public @NotNull Component getHelp() { + return BoxAdminMessage.STOCK_INFO_HELP; + } + + @Override + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length < 4) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_NOT_ENOUGH_ARGUMENT); + sender.sendMessage(getHelp()); + return; + } + + var boxItem = BoxProvider.get().getItemManager().getBoxItem(args[3]); + + if (boxItem.isEmpty()) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_ITEM_NOT_FOUND.apply(args[3])); + return; + } + + UserStockHolderOperator.create(args[2]) + .supportOffline(true) + .stockHolderOperator(target -> { + var message = + BoxAdminMessage.STOCK_INFO_AMOUNT.apply(target.getName(), boxItem.get(), target.getAmount(boxItem.get())); + sender.sendMessage(message); + }) + .onNotFound(name -> sender.sendMessage(GeneralMessage.ERROR_COMMAND_PLAYER_NOT_FOUND.apply(name))) + .run(); + } + + @Override + public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length == 3) { + return TabCompleter.players(args[2]); + } + + if (args.length == 4) { + return TabCompleter.itemNames(args[3]); + } + + return Collections.emptyList(); + } +} diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java new file mode 100644 index 0000000000..f1f35d954b --- /dev/null +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java @@ -0,0 +1,239 @@ +package net.okocraft.box.feature.command.boxadmin.stock; + +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.JoinConfiguration; +import net.okocraft.box.api.command.AbstractCommand; +import net.okocraft.box.api.message.GeneralMessage; +import net.okocraft.box.api.model.stock.StockData; +import net.okocraft.box.feature.command.message.BoxAdminMessage; +import net.okocraft.box.feature.command.util.TabCompleter; +import net.okocraft.box.feature.command.util.UserStockHolderOperator; +import org.bukkit.command.CommandSender; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Stream; + +public class StockListCommand extends AbstractCommand { + + private static final Map ARGUMENT_MAP; + + static { + var map = new HashMap(); + + for (var arg : ArgumentType.values()) { + map.put("--" + arg.getLongArg(), arg); + map.put("-" + arg.getShortArg(), arg); + } + + ARGUMENT_MAP = Collections.unmodifiableMap(map); + } + + public StockListCommand() { + super("list", "box.admin.command.stock.list", Set.of("l")); + } + + @Override + public @NotNull Component getHelp() { + return BoxAdminMessage.STOCK_LIST_HELP; + } + + @Override + public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length < 3) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_NOT_ENOUGH_ARGUMENT); + sender.sendMessage(getHelp()); + return; + } + + var targetStockHolder = UserStockHolderOperator.create(args[2]).supportOffline(true).getUserStockHolder(); + + if (targetStockHolder == null) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_PLAYER_NOT_FOUND.apply(args[2])); + return; + } + + var context = new Context(); + + if (3 < args.length) { + ArgumentType type = null; + for (var arg : Arrays.copyOfRange(args, 3, args.length)) { + if (type != null) { + type.getContextConsumer().accept(arg, context); + type = null; + } else { + type = ARGUMENT_MAP.get(arg.toLowerCase(Locale.ENGLISH)); + } + } + } + + var stockDataCollection = targetStockHolder.toStockDataCollection(); + + var sorter = context.getSorter(); + var filter = context.getFilter(); + + if (sorter != null || (filter != null && !filter.isEmpty())) { + var stream = stockDataCollection.stream(); + + if (sorter != null) { + stream = stream.sorted(sorter); + } + + if (filter != null && !filter.isEmpty()) { + stream = stream.filter(stock -> stock.item().getPlainName().startsWith(filter)); + } + + stockDataCollection = stream.toList(); + } + + int maxPage = stockDataCollection.size() / 8 + 1; + int page = Math.max(Math.min(context.getPage(), maxPage), 1); + + int start = (page - 1) * 8; + var counter = new AtomicInteger(start); + + var result = + stockDataCollection.stream() + .skip(start) + .limit(8) + .map(stock -> BoxAdminMessage.STOCK_LIST_ITEM_AMOUNT.apply(counter.incrementAndGet(), stock)) + .toList(); + + sender.sendMessage( + BoxAdminMessage.STOCK_LIST_HEADER + .apply(targetStockHolder, page, maxPage) + .append(Component.newline()) + .append(Component.join(JoinConfiguration.separator(Component.newline()), result)) + ); + } + + @Override + public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length < 3) { + return Collections.emptyList(); + } + + if (args.length == 3) { + return TabCompleter.players(args[2]); + } + + if (args.length == 4) { + return List.copyOf(ARGUMENT_MAP.keySet()); + } + + int index = args.length - 1; + var type = ARGUMENT_MAP.get(args[index - 1]); + + if (type != null) { + return type.getTabCompleter().apply(args[index]); + } else { + return List.copyOf(ARGUMENT_MAP.keySet()); + } + } + + private static class Context { + + private static final Comparator NAME_ASC = Comparator.comparing(stock -> stock.item().getPlainName()); + private static final Comparator NAME_DESC = NAME_ASC.reversed(); + private static final Comparator AMOUNT_ASC = Comparator.comparing(StockData::amount); + private static final Comparator AMOUNT_DESC = AMOUNT_ASC.reversed(); + + private Comparator sorter; + private int page; + private String filter; + + private Context() { + } + + public @Nullable Comparator getSorter() { + return sorter; + } + + public void setSorter(Comparator sorter) { + this.sorter = sorter; + } + + public int getPage() { + return page; + } + + public void setPage(int page) { + this.page = page; + } + + public @Nullable String getFilter() { + return filter; + } + + public void setFilter(String filter) { + this.filter = filter; + } + } + + private enum ArgumentType { + SORTER( + "sorter", "s", + (arg, context) -> { + context.setSorter(switch (arg.toLowerCase(Locale.ROOT)) { + case "na", "name-asc" -> Context.NAME_ASC; + case "nd", "name-desc" -> Context.NAME_DESC; + case "aa", "amount-asc" -> Context.AMOUNT_ASC; + case "ad", "amount-desc" -> Context.AMOUNT_DESC; + default -> null; + }); + }, + arg -> { + return Stream.of("na", "name-asc", "nd", "name-desc", "aa", "amount-asc", "ad", "amount-desc") + .filter(sorter -> sorter.startsWith(arg.toLowerCase(Locale.ENGLISH))) + .toList(); + } + ), + PAGE("page", "p", (arg, context) -> { + try { + context.setPage(Integer.parseInt(arg)); + } catch (NumberFormatException ignored) { + } + }, arg -> Collections.emptyList()), + FILTER("filter", "f", (arg, context) -> context.setFilter(arg), TabCompleter::itemNames); + + private final String longArg; + private final String shortArg; + private final BiConsumer contextConsumer; + private final Function> tabCompleter; + + ArgumentType(@NotNull String longArg, @NotNull String shortArg, @NotNull BiConsumer contextConsumer, + @NotNull Function> tabCompleter) { + this.longArg = longArg; + this.shortArg = shortArg; + this.contextConsumer = contextConsumer; + this.tabCompleter = tabCompleter; + } + + public @NotNull String getLongArg() { + return longArg; + } + + public @NotNull String getShortArg() { + return shortArg; + } + + public @NotNull BiConsumer getContextConsumer() { + return contextConsumer; + } + + public @NotNull Function> getTabCompleter() { + return tabCompleter; + } + } +} diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/message/BoxAdminMessage.java b/features/command/src/main/java/net/okocraft/box/feature/command/message/BoxAdminMessage.java index 87c6d6fabd..9222d22dfe 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/message/BoxAdminMessage.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/message/BoxAdminMessage.java @@ -8,12 +8,14 @@ import net.okocraft.box.api.message.argument.TripleArgument; import net.okocraft.box.api.model.item.BoxCustomItem; import net.okocraft.box.api.model.item.BoxItem; +import net.okocraft.box.api.model.stock.StockData; import net.okocraft.box.api.model.stock.UserStockHolder; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import static net.kyori.adventure.text.Component.newline; +import static net.kyori.adventure.text.Component.space; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.Component.translatable; import static net.kyori.adventure.text.format.NamedTextColor.AQUA; @@ -300,6 +302,85 @@ public final class BoxAdminMessage { .append(text(" - ", DARK_GRAY)) .append(translatable("box.command.boxadmin.reset.help.description", GRAY)); + public static final Component STOCK_HELP = + translatable("box.command.boxadmin.stock.help.command-line", AQUA) + .append(text(" - ", DARK_GRAY)) + .append(translatable("box.command.boxadmin.stock.help.description", GRAY)); + + public static final Component STOCK_INFO_HELP = + translatable("box.command.boxadmin.stock.info.help.command-line", AQUA) + .append(text(" - ", DARK_GRAY)) + .append(translatable("box.command.boxadmin.stock.info.help.description", GRAY)); + + public static final TripleArgument STOCK_INFO_AMOUNT = + (targetName, item, amount) -> + translatable() + .key("box.command.boxadmin.stock.info.amount") + .args( + text(targetName, AQUA), + item.getDisplayName().color(AQUA).hoverEvent(item.getOriginal()), + text(amount, AQUA) + ) + .color(GRAY) + .build(); + + public static final Component STOCK_LIST_HELP = + text().append(translatable("box.command.boxadmin.stock.list.help.command-line", AQUA)) + .append(text(" - ", DARK_GRAY)) + .append(translatable("box.command.boxadmin.stock.list.help.description", GRAY)) + .append(newline()).append(space()) + .append( + translatable() + .key("box.command.boxadmin.stock.list.help.argument.sorter.format") + .args( + text("-s", AQUA), text("--sorter", AQUA), + translatable("box.command.boxadmin.stock.list.help.argument.sorter.value", AQUA) + ) + .color(GRAY) + ).append(newline()).append(space()) + .append( + translatable() + .key("box.command.boxadmin.stock.list.help.argument.page.format") + .args( + text("-p", AQUA), text("--page", AQUA), + translatable("box.command.boxadmin.stock.list.help.argument.page.value", AQUA) + ) + .color(GRAY) + ).append(newline()).append(space()) + .append( + translatable() + .key("box.command.boxadmin.stock.list.help.argument.filter.format") + .args( + text("-f", AQUA), text("--filter", AQUA), + translatable("box.command.boxadmin.stock.list.help.argument.page.value", AQUA) + ) + .color(GRAY) + ).build(); + + public static final TripleArgument STOCK_LIST_HEADER = + (target, page, maxPage) -> + translatable() + .key("box.command.boxadmin.stock.list.header") + .args( + text(target.getName(), AQUA), + text(page, AQUA), + text(maxPage, AQUA) + ) + .color(GRAY) + .build(); + + public static final DoubleArgument STOCK_LIST_ITEM_AMOUNT = + (num, stockData) -> + translatable() + .key("box.command.boxadmin.stock.list.amount") + .args( + text(num, GRAY), + stockData.item().getDisplayName().color(AQUA).hoverEvent(stockData.item().getOriginal()), + text(stockData.amount(), AQUA) + ) + .color(GRAY) + .build(); + private BoxAdminMessage() { throw new UnsupportedOperationException(); } diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java b/features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java index 8a457a36ce..e49b1556b3 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java @@ -58,7 +58,7 @@ public void run() { } } - private @Nullable UserStockHolder getUserStockHolder() { + public @Nullable UserStockHolder getUserStockHolder() { UUID uuid = null; try { From ecbeed88784070211278ee13a4ba7832d4b2741b Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 14:47:20 +0900 Subject: [PATCH 07/65] chore(bundle): add the /ba stock permissions --- bundle/src/main/resources/plugin.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bundle/src/main/resources/plugin.yml b/bundle/src/main/resources/plugin.yml index ac135a2a1e..6488831678 100644 --- a/bundle/src/main/resources/plugin.yml +++ b/bundle/src/main/resources/plugin.yml @@ -97,6 +97,9 @@ permissions: - box.admin.command.give - box.admin.command.set - box.admin.command.take + - box.admin.command.stock + - box.admin.command.stock.info + - box.admin.command.stock.list - box.admin.command.version box.admin.command.customstick: default: op @@ -116,6 +119,12 @@ permissions: default: op box.admin.command.take: default: op + box.admin.command.stock: + default: op + box.admin.command.stock.info: + default: op + box.admin.command.stock.list: + default: op box.admin.command.version: default: op box.admin.ignore-disabled-world: From 86d419cdff2f821b276708cbf3b3f80b72707deb Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 14:47:35 +0900 Subject: [PATCH 08/65] chore(bundle): add messages of the command /ba stock --- bundle/src/main/resources/en.yml | 25 +++++++++++++++++++++++++ bundle/src/main/resources/ja_JP.yml | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/bundle/src/main/resources/en.yml b/bundle/src/main/resources/en.yml index 4170bf7804..e7004e99ac 100644 --- a/bundle/src/main/resources/en.yml +++ b/bundle/src/main/resources/en.yml @@ -185,6 +185,31 @@ box: help: command-line: "/boxadmin reset " description: "Resets all stock" + stock: + help: + command-line: "/boxadmin stock " + description: "Shows player's stock" + info: + amount: "The amount of player {0}''s item {1} : {2}" + help: + command-line: "/boxadmin stock info " + description: "Shows the amount of stock" + list: + header: "Player {0}''s stock list (Page {1}/{2})" + amount: "{0}. {1} - {2}" + help: + command-line: "/boxadmin stock list {args}" + description: "Shows the stock list" + argument: + sorter: + format: "{0} ({1}) {2} - Specifies the order of stock" + value: "" + page: + format: "{0} ({1}) {2} - Specifies the page" + value: "" + filter: + format: "{0} ({1}) {2} - Filters items" + value: "" set: success: sender: "Player {0}''s item {1} has been set to {2}." diff --git a/bundle/src/main/resources/ja_JP.yml b/bundle/src/main/resources/ja_JP.yml index 74e5d06740..c3e75e9a96 100644 --- a/bundle/src/main/resources/ja_JP.yml +++ b/bundle/src/main/resources/ja_JP.yml @@ -185,6 +185,31 @@ box: help: command-line: "/boxadmin reset <プレイヤー名>" description: "在庫をすべてリセットする" + stock: + help: + command-line: "/boxadmin stock <引数>" + description: "在庫情報を表示する" + info: + amount: "プレイヤー {0} のアイテム {1} の在庫: {2} 個" + help: + command-line: "/boxadmin stock info <プレイヤー名> <アイテム名>" + description: "在庫数を表示する" + list: + header: "プレイヤー {0} の在庫リスト ({1}/{2}ページ)" + amount: "{0}. {1} - {2} 個" + help: + command-line: "/boxadmin stock list <プレイヤー名> {引数}" + description: "在庫リストを表示する" + argument: + sorter: + format: "{0} ({1}) {2} - 表示順を指定する" + value: "<ソート方法>" + page: + format: "{0} ({1}) {2} - ページを指定する" + value: "<ページ数>" + filter: + format: "{0} ({1}) {2} - アイテムを絞り込む" + value: "<アイテム名>" set: success: sender: "プレイヤー {0} のアイテム {1} の在庫を {2} 個にセットしました。" From 652c71a0a528492b7938720a9e3ca7c3528684e5 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 15:40:57 +0900 Subject: [PATCH 09/65] feat(api): move TabCompleter and UserStockHolderOperator to api module --- .../okocraft/box/api}/util/TabCompleter.java | 24 +++++++++++- .../api}/util/UserStockHolderOperator.java | 39 ++++++++++++++++++- .../box/feature/command/box/GiveCommand.java | 2 +- .../command/boxadmin/ResetCommand.java | 4 +- .../command/boxadmin/StockModifyCommands.java | 4 +- .../boxadmin/stock/StockInfoCommand.java | 4 +- .../boxadmin/stock/StockListCommand.java | 4 +- 7 files changed, 69 insertions(+), 12 deletions(-) rename {features/command/src/main/java/net/okocraft/box/feature/command => api/src/main/java/net/okocraft/box/api}/util/TabCompleter.java (70%) rename {features/command/src/main/java/net/okocraft/box/feature/command => api/src/main/java/net/okocraft/box/api}/util/UserStockHolderOperator.java (71%) diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/util/TabCompleter.java b/api/src/main/java/net/okocraft/box/api/util/TabCompleter.java similarity index 70% rename from features/command/src/main/java/net/okocraft/box/feature/command/util/TabCompleter.java rename to api/src/main/java/net/okocraft/box/api/util/TabCompleter.java index f35f55efe5..e4f558edfd 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/util/TabCompleter.java +++ b/api/src/main/java/net/okocraft/box/api/util/TabCompleter.java @@ -1,4 +1,4 @@ -package net.okocraft.box.feature.command.util; +package net.okocraft.box.api.util; import net.okocraft.box.api.BoxProvider; import org.bukkit.Bukkit; @@ -9,8 +9,17 @@ import java.util.Locale; import java.util.stream.Collectors; +/** + * A utility class for tab completions. + */ public final class TabCompleter { + /** + * Gets the set of item names that match the filter. + * + * @param filter the item name filter + * @return the set of item names that match the filter + */ public static @NotNull List itemNames(@NotNull String filter) { var itemNameFilter = filter.toUpperCase(Locale.ROOT); return BoxProvider.get() @@ -21,6 +30,12 @@ public final class TabCompleter { .collect(Collectors.toList()); } + /** + * Gets the set of player names that match the filter. + * + * @param filter the player name filter + * @return the set of player names that match the filter + */ public static @NotNull List players(@NotNull String filter) { var playerNameFilter = filter.toLowerCase(Locale.ROOT); @@ -32,6 +47,13 @@ public final class TabCompleter { .collect(Collectors.toList()); } + /** + * Gets the set of player names that match the filter. + * + * @param filter the player name filter + * @param permissionNode the permission node to check + * @return the set of player names that match the filter + */ public static @NotNull List players(@NotNull String filter, @NotNull String permissionNode) { var playerNameFilter = filter.toLowerCase(Locale.ROOT); diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java b/api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java similarity index 71% rename from features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java rename to api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java index e49b1556b3..67a2507b12 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/util/UserStockHolderOperator.java +++ b/api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java @@ -1,4 +1,4 @@ -package net.okocraft.box.feature.command.util; +package net.okocraft.box.api.util; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.model.stock.UserStockHolder; @@ -10,7 +10,10 @@ import java.util.UUID; import java.util.function.Consumer; -public class UserStockHolderOperator { +/** + * A utility class to get the UserStockHolder and do something with it. + */ +public final class UserStockHolderOperator { private final String argument; private boolean supportOffline = false; @@ -21,29 +24,56 @@ private UserStockHolderOperator(@NotNull String argument) { this.argument = argument; } + /** + * Creates a new {@link UserStockHolderOperator}. + * + * @param argument the argument + * @return a new {@link UserStockHolderOperator} + */ @Contract(value = "_ -> new", pure = true) public static @NotNull UserStockHolderOperator create(@NotNull String argument) { return new UserStockHolderOperator(argument); } + /** + * Sets whether to support offline players. + * + * @param bool {@code true} to support offline players, {@code false} otherwise + * @return this builder + */ @Contract(value = "_ -> this") public @NotNull UserStockHolderOperator supportOffline(boolean bool) { supportOffline = bool; return this; } + /** + * Sets the {@link Consumer} of the {@link UserStockHolder}. + * + * @param stockHolderConsumer the {@link Consumer} of the {@link UserStockHolder} + * @return this builder + */ @Contract(value = "_ -> this") public @NotNull UserStockHolderOperator stockHolderOperator(@NotNull Consumer stockHolderConsumer) { this.stockHolderConsumer = stockHolderConsumer; return this; } + /** + * Sets the {@link Consumer} of the argument that is called when the player is not found. + * + * @param argumentConsumer the {@link Consumer} of the argument + * @return this builder + */ @Contract(value = "_ -> this") public @NotNull UserStockHolderOperator onNotFound(@NotNull Consumer argumentConsumer) { this.argumentConsumer = argumentConsumer; return this; } + /** + * Runs this operator. + */ public void run() { if (stockHolderConsumer == null) { return; @@ -58,6 +88,11 @@ public void run() { } } + /** + * Gets the search result of the {@link UserStockHolder}. + * + * @return the search result of the {@link UserStockHolder} + */ public @Nullable UserStockHolder getUserStockHolder() { UUID uuid = null; diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/box/GiveCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/box/GiveCommand.java index c263f4d349..ea4f7cfdd6 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/box/GiveCommand.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/box/GiveCommand.java @@ -6,7 +6,7 @@ import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.feature.command.message.BoxMessage; -import net.okocraft.box.feature.command.util.TabCompleter; +import net.okocraft.box.api.util.TabCompleter; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java index 22caebbc73..114be7ed52 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java @@ -6,8 +6,8 @@ import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.api.model.stock.UserStockHolder; import net.okocraft.box.feature.command.message.BoxAdminMessage; -import net.okocraft.box.feature.command.util.TabCompleter; -import net.okocraft.box.feature.command.util.UserStockHolderOperator; +import net.okocraft.box.api.util.TabCompleter; +import net.okocraft.box.api.util.UserStockHolderOperator; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java index 2b51dc5414..a2aac54baf 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java @@ -8,8 +8,8 @@ import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.api.model.stock.StockHolder; import net.okocraft.box.feature.command.message.BoxAdminMessage; -import net.okocraft.box.feature.command.util.TabCompleter; -import net.okocraft.box.feature.command.util.UserStockHolderOperator; +import net.okocraft.box.api.util.TabCompleter; +import net.okocraft.box.api.util.UserStockHolderOperator; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java index 94357ee121..8683ad44c9 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockInfoCommand.java @@ -5,8 +5,8 @@ import net.okocraft.box.api.command.AbstractCommand; import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.feature.command.message.BoxAdminMessage; -import net.okocraft.box.feature.command.util.TabCompleter; -import net.okocraft.box.feature.command.util.UserStockHolderOperator; +import net.okocraft.box.api.util.TabCompleter; +import net.okocraft.box.api.util.UserStockHolderOperator; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java index f1f35d954b..1f2026c74c 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/stock/StockListCommand.java @@ -6,8 +6,8 @@ import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.api.model.stock.StockData; import net.okocraft.box.feature.command.message.BoxAdminMessage; -import net.okocraft.box.feature.command.util.TabCompleter; -import net.okocraft.box.feature.command.util.UserStockHolderOperator; +import net.okocraft.box.api.util.TabCompleter; +import net.okocraft.box.api.util.UserStockHolderOperator; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; From 8789c97dc37c70339968ec5856eae26dbddedd6d Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 23:00:38 +0900 Subject: [PATCH 10/65] docs(api): fix link --- .../java/net/okocraft/box/api/util/UserStockHolderOperator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java b/api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java index 67a2507b12..ef539c6856 100644 --- a/api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java +++ b/api/src/main/java/net/okocraft/box/api/util/UserStockHolderOperator.java @@ -11,7 +11,7 @@ import java.util.function.Consumer; /** - * A utility class to get the UserStockHolder and do something with it. + * A utility class to get the {@link UserStockHolder}. and do something with it. */ public final class UserStockHolderOperator { From d7ca7ccfff5badf6914ec301feec576b16c200c8 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Thu, 9 Dec 2021 23:52:08 +0900 Subject: [PATCH 11/65] chore(bundle): fix box.command.boxadmin.stock.list.help.command-line --- bundle/src/main/resources/en.yml | 2 +- bundle/src/main/resources/ja_JP.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bundle/src/main/resources/en.yml b/bundle/src/main/resources/en.yml index e7004e99ac..66bb36934a 100644 --- a/bundle/src/main/resources/en.yml +++ b/bundle/src/main/resources/en.yml @@ -198,7 +198,7 @@ box: header: "Player {0}''s stock list (Page {1}/{2})" amount: "{0}. {1} - {2}" help: - command-line: "/boxadmin stock list {args}" + command-line: "/boxadmin stock list [args]" description: "Shows the stock list" argument: sorter: diff --git a/bundle/src/main/resources/ja_JP.yml b/bundle/src/main/resources/ja_JP.yml index c3e75e9a96..18a0538fc0 100644 --- a/bundle/src/main/resources/ja_JP.yml +++ b/bundle/src/main/resources/ja_JP.yml @@ -198,7 +198,7 @@ box: header: "プレイヤー {0} の在庫リスト ({1}/{2}ページ)" amount: "{0}. {1} - {2} 個" help: - command-line: "/boxadmin stock list <プレイヤー名> {引数}" + command-line: "/boxadmin stock list <プレイヤー名> [引数]" description: "在庫リストを表示する" argument: sorter: From 5226a37cf1ae3022eb3cb191403422ee01769f0c Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 10 Dec 2021 00:34:53 +0900 Subject: [PATCH 12/65] fix(core): limit to one instance of UserStockHolder per BoxUser to avoid conflicts in stock operations --- .../java/net/okocraft/box/core/BoxPlugin.java | 5 +- .../core/listener/StockHolderListener.java | 13 +++ .../model/loader/UserStockHolderLoader.java | 109 ++++++++++++++++++ .../core/model/manager/BoxStockManager.java | 34 ++++-- .../box/core/model/user/BoxUserImpl.java | 19 +++ .../box/core/player/BoxPlayerMapImpl.java | 34 ++++-- 6 files changed, 194 insertions(+), 20 deletions(-) create mode 100644 core/src/main/java/net/okocraft/box/core/model/loader/UserStockHolderLoader.java diff --git a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java index d8364a7c87..cc69dadb11 100644 --- a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java +++ b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java @@ -78,7 +78,6 @@ public class BoxPlugin implements BoxAPI { private final List features = new ArrayList<>(); private final AutoSaveTask autoSaveTask = new AutoSaveTask(); - private final StockHolderListener stockHolderListener = new StockHolderListener(); private Storage storage; private BoxItemManager itemManager; @@ -87,6 +86,8 @@ public class BoxPlugin implements BoxAPI { private BoxCustomDataContainer customDataContainer; private BoxPlayerMapImpl playerMap; + private StockHolderListener stockHolderListener; + public BoxPlugin(@NotNull JavaPlugin plugin, @NotNull Path jarFile) { this.plugin = plugin; this.pluginDirectory = plugin.getDataFolder().toPath(); @@ -168,6 +169,8 @@ public boolean enable() { Bukkit.getPluginManager().registerEvents(new PlayerConnectionListener(playerMap), plugin); autoSaveTask.start(); + + stockHolderListener = new StockHolderListener(stockManager); stockHolderListener.register(); getLogger().info("Registering commands..."); diff --git a/core/src/main/java/net/okocraft/box/core/listener/StockHolderListener.java b/core/src/main/java/net/okocraft/box/core/listener/StockHolderListener.java index feb4f42cf5..5e73096350 100644 --- a/core/src/main/java/net/okocraft/box/core/listener/StockHolderListener.java +++ b/core/src/main/java/net/okocraft/box/core/listener/StockHolderListener.java @@ -12,6 +12,7 @@ import net.okocraft.box.api.model.stock.UserStockHolder; import net.okocraft.box.api.model.user.BoxUser; import net.okocraft.box.core.message.ErrorMessages; +import net.okocraft.box.core.model.manager.BoxStockManager; import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; @@ -24,6 +25,11 @@ public class StockHolderListener { private final Key listenerKey = Key.of(getClass().getSimpleName()); private final List modifiedStockHolders = new ArrayList<>(); + private final BoxStockManager stockManager; + + public StockHolderListener(@NotNull BoxStockManager stockManager) { + this.stockManager = stockManager; + } public void register() { var eventBus = BoxProvider.get().getEventBus(); @@ -72,6 +78,13 @@ private void saveModifiedStockHolders(@NotNull AutoSaveStartEvent task) { modifiedStockHolders.clear(); copied.forEach(this::save); + + for (var loader : stockManager.getUserStockHolderLoaders()) { + if (Bukkit.getPlayer(loader.getUser().getUUID()) == null && + !modifiedStockHolders.contains(loader.getSource()) && loader.isLoaded()) { + loader.unload(); + } + } } private void save(@NotNull UserStockHolder userStockHolder) { diff --git a/core/src/main/java/net/okocraft/box/core/model/loader/UserStockHolderLoader.java b/core/src/main/java/net/okocraft/box/core/model/loader/UserStockHolderLoader.java new file mode 100644 index 0000000000..6a84105532 --- /dev/null +++ b/core/src/main/java/net/okocraft/box/core/model/loader/UserStockHolderLoader.java @@ -0,0 +1,109 @@ +package net.okocraft.box.core.model.loader; + +import net.okocraft.box.api.model.item.BoxItem; +import net.okocraft.box.api.model.stock.StockData; +import net.okocraft.box.api.model.stock.UserStockHolder; +import net.okocraft.box.api.model.user.BoxUser; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collection; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Function; + +public class UserStockHolderLoader implements UserStockHolder { + + private final BoxUser user; + private final Function loader; + private final AtomicReference loadedStockHolderReference = new AtomicReference<>(); + + public UserStockHolderLoader(@NotNull BoxUser user, + @NotNull Function loader) { + this.user = user; + this.loader = loader; + } + + @Override + public @NotNull String getName() { + return user.getName().orElse("Unknown"); + } + + @Override + public @NotNull UUID getUUID() { + return user.getUUID(); + } + + @Override + public @NotNull BoxUser getUser() { + return user; + } + + @Override + public int getAmount(@NotNull BoxItem item) { + return checkAndGetUserStockHolder().getAmount(item); + } + + @Override + public void setAmount(@NotNull BoxItem item, int amount) { + checkAndGetUserStockHolder().setAmount(item, amount); + } + + @Override + public int increase(@NotNull BoxItem item) { + return checkAndGetUserStockHolder().increase(item); + } + + @Override + public int increase(@NotNull BoxItem item, int increment) { + return checkAndGetUserStockHolder().increase(item, increment); + } + + @Override + public int decrease(@NotNull BoxItem item) { + return checkAndGetUserStockHolder().decrease(item); + } + + @Override + public int decrease(@NotNull BoxItem item, int decrement) { + return checkAndGetUserStockHolder().decrease(item, decrement); + } + + @Override + public @NotNull @Unmodifiable Collection getStockedItems() { + return checkAndGetUserStockHolder().getStockedItems(); + } + + @Override + public @NotNull @Unmodifiable Collection toStockDataCollection() { + return checkAndGetUserStockHolder().toStockDataCollection(); + } + + public boolean isLoaded() { + return loadedStockHolderReference.get() != null; + } + + public void load() { + loadedStockHolderReference.set(loader.apply(user)); + } + + public void unload() { + loadedStockHolderReference.set(null); + } + + public @NotNull UserStockHolder getSource() { + if (isLoaded()) { + return loadedStockHolderReference.get(); + } else { + throw new IllegalStateException("The stockholder is not set (" + getUUID() + ")"); + } + } + + private @NotNull UserStockHolder checkAndGetUserStockHolder() { + if (!isLoaded()) { + load(); + } + + return loadedStockHolderReference.get(); + } +} diff --git a/core/src/main/java/net/okocraft/box/core/model/manager/BoxStockManager.java b/core/src/main/java/net/okocraft/box/core/model/manager/BoxStockManager.java index ae27532f89..4cb179e398 100644 --- a/core/src/main/java/net/okocraft/box/core/model/manager/BoxStockManager.java +++ b/core/src/main/java/net/okocraft/box/core/model/manager/BoxStockManager.java @@ -6,10 +6,14 @@ import net.okocraft.box.api.model.manager.StockManager; import net.okocraft.box.api.model.stock.UserStockHolder; import net.okocraft.box.api.model.user.BoxUser; +import net.okocraft.box.core.model.loader.UserStockHolderLoader; import net.okocraft.box.core.storage.model.stock.StockStorage; import net.okocraft.box.core.util.executor.InternalExecutors; import org.jetbrains.annotations.NotNull; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; @@ -19,6 +23,8 @@ public class BoxStockManager implements StockManager { private final StockStorage stockStorage; private final ExecutorService executor; + private final Map loaderMap = new HashMap<>(); + public BoxStockManager(@NotNull StockStorage stockStorage) { this.stockStorage = stockStorage; this.executor = InternalExecutors.newSingleThreadExecutor("Stock Manager"); @@ -29,15 +35,15 @@ public BoxStockManager(@NotNull StockStorage stockStorage) { Objects.requireNonNull(user); return CompletableFuture.supplyAsync(() -> { - UserStockHolder stockHolder; - try { - stockHolder = stockStorage.loadUserStockHolder(user); - } catch (Exception e) { - throw new RuntimeException("Could not load user stock holder (" + user.getUUID() + ")", e); + if (loaderMap.containsKey(user)) { + return loaderMap.get(user); } - BoxProvider.get().getEventBus().callEvent(new StockHolderLoadEvent(stockHolder)); - return stockHolder; + var loader = new UserStockHolderLoader(user, this::loadUserStockHolder); + loaderMap.put(user, loader); + loader.load(); + + return loader; }, executor); } @@ -54,4 +60,18 @@ public BoxStockManager(@NotNull StockStorage stockStorage) { BoxProvider.get().getEventBus().callEvent(new StockHolderSaveEvent(stockHolder)); }, executor); } + + public @NotNull Collection getUserStockHolderLoaders() { + return loaderMap.values(); + } + + private @NotNull UserStockHolder loadUserStockHolder(@NotNull BoxUser user) { + try { + var stockHolder = stockStorage.loadUserStockHolder(user); + BoxProvider.get().getEventBus().callEvent(new StockHolderLoadEvent(stockHolder)); + return stockHolder; + } catch (Exception e) { + throw new RuntimeException("Could not load user stock holder (" + user.getUUID() + ")", e); + } + } } diff --git a/core/src/main/java/net/okocraft/box/core/model/user/BoxUserImpl.java b/core/src/main/java/net/okocraft/box/core/model/user/BoxUserImpl.java index 86fca98ce0..585196d1ff 100644 --- a/core/src/main/java/net/okocraft/box/core/model/user/BoxUserImpl.java +++ b/core/src/main/java/net/okocraft/box/core/model/user/BoxUserImpl.java @@ -36,4 +36,23 @@ public BoxUserImpl(@NotNull UUID uuid, @NotNull String name) { public void setName(@NotNull String name) { this.name = Objects.requireNonNull(name); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + return o instanceof BoxUserImpl boxUser && uuid.equals(boxUser.uuid); + } + + @Override + public int hashCode() { + return Objects.hash(uuid); + } + + @Override + public String toString() { + return "BoxUserImpl{" + + "uuid=" + uuid + + ", name='" + name + '\'' + + '}'; + } } diff --git a/core/src/main/java/net/okocraft/box/core/player/BoxPlayerMapImpl.java b/core/src/main/java/net/okocraft/box/core/player/BoxPlayerMapImpl.java index 2e2b577d61..d2885784c6 100644 --- a/core/src/main/java/net/okocraft/box/core/player/BoxPlayerMapImpl.java +++ b/core/src/main/java/net/okocraft/box/core/player/BoxPlayerMapImpl.java @@ -9,6 +9,7 @@ import net.okocraft.box.api.player.BoxPlayer; import net.okocraft.box.api.player.BoxPlayerMap; import net.okocraft.box.core.message.ErrorMessages; +import net.okocraft.box.core.model.loader.UserStockHolderLoader; import net.okocraft.box.core.model.user.BoxUserImpl; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -70,7 +71,6 @@ public boolean isLoaded(@NotNull Player player) { if (boxPlayer != null) { BoxProvider.get().getEventBus().callEvent(new PlayerUnloadEvent(boxPlayer)); - return stockManager.saveUserStock(boxPlayer.getUserStockHolder()); } else { return CompletableFuture.completedFuture(null); @@ -91,19 +91,16 @@ public void loadAll() { public void unloadAll() { for (var boxPlayer : playerMap.values()) { - BoxProvider.get().getEventBus().callEvent(new PlayerUnloadEvent(boxPlayer)); - - stockManager.saveUserStock(boxPlayer.getUserStockHolder()) - .exceptionallyAsync(e -> { - if (boxPlayer.getPlayer().isOnline()) { - boxPlayer.getPlayer().sendMessage(ErrorMessages.ERROR_SAVE_PLAYER_DATA); - } + unloadAndSave(boxPlayer).exceptionally(e -> { + if (boxPlayer.getPlayer().isOnline()) { + boxPlayer.getPlayer().sendMessage(ErrorMessages.ERROR_SAVE_PLAYER_DATA); + } - BoxProvider.get().getLogger().log(Level.SEVERE, - "Could not save player data (" + boxPlayer.getName() + ")", e); + BoxProvider.get().getLogger().log(Level.SEVERE, + "Could not save player data (" + boxPlayer.getName() + ")", e); - return null; - }); + return null; + }); } playerMap.clear(); @@ -117,4 +114,17 @@ private void updateUserName(@NotNull BoxUser user) { return null; }); } + + private @NotNull CompletableFuture unloadAndSave(@NotNull BoxPlayer boxPlayer) { + BoxProvider.get().getEventBus().callEvent(new PlayerUnloadEvent(boxPlayer)); + + var stockHolder = boxPlayer.getUserStockHolder(); + + if (stockHolder instanceof UserStockHolderLoader loader) { + stockHolder = loader.getSource(); + loader.unload(); + } + + return stockManager.saveUserStock(stockHolder); + } } From f89a302b29404fb2724866b69fb73f5b46f0f04b Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 10 Dec 2021 00:35:08 +0900 Subject: [PATCH 13/65] improve(command): remove saving stockholder --- .../box/feature/command/boxadmin/ResetCommand.java | 5 +---- .../feature/command/boxadmin/StockModifyCommands.java | 9 +-------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java index 114be7ed52..d19e7d2b58 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/ResetCommand.java @@ -1,13 +1,12 @@ package net.okocraft.box.feature.command.boxadmin; import net.kyori.adventure.text.Component; -import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.command.AbstractCommand; import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.api.model.stock.UserStockHolder; -import net.okocraft.box.feature.command.message.BoxAdminMessage; import net.okocraft.box.api.util.TabCompleter; import net.okocraft.box.api.util.UserStockHolderOperator; +import net.okocraft.box.feature.command.message.BoxAdminMessage; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -55,8 +54,6 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { if (targetPlayer != null && !sender.getName().equals(targetPlayer.getName())) { targetPlayer.sendMessage(BoxAdminMessage.RESET_SUCCESS_TARGET.apply(sender)); - } else { - BoxProvider.get().getStockManager().saveUserStock(target).join(); } return; diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java index a2aac54baf..144eecbcf7 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/boxadmin/StockModifyCommands.java @@ -138,14 +138,7 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { .supportOffline(true) .stockHolderOperator(target -> { int current = modifyStock(target, item.get(), amount); - - var targetPlayer = Bukkit.getPlayer(target.getUUID()); - - if (targetPlayer == null) { - BoxProvider.get().getStockManager().saveUserStock(target).join(); - } - - sendMessage(sender, targetPlayer, target.getName(), item.get(), amount, current); + sendMessage(sender, Bukkit.getPlayer(target.getUUID()), target.getName(), item.get(), amount, current); }) .onNotFound(name -> sender.sendMessage(GeneralMessage.ERROR_COMMAND_PLAYER_NOT_FOUND.apply(name))) .run(); From deeaf466a14b315176a14b5349bcc3e9fcfd2501 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 10 Dec 2021 00:49:46 +0900 Subject: [PATCH 14/65] feat(api): add BoxEvent#toDebugLog --- .../net/okocraft/box/api/event/BoxEvent.java | 11 +++++++++ .../box/api/event/feature/FeatureEvent.java | 8 +++++++ .../api/event/general/AutoSaveStartEvent.java | 7 ++++++ .../box/api/event/player/PlayerLoadEvent.java | 8 +++++++ .../player/PlayerStockHolderChangeEvent.java | 24 ++++++++++++++++++- .../api/event/player/PlayerUnloadEvent.java | 8 +++++++ .../api/event/stock/StockDecreaseEvent.java | 12 ++++++++++ .../api/event/stock/StockIncreaseEvent.java | 12 ++++++++++ .../box/api/event/stock/StockSetEvent.java | 11 +++++++++ .../event/stockholder/StockHolderEvent.java | 9 +++++++ 10 files changed, 109 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/net/okocraft/box/api/event/BoxEvent.java b/api/src/main/java/net/okocraft/box/api/event/BoxEvent.java index e3ddd48072..447ee88519 100644 --- a/api/src/main/java/net/okocraft/box/api/event/BoxEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/BoxEvent.java @@ -1,9 +1,20 @@ package net.okocraft.box.api.event; import com.github.siroshun09.event4j.event.Event; +import org.jetbrains.annotations.NotNull; /** * A superclass for all events fired by the Box. */ public class BoxEvent extends Event { + + /** + * Creates the debug log from this event. + * + * @return the debug log + */ + public @NotNull String toDebugLog() { + return toString(); + } + } diff --git a/api/src/main/java/net/okocraft/box/api/event/feature/FeatureEvent.java b/api/src/main/java/net/okocraft/box/api/event/feature/FeatureEvent.java index 340515ae77..82faebe9ec 100644 --- a/api/src/main/java/net/okocraft/box/api/event/feature/FeatureEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/feature/FeatureEvent.java @@ -43,6 +43,14 @@ public FeatureEvent(@NotNull BoxFeature feature, @NotNull Type type) { return type; } + @Override + public @NotNull String toDebugLog() { + return "FeatureEvent{" + + "feature=" + feature.getName() + + ", type=" + type + + '}'; + } + @Override public String toString() { return "FeatureEvent{" + diff --git a/api/src/main/java/net/okocraft/box/api/event/general/AutoSaveStartEvent.java b/api/src/main/java/net/okocraft/box/api/event/general/AutoSaveStartEvent.java index 7f5d59e53c..34d61e420d 100644 --- a/api/src/main/java/net/okocraft/box/api/event/general/AutoSaveStartEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/general/AutoSaveStartEvent.java @@ -1,9 +1,16 @@ package net.okocraft.box.api.event.general; import net.okocraft.box.api.event.BoxEvent; +import org.jetbrains.annotations.NotNull; /** * An event called when the auto save task started. */ public class AutoSaveStartEvent extends BoxEvent { + + @Override + public @NotNull String toDebugLog() { + return getEventName(); + } + } diff --git a/api/src/main/java/net/okocraft/box/api/event/player/PlayerLoadEvent.java b/api/src/main/java/net/okocraft/box/api/event/player/PlayerLoadEvent.java index 0923403163..5dc9a8f173 100644 --- a/api/src/main/java/net/okocraft/box/api/event/player/PlayerLoadEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/player/PlayerLoadEvent.java @@ -17,6 +17,14 @@ public PlayerLoadEvent(@NotNull BoxPlayer boxPlayer) { super(boxPlayer); } + @Override + public @NotNull String toDebugLog() { + return "PlayerLoadEvent{" + + "uuid=" + getBoxPlayer().getUUID() + + ", name=" + getBoxPlayer().getName() + + '}'; + } + @Override public String toString() { return "PlayerLoadEvent{" + diff --git a/api/src/main/java/net/okocraft/box/api/event/player/PlayerStockHolderChangeEvent.java b/api/src/main/java/net/okocraft/box/api/event/player/PlayerStockHolderChangeEvent.java index 9239dadd15..325dbb3345 100644 --- a/api/src/main/java/net/okocraft/box/api/event/player/PlayerStockHolderChangeEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/player/PlayerStockHolderChangeEvent.java @@ -18,7 +18,7 @@ public class PlayerStockHolderChangeEvent extends PlayerEvent implements AsyncEv * The constructor of a {@link PlayerStockHolderChangeEvent}. * * @param boxPlayer the player of this event - * @param previous the previous {@link StockHolder} + * @param previous the previous {@link StockHolder} */ public PlayerStockHolderChangeEvent(@NotNull BoxPlayer boxPlayer, @NotNull StockHolder previous) { @@ -34,4 +34,26 @@ public PlayerStockHolderChangeEvent(@NotNull BoxPlayer boxPlayer, public @NotNull StockHolder getPreviousStockHolder() { return previous; } + + @Override + public @NotNull String toDebugLog() { + return "PlayerStockHolderChangeEvent{" + + "uuid=" + getBoxPlayer().getUUID() + + ", name=" + getBoxPlayer().getName() + + ", previousStockholderUuid=" + previous.getUUID() + + ", previousStockHolderName=" + previous.getName() + + ", previousStockHolderClass=" + previous.getClass().getSimpleName() + + ", currentStockholderUuid=" + getBoxPlayer().getCurrentStockHolder().getUUID() + + ", currentStockHolderName=" + getBoxPlayer().getCurrentStockHolder().getName() + + ", currentStockHolderClass=" + getBoxPlayer().getCurrentStockHolder().getClass().getSimpleName() + + '}'; + } + + @Override + public String toString() { + return "PlayerStockHolderChangeEvent{" + + "boxPlayer=" + getBoxPlayer() + + ", previous=" + previous + + '}'; + } } diff --git a/api/src/main/java/net/okocraft/box/api/event/player/PlayerUnloadEvent.java b/api/src/main/java/net/okocraft/box/api/event/player/PlayerUnloadEvent.java index 45a0e821f9..db276ed31a 100644 --- a/api/src/main/java/net/okocraft/box/api/event/player/PlayerUnloadEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/player/PlayerUnloadEvent.java @@ -17,6 +17,14 @@ public PlayerUnloadEvent(@NotNull BoxPlayer boxPlayer) { super(boxPlayer); } + @Override + public @NotNull String toDebugLog() { + return "PlayerUnloadEvent{" + + "uuid=" + getBoxPlayer().getUUID() + + ", name=" + getBoxPlayer().getName() + + '}'; + } + @Override public String toString() { return "PlayerUnloadEvent{" + diff --git a/api/src/main/java/net/okocraft/box/api/event/stock/StockDecreaseEvent.java b/api/src/main/java/net/okocraft/box/api/event/stock/StockDecreaseEvent.java index b2b01ca289..e598489e63 100644 --- a/api/src/main/java/net/okocraft/box/api/event/stock/StockDecreaseEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/stock/StockDecreaseEvent.java @@ -58,6 +58,18 @@ public int getAmount() { return amount; } + @Override + public @NotNull String toDebugLog() { + return "StockDecreaseEvent{" + + "stockholderUuid=" + getStockHolder().getUUID() + + ", stockHolderName=" + getStockHolder().getName() + + ", stockHolderClass=" + getStockHolder().getClass().getSimpleName() + + ", item=" + item + + ", decrements=" + decrements + + ", amount=" + amount + + '}'; + } + @Override public String toString() { return "StockDecreaseEvent{" + diff --git a/api/src/main/java/net/okocraft/box/api/event/stock/StockIncreaseEvent.java b/api/src/main/java/net/okocraft/box/api/event/stock/StockIncreaseEvent.java index 3254144050..d2e5ab1299 100644 --- a/api/src/main/java/net/okocraft/box/api/event/stock/StockIncreaseEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/stock/StockIncreaseEvent.java @@ -58,6 +58,18 @@ public int getAmount() { return amount; } + @Override + public @NotNull String toDebugLog() { + return "StockIncreaseEvent{" + + "stockholderUuid=" + getStockHolder().getUUID() + + ", stockHolderName=" + getStockHolder().getName() + + ", stockHolderClass=" + getStockHolder().getClass().getSimpleName() + + ", item=" + item + + ", increments=" + increments + + ", amount=" + amount + + '}'; + } + @Override public String toString() { return "StockIncreaseEvent{" + diff --git a/api/src/main/java/net/okocraft/box/api/event/stock/StockSetEvent.java b/api/src/main/java/net/okocraft/box/api/event/stock/StockSetEvent.java index a2786195bc..d733de500e 100644 --- a/api/src/main/java/net/okocraft/box/api/event/stock/StockSetEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/stock/StockSetEvent.java @@ -55,6 +55,17 @@ public int getPreviousAmount() { return previousAmount; } + @Override + public @NotNull String toDebugLog() { + return "StockSetEvent{" + + "stockholderUuid=" + getStockHolder().getUUID() + + ", stockHolderName=" + getStockHolder().getName() + + ", stockHolderClass=" + getStockHolder().getClass().getSimpleName() + + ", item=" + item + + ", amount=" + amount + + '}'; + } + @Override public String toString() { return "StockSetEvent{" + diff --git a/api/src/main/java/net/okocraft/box/api/event/stockholder/StockHolderEvent.java b/api/src/main/java/net/okocraft/box/api/event/stockholder/StockHolderEvent.java index bb34eb0d95..868a72caf9 100644 --- a/api/src/main/java/net/okocraft/box/api/event/stockholder/StockHolderEvent.java +++ b/api/src/main/java/net/okocraft/box/api/event/stockholder/StockHolderEvent.java @@ -58,4 +58,13 @@ public boolean isUserStockHolder() { throw new IllegalStateException("The StockHolder of this event is not UserStockHolder."); } } + + @Override + public @NotNull String toDebugLog() { + return getEventName() + "{" + + "uuid=" + getStockHolder().getUUID() + + ", name=" + getStockHolder().getName() + + ", class=" + getStockHolder().getClass().getSimpleName() + + "}"; + } } From ba6562d816c8b6f0eadfa53fba4703c43245f046 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 10 Dec 2021 00:50:49 +0900 Subject: [PATCH 15/65] improve(core): use BoxEvent#toDebugLog to log debugs --- .../box/core/listener/DebugListener.java | 82 +------------------ 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java b/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java index eacca9cd96..ac2378fadc 100644 --- a/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java +++ b/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java @@ -3,12 +3,6 @@ import com.github.siroshun09.event4j.handlerlist.Key; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.event.BoxEvent; -import net.okocraft.box.api.event.player.PlayerEvent; -import net.okocraft.box.api.event.player.PlayerStockHolderChangeEvent; -import net.okocraft.box.api.event.stock.StockDecreaseEvent; -import net.okocraft.box.api.event.stock.StockIncreaseEvent; -import net.okocraft.box.api.event.stock.StockSetEvent; -import net.okocraft.box.api.event.stockholder.StockHolderEvent; import org.jetbrains.annotations.NotNull; public class DebugListener { @@ -24,80 +18,6 @@ public void unregister() { } private void handleEvent(@NotNull BoxEvent event) { - if (event instanceof StockHolderEvent stockHolderEvent) { - if (event instanceof StockIncreaseEvent increaseEvent) { - printLog( - increaseEvent.getEventName() + "{" + - "stockholderName='" + increaseEvent.getStockHolder().getName() + "', " + - "stockholderClass=" + increaseEvent.getStockHolder().getClass().getSimpleName() + ", " + - "boxItem=" + increaseEvent.getItem() + ", " + - "increments=" + increaseEvent.getIncrements() + ", " + - "current=" + increaseEvent.getAmount() + - "}" - ); - return; - } - - if (event instanceof StockDecreaseEvent decreaseEvent) { - printLog( - decreaseEvent.getEventName() + "{" + - "stockholderName='" + decreaseEvent.getStockHolder().getName() + "', " + - "stockholderClass=" + decreaseEvent.getStockHolder().getClass().getSimpleName() + ", " + - "boxItem=" + decreaseEvent.getItem() + ", " + - "decrements=" + decreaseEvent.getDecrements() + ", " + - "current=" + decreaseEvent.getAmount() + - "}" - ); - return; - } - - if (event instanceof StockSetEvent setEvent) { - printLog( - setEvent.getEventName() + "{" + - "stockholderName='" + setEvent.getStockHolder().getName() + "', " + - "stockholderClass=" + setEvent.getStockHolder().getClass().getSimpleName() + ", " + - "boxItem=" + setEvent.getItem() + ", " + - "current=" + setEvent.getAmount() + - "}" - ); - return; - } - - printLog( - stockHolderEvent.getEventName() + "{" + - "stockholderName='" + stockHolderEvent.getStockHolder().getName() + "', " + - "stockholderClass=" + stockHolderEvent.getStockHolder().getClass().getSimpleName() + - "}" - ); - return; - } - - if (event instanceof PlayerEvent playerEvent) { - if (event instanceof PlayerStockHolderChangeEvent changeEvent) { - printLog(changeEvent.getEventName() + "{" + - "playerUuid=" + changeEvent.getBoxPlayer().getUUID() + ", " + - "playerName='" + changeEvent.getBoxPlayer().getName() + "', " + - "previousStockHolderName='" + changeEvent.getPreviousStockHolder().getName() + "', " + - "previousStockHolderClass='" + changeEvent.getPreviousStockHolder().getClass().getSimpleName() + "'," + - "currentStockHolderName='" + changeEvent.getBoxPlayer().getName() + "', " + - "currentStockHolderClass='" + changeEvent.getBoxPlayer().getClass().getSimpleName() + "'" + - "}" - ); - return; - } - - printLog(playerEvent.getEventName() + "{" + - "playerUuid=" + playerEvent.getBoxPlayer().getUUID() + ", " + - "playerName='" + playerEvent.getBoxPlayer().getName() + "'" + - "}" - ); - return; - } - - printLog(event.toString()); - } - - private void printLog(@NotNull String log) { - BoxProvider.get().getLogger().info("DEBUG: " + log); + BoxProvider.get().getLogger().info("DEBUG: " + event.toDebugLog()); } } From 8014a7f074ffa5cef5283a24d3f9529a841f1a33 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 10 Dec 2021 07:50:59 +0900 Subject: [PATCH 16/65] build(parent): update cache version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index acc11dda92..836faf5192 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,4 +17,4 @@ tasks { } } -/* cache version for gh-actions: 1 */ +/* cache version for gh-actions: 2 */ From 33b8a16915874fc84c62874769552c61f3c01767 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sat, 11 Dec 2021 12:26:47 +0900 Subject: [PATCH 17/65] feat(gui): other player's gui --- .../box/feature/craft/button/CraftButton.java | 6 ++-- .../feature/craft/command/CraftCommand.java | 5 +++- .../feature/craft/menu/RecipeItemIcon.java | 4 +-- .../craft/util/IngredientRenderer.java | 4 +-- .../box/feature/craft/util/ItemCrafter.java | 3 +- .../gui/api/session/PlayerSession.java | 15 ++++++++++ .../gui/internal/command/MenuOpenCommand.java | 29 ++++++++++++++++++- .../gui/internal/mode/StorageMode.java | 22 +++++++------- 8 files changed, 68 insertions(+), 20 deletions(-) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/button/CraftButton.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/button/CraftButton.java index 3ed9d32ba5..dc350e3fef 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/button/CraftButton.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/button/CraftButton.java @@ -1,12 +1,12 @@ package net.okocraft.box.feature.craft.button; import net.kyori.adventure.text.Component; -import net.okocraft.box.api.BoxProvider; import net.okocraft.box.feature.craft.lang.Displays; import net.okocraft.box.feature.craft.model.SelectedRecipe; import net.okocraft.box.feature.craft.util.IngredientRenderer; import net.okocraft.box.feature.craft.util.ItemCrafter; import net.okocraft.box.feature.gui.api.button.RefreshableButton; +import net.okocraft.box.feature.gui.api.session.PlayerSession; import net.okocraft.box.feature.gui.api.util.TranslationUtil; import org.bukkit.Material; import org.bukkit.Sound; @@ -73,7 +73,7 @@ public int getIconAmount() { target.displayName(TranslationUtil.render(Displays.CRAFT_BUTTON_DISPLAY_NAME.apply(times), viewer)); - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(viewer).getCurrentStockHolder(); + var stockHolder = PlayerSession.get(viewer).getStockHolder(); var lore = new ArrayList(); var recipe = recipeSupplier.get(); @@ -127,7 +127,7 @@ public void onClick(@NotNull Player clicker, @NotNull ClickType clickType) { private boolean canCraft() { return ItemCrafter.canCraft( - BoxProvider.get().getBoxPlayerMap().get(crafter).getCurrentStockHolder(), + PlayerSession.get(crafter).getStockHolder(), recipeSupplier.get(), timesSupplier.get() ); diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/command/CraftCommand.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/command/CraftCommand.java index fc46411cbf..b335fe3d0e 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/command/CraftCommand.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/command/CraftCommand.java @@ -56,7 +56,10 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { Menu menu; - PlayerSession.get(player).resetCustomNumbers(); + var session = PlayerSession.get(player); + + session.resetCustomNumbers(); + session.setStockHolder(BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder()); if (recipeHolder.getRecipeList().size() == 1) { menu = new CraftMenu(recipeHolder.getRecipeList().get(0), null); diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/RecipeItemIcon.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/RecipeItemIcon.java index 6b456a989f..2d7593978a 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/RecipeItemIcon.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/RecipeItemIcon.java @@ -1,12 +1,12 @@ package net.okocraft.box.feature.craft.menu; import net.kyori.adventure.text.Component; -import net.okocraft.box.api.BoxProvider; import net.okocraft.box.feature.craft.RecipeRegistry; import net.okocraft.box.feature.craft.lang.Displays; import net.okocraft.box.feature.gui.api.lang.Styles; import net.okocraft.box.feature.gui.api.menu.Menu; import net.okocraft.box.feature.gui.api.menu.RenderedButton; +import net.okocraft.box.feature.gui.api.session.PlayerSession; import net.okocraft.box.feature.gui.api.util.MenuOpener; import net.okocraft.box.feature.gui.api.util.TranslationUtil; import org.bukkit.Material; @@ -48,7 +48,7 @@ public int getSlot() { var lore = new ArrayList(); - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(viewer).getCurrentStockHolder(); + var stockHolder = PlayerSession.get(viewer).getStockHolder(); if (ingredients.size() != 1) { for (var ingredient : ingredients.get()) { diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/util/IngredientRenderer.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/util/IngredientRenderer.java index f0aba36019..a97329f6fb 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/util/IngredientRenderer.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/util/IngredientRenderer.java @@ -1,7 +1,6 @@ package net.okocraft.box.feature.craft.util; import net.kyori.adventure.text.Component; -import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.feature.craft.lang.Displays; import net.okocraft.box.feature.craft.model.BoxIngredientItem; @@ -9,6 +8,7 @@ import net.okocraft.box.feature.craft.model.IngredientHolder; import net.okocraft.box.feature.craft.model.SelectedRecipe; import net.okocraft.box.feature.gui.api.lang.Styles; +import net.okocraft.box.feature.gui.api.session.PlayerSession; import net.okocraft.box.feature.gui.api.util.TranslationUtil; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -26,7 +26,7 @@ public final class IngredientRenderer { public static void render(@NotNull List target, @NotNull SelectedRecipe recipe, @NotNull Player viewer, int times) { - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(viewer).getCurrentStockHolder(); + var stockHolder = PlayerSession.get(viewer).getStockHolder(); target.add(TranslationUtil.render(Displays.CRAFT_BUTTON_INGREDIENTS.append(text(":")), viewer)); diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java index dfb746b737..210b88dacd 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java @@ -5,6 +5,7 @@ import net.okocraft.box.api.model.stock.StockHolder; import net.okocraft.box.api.transaction.InventoryTransaction; import net.okocraft.box.feature.craft.model.SelectedRecipe; +import net.okocraft.box.feature.gui.api.session.PlayerSession; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -37,7 +38,7 @@ public static boolean canCraft(@NotNull StockHolder stockHolder, @NotNull Select } public static boolean craft(@NotNull Player crafter, @NotNull SelectedRecipe recipe, int times) { - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(crafter).getCurrentStockHolder(); + var stockHolder = PlayerSession.get(crafter).getStockHolder(); if (!canCraft(stockHolder, recipe, times)) { return false; diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/api/session/PlayerSession.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/api/session/PlayerSession.java index cd320ada1a..b937bc7283 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/api/session/PlayerSession.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/api/session/PlayerSession.java @@ -1,9 +1,11 @@ package net.okocraft.box.feature.gui.api.session; +import net.okocraft.box.api.model.stock.StockHolder; import net.okocraft.box.feature.gui.api.mode.BoxItemClickMode; import net.okocraft.box.feature.gui.api.mode.ClickModeRegistry; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; @@ -21,6 +23,7 @@ public class PlayerSession { private BoxItemClickMode currentClickMode = ClickModeRegistry.getModes().get(0); private final Map customNumberMap = new HashMap<>(); + private @Nullable StockHolder stockHolder; private PlayerSession() { } @@ -40,4 +43,16 @@ public void setBoxItemClickMode(@NotNull BoxItemClickMode boxItemClickMode) { public void resetCustomNumbers() { customNumberMap.values().forEach(num -> num.setAmount(1)); } + + public @NotNull StockHolder getStockHolder() { + if (stockHolder != null) { + return stockHolder; + } else { + throw new IllegalStateException("The stockholder is not set"); + } + } + + public void setStockHolder(@Nullable StockHolder stockHolder) { + this.stockHolder = stockHolder; + } } diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java index 464bb2d83f..2b94c1e2ae 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java @@ -1,7 +1,11 @@ package net.okocraft.box.feature.gui.internal.command; import net.kyori.adventure.text.Component; +import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.command.AbstractCommand; +import net.okocraft.box.api.message.GeneralMessage; +import net.okocraft.box.api.model.stock.StockHolder; +import net.okocraft.box.api.util.UserStockHolderOperator; import net.okocraft.box.feature.gui.api.mode.ClickModeRegistry; import net.okocraft.box.feature.gui.api.session.PlayerSession; import net.okocraft.box.feature.gui.api.util.MenuOpener; @@ -27,13 +31,36 @@ public MenuOpenCommand() { @Override public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { if (!(sender instanceof Player player)) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_ONLY_PLAYER); return; } - var session =PlayerSession.get(player); + var session = PlayerSession.get(player); + session.setBoxItemClickMode(ClickModeRegistry.getModes().get(0)); session.resetCustomNumbers(); + StockHolder stockHolder; + + if (1 < args.length) { + var permission = "box.admin.command.gui.other"; + if (!sender.hasPermission(permission)) { + sender.sendMessage(GeneralMessage.ERROR_NO_PERMISSION.apply(permission)); + return; + } + + stockHolder = UserStockHolderOperator.create(args[1]).supportOffline(true).getUserStockHolder(); + + if (stockHolder == null) { + sender.sendMessage(GeneralMessage.ERROR_COMMAND_PLAYER_NOT_FOUND.apply(args[1])); + return; + } + } else { + stockHolder = BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder(); + } + + session.setStockHolder(stockHolder); + MenuOpener.open(new CategorySelectorMenu(), player); } diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/mode/StorageMode.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/mode/StorageMode.java index 55a6844da8..b8aca1dbc3 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/mode/StorageMode.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/mode/StorageMode.java @@ -75,9 +75,10 @@ public boolean hasAdditionalButton() { } private @NotNull @Unmodifiable List createLore(@NotNull BoxItem item, @NotNull Player player) { - int currentStock = BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder().getAmount(item); - int transactionAmount = - PlayerSession.get(player).getCustomNumberHolder(TRANSACTION_AMOUNT_NAME).getAmount(); + var session = PlayerSession.get(player); + + int currentStock = session.getStockHolder().getAmount(item); + int transactionAmount = session.getCustomNumberHolder(TRANSACTION_AMOUNT_NAME).getAmount(); return List.of( Displays.STORAGE_MODE_LEFT_CLICK_TO_DEPOSIT.apply(transactionAmount), @@ -90,8 +91,9 @@ public boolean hasAdditionalButton() { @SuppressWarnings("DuplicatedCode") private void processDeposit(@NotNull Context context) { var player = context.clicker(); - int transactionAmount = - PlayerSession.get(player).getCustomNumberHolder(TRANSACTION_AMOUNT_NAME).getAmount(); + var session = PlayerSession.get(player); + + int transactionAmount = session.getCustomNumberHolder(TRANSACTION_AMOUNT_NAME).getAmount(); var resultList = BoxProvider.get().getTaskFactory().supply( @@ -103,7 +105,7 @@ private void processDeposit(@NotNull Context context) { return; } - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder(); + var stockHolder = session.getStockHolder(); resultList.getResultList() .stream() @@ -115,8 +117,9 @@ private void processDeposit(@NotNull Context context) { private void processWithdraw(@NotNull Context context) { var player = context.clicker(); + var session = PlayerSession.get(player); - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(player).getCurrentStockHolder(); + var stockHolder = session.getStockHolder(); var currentStock = stockHolder.getAmount(context.item()); if (currentStock < 1) { @@ -124,8 +127,7 @@ private void processWithdraw(@NotNull Context context) { return; } - int transactionAmount = - PlayerSession.get(player).getCustomNumberHolder(TRANSACTION_AMOUNT_NAME).getAmount(); + int transactionAmount = session.getCustomNumberHolder(TRANSACTION_AMOUNT_NAME).getAmount(); var amount = Math.min(currentStock, transactionAmount); @@ -185,7 +187,7 @@ public void onClick(@NotNull Player clicker, @NotNull ClickType clickType) { return; } - var stockHolder = BoxProvider.get().getBoxPlayerMap().get(clicker).getCurrentStockHolder(); + var stockHolder = PlayerSession.get(clicker).getStockHolder(); resultList.getResultList() .stream() From b31e46e36d61762d7ae4ebcb26d59ab7e7191828 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sat, 11 Dec 2021 12:26:56 +0900 Subject: [PATCH 18/65] chore(bundle): add the permission of other player's gui --- bundle/src/main/resources/plugin.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bundle/src/main/resources/plugin.yml b/bundle/src/main/resources/plugin.yml index 6488831678..2f5630cb14 100644 --- a/bundle/src/main/resources/plugin.yml +++ b/bundle/src/main/resources/plugin.yml @@ -95,6 +95,7 @@ permissions: - box.admin.command.rename - box.admin.command.reset - box.admin.command.give + - box.admin.command.gui.other - box.admin.command.set - box.admin.command.take - box.admin.command.stock @@ -115,6 +116,8 @@ permissions: default: op box.admin.command.give: default: op + box.admin.command.gui.other: + default: op box.admin.command.set: default: op box.admin.command.take: From 9e5a9f918c74b762dba3bc5fce41c7f5bf2e9f68 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sat, 11 Dec 2021 12:38:12 +0900 Subject: [PATCH 19/65] fix(core): specify the priority of the listener --- .../java/net/okocraft/box/core/listener/DebugListener.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java b/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java index ac2378fadc..2d5b235889 100644 --- a/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java +++ b/core/src/main/java/net/okocraft/box/core/listener/DebugListener.java @@ -1,6 +1,7 @@ package net.okocraft.box.core.listener; import com.github.siroshun09.event4j.handlerlist.Key; +import com.github.siroshun09.event4j.handlerlist.Priority; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.event.BoxEvent; import org.jetbrains.annotations.NotNull; @@ -10,7 +11,7 @@ public class DebugListener { private final Key listenerKey = Key.of("box:debug"); public void register() { - BoxProvider.get().getEventBus().getHandlerList(BoxEvent.class).subscribe(listenerKey, this::handleEvent); + BoxProvider.get().getEventBus().getHandlerList(BoxEvent.class).subscribe(listenerKey, this::handleEvent, Priority.of(Integer.MIN_VALUE)); } public void unregister() { From fc2308760d7f7921d328aad66a0dfe98815b165a Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Wed, 15 Dec 2021 22:47:10 +0900 Subject: [PATCH 20/65] build: update gradle to 7.3.2 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 84d1f85fd6..d2880ba800 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From 8dad50f1b20f429d858ce54cfb1825d781d52bba Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Wed, 15 Dec 2021 22:48:13 +0900 Subject: [PATCH 21/65] build: update cache version to 3 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 836faf5192..af203bd508 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,4 +17,4 @@ tasks { } } -/* cache version for gh-actions: 2 */ +/* cache version for gh-actions: 3 */ From bc7ff1be900542509ab0396f19857219fa278a3a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Dec 2021 11:22:19 +0000 Subject: [PATCH 22/65] build(deps): bump com.github.johnrengelman.shadow from 7.1.0 to 7.1.1 Bumps com.github.johnrengelman.shadow from 7.1.0 to 7.1.1. --- updated-dependencies: - dependency-name: com.github.johnrengelman.shadow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- bundle/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle/build.gradle.kts b/bundle/build.gradle.kts index f86b3e5541..e32e2653cd 100644 --- a/bundle/build.gradle.kts +++ b/bundle/build.gradle.kts @@ -2,7 +2,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar plugins { id("box.common-conventions") - id("com.github.johnrengelman.shadow") version "7.1.0" + id("com.github.johnrengelman.shadow") version "7.1.1" } dependencies { From 9064cdc93d8e401386ce9621de9d42ed83bb6dfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Dec 2021 11:24:25 +0000 Subject: [PATCH 23/65] build(deps): bump actions/upload-artifact from 2.3.0 to 2.3.1 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2.3.0 to 2.3.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2.3.0...v2.3.1) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index d605563078..c467fb5d8d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -32,7 +32,7 @@ jobs: mv features/gui/build staging/features/gui mv features/notifier/build staging/features/notifier mv features/stick/build staging/features/stick - - uses: actions/upload-artifact@v2.3.0 + - uses: actions/upload-artifact@v2.3.1 with: name: Package path: staging From c42992c299835363e3923976c850c8d791267293 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 17 Dec 2021 11:15:35 +0900 Subject: [PATCH 24/65] feat(api): add Disableable --- .../java/net/okocraft/box/api/feature/Disableable.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 api/src/main/java/net/okocraft/box/api/feature/Disableable.java diff --git a/api/src/main/java/net/okocraft/box/api/feature/Disableable.java b/api/src/main/java/net/okocraft/box/api/feature/Disableable.java new file mode 100644 index 0000000000..1c13b44e8c --- /dev/null +++ b/api/src/main/java/net/okocraft/box/api/feature/Disableable.java @@ -0,0 +1,7 @@ +package net.okocraft.box.api.feature; + +/** + * An interface to indicate that the {@link BoxFeature} can be disabled in config.yml. + */ +public interface Disableable { +} From 06f79880a7b43aee55cc9ef36044a3247a9635bd Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Fri, 17 Dec 2021 11:16:33 +0900 Subject: [PATCH 25/65] feat(core): implements Disableable feature --- core/src/main/java/net/okocraft/box/core/BoxPlugin.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java index cc69dadb11..ff7e349d77 100644 --- a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java +++ b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java @@ -12,6 +12,7 @@ import net.okocraft.box.api.command.base.BoxCommand; import net.okocraft.box.api.event.feature.FeatureEvent; import net.okocraft.box.api.feature.BoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; import net.okocraft.box.api.model.data.CustomDataContainer; import net.okocraft.box.api.model.manager.ItemManager; @@ -380,7 +381,8 @@ private void saveDefaultLanguages(@NotNull Path directory) throws IOException { @Override public void register(@NotNull BoxFeature boxFeature) { - if (configuration.get(Settings.DISABLED_FEATURES).contains(boxFeature.getName())) { + if (boxFeature instanceof Disableable && + configuration.get(Settings.DISABLED_FEATURES).contains(boxFeature.getName())) { getLogger().warning("The " + boxFeature.getName() + " feature is disabled in config.yml"); return; } From dd7d0f14e4e18b82e3a3210d742eac5818bb59fe Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sat, 18 Dec 2021 12:36:35 +0900 Subject: [PATCH 26/65] feat: implements Disableable for features --- .../net/okocraft/box/feature/autostore/AutoStoreFeature.java | 3 ++- .../net/okocraft/box/feature/category/CategoryFeature.java | 3 ++- .../main/java/net/okocraft/box/feature/craft/CraftFeature.java | 3 ++- .../src/main/java/net/okocraft/box/feature/gui/GuiFeature.java | 3 ++- .../net/okocraft/box/feature/notifier/NotifierFeature.java | 3 ++- .../main/java/net/okocraft/box/feature/stick/StickFeature.java | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) diff --git a/features/autostore/src/main/java/net/okocraft/box/feature/autostore/AutoStoreFeature.java b/features/autostore/src/main/java/net/okocraft/box/feature/autostore/AutoStoreFeature.java index 5a72d0e19b..6b86b28670 100644 --- a/features/autostore/src/main/java/net/okocraft/box/feature/autostore/AutoStoreFeature.java +++ b/features/autostore/src/main/java/net/okocraft/box/feature/autostore/AutoStoreFeature.java @@ -2,6 +2,7 @@ import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; import net.okocraft.box.feature.autostore.command.AutoStoreCommand; import net.okocraft.box.feature.autostore.gui.AutoStoreClickMode; @@ -14,7 +15,7 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -public class AutoStoreFeature extends AbstractBoxFeature implements Reloadable { +public class AutoStoreFeature extends AbstractBoxFeature implements Disableable, Reloadable { private final BoxPlayerListener boxPlayerListener = new BoxPlayerListener(); private final AutoSaveListener autoSaveListener = new AutoSaveListener(); diff --git a/features/category/src/main/java/net/okocraft/box/feature/category/CategoryFeature.java b/features/category/src/main/java/net/okocraft/box/feature/category/CategoryFeature.java index 5acebcff9b..8fda9d481b 100644 --- a/features/category/src/main/java/net/okocraft/box/feature/category/CategoryFeature.java +++ b/features/category/src/main/java/net/okocraft/box/feature/category/CategoryFeature.java @@ -5,6 +5,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; import net.okocraft.box.feature.category.internal.CategoryLoader; import net.okocraft.box.feature.category.internal.CustomItemListener; @@ -15,7 +16,7 @@ import java.nio.file.Files; import java.util.logging.Level; -public class CategoryFeature extends AbstractBoxFeature implements Reloadable { +public class CategoryFeature extends AbstractBoxFeature implements Disableable, Reloadable { private final CustomItemListener customItemListener = new CustomItemListener(); diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java index b8006d9cc0..c6369bae3b 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java @@ -4,6 +4,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; import net.okocraft.box.feature.craft.command.CraftCommand; import net.okocraft.box.feature.craft.loader.RecipeLoader; @@ -12,7 +13,7 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; -public class CraftFeature extends AbstractBoxFeature implements Reloadable { +public class CraftFeature extends AbstractBoxFeature implements Disableable, Reloadable { private final CraftMode craftMode = new CraftMode(); private final CraftCommand craftCommand = new CraftCommand(); diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java index fd070e5b23..14d534b414 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java @@ -4,6 +4,7 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; import net.okocraft.box.feature.gui.api.mode.ClickModeRegistry; import net.okocraft.box.feature.gui.internal.command.MenuOpenCommand; @@ -16,7 +17,7 @@ import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; -public class GuiFeature extends AbstractBoxFeature implements Reloadable { +public class GuiFeature extends AbstractBoxFeature implements Disableable, Reloadable { private final MenuOpenCommand command = new MenuOpenCommand(); private final InventoryListener listener = new InventoryListener(); diff --git a/features/notifier/src/main/java/net/okocraft/box/feature/notifier/NotifierFeature.java b/features/notifier/src/main/java/net/okocraft/box/feature/notifier/NotifierFeature.java index 0f00f8a993..79411b987f 100644 --- a/features/notifier/src/main/java/net/okocraft/box/feature/notifier/NotifierFeature.java +++ b/features/notifier/src/main/java/net/okocraft/box/feature/notifier/NotifierFeature.java @@ -1,9 +1,10 @@ package net.okocraft.box.feature.notifier; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.feature.notifier.listener.StockHolderListener; -public class NotifierFeature extends AbstractBoxFeature { +public class NotifierFeature extends AbstractBoxFeature implements Disableable { private final StockHolderListener stockHolderListener = new StockHolderListener(); diff --git a/features/stick/src/main/java/net/okocraft/box/feature/stick/StickFeature.java b/features/stick/src/main/java/net/okocraft/box/feature/stick/StickFeature.java index 2d27b4f058..df4a872a74 100644 --- a/features/stick/src/main/java/net/okocraft/box/feature/stick/StickFeature.java +++ b/features/stick/src/main/java/net/okocraft/box/feature/stick/StickFeature.java @@ -2,6 +2,7 @@ import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.feature.stick.command.CustomStickCommand; import net.okocraft.box.feature.stick.command.StickCommand; import net.okocraft.box.feature.stick.item.BoxStickItem; @@ -10,7 +11,7 @@ import org.bukkit.NamespacedKey; import org.bukkit.event.HandlerList; -public class StickFeature extends AbstractBoxFeature { +public class StickFeature extends AbstractBoxFeature implements Disableable { private final NamespacedKey key = BoxProvider.get().createNamespacedKey("stick"); From ad76316ce18928cecaf7a1dcebd385828802100c Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:55:59 +0900 Subject: [PATCH 27/65] feat(api): add BoxFeature#getDependencies --- .../net/okocraft/box/api/feature/BoxFeature.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/api/src/main/java/net/okocraft/box/api/feature/BoxFeature.java b/api/src/main/java/net/okocraft/box/api/feature/BoxFeature.java index 321202cec5..c682fbfc1e 100644 --- a/api/src/main/java/net/okocraft/box/api/feature/BoxFeature.java +++ b/api/src/main/java/net/okocraft/box/api/feature/BoxFeature.java @@ -2,6 +2,10 @@ import com.github.siroshun09.event4j.handlerlist.Key; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Collections; +import java.util.Set; /** * An interface that adds a box feature. @@ -33,4 +37,13 @@ public interface BoxFeature { * This method will be called even if an exception is thrown while executing {@link #enable()}. */ void disable(); + + /** + * Gets classes of the dependent {@link BoxFeature}. + * + * @return classes of the dependent {@link BoxFeature} + */ + default @NotNull @Unmodifiable Set> getDependencies() { + return Collections.emptySet(); + } } From 4251b3abf9fae6eb24b35347e8c63f547a7168cc Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 01:08:24 +0900 Subject: [PATCH 28/65] feat(core): checks if the dependencies of the feature are registered --- .../main/java/net/okocraft/box/core/BoxPlugin.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java index ff7e349d77..112e7c0466 100644 --- a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java +++ b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java @@ -387,6 +387,19 @@ public void register(@NotNull BoxFeature boxFeature) { return; } + var dependencies = boxFeature.getDependencies(); + + if (!dependencies.isEmpty()) { + for (var dependencyClass : dependencies) { + if (features.stream().noneMatch(feature -> dependencyClass.isAssignableFrom(feature.getClass()))) { + getLogger().warning( + dependencyClass.getSimpleName() + " that is the dependency of the " + boxFeature.getName() + " is not registered." + ); + return; + } + } + } + try { boxFeature.enable(); } catch (Throwable throwable) { From 4e5e32162d6fbe20fcdf54867dd90fa20066c2bd Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 01:08:45 +0900 Subject: [PATCH 29/65] feat(craft): add CraftFeature#getDependencies --- .../net/okocraft/box/feature/craft/CraftFeature.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java index c6369bae3b..d91b901c17 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java @@ -4,14 +4,19 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.BoxFeature; import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; import net.okocraft.box.feature.craft.command.CraftCommand; import net.okocraft.box.feature.craft.loader.RecipeLoader; import net.okocraft.box.feature.craft.mode.CraftMode; +import net.okocraft.box.feature.gui.GuiFeature; import net.okocraft.box.feature.gui.api.mode.ClickModeRegistry; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Set; public class CraftFeature extends AbstractBoxFeature implements Disableable, Reloadable { @@ -49,4 +54,9 @@ public void reload(@NotNull CommandSender sender) { // IllegalStateException: Exceeded maximum depth of 512 while attempting to flatten components! } } + + @Override + public @NotNull @Unmodifiable Set> getDependencies() { + return Set.of(GuiFeature.class); + } } From 6c469d9a271e79babf1f737a84d0c85b9657f0dc Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 01:08:52 +0900 Subject: [PATCH 30/65] feat(gui): add GuiFeature#getDependencies --- .../java/net/okocraft/box/feature/gui/GuiFeature.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java index 14d534b414..bdf18d8046 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/GuiFeature.java @@ -4,8 +4,10 @@ import net.kyori.adventure.text.format.NamedTextColor; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.feature.AbstractBoxFeature; +import net.okocraft.box.api.feature.BoxFeature; import net.okocraft.box.api.feature.Disableable; import net.okocraft.box.api.feature.Reloadable; +import net.okocraft.box.feature.category.CategoryFeature; import net.okocraft.box.feature.gui.api.mode.ClickModeRegistry; import net.okocraft.box.feature.gui.internal.command.MenuOpenCommand; import net.okocraft.box.feature.gui.internal.holder.BoxInventoryHolder; @@ -16,6 +18,9 @@ import org.bukkit.entity.HumanEntity; import org.bukkit.event.HandlerList; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import java.util.Set; public class GuiFeature extends AbstractBoxFeature implements Disableable, Reloadable { @@ -79,4 +84,9 @@ public void reload(@NotNull CommandSender sender) { // IllegalStateException: Exceeded maximum depth of 512 while attempting to flatten components! } } + + @Override + public @NotNull @Unmodifiable Set> getDependencies() { + return Set.of(CategoryFeature.class); + } } From 3a8a10d79ba43e362e5153fc250e6067fd7889d8 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:47:36 +0900 Subject: [PATCH 31/65] build: update configapi-yaml to 4.6.0 --- build-logic/src/main/kotlin/box.dependencies.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-logic/src/main/kotlin/box.dependencies.gradle.kts b/build-logic/src/main/kotlin/box.dependencies.gradle.kts index a524f5b53b..c705e70301 100644 --- a/build-logic/src/main/kotlin/box.dependencies.gradle.kts +++ b/build-logic/src/main/kotlin/box.dependencies.gradle.kts @@ -12,7 +12,7 @@ repositories { } dependencies { - implementation("com.github.siroshun09.configapi:configapi-yaml:4.5.0") + implementation("com.github.siroshun09.configapi:configapi-yaml:4.6.0") implementation("com.github.siroshun09.event4j:event4j:2.2.0") compileOnly("io.papermc.paper:paper-api:1.17.1-R0.1-SNAPSHOT") From abe82387d92ca01e8d9603ad0cecfeb7b730dc2d Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:48:10 +0900 Subject: [PATCH 32/65] build: update translationloader to 2.0.0 --- core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index bc29695b24..8e868272d6 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -3,6 +3,6 @@ plugins { } dependencies { - implementation("com.github.siroshun09.translationloader:translationloader:1.1.1") + implementation("com.github.siroshun09.translationloader:translationloader:2.0.0") compileOnly(project(":api")) } From ef328b559b6b84689c837858a7cc469ccf9fae9d Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:49:30 +0900 Subject: [PATCH 33/65] fix: translationloader changes --- .../java/net/okocraft/box/core/BoxPlugin.java | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java index 112e7c0466..5cd0c05881 100644 --- a/core/src/main/java/net/okocraft/box/core/BoxPlugin.java +++ b/core/src/main/java/net/okocraft/box/core/BoxPlugin.java @@ -1,8 +1,11 @@ package net.okocraft.box.core; +import com.github.siroshun09.configapi.api.Configuration; import com.github.siroshun09.configapi.api.util.ResourceUtils; import com.github.siroshun09.configapi.yaml.YamlConfiguration; import com.github.siroshun09.event4j.bus.EventBus; +import com.github.siroshun09.translationloader.ConfigurationLoader; +import com.github.siroshun09.translationloader.TranslationLoader; import com.github.siroshun09.translationloader.directory.TranslationDirectory; import net.kyori.adventure.key.Key; import net.kyori.adventure.text.Component; @@ -47,6 +50,7 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Unmodifiable; import java.io.IOException; @@ -97,7 +101,14 @@ public BoxPlugin(@NotNull JavaPlugin plugin, @NotNull Path jarFile) { this.configuration = YamlConfiguration.create(pluginDirectory.resolve("config.yml")); this.translationDirectory = - TranslationDirectory.create(pluginDirectory.resolve("languages"), Key.key("box", "language")); + TranslationDirectory.newBuilder() + .setDirectory(pluginDirectory.resolve("languages")) + .setKey(Key.key("box", "language")) + .setDefaultLocale(Locale.ENGLISH) + .onDirectoryCreated(this::saveDefaultLanguages) + .setVersion(getPluginInstance().getDescription().getVersion()) + .setTranslationLoaderCreator(this::getBundledTranslation) + .build(); BoxProvider.set(this); } @@ -115,11 +126,7 @@ public boolean load() { getLogger().info("Loading languages..."); - translationDirectory.getRegistry().defaultLocale(Locale.ENGLISH); - try { - translationDirectory.createDirectoryIfNotExists(); - saveDefaultLanguages(translationDirectory.getDirectory()); translationDirectory.load(); } catch (IOException e) { getLogger().log(Level.SEVERE, "Could not load languages", e); @@ -269,10 +276,7 @@ public void accept(Supplier componentSupplier) { } try { - translationDirectory.createDirectoryIfNotExists(); - saveDefaultLanguages(translationDirectory.getDirectory()); translationDirectory.load(); - translationDirectory.getRegistry().defaultLocale(Locale.ENGLISH); sender.sendMessage(MicsMessages.LANGUAGES_RELOADED); } catch (Throwable e) { playerMessenger.accept(() -> ErrorMessages.ERROR_RELOAD_FAILURE.apply("languages", e)); @@ -304,6 +308,25 @@ private void saveDefaultLanguages(@NotNull Path directory) throws IOException { ResourceUtils.copyFromJarIfNotExists(jarFile, japanese, directory.resolve(japanese)); } + private @Nullable TranslationLoader getBundledTranslation(@NotNull Locale locale) throws IOException { + var strLocale = locale.toString(); + + if (!(strLocale.equals("en") || strLocale.equals("ja_JP"))) { + return null; + } + + Configuration source; + + try (var input = ResourceUtils.getInputStreamFromJar(getJar(), strLocale + ".yml")) { + source = YamlConfiguration.loadFromInputStream(input); + } + + var loader = ConfigurationLoader.create(locale, source); + loader.load(); + + return loader; + } + @Override public @NotNull Plugin getPluginInstance() { return plugin; From b3d31656a7a455e5169a08ddd6f2b9fe62fb6112 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:49:56 +0900 Subject: [PATCH 34/65] chore: add version placeholder --- bundle/src/main/resources/en.yml | 1 + bundle/src/main/resources/ja_JP.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/bundle/src/main/resources/en.yml b/bundle/src/main/resources/en.yml index 66bb36934a..7b32012c54 100644 --- a/bundle/src/main/resources/en.yml +++ b/bundle/src/main/resources/en.yml @@ -1,3 +1,4 @@ +v: "${projectVersion}" box: autostore: error: diff --git a/bundle/src/main/resources/ja_JP.yml b/bundle/src/main/resources/ja_JP.yml index 18a0538fc0..5701984b81 100644 --- a/bundle/src/main/resources/ja_JP.yml +++ b/bundle/src/main/resources/ja_JP.yml @@ -1,3 +1,4 @@ +v: "${projectVersion}" box: autostore: error: From 0ac3ee9be253d43972c6c26b7322a315c5ff50ef Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:50:45 +0900 Subject: [PATCH 35/65] chore: enclose version placeholders in double quotes --- bundle/src/main/resources/plugin.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle/src/main/resources/plugin.yml b/bundle/src/main/resources/plugin.yml index 2f5630cb14..1972793f74 100644 --- a/bundle/src/main/resources/plugin.yml +++ b/bundle/src/main/resources/plugin.yml @@ -1,6 +1,6 @@ name: Box main: net.okocraft.box.bundle.BoxBootstrap -version: ${projectVersion} +version: "${projectVersion}" authors: [ lazy_gon, Siroshun09 ] api-version: 1.17 commands: From 596293822734d54aa4fbc3d16e8fd5d55ec02c38 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 00:51:12 +0900 Subject: [PATCH 36/65] build: replace project version in plugin.yml, en.yml, and ja_JP.yml --- bundle/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle/build.gradle.kts b/bundle/build.gradle.kts index e32e2653cd..f8d908d297 100644 --- a/bundle/build.gradle.kts +++ b/bundle/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { } tasks.named("processResources") { - filesMatching("plugin.yml") { + filesMatching(listOf("plugin.yml", "en.yml", "ja_JP.yml")) { expand("projectVersion" to project.version) } } From 61f24e3f5bf8807d59f4ff8fbe59666e17bc2477 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 02:32:44 +0900 Subject: [PATCH 37/65] feat(craft): implements disabled-recipes and custom recipes --- .../box/feature/craft/CraftFeature.java | 19 +++++- .../box/feature/craft/loader/Processor.java | 68 +++++++++++++++++++ .../feature/craft/loader/RecipeLoader.java | 11 ++- .../feature/craft/model/IngredientHolder.java | 4 ++ 4 files changed, 98 insertions(+), 4 deletions(-) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java index d91b901c17..6f28b67c9e 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java @@ -1,5 +1,7 @@ package net.okocraft.box.feature.craft; +import com.github.siroshun09.configapi.api.util.ResourceUtils; +import com.github.siroshun09.configapi.yaml.YamlConfiguration; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.okocraft.box.api.BoxProvider; @@ -16,7 +18,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; +import java.io.IOException; import java.util.Set; +import java.util.logging.Level; public class CraftFeature extends AbstractBoxFeature implements Disableable, Reloadable { @@ -29,8 +33,21 @@ public CraftFeature() { @Override public void enable() { - RecipeRegistry.setRecipeMap(RecipeLoader.load()); + var recipeFile = BoxProvider.get().getPluginDirectory().resolve("recipes.yml"); + + var recipeConfig = YamlConfiguration.create(recipeFile); + + try { + ResourceUtils.copyFromJarIfNotExists(BoxProvider.get().getJar(), "recipes.yml", recipeConfig.getPath()); + recipeConfig.load(); + } catch (IOException e) { + BoxProvider.get().getLogger().log(Level.SEVERE, "Could not load recipes.yml", e); + } + + RecipeRegistry.setRecipeMap(RecipeLoader.load(recipeConfig)); + ClickModeRegistry.register(craftMode); + BoxProvider.get().getBoxCommand().getSubCommandHolder().register(craftCommand); } diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java index 8d40720673..7293c999fa 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java @@ -1,5 +1,6 @@ package net.okocraft.box.feature.craft.loader; +import com.github.siroshun09.configapi.api.Configuration; import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.api.model.manager.ItemManager; @@ -17,6 +18,7 @@ import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Set; @@ -24,9 +26,14 @@ final class Processor { private static final Set DISABLED_ITEM = Set.of(new ItemStack(Material.FIREWORK_ROCKET)); + private final Configuration recipeConfig; private final ItemManager itemManager = BoxProvider.get().getItemManager(); private final Map recipeMap = new HashMap<>(100, 0.8f); + Processor(@NotNull Configuration recipeConfig) { + this.recipeConfig = recipeConfig; + } + void processRecipe(@NotNull Recipe recipe) { var item = recipe.getResult().clone(); @@ -52,11 +59,57 @@ void processRecipe(@NotNull Recipe recipe) { } } + void processCustomRecipes() { + var section = recipeConfig.getSection("custom-recipes"); + + if (section == null) { + return; + } + + var logger = BoxProvider.get().getLogger(); + var itemManager = BoxProvider.get().getItemManager(); + + for (var key : section.getKeyList()) { + var ingredients = new ArrayList(); + + for (var ingredientItemName : section.getStringList(key + ".ingredients")) { + var item = itemManager.getBoxItem(ingredientItemName); + + if (item.isEmpty()) { + logger.warning("Could not get an ingredient item in recipes.yml (" + ingredientItemName + ")"); + ingredients.clear(); + break; + } else { + ingredients.add(item.get()); + } + } + + if (ingredients.isEmpty()) { + continue; + } + + var resultItemName = section.getString(key + ".result-item"); + var resultItem = itemManager.getBoxItem(resultItemName); + + if (resultItem.isEmpty()) { + logger.warning("Could not get a result item in recipes.yml (" + resultItemName + ")"); + continue; + } + + var amount = Math.max(1, section.getInteger(key + ".amount")); + processCustomRecipe(ingredients, resultItem.get(), amount); + } + } + @NotNull Map result() { return recipeMap; } private void processShapedRecipe(@NotNull ShapedRecipe recipe, @NotNull BoxItem result) { + if (recipeConfig.getString("disabled-recipes").contains(recipe.getKey().toString())) { + return; + } + var ingredients = new ArrayList(); for (var entry : recipe.getChoiceMap().entrySet()) { @@ -82,6 +135,10 @@ private void processShapedRecipe(@NotNull ShapedRecipe recipe, @NotNull BoxItem } private void processShapelessRecipe(@NotNull ShapelessRecipe recipe, @NotNull BoxItem result) { + if (recipeConfig.getString("disabled-recipes").contains(recipe.getKey().toString())) { + return; + } + var ingredients = new ArrayList(); int slot = 0; @@ -104,7 +161,18 @@ private void processShapelessRecipe(@NotNull ShapelessRecipe recipe, @NotNull Bo } getRecipeHolder(result).addRecipe(new BoxItemRecipe(ingredients, result, recipe.getResult().getAmount())); + } + + private void processCustomRecipe(@NotNull List ingredients, @NotNull BoxItem result, int amount) { + var ingredientHolders = new ArrayList(); + + int slot = 0; + for (var ingredient : ingredients) { + ingredientHolders.add(IngredientHolder.fromSingleItem(slot, ingredient.getOriginal())); + slot++; + } + getRecipeHolder(result).addRecipe(new BoxItemRecipe(ingredientHolders, result, amount)); } @Contract(pure = true) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java index fac7a5ed6f..a82e516b42 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java @@ -1,5 +1,6 @@ package net.okocraft.box.feature.craft.loader; +import com.github.siroshun09.configapi.api.Configuration; import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.feature.craft.model.RecipeHolder; import org.bukkit.Bukkit; @@ -9,11 +10,15 @@ public final class RecipeLoader { - public static @NotNull Map load() { - var processor = new Processor(); + public static @NotNull Map load(@NotNull Configuration recipeConfig) { + var processor = new Processor(recipeConfig); + Bukkit.recipeIterator().forEachRemaining(processor::processRecipe); + AdditionalRecipes.RECIPES.forEach(processor::processRecipe); + + processor.processCustomRecipes(); + return processor.result(); } - } diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/model/IngredientHolder.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/model/IngredientHolder.java index 086b039917..bf60c717ff 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/model/IngredientHolder.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/model/IngredientHolder.java @@ -20,6 +20,10 @@ public class IngredientHolder { return new IngredientHolder(slot, choice.getChoices()); } + public static @NotNull IngredientHolder fromSingleItem(int slot, @NotNull ItemStack itemStack) { + return new IngredientHolder(slot, List.of(itemStack)); + } + private final int slot; private final List patterns; From ed2b9202f2e1acdff554e88b6f3d4d6f9de7a121 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 02:32:50 +0900 Subject: [PATCH 38/65] chore(craft): add default recipes.yml --- features/craft/src/main/resources/recipes.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 features/craft/src/main/resources/recipes.yml diff --git a/features/craft/src/main/resources/recipes.yml b/features/craft/src/main/resources/recipes.yml new file mode 100644 index 0000000000..b078f01f8f --- /dev/null +++ b/features/craft/src/main/resources/recipes.yml @@ -0,0 +1,17 @@ +# The list to disable default recipes. +# +# disabled-recipes: +# - "minecraft:crossbow" +# +disabled-recipes: [] + +# The list to create custom recipes in Box +# +# custom-recipes: +# example-name: # WHITE_CONCRETE_POWDER x 1 -> WHITE_CONCRETE x 1 +# ingredients: +# - WHITE_CONCRETE_POWDER +# result-item: WHITE_CONCRETE +# amount: 1 +# +custom-recipes: [] From 696859ddde1a3606528e21d24ea83fa6d129603b Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 15:00:52 +0900 Subject: [PATCH 39/65] improve(craft): reduce settings --- .../box/feature/craft/loader/Processor.java | 15 +++++++-------- features/craft/src/main/resources/recipes.yml | 7 +++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java index 7293c999fa..165157236b 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java @@ -70,6 +70,13 @@ void processCustomRecipes() { var itemManager = BoxProvider.get().getItemManager(); for (var key : section.getKeyList()) { + var resultItem = itemManager.getBoxItem(key); + + if (resultItem.isEmpty()) { + logger.warning("Could not get a result item in recipes.yml (" + key + ")"); + continue; + } + var ingredients = new ArrayList(); for (var ingredientItemName : section.getStringList(key + ".ingredients")) { @@ -88,14 +95,6 @@ void processCustomRecipes() { continue; } - var resultItemName = section.getString(key + ".result-item"); - var resultItem = itemManager.getBoxItem(resultItemName); - - if (resultItem.isEmpty()) { - logger.warning("Could not get a result item in recipes.yml (" + resultItemName + ")"); - continue; - } - var amount = Math.max(1, section.getInteger(key + ".amount")); processCustomRecipe(ingredients, resultItem.get(), amount); } diff --git a/features/craft/src/main/resources/recipes.yml b/features/craft/src/main/resources/recipes.yml index b078f01f8f..8ef3d589d1 100644 --- a/features/craft/src/main/resources/recipes.yml +++ b/features/craft/src/main/resources/recipes.yml @@ -8,10 +8,9 @@ disabled-recipes: [] # The list to create custom recipes in Box # # custom-recipes: -# example-name: # WHITE_CONCRETE_POWDER x 1 -> WHITE_CONCRETE x 1 -# ingredients: +# WHITE_CONCRETE: # result item name (in Box) +# ingredients: # the name of the item to be used as an ingredient. (1~9 items, shapeless) # - WHITE_CONCRETE_POWDER -# result-item: WHITE_CONCRETE -# amount: 1 +# amount: 1 # the amount of the result item # custom-recipes: [] From b69a499cf6d87dfc7e01f91caa5401545f4b05d2 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 15:01:14 +0900 Subject: [PATCH 40/65] feat(gui): add tabcompleter for /box gui {other} --- .../gui/internal/command/MenuOpenCommand.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java index 2b94c1e2ae..85e9a7795f 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/command/MenuOpenCommand.java @@ -5,6 +5,7 @@ import net.okocraft.box.api.command.AbstractCommand; import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.api.model.stock.StockHolder; +import net.okocraft.box.api.util.TabCompleter; import net.okocraft.box.api.util.UserStockHolderOperator; import net.okocraft.box.feature.gui.api.mode.ClickModeRegistry; import net.okocraft.box.feature.gui.api.session.PlayerSession; @@ -14,6 +15,8 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.util.Collections; +import java.util.List; import java.util.Set; import static net.kyori.adventure.text.Component.text; @@ -24,6 +27,8 @@ public class MenuOpenCommand extends AbstractCommand { + private static final String OTHER_PLAYERS_GUI_PERMISSION = "box.admin.command.gui.other"; + public MenuOpenCommand() { super("gui", "box.command.gui", Set.of("g", "menu", "m")); } @@ -43,9 +48,8 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { StockHolder stockHolder; if (1 < args.length) { - var permission = "box.admin.command.gui.other"; - if (!sender.hasPermission(permission)) { - sender.sendMessage(GeneralMessage.ERROR_NO_PERMISSION.apply(permission)); + if (!sender.hasPermission(OTHER_PLAYERS_GUI_PERMISSION)) { + sender.sendMessage(GeneralMessage.ERROR_NO_PERMISSION.apply(OTHER_PLAYERS_GUI_PERMISSION)); return; } @@ -70,4 +74,13 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { .append(text(" - ", DARK_GRAY)) .append(translatable("box.gui.command-help.description", GRAY)); } + + @Override + public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length == 2 && sender.hasPermission(OTHER_PLAYERS_GUI_PERMISSION)) { + return TabCompleter.players(args[1]); + } else { + return Collections.emptyList(); + } + } } From 2af0d80493c6d8e35cddffc08bdad0332ca045cf Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Sun, 19 Dec 2021 15:09:30 +0900 Subject: [PATCH 41/65] feat(gui): add tabcompleter for /box iteminfo {item} --- .../box/feature/command/box/ItemInfoCommand.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/features/command/src/main/java/net/okocraft/box/feature/command/box/ItemInfoCommand.java b/features/command/src/main/java/net/okocraft/box/feature/command/box/ItemInfoCommand.java index e2ee9b630c..1fb1b81132 100644 --- a/features/command/src/main/java/net/okocraft/box/feature/command/box/ItemInfoCommand.java +++ b/features/command/src/main/java/net/okocraft/box/feature/command/box/ItemInfoCommand.java @@ -5,11 +5,14 @@ import net.okocraft.box.api.command.AbstractCommand; import net.okocraft.box.api.message.GeneralMessage; import net.okocraft.box.api.model.item.BoxItem; +import net.okocraft.box.api.util.TabCompleter; import net.okocraft.box.feature.command.message.BoxMessage; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.util.Collections; +import java.util.List; import java.util.Set; public class ItemInfoCommand extends AbstractCommand { @@ -64,4 +67,13 @@ public void onCommand(@NotNull CommandSender sender, @NotNull String[] args) { public @NotNull Component getHelp() { return BoxMessage.ITEM_INFO_HELP; } + + @Override + public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull String[] args) { + if (args.length == 2) { + return TabCompleter.itemNames(args[1]); + } else { + return Collections.emptyList(); + } + } } From 7059f8c0cb1576794c2a24cc4f24bea200a74edc Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Tue, 21 Dec 2021 00:23:09 +0900 Subject: [PATCH 42/65] feat(craft): add RecipeImportEvent for debug --- .../craft/event/RecipeImportEvent.java | 27 +++++++++++++++++++ .../box/feature/craft/loader/Processor.java | 13 +++++---- 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 features/craft/src/main/java/net/okocraft/box/feature/craft/event/RecipeImportEvent.java diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/event/RecipeImportEvent.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/event/RecipeImportEvent.java new file mode 100644 index 0000000000..87ee1c2b5e --- /dev/null +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/event/RecipeImportEvent.java @@ -0,0 +1,27 @@ +package net.okocraft.box.feature.craft.event; + +import net.okocraft.box.api.event.BoxEvent; +import net.okocraft.box.feature.craft.model.BoxItemRecipe; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class RecipeImportEvent extends BoxEvent { + + private final BoxItemRecipe recipe; + + public RecipeImportEvent(@NotNull BoxItemRecipe recipe) { + this.recipe = Objects.requireNonNull(recipe); + } + + public @NotNull BoxItemRecipe getRecipe() { + return recipe; + } + + @Override + public String toString() { + return "RecipeImportEvent{" + + "recipe=" + recipe + + '}'; + } +} diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java index 165157236b..e233467ae0 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/Processor.java @@ -4,6 +4,7 @@ import net.okocraft.box.api.BoxProvider; import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.api.model.manager.ItemManager; +import net.okocraft.box.feature.craft.event.RecipeImportEvent; import net.okocraft.box.feature.craft.model.BoxItemRecipe; import net.okocraft.box.feature.craft.model.IngredientHolder; import net.okocraft.box.feature.craft.model.RecipeHolder; @@ -130,7 +131,7 @@ private void processShapedRecipe(@NotNull ShapedRecipe recipe, @NotNull BoxItem } } - getRecipeHolder(result).addRecipe(new BoxItemRecipe(ingredients, result, recipe.getResult().getAmount())); + addRecipe(ingredients, result, recipe.getResult().getAmount()); } private void processShapelessRecipe(@NotNull ShapelessRecipe recipe, @NotNull BoxItem result) { @@ -159,7 +160,7 @@ private void processShapelessRecipe(@NotNull ShapelessRecipe recipe, @NotNull Bo slot++; } - getRecipeHolder(result).addRecipe(new BoxItemRecipe(ingredients, result, recipe.getResult().getAmount())); + addRecipe(ingredients, result, recipe.getResult().getAmount()); } private void processCustomRecipe(@NotNull List ingredients, @NotNull BoxItem result, int amount) { @@ -171,7 +172,7 @@ private void processCustomRecipe(@NotNull List ingredients, @NotNull Bo slot++; } - getRecipeHolder(result).addRecipe(new BoxItemRecipe(ingredientHolders, result, amount)); + addRecipe(ingredientHolders, result, amount); } @Contract(pure = true) @@ -188,7 +189,9 @@ private int getPosition(char c, String @NotNull [] shape) { return 8; } - private @NotNull RecipeHolder getRecipeHolder(@NotNull BoxItem item) { - return recipeMap.computeIfAbsent(item, i -> new RecipeHolder()); + private void addRecipe(@NotNull List ingredients, @NotNull BoxItem result, int amount) { + var recipe = new BoxItemRecipe(ingredients, result, amount); + recipeMap.computeIfAbsent(result, i -> new RecipeHolder()).addRecipe(recipe); + BoxProvider.get().getEventBus().callEvent(new RecipeImportEvent(recipe)); } } From 1e106087cc13d5d39297b244253e444103632b48 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Tue, 21 Dec 2021 00:25:38 +0900 Subject: [PATCH 43/65] improve(craft): remove constant --- .../box/feature/craft/loader/AdditionalRecipes.java | 8 ++------ .../okocraft/box/feature/craft/loader/RecipeLoader.java | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/AdditionalRecipes.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/AdditionalRecipes.java index 76c7907fa0..cc761a0f62 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/AdditionalRecipes.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/AdditionalRecipes.java @@ -12,12 +12,8 @@ final class AdditionalRecipes { - static final List RECIPES; - - static { - RECIPES = List.of( - fireworkRocket(1), fireworkRocket(2), fireworkRocket(3) - ); + static @NotNull List getFireworkRocketRecipes() { + return List.of(fireworkRocket(1), fireworkRocket(2), fireworkRocket(3)); } private static @NotNull Recipe fireworkRocket(int power) { diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java index a82e516b42..1c5a68d78d 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/loader/RecipeLoader.java @@ -15,7 +15,7 @@ public final class RecipeLoader { Bukkit.recipeIterator().forEachRemaining(processor::processRecipe); - AdditionalRecipes.RECIPES.forEach(processor::processRecipe); + AdditionalRecipes.getFireworkRocketRecipes().forEach(processor::processRecipe); processor.processCustomRecipes(); From bd0c0d303aaad2fa2169738b2dbddf3af64b799a Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Tue, 21 Dec 2021 00:38:11 +0900 Subject: [PATCH 44/65] feat(craft): add BoxCraftEvent --- .../feature/craft/event/BoxCraftEvent.java | 80 +++++++++++++++++++ .../box/feature/craft/util/ItemCrafter.java | 8 ++ 2 files changed, 88 insertions(+) create mode 100644 features/craft/src/main/java/net/okocraft/box/feature/craft/event/BoxCraftEvent.java diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/event/BoxCraftEvent.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/event/BoxCraftEvent.java new file mode 100644 index 0000000000..305e53ac39 --- /dev/null +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/event/BoxCraftEvent.java @@ -0,0 +1,80 @@ +package net.okocraft.box.feature.craft.event; + +import com.github.siroshun09.event4j.event.Cancellable; +import net.okocraft.box.api.event.BoxEvent; +import net.okocraft.box.feature.craft.model.SelectedRecipe; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class BoxCraftEvent extends BoxEvent implements Cancellable { + + private final Player crafter; + private final SelectedRecipe selectedRecipe; + private final int times; + private boolean cancelled; + + public BoxCraftEvent(@NotNull Player crafter, @NotNull SelectedRecipe selectedRecipe, int times) { + this.crafter = Objects.requireNonNull(crafter); + this.selectedRecipe = Objects.requireNonNull(selectedRecipe); + this.times = times; + } + + /** + * Gets the player who is trying to craft. + * + * @return the player who is trying to craft + */ + public @NotNull Player getCrafter() { + return crafter; + } + + /** + * Gets the recipe to craft. + * + * @return the recipe to craft + */ + public @NotNull SelectedRecipe getSelectedRecipe() { + return selectedRecipe; + } + + /** + * Gets the number of times to craft. + * + * @return the number of times to craft + */ + public int getTimes() { + return times; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public String toString() { + return "BoxCraftEvent{" + + "crafter=" + crafter + + ", selectedRecipe=" + selectedRecipe + + ", times=" + times + + ", cancelled=" + cancelled + + '}'; + } + + @Override + public @NotNull String toDebugLog() { + return "BoxCraftEvent{" + + "crafterUuid=" + crafter.getUniqueId() + + ", crafterName=" + crafter.getName() + + ", selectedRecipe=" + selectedRecipe + + ", times=" + times + + '}'; + } +} diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java index 210b88dacd..82e59ae1a6 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/util/ItemCrafter.java @@ -4,6 +4,7 @@ import net.okocraft.box.api.model.item.BoxItem; import net.okocraft.box.api.model.stock.StockHolder; import net.okocraft.box.api.transaction.InventoryTransaction; +import net.okocraft.box.feature.craft.event.BoxCraftEvent; import net.okocraft.box.feature.craft.model.SelectedRecipe; import net.okocraft.box.feature.gui.api.session.PlayerSession; import org.bukkit.entity.Player; @@ -44,6 +45,13 @@ public static boolean craft(@NotNull Player crafter, @NotNull SelectedRecipe rec return false; } + var event = new BoxCraftEvent(crafter, recipe, times); + BoxProvider.get().getEventBus().callEvent(event); + + if (event.isCancelled()) { + return false; + } + for (var ingredient : recipe.ingredients()) { stockHolder.decrease(ingredient.item(), ingredient.amount() * times); } From f7a4a2c0d12108e813b7459ba708c554b9747c87 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Tue, 21 Dec 2021 00:41:41 +0900 Subject: [PATCH 45/65] feat(craft): log the number of recipes --- .../java/net/okocraft/box/feature/craft/CraftFeature.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java index 6f28b67c9e..bed497885f 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/CraftFeature.java @@ -44,7 +44,11 @@ public void enable() { BoxProvider.get().getLogger().log(Level.SEVERE, "Could not load recipes.yml", e); } - RecipeRegistry.setRecipeMap(RecipeLoader.load(recipeConfig)); + var recipeMap = RecipeLoader.load(recipeConfig); + + RecipeRegistry.setRecipeMap(recipeMap); + + BoxProvider.get().getLogger().info(recipeMap.size() + " recipes are imported!"); ClickModeRegistry.register(craftMode); From 6104e6fe74f7c7ab597cd6c80cb3d72bdc0b7bf1 Mon Sep 17 00:00:00 2001 From: Siroshun09 Date: Tue, 21 Dec 2021 02:15:48 +0900 Subject: [PATCH 46/65] feat(gui): what's xmas? --- .../box/feature/craft/menu/CraftMenu.java | 3 +- .../box/feature/gui/api/button/Button.java | 15 +++++++ .../box/feature/gui/api/util/MenuOpener.java | 7 +++- .../internal/menu/CategorySelectorMenu.java | 3 +- .../gui/internal/util/XmasChecker.java | 42 +++++++++++++++++++ 5 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 features/gui/src/main/java/net/okocraft/box/feature/gui/internal/util/XmasChecker.java diff --git a/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/CraftMenu.java b/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/CraftMenu.java index a7b24fe76b..ff164c8759 100644 --- a/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/CraftMenu.java +++ b/features/craft/src/main/java/net/okocraft/box/feature/craft/menu/CraftMenu.java @@ -18,7 +18,6 @@ import net.okocraft.box.feature.gui.api.menu.Menu; import net.okocraft.box.feature.gui.api.menu.RenderedButton; import net.okocraft.box.feature.gui.api.session.PlayerSession; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,7 +68,7 @@ public void updateMenu(@NotNull Player viewer) { for (int slot = 0, limit = getRows() * 9; slot < limit; slot++) { if (!RECIPE_SLOTS.contains(slot) && slot != 24) { - buttons.add(Button.empty(Material.GRAY_STAINED_GLASS_PANE, slot)); + buttons.add(Button.glassPane(slot)); } } diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/api/button/Button.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/api/button/Button.java index 5659b65245..0d40977ce0 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/api/button/Button.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/api/button/Button.java @@ -1,5 +1,6 @@ package net.okocraft.box.feature.gui.api.button; +import net.okocraft.box.feature.gui.internal.util.XmasChecker; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; @@ -9,6 +10,20 @@ public interface Button { + static @NotNull Button glassPane(int slot) { + Material material; + + if (XmasChecker.isXmas()) { + material = slot % 2 == 0 ? + Material.GREEN_STAINED_GLASS_PANE : + Material.RED_STAINED_GLASS_PANE; + } else { + material = Material.GRAY_STAINED_GLASS_PANE; + } + + return empty(material, slot); + } + static @NotNull Button empty(@NotNull Material material, int slot) { return new EmptyButton(material, slot); } diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/api/util/MenuOpener.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/api/util/MenuOpener.java index 0c69009050..b9f342c52c 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/api/util/MenuOpener.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/api/util/MenuOpener.java @@ -3,6 +3,7 @@ import net.okocraft.box.api.BoxProvider; import net.okocraft.box.feature.gui.api.menu.Menu; import net.okocraft.box.feature.gui.internal.holder.BoxInventoryHolder; +import net.okocraft.box.feature.gui.internal.util.XmasChecker; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -19,7 +20,11 @@ public static void open(@NotNull Menu menu, @NotNull Player viewer) { .run(() -> viewer.openInventory(holder.getInventory())) .join(); - viewer.playSound(viewer.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 100f, 2.0f); + if (XmasChecker.isXmas()) { + viewer.playSound(viewer.getLocation(), Sound.BLOCK_NOTE_BLOCK_CHIME, 100f, 1.8f); + } else { + viewer.playSound(viewer.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 100f, 2.0f); + } } private MenuOpener() { diff --git a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/menu/CategorySelectorMenu.java b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/menu/CategorySelectorMenu.java index da24019ef0..7664611408 100644 --- a/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/menu/CategorySelectorMenu.java +++ b/features/gui/src/main/java/net/okocraft/box/feature/gui/internal/menu/CategorySelectorMenu.java @@ -8,7 +8,6 @@ import net.okocraft.box.feature.gui.api.menu.paginate.AbstractPaginatedMenu; import net.okocraft.box.feature.gui.internal.button.CategoryButton; import net.okocraft.box.feature.gui.internal.lang.Displays; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; @@ -31,7 +30,7 @@ protected void addAdditionalButtons(@NotNull Player viewer, @NotNull List