1+ package me .retucio .sputnik .module .modules .misc ;
2+
3+ import me .retucio .sputnik .event .SubscribeEvent ;
4+ import me .retucio .sputnik .event .events .network .DisconnectEvent ;
5+ import me .retucio .sputnik .module .Category ;
6+ import me .retucio .sputnik .module .Module ;
7+ import me .retucio .sputnik .module .setting .SettingGroup ;
8+ import me .retucio .sputnik .module .setting .settings .BooleanSetting ;
9+ import me .retucio .sputnik .module .setting .settings .NumberSetting ;
10+ import me .retucio .sputnik .module .setting .settings .StringSetting ;
11+ import me .retucio .sputnik .util .ChatUtil ;
12+ import me .retucio .sputnik .util .InventoryUtil ;
13+ import net .minecraft .client .font .TextHandler ;
14+ import net .minecraft .component .DataComponentTypes ;
15+ import net .minecraft .component .type .WritableBookContentComponent ;
16+ import net .minecraft .component .type .WrittenBookContentComponent ;
17+ import net .minecraft .item .ItemStack ;
18+ import net .minecraft .item .Items ;
19+ import net .minecraft .network .packet .c2s .play .BookUpdateC2SPacket ;
20+ import net .minecraft .text .*;
21+
22+ import java .util .ArrayList ;
23+ import java .util .List ;
24+ import java .util .Optional ;
25+ import java .util .PrimitiveIterator ;
26+ import java .util .Random ;
27+ import java .util .function .Predicate ;
28+
29+
30+ public class BookBot extends Module {
31+
32+ private final SettingGroup sgBook = addSg (new SettingGroup ("libro" , true ));
33+
34+ private final NumberSetting delay = sgGeneral .add (new NumberSetting (
35+ "delay" ,
36+ "delay entre la escritura de libros" ,
37+ 20 ,
38+ 1 ,
39+ 200 ,
40+ 1
41+ ));
42+
43+ private final BooleanSetting toggleOnDisconnect = sgGeneral .add (new BooleanSetting (
44+ "desactivar al desconectarse" ,
45+ "." ,
46+ true
47+ ));
48+
49+ private final StringSetting name = sgBook .add (new StringSetting (
50+ "nombre" ,
51+ "nombre a usar para los libros" ,
52+ "mortadela y filetón" ,
53+ 100
54+ ));
55+
56+ private final BooleanSetting count = sgBook .add (new BooleanSetting (
57+ "contar" ,
58+ "contar los libros y añadir el número al final del nombre" ,
59+ true
60+ ));
61+
62+ private final NumberSetting pages = sgBook .add (new NumberSetting (
63+ "páginas" ,
64+ "número de páginas a llenar con mierda" ,
65+ 50 ,
66+ 1 ,
67+ 100 ,
68+ 1
69+ ));
70+
71+ private final BooleanSetting sign = sgBook .add (new BooleanSetting (
72+ "firmar" ,
73+ "firmar el libro" ,
74+ true
75+ ));
76+
77+ private final BooleanSetting onlyAscii = sgBook .add (new BooleanSetting (
78+ "solo ascii" ,
79+ "usar solamente caracteres ascii" ,
80+ false
81+ ));
82+
83+ private int delayTimer , bookCount ;
84+ private Random random ;
85+
86+ public BookBot () {
87+ super ("j. k. rowling" , "rellena libros con caca" , Category .MISC );
88+ }
89+
90+ @ Override
91+ public void onEnable () {
92+ random = new Random ();
93+ delayTimer = delay .getIntValue ();
94+ bookCount = 0 ;
95+ super .onEnable ();
96+ }
97+
98+ @ Override
99+ public void onTick () {
100+ if (mc .player == null ) return ;
101+
102+ Predicate <ItemStack > bookPredicate = stack -> {
103+ WritableBookContentComponent component = stack .get (DataComponentTypes .WRITABLE_BOOK_CONTENT );
104+ return stack .getItem () == Items .WRITABLE_BOOK && (component == null || component .pages ().isEmpty ());
105+ };
106+
107+ ItemStack book = InventoryUtil .find (bookPredicate );
108+ if (book == null ) {
109+ ChatUtil .warn ("no se encontró ningún libro" );
110+ toggle ();
111+ return ;
112+ }
113+
114+ if (mc .player .getMainHandStack () != book ) {
115+ InventoryUtil .swapWithHotbar (
116+ mc .player .getInventory ().getSlotWithStack (book ),
117+ mc .player .getInventory ().getSelectedSlot ()
118+ );
119+ }
120+
121+ if (delayTimer > 0 ) {
122+ delayTimer --;
123+ return ;
124+ }
125+
126+ delayTimer = delay .getIntValue ();
127+
128+ int origin = onlyAscii .getValue () ? 0x21 : 0x0800 ;
129+ int bound = onlyAscii .getValue () ? 0x7E : 0x10FFFF ;
130+
131+ writeBook (random .ints (origin , bound )
132+ .filter (i -> !Character .isWhitespace (i )
133+ && i != '\r' && i != '\n' )
134+ .iterator ()
135+ );
136+ }
137+
138+ @ SubscribeEvent
139+ private void onDisconnect (DisconnectEvent event ) {
140+ if (toggleOnDisconnect .getValue ()) {
141+ toggle ();
142+ }
143+ }
144+
145+ private void writeBook (PrimitiveIterator .OfInt chars ) {
146+ ArrayList <String > pages = new ArrayList <>();
147+ ArrayList <RawFilteredPair <Text >> filteredPages = new ArrayList <>();
148+ int maxPages = this .pages .getIntValue ();
149+
150+ TextHandler .WidthRetriever widthRetriever = mc .textRenderer .getTextHandler ().widthRetriever ;
151+ int pageIndex = 0 ;
152+ int lineIndex = 0 ;
153+ final StringBuilder page = new StringBuilder ();
154+ float lineWidth = 0 ;
155+
156+ while (chars .hasNext () && pageIndex < maxPages ) {
157+ int c = chars .nextInt ();
158+
159+ if (c == '\r' || c == '\n' ) {
160+ page .append ('\n' );
161+ lineWidth = 0 ;
162+ lineIndex ++;
163+ } else {
164+ float charWidth = widthRetriever .getWidth (c , Style .EMPTY );
165+
166+ if (lineWidth + charWidth > 114f ) {
167+ page .append ('\n' );
168+ lineWidth = charWidth ;
169+ lineIndex ++;
170+ if (lineIndex != 14 ) page .appendCodePoint (c );
171+ } else if (lineWidth == 0f && c == ' ' ) {
172+ continue ;
173+ } else {
174+ lineWidth += charWidth ;
175+ page .appendCodePoint (c );
176+ }
177+ }
178+
179+ if (lineIndex == 14 ) {
180+ filteredPages .add (RawFilteredPair .of (Text .of (page .toString ())));
181+ pages .add (page .toString ());
182+ page .setLength (0 );
183+ pageIndex ++;
184+ lineIndex = 0 ;
185+ lineWidth = 0 ;
186+ }
187+ }
188+
189+ if (!page .isEmpty () && pageIndex < maxPages ) {
190+ filteredPages .add (RawFilteredPair .of (Text .of (page .toString ())));
191+ pages .add (page .toString ());
192+ }
193+
194+ if (bookCount > 0 ) {
195+ ChatUtil .info ("creado libro n. " + bookCount );
196+ }
197+
198+ createBook (pages , filteredPages );
199+ }
200+
201+ private void processLinesToPages (List <StringVisitable > lines , ArrayList <String > pages , ArrayList <RawFilteredPair <Text >> filteredPages , int maxPages ) {
202+ int pageIndex = 0 ;
203+ int lineIndex = 0 ;
204+ StringBuilder currentPage = new StringBuilder ();
205+
206+ for (StringVisitable line : lines ) {
207+ String lineText = line .getString ();
208+
209+ if (!currentPage .isEmpty ()) {
210+ currentPage .append ('\n' );
211+ }
212+
213+ currentPage .append (lineText );
214+ lineIndex ++;
215+
216+ if (lineIndex == 14 ) {
217+ filteredPages .add (RawFilteredPair .of (Text .of (currentPage .toString ())));
218+ pages .add (currentPage .toString ());
219+ currentPage .setLength (0 );
220+ pageIndex ++;
221+ lineIndex = 0 ;
222+
223+ if (pageIndex == maxPages ) break ;
224+ }
225+ }
226+
227+ if (!currentPage .isEmpty () && pageIndex < maxPages ) {
228+ filteredPages .add (RawFilteredPair .of (Text .of (currentPage .toString ())));
229+ pages .add (currentPage .toString ());
230+ }
231+ }
232+
233+ private void createBook (ArrayList <String > pages , ArrayList <RawFilteredPair <Text >> filteredPages ) {
234+ String title = name .getValue ();
235+ if (count .getValue () && bookCount != 0 ) title += " #" + bookCount ;
236+
237+ mc .player .getMainHandStack ().set (DataComponentTypes .WRITTEN_BOOK_CONTENT , new WrittenBookContentComponent (
238+ RawFilteredPair .of (title ),
239+ mc .player .getGameProfile ().name (),
240+ 0 ,
241+ filteredPages ,
242+ true
243+ ));
244+
245+ mc .player .networkHandler .sendPacket (new BookUpdateC2SPacket (
246+ mc .player .getInventory ().getSelectedSlot (),
247+ pages ,
248+ sign .getValue ()
249+ ? Optional .of (title )
250+ : Optional .empty ()
251+ ));
252+
253+ bookCount ++;
254+ }
255+ }
0 commit comments