diff --git a/Pagination/src/main/java/fr/altarik/toolbox/pagination/PaginatedContent.java b/Pagination/src/main/java/fr/altarik/toolbox/pagination/PaginatedContent.java index 50eb02c..706605f 100644 --- a/Pagination/src/main/java/fr/altarik/toolbox/pagination/PaginatedContent.java +++ b/Pagination/src/main/java/fr/altarik/toolbox/pagination/PaginatedContent.java @@ -1,9 +1,71 @@ package fr.altarik.toolbox.pagination; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.text.ClickEvent; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + public class PaginatedContent { + private final List pages; + private final String header; + public PaginatedContent(String header, String content) { - // TODO: 19/03/2023 + this.header = header; + pages = new ArrayList<>(); + List secondSplit = new ArrayList<>(); + for(String elem : Stream.of(content.split("\n")).collect(Collectors.toCollection(ArrayList::new))) { + if(elem.length() > 50) { + secondSplit.add(elem.substring(0, 50)); + secondSplit.add(elem.substring(51, elem.length() - 1)); + } else { + secondSplit.add(elem); + } + } + int line = 0; + List currentPage = new ArrayList<>(); + for(String elem : secondSplit) { + line++; + currentPage.add(elem); + if(line == 8 || elem.isEmpty()) { + pages.add(new Page(currentPage)); + line = 0; + currentPage = new ArrayList<>(); + } + } + } + + public void display(ServerPlayerEntity playerEntity, int page) { + if(page >= this.pages.size()) { + throw new IllegalArgumentException("There's " + this.pages.size() + " paginated pages but you wanted page n°" + page); + } else if(page < 0) { + throw new IllegalArgumentException("argument page is lower than 0"); + } else { + playerEntity.sendMessage(Text.literal(header)); + for(String s : pages.get(page).lines) { + playerEntity.sendMessage(Text.literal(s)); + } + MutableText left = Text.literal("<").styled( + style -> style + .withColor(Formatting.YELLOW) + .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/table page " + (page - 1))) + ); + MutableText right = Text.literal(">").styled( + style -> style + .withColor(Formatting.YELLOW) + .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/table page " + (page + 1))) + ); + playerEntity.sendMessage(left.append(" " + page + " ").append(right)); + } + } + + private record Page(List lines) { } } diff --git a/Pagination/src/main/java/fr/altarik/toolbox/pagination/Pagination.java b/Pagination/src/main/java/fr/altarik/toolbox/pagination/Pagination.java index 009e005..8e4b19e 100644 --- a/Pagination/src/main/java/fr/altarik/toolbox/pagination/Pagination.java +++ b/Pagination/src/main/java/fr/altarik/toolbox/pagination/Pagination.java @@ -19,7 +19,7 @@ public class Pagination implements ModInitializer { @Override public void onInitialize() { - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> new CommandsRegister().register(dispatcher, environment.dedicated)); + CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> new CommandsRegister(this).register(dispatcher, environment.dedicated)); } public @NotNull PaginationApi getApi() { diff --git a/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApi.java b/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApi.java index 36f4f07..34f8f23 100644 --- a/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApi.java +++ b/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApi.java @@ -23,4 +23,14 @@ public interface PaginationApi { */ void createTable(ServerPlayerEntity playerEntity, String content, String header); + /** + * Display the given page for the given player + * @param player display the content of this player + * @param page display this page + * @throws IllegalArgumentException if page is invalid + * @throws NullPointerException if player is null or paginated content for the player doesn't exist (or have expired) + * @see fr.altarik.toolbox.pagination.PaginatedContent#display(ServerPlayerEntity, int) + */ + void display(ServerPlayerEntity player, int page); + } diff --git a/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApiImpl.java b/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApiImpl.java index 93e7972..8a2abf9 100644 --- a/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApiImpl.java +++ b/Pagination/src/main/java/fr/altarik/toolbox/pagination/api/PaginationApiImpl.java @@ -4,10 +4,14 @@ import fr.altarik.toolbox.pagination.PaginatedContent; import fr.altarik.toolbox.pagination.precondition.ContentCondition; import fr.altarik.toolbox.pagination.precondition.HeaderCondition; import fr.altarik.toolbox.pagination.precondition.NullPlayerCondition; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Pair; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.function.Predicate; @@ -15,15 +19,46 @@ public class PaginationApiImpl implements PaginationApi { /** * Integer represent relative tts of the paginated content, decreased by 1 every seconds */ - private final Map> paginatedContent = new HashMap<>(); + public final Map> paginatedContent = new HashMap<>(); private final Predicate playerCondition = new NullPlayerCondition().negate(); private final Predicate headerCondition = new HeaderCondition().negate(); private final Predicate contentCondition = new ContentCondition().negate(); + + public PaginationApiImpl() { + ServerTickEvents.START_SERVER_TICK.register(this::serverTick); + } + @Override public void createTable(ServerPlayerEntity playerEntity, String content, String header) { if(playerCondition.test(playerEntity) || headerCondition.test(header) || contentCondition.test(content)) { throw new IllegalArgumentException("Preconditions aren't satisfied"); } - paginatedContent.put(playerEntity, new Pair<>(900, new PaginatedContent(header, content))); + PaginatedContent paginatedContent1 = new PaginatedContent(header, content); + paginatedContent.put(playerEntity, new Pair<>(18000, paginatedContent1)); + paginatedContent1.display(playerEntity, 0); + } + + @Override + public void display(ServerPlayerEntity player, int page) { + if(player == null) + throw new NullPointerException("Player is null"); + Pair pair = paginatedContent.get(player); + if(pair == null) + throw new NullPointerException("No paginated page for player " + player.getCustomName()); + pair.getRight().display(player, page); + } + + private void serverTick(MinecraftServer server) { + List toRemove = new ArrayList<>(); + for(Map.Entry> content : paginatedContent.entrySet()) { + if(content.getValue().getLeft() == 0) { + toRemove.add(content.getKey()); + } else { + content.getValue().setLeft(content.getValue().getLeft() - 1); + } + } + for(ServerPlayerEntity player : toRemove) { + paginatedContent.remove(player); + } } } diff --git a/Pagination/src/main/java/fr/altarik/toolbox/pagination/command/CommandsRegister.java b/Pagination/src/main/java/fr/altarik/toolbox/pagination/command/CommandsRegister.java index ae295a4..fa01f2e 100644 --- a/Pagination/src/main/java/fr/altarik/toolbox/pagination/command/CommandsRegister.java +++ b/Pagination/src/main/java/fr/altarik/toolbox/pagination/command/CommandsRegister.java @@ -2,19 +2,42 @@ package fr.altarik.toolbox.pagination.command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import fr.altarik.toolbox.pagination.Pagination; +import fr.altarik.toolbox.pagination.api.PaginationApi; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.text.Text; import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class CommandsRegister { + private final PaginationApi api; + + public CommandsRegister(Pagination instance) { + this.api = instance.getApi(); + } + public void register(CommandDispatcher dispatcher, boolean dedicated) { dispatcher.register(literal("table") .then(literal("page") - .then(argument("page", IntegerArgumentType.integer())) + .then(argument("page", IntegerArgumentType.integer()) + .executes(this::selectPageCommand) + ) ) ); } + private int selectPageCommand(CommandContext context) throws CommandSyntaxException { + try { + int page = IntegerArgumentType.getInteger(context, "page"); + api.display(context.getSource().getPlayerOrThrow(), page); + } catch(NullPointerException | IllegalArgumentException e) { + context.getSource().sendFeedback(Text.literal("Error: " + e.getMessage()), false); + } + return 0; + } + }