diff --git a/api/src/main/java/broccolai/tags/api/service/ActionService.java b/api/src/main/java/broccolai/tags/api/service/ActionService.java new file mode 100644 index 0000000..09f0f8d --- /dev/null +++ b/api/src/main/java/broccolai/tags/api/service/ActionService.java @@ -0,0 +1,13 @@ +package broccolai.tags.api.service; + +import broccolai.tags.api.model.tag.ConstructedTag; +import broccolai.tags.api.model.user.TagsUser; +import org.checkerframework.checker.nullness.qual.NonNull; + +public interface ActionService { + + boolean select(@NonNull TagsUser user, @NonNull ConstructedTag tag); + + void remove(@NonNull TagsUser user); + +} diff --git a/bukkit/src/main/java/broccolai/tags/bukkit/menu/TagsMenuFactory.java b/bukkit/src/main/java/broccolai/tags/bukkit/menu/TagsMenuFactory.java index 771a97f..c8c39fb 100644 --- a/bukkit/src/main/java/broccolai/tags/bukkit/menu/TagsMenuFactory.java +++ b/bukkit/src/main/java/broccolai/tags/bukkit/menu/TagsMenuFactory.java @@ -3,46 +3,81 @@ import broccolai.corn.paper.item.PaperItemBuilder; import broccolai.tags.api.model.tag.ConstructedTag; import broccolai.tags.api.model.user.TagsUser; +import broccolai.tags.api.service.ActionService; import broccolai.tags.api.service.TagsService; +import broccolai.tags.core.config.LocaleConfiguration; +import broccolai.tags.core.util.FormatingUtilites; import com.google.inject.Inject; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.checkerframework.checker.nullness.qual.NonNull; +import org.incendo.interfaces.core.click.ClickHandler; import org.incendo.interfaces.core.transform.types.PaginatedTransform; import org.incendo.interfaces.core.util.Vector2; +import org.incendo.interfaces.core.view.InterfaceView; import org.incendo.interfaces.paper.PlayerViewer; import org.incendo.interfaces.paper.element.ItemStackElement; import org.incendo.interfaces.paper.pane.ChestPane; import org.incendo.interfaces.paper.type.ChestInterface; import org.slf4j.Logger; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; public final class TagsMenuFactory { + private static final ItemStackElement BOTTOM_BAR_ELEMENT = new ItemStackElement<>( + PaperItemBuilder.ofType(Material.WHITE_STAINED_GLASS_PANE) + .name(Component.empty()) + .build(), + ClickHandler.cancel() + ); + private final Logger logger; private final TagsService tagsService; + private final ActionService actionService; + private final LocaleConfiguration.MenuLocaleConfiguration locale; @Inject public TagsMenuFactory( final @NonNull Logger logger, - final @NonNull TagsService tagsService + final @NonNull TagsService tagsService, + final @NonNull ActionService actionService, + final @NonNull LocaleConfiguration locale ) { this.logger = logger; this.tagsService = tagsService; + this.actionService = actionService; + this.locale = locale.menu; } public ChestInterface create(final @NonNull TagsUser user) { return ChestInterface.builder() + .title(this.locale.title.asComponent()) .rows(4) + .addTransform(this::createFillTransform) .addReactiveTransform(this.createTagTransform(user)) .build(); } + private ChestPane createFillTransform(ChestPane pane, InterfaceView view) { + ChestPane result = pane; + + for (int i = 0; i < 9; i++) { + result = result.element(BOTTOM_BAR_ELEMENT, i, 3); + } + + return result; + } + private PaginatedTransform, ChestPane, PlayerViewer> createTagTransform(final @NonNull TagsUser user) { return new PaginatedTransform<>( Vector2.at(0, 0), - Vector2.at(8, 3), + Vector2.at(8, 2), () -> this.createTagElements(user) ); } @@ -50,17 +85,40 @@ private PaginatedTransform, ChestPane, PlayerViewer> private List> createTagElements(final @NonNull TagsUser user) { return this.tagsService.allTags(user) .stream() - .map(this::createTagElement) + .map((tag) -> createTagElement(user, tag)) .toList(); } - private ItemStackElement createTagElement(final @NonNull ConstructedTag tag) { + private ItemStackElement createTagElement(final @NonNull TagsUser user, final @NonNull ConstructedTag tag) { + + Material material = matchMaterialOrDefault(tag.displayInformation().material()); ItemStack item = PaperItemBuilder.ofType(material) .name(tag.component()) + .lore(this.createTagLore(tag)) .build(); - return ItemStackElement.of(item); + return ItemStackElement.of(item, (ctx) -> { + this.actionService.select(user, tag); + }); + } + + private List createTagLore(final @NonNull ConstructedTag tag) { + List result = new ArrayList<>(); + + result.addAll(formatTagReason(tag.reason())); + + result.add(Component.empty()); + result.add(this.locale.equip.asComponent()); + + return result; + } + + private List formatTagReason(final @NonNull String reason) { + return FormatingUtilites.splitString(reason, 30) + .stream() + .map((text) -> Component.text(text, NamedTextColor.WHITE)) + .collect(Collectors.toList()); } private Material matchMaterialOrDefault(final @NonNull String input) { diff --git a/core/src/main/java/broccolai/tags/core/commands/TagsCommand.java b/core/src/main/java/broccolai/tags/core/commands/TagsCommand.java index e4bf5e9..5068461 100644 --- a/core/src/main/java/broccolai/tags/core/commands/TagsCommand.java +++ b/core/src/main/java/broccolai/tags/core/commands/TagsCommand.java @@ -3,6 +3,7 @@ import broccolai.tags.api.events.event.TagChangeEvent; import broccolai.tags.api.model.tag.ConstructedTag; import broccolai.tags.api.model.user.TagsUser; +import broccolai.tags.api.service.ActionService; import broccolai.tags.api.service.EventService; import broccolai.tags.api.service.MessageService; import broccolai.tags.api.service.TagsService; @@ -24,7 +25,7 @@ public final class TagsCommand implements PluginCommand { private final @NonNull MessageService messageService; private final @NonNull UserService userService; private final @NonNull TagsService tagsService; - private final @NonNull EventService eventService; + private final @NonNull ActionService actionService; @Inject public TagsCommand( @@ -32,13 +33,13 @@ public TagsCommand( final @NonNull MessageService messageService, final @NonNull UserService userService, final @NonNull TagsService tagsService, - final @NonNull EventService eventService + final @NonNull ActionService actionService ) { this.argumentFactory = argumentFactory; this.messageService = messageService; this.userService = userService; this.tagsService = tagsService; - this.eventService = eventService; + this.actionService = actionService; } @Override @@ -73,10 +74,9 @@ private void handleSelect(final @NonNull CommandContext context) { TagsUser user = this.userService.get(sender.uuid()); ConstructedTag tag = context.get("tag"); - TagChangeEvent event = new TagChangeEvent(user, tag); - this.eventService.post(event); + boolean success = this.actionService.select(user, tag); - if (!event.cancelled()) { + if (success) { sender.sendMessage(this.messageService.commandSelect(tag)); } } diff --git a/core/src/main/java/broccolai/tags/core/config/LocaleConfiguration.java b/core/src/main/java/broccolai/tags/core/config/LocaleConfiguration.java index af7df59..b227539 100644 --- a/core/src/main/java/broccolai/tags/core/config/LocaleConfiguration.java +++ b/core/src/main/java/broccolai/tags/core/config/LocaleConfiguration.java @@ -23,6 +23,10 @@ public final class LocaleConfiguration implements Configuration { @Comment("Locales for command feedback related messages") public FeedbackLocaleConfiguration commands = new FeedbackLocaleConfiguration(); + @Setting + @Comment("Locales for menu related translations") + public MenuLocaleConfiguration menu = new MenuLocaleConfiguration(); + @ConfigSerializable public static final class FeedbackLocaleConfiguration { @@ -83,6 +87,17 @@ public static final class ErrorLocaleConfiguration { } + @ConfigSerializable + public static final class MenuLocaleConfiguration { + + @Setting + public LocaleEntry title = new BasicLocaleEntry("Tags Menu"); + + @Setting + public LocaleEntry equip = new BasicLocaleEntry("Left click to equip"); + + } + //region Configurate private static final @NonNull ObjectMapper MAPPER; diff --git a/core/src/main/java/broccolai/tags/core/inject/ServiceModule.java b/core/src/main/java/broccolai/tags/core/inject/ServiceModule.java index fafc774..077501f 100644 --- a/core/src/main/java/broccolai/tags/core/inject/ServiceModule.java +++ b/core/src/main/java/broccolai/tags/core/inject/ServiceModule.java @@ -1,11 +1,13 @@ package broccolai.tags.core.inject; +import broccolai.tags.api.service.ActionService; import broccolai.tags.api.service.DataService; import broccolai.tags.api.service.EventService; import broccolai.tags.api.service.MessageService; import broccolai.tags.api.service.TagsService; import broccolai.tags.core.config.MainConfiguration; import broccolai.tags.core.data.StorageMethod; +import broccolai.tags.core.service.action.EventActionService; import broccolai.tags.core.service.data.LPDataService; import broccolai.tags.core.service.data.H2DataService; import broccolai.tags.core.service.event.ASMEventService; @@ -26,6 +28,7 @@ protected void configure() { this.bind(MessageService.class).to(MiniMessageService.class); this.bind(TagsService.class).to(MappedTagsService.class); this.bind(EventService.class).to(ASMEventService.class); + this.bind(ActionService.class).to(EventActionService.class); } @Provides diff --git a/core/src/main/java/broccolai/tags/core/service/action/EventActionService.java b/core/src/main/java/broccolai/tags/core/service/action/EventActionService.java new file mode 100644 index 0000000..4492738 --- /dev/null +++ b/core/src/main/java/broccolai/tags/core/service/action/EventActionService.java @@ -0,0 +1,33 @@ +package broccolai.tags.core.service.action; + +import broccolai.tags.api.events.event.TagChangeEvent; +import broccolai.tags.api.model.tag.ConstructedTag; +import broccolai.tags.api.model.user.TagsUser; +import broccolai.tags.api.service.ActionService; +import broccolai.tags.api.service.EventService; +import com.google.inject.Inject; +import org.checkerframework.checker.nullness.qual.NonNull; + +public final class EventActionService implements ActionService { + + private final EventService eventService; + + @Inject + public EventActionService(final @NonNull EventService eventService) { + this.eventService = eventService; + } + + @Override + public boolean select(final @NonNull TagsUser user, final @NonNull ConstructedTag tag) { + TagChangeEvent event = new TagChangeEvent(user, tag); + this.eventService.post(event); + + return event.cancelled(); + } + + @Override + public void remove(final @NonNull TagsUser user) { + + } + +} diff --git a/core/src/main/java/broccolai/tags/core/subscribers/TagChangeSubscriber.java b/core/src/main/java/broccolai/tags/core/subscribers/TagChangeSubscriber.java index 5d39d6d..d0a00c0 100644 --- a/core/src/main/java/broccolai/tags/core/subscribers/TagChangeSubscriber.java +++ b/core/src/main/java/broccolai/tags/core/subscribers/TagChangeSubscriber.java @@ -11,7 +11,7 @@ public final class TagChangeSubscriber implements EventListener { @Subscribe @PostOrder(PostOrders.LAST) - public void onTagChance(final @NonNull TagChangeEvent event) { + public void onTagChange(final @NonNull TagChangeEvent event) { event.user().setCurrent(event.tag()); } diff --git a/core/src/main/java/broccolai/tags/core/util/FormatingUtilites.java b/core/src/main/java/broccolai/tags/core/util/FormatingUtilites.java new file mode 100644 index 0000000..00be6a3 --- /dev/null +++ b/core/src/main/java/broccolai/tags/core/util/FormatingUtilites.java @@ -0,0 +1,31 @@ +package broccolai.tags.core.util; + +import java.util.ArrayList; +import java.util.List; + +public final class FormatingUtilites { + + public static List splitString(String input, int maxLength) { + List lines = new ArrayList<>(); + StringBuilder currentLine = new StringBuilder(); + + String[] words = input.split(" "); + + for (String word : words) { + if (currentLine.length() + word.length() + 1 <= maxLength) { + if (!currentLine.isEmpty()) { + currentLine.append(" "); + } + currentLine.append(word); + } else { + lines.add(currentLine.toString()); + currentLine = new StringBuilder(word); + } + } + + lines.add(currentLine.toString()); + + return lines; + } + +}