001/* 002 * This file is part of Baritone. 003 * 004 * Baritone is free software: you can redistribute it and/or modify 005 * it under the terms of the GNU Lesser General Public License as published by 006 * the Free Software Foundation, either version 3 of the License, or 007 * (at your option) any later version. 008 * 009 * Baritone is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 * GNU Lesser General Public License for more details. 013 * 014 * You should have received a copy of the GNU Lesser General Public License 015 * along with Baritone. If not, see <https://www.gnu.org/licenses/>. 016 */ 017 018package baritone.api.command.helpers; 019 020import baritone.api.command.argument.IArgConsumer; 021import baritone.api.command.exception.CommandException; 022import baritone.api.command.exception.CommandInvalidTypeException; 023import baritone.api.utils.Helper; 024 025import java.awt.*; 026import java.util.Arrays; 027import java.util.List; 028import java.util.function.Function; 029import net.minecraft.ChatFormatting; 030import net.minecraft.network.chat.ClickEvent; 031import net.minecraft.network.chat.Component; 032import net.minecraft.network.chat.HoverEvent; 033import net.minecraft.network.chat.MutableComponent; 034 035public class Paginator<E> implements Helper { 036 037 public final List<E> entries; 038 public int pageSize = 8; 039 public int page = 1; 040 041 public Paginator(List<E> entries) { 042 this.entries = entries; 043 } 044 045 public Paginator(E... entries) { 046 this.entries = Arrays.asList(entries); 047 } 048 049 public Paginator<E> setPageSize(int pageSize) { 050 this.pageSize = pageSize; 051 return this; 052 } 053 054 public int getMaxPage() { 055 return (entries.size() - 1) / pageSize + 1; 056 } 057 058 public boolean validPage(int page) { 059 return page > 0 && page <= getMaxPage(); 060 } 061 062 public Paginator<E> skipPages(int pages) { 063 page += pages; 064 return this; 065 } 066 067 public void display(Function<E, Component> transform, String commandPrefix) { 068 int offset = (page - 1) * pageSize; 069 for (int i = offset; i < offset + pageSize; i++) { 070 if (i < entries.size()) { 071 logDirect(transform.apply(entries.get(i))); 072 } else { 073 logDirect("--", ChatFormatting.DARK_GRAY); 074 } 075 } 076 boolean hasPrevPage = commandPrefix != null && validPage(page - 1); 077 boolean hasNextPage = commandPrefix != null && validPage(page + 1); 078 MutableComponent prevPageComponent = Component.literal("<<"); 079 if (hasPrevPage) { 080 prevPageComponent.setStyle(prevPageComponent.getStyle() 081 .withClickEvent(new ClickEvent( 082 ClickEvent.Action.RUN_COMMAND, 083 String.format("%s %d", commandPrefix, page - 1) 084 )) 085 .withHoverEvent(new HoverEvent( 086 HoverEvent.Action.SHOW_TEXT, 087 Component.literal("Click to view previous page") 088 ))); 089 } else { 090 prevPageComponent.setStyle(prevPageComponent.getStyle().withColor(ChatFormatting.DARK_GRAY)); 091 } 092 MutableComponent nextPageComponent = Component.literal(">>"); 093 if (hasNextPage) { 094 nextPageComponent.setStyle(nextPageComponent.getStyle() 095 .withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("%s %d", commandPrefix, page + 1))) 096 .withHoverEvent(new HoverEvent( 097 HoverEvent.Action.SHOW_TEXT, 098 Component.literal("Click to view next page") 099 ))); 100 } else { 101 nextPageComponent.setStyle(nextPageComponent.getStyle().withColor(ChatFormatting.DARK_GRAY)); 102 } 103 MutableComponent pagerComponent = Component.literal(""); 104 pagerComponent.setStyle(pagerComponent.getStyle().withColor(ChatFormatting.GRAY)); 105 pagerComponent.append(prevPageComponent); 106 pagerComponent.append(" | "); 107 pagerComponent.append(nextPageComponent); 108 pagerComponent.append(String.format(" %d/%d", page, getMaxPage())); 109 logDirect(pagerComponent); 110 } 111 112 public void display(Function<E, Component> transform) { 113 display(transform, null); 114 } 115 116 public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Runnable pre, Function<T, Component> transform, String commandPrefix) throws CommandException { 117 int page = 1; 118 consumer.requireMax(1); 119 if (consumer.hasAny()) { 120 page = consumer.getAs(Integer.class); 121 if (!pagi.validPage(page)) { 122 throw new CommandInvalidTypeException( 123 consumer.consumed(), 124 String.format( 125 "a valid page (1-%d)", 126 pagi.getMaxPage() 127 ), 128 consumer.consumed().getValue() 129 ); 130 } 131 } 132 pagi.skipPages(page - pagi.page); 133 if (pre != null) { 134 pre.run(); 135 } 136 pagi.display(transform, commandPrefix); 137 } 138 139 public static <T> void paginate(IArgConsumer consumer, List<T> elems, Runnable pre, Function<T, Component> transform, String commandPrefix) throws CommandException { 140 paginate(consumer, new Paginator<>(elems), pre, transform, commandPrefix); 141 } 142 143 public static <T> void paginate(IArgConsumer consumer, T[] elems, Runnable pre, Function<T, Component> transform, String commandPrefix) throws CommandException { 144 paginate(consumer, Arrays.asList(elems), pre, transform, commandPrefix); 145 } 146 147 public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Function<T, Component> transform, String commandPrefix) throws CommandException { 148 paginate(consumer, pagi, null, transform, commandPrefix); 149 } 150 151 public static <T> void paginate(IArgConsumer consumer, List<T> elems, Function<T, Component> transform, String commandPrefix) throws CommandException { 152 paginate(consumer, new Paginator<>(elems), null, transform, commandPrefix); 153 } 154 155 public static <T> void paginate(IArgConsumer consumer, T[] elems, Function<T, Component> transform, String commandPrefix) throws CommandException { 156 paginate(consumer, Arrays.asList(elems), null, transform, commandPrefix); 157 } 158 159 public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Runnable pre, Function<T, Component> transform) throws CommandException { 160 paginate(consumer, pagi, pre, transform, null); 161 } 162 163 public static <T> void paginate(IArgConsumer consumer, List<T> elems, Runnable pre, Function<T, Component> transform) throws CommandException { 164 paginate(consumer, new Paginator<>(elems), pre, transform, null); 165 } 166 167 public static <T> void paginate(IArgConsumer consumer, T[] elems, Runnable pre, Function<T, Component> transform) throws CommandException { 168 paginate(consumer, Arrays.asList(elems), pre, transform, null); 169 } 170 171 public static <T> void paginate(IArgConsumer consumer, Paginator<T> pagi, Function<T, Component> transform) throws CommandException { 172 paginate(consumer, pagi, null, transform, null); 173 } 174 175 public static <T> void paginate(IArgConsumer consumer, List<T> elems, Function<T, Component> transform) throws CommandException { 176 paginate(consumer, new Paginator<>(elems), null, transform, null); 177 } 178 179 public static <T> void paginate(IArgConsumer consumer, T[] elems, Function<T, Component> transform) throws CommandException { 180 paginate(consumer, Arrays.asList(elems), null, transform, null); 181 } 182}