11package com .deflanko .MCCFishingMessages ;
22
33import com .deflanko .MCCFishingMessages .config .Config ;
4+ import com .deflanko .MCCFishingMessages .config .ConfigManager ;
45import net .minecraft .client .MinecraftClient ;
56import net .minecraft .client .gui .DrawContext ;
7+ import net .minecraft .client .gui .hud .ChatHudLine ;
68import net .minecraft .client .gui .hud .MessageIndicator ;
79import net .minecraft .client .render .RenderTickCounter ;
10+ import net .minecraft .network .message .MessageSignatureData ;
811import net .minecraft .text .OrderedText ;
12+ import net .minecraft .text .Style ;
913import net .minecraft .text .Text ;
1014import net .minecraft .util .math .MathHelper ;
15+ import org .jetbrains .annotations .Nullable ;
1116//import net.minecraft.client.main.Main;
1217//import net.minecraft.text.Style;
1318//import net.minecraft.client.font.TextRenderer;
@@ -27,22 +32,29 @@ public class FishingChatBox {
2732 private int scrollOffset = 0 ;
2833 private boolean focused = false ;
2934 private boolean visible = true ;
30-
31-
32- private int boxX = 0 ; // Default position
33- private int boxY = 30 ; // Top of screen, below hot bar
34- private int boxWidth = 330 ;
35- private int boxHeight = 110 ;
36- private float fontSize = 1.0f ;
35+ private boolean editMode = false ;
36+ private EditState state = EditState .NONE ;
37+ private int xDisplacement ;
38+ private int yDisplacement ;
39+ private int backupX ;
40+ private int backupY ;
41+ private int backupHeight ;
42+ private int backupWidth ;
43+ private final int minBoxWidth = 140 ;
44+ private final int minBoxHeight = 45 ;
45+ private int boxX ; // Default position
46+ private int boxY ; // Top of screen, below hot bar
47+ private int boxWidth ;
48+ private int boxHeight ;
49+ private float fontSize ;
3750 private int guiScaleFactor = 1 ;
3851 private int maxVisibleMessages = 10 ;
52+ private int linesPerScroll ;
3953
4054 // Add at the top of the class
4155 private static final Text COPY_ICON = Text .literal ("📋" );
4256 private static final int COPY_ICON_COLOR = 0xFF00DCFF ;
4357
44- //For islandText
45- private String islandText = "" ;
4658 private final FishingLocation location = new FishingLocation ();
4759
4860 public FishingChatBox (MinecraftClient client , Config config ) {
@@ -52,6 +64,17 @@ public FishingChatBox(MinecraftClient client, Config config) {
5264 this .boxHeight = config .boxHeight ;
5365 this .boxWidth = config .boxWidth ;
5466 this .fontSize = config .fontSize ;
67+ this .linesPerScroll = config .scrollAmount ;
68+ if (this .boxWidth < minBoxWidth ){
69+ this .boxWidth = minBoxWidth ;
70+ }
71+ if (this .boxHeight < minBoxHeight ){
72+ this .boxHeight = minBoxHeight ;
73+ }
74+ backupX = boxX ;
75+ backupY = boxY ;
76+ backupHeight = boxHeight ;
77+ backupWidth = boxWidth ;
5578 }
5679
5780 public void render (DrawContext context , double mouseX , double mouseY , RenderTickCounter tickCounter ) {
@@ -64,6 +87,13 @@ public void render(DrawContext context, double mouseX, double mouseY, RenderTick
6487 if (focused && !client .inGameHud .getChatHud ().isChatFocused ()){
6588 focused = false ;
6689 scrollOffset = 0 ; //reset scroll offset to 0 to warp box back to the bottom
90+ if (state != EditState .NONE ){
91+ state = EditState .NONE ;
92+ boxX = backupX ;
93+ boxY = backupY ;
94+ boxHeight = backupHeight ;
95+ boxWidth = backupWidth ;
96+ }
6797 }
6898 if (focused ){
6999 context .drawBorder (boxX , boxY , boxWidth +2 , boxHeight +2 , 0xFFFFFFFF );
@@ -79,7 +109,8 @@ public void render(DrawContext context, double mouseX, double mouseY, RenderTick
79109 } //sets title to none if box width is smaller than everything.
80110 context .drawText (client .textRenderer , title , boxX + 5 , boxY + 5 , 0xFFFFFFFF , true );
81111 context .drawText (client .textRenderer , cords , (boxX + boxWidth ) - (client .textRenderer .getWidth (cords ) + 20 ), boxY + 5 , 0xFFA000 , true );
82-
112+ //draw a line to underline Title area
113+ context .drawBorder (boxX , boxY +16 , boxWidth , 1 , 0xFFFFFFFF );
83114 // Add clipboard icon
84115 int iconX = boxX + (boxWidth - 10 );
85116 context .drawText (client .textRenderer , COPY_ICON , iconX , boxY + 5 , COPY_ICON_COLOR , true );
@@ -89,6 +120,7 @@ public void render(DrawContext context, double mouseX, double mouseY, RenderTick
89120 mouseY >= (boxY + 5 )*guiScaleFactor && mouseY <= (boxY + 5 + 9 )*guiScaleFactor ) {
90121 context .fill (iconX , boxY + 5 , iconX + client .textRenderer .getWidth (COPY_ICON ), boxY + 14 , 0xAAFFFFFF );
91122 }
123+
92124 //apply font size
93125 context .getMatrices ().push ();
94126 context .getMatrices ().scale (fontSize ,fontSize ,fontSize );
@@ -103,11 +135,11 @@ public void render(DrawContext context, double mouseX, double mouseY, RenderTick
103135 maxVisibleMessages = (int )((boxHeight - 18 )/fontSize )/MESSAGE_HEIGHT ;
104136 List <ChatMessage > visibleMessages = new ArrayList <>(messages );
105137 int startIndex = Math .max (0 , Math .min (scrollOffset , messages .size () - maxVisibleMessages ));
106-
138+ List < OrderedText > onScreenMessages = new ArrayList <>();
107139
108140 for (int i = startIndex ; i < visibleMessages .size () && visibleCount < maxVisibleMessages ; i ++) {
109141 ChatMessage message = visibleMessages .get (i );
110- List <OrderedText > wrappedText = new ArrayList <>(client .textRenderer .wrapLines (message .text , fontMarginWidth ));
142+ List <OrderedText > wrappedText = new ArrayList <>(client .textRenderer .wrapLines (message .chathudline . content () , fontMarginWidth ));
111143 reverseList (wrappedText );
112144 int localSize = 0 ;
113145 for (OrderedText line : wrappedText ) {
@@ -121,11 +153,31 @@ public void render(DrawContext context, double mouseX, double mouseY, RenderTick
121153 }
122154 yOffset -= MESSAGE_HEIGHT ;
123155 visibleCount ++;
156+ onScreenMessages .add (line );
124157 }
125158 }
126- context .getMatrices ().pop ();
127-
128159
160+ context .getMatrices ().pop ();
161+ //check for hover text
162+
163+ if (visible && MouseWithinBox (mouseX , mouseY )){
164+ int i = (int )Math .floor ((mouseY /guiScaleFactor )) - boxY - 17 + (int )Math .floor ((MESSAGE_HEIGHT *fontSize )/2 );
165+ int lineIndex = (int )(i /fontSize )/MESSAGE_HEIGHT ;
166+ lineIndex -= (maxVisibleMessages - Math .min (onScreenMessages .size (), maxVisibleMessages ));
167+ lineIndex -= 1 ;
168+ lineIndex = (onScreenMessages .size ()-1 ) - lineIndex ;
169+ if (lineIndex >= 0 && lineIndex < onScreenMessages .size ()) {
170+ int translatedMouseX = (int )Math .floor (((mouseX -boxX )/guiScaleFactor )/fontSize )-2 ;
171+ if (translatedMouseX > 0 ){
172+ Style style = this .client .textRenderer .getTextHandler ().getStyleAt (onScreenMessages .get (lineIndex ), translatedMouseX );
173+ if (style != null && style .getHoverEvent () != null ) {
174+ int scaledX = (int )Math .floor ((mouseX /guiScaleFactor ));
175+ int scaledY = (int )Math .floor ((mouseY /guiScaleFactor ));
176+ context .drawHoverEvent (this .client .textRenderer , style , scaledX , scaledY );
177+ }
178+ }
179+ }
180+ }
129181 // Draw scroll bar if needed
130182 if (messages .size () > maxVisibleMessages ) {
131183 int scrollBarHeight = boxHeight - 25 ;
@@ -138,6 +190,26 @@ public void render(DrawContext context, double mouseX, double mouseY, RenderTick
138190 context .fill (boxX + boxWidth - 5 , boxY + boxHeight - 5 - thumbPosition , boxX + boxWidth - 2 ,
139191 boxY + boxHeight - 5 - thumbPosition - thumbSize , 0xFFAAAAAA );
140192 }
193+ //edit mode stuff
194+ if (editMode && focused ){
195+ //move box
196+ context .fill (boxX + 5 , boxY + 2 , boxX + boxWidth - 20 , boxY + 17 , 0xFFFFFF20 );
197+ if (state == EditState .BOX ){
198+ boxX = Math .max ((int )(mouseX /guiScaleFactor ) - xDisplacement , 0 );
199+ boxY = Math .max ((int )(mouseY /guiScaleFactor ) - yDisplacement , 0 );
200+ }
201+ //right box
202+ context .fill (boxX + boxWidth - 5 , boxY + 10 , boxX + boxWidth , boxY + boxHeight - 8 , 0xFFFF20FF );
203+ if (state == EditState .WIDTH ){
204+ boxWidth = Math .max ((int )(mouseX /guiScaleFactor ), minBoxWidth + boxX ) - boxX + 2 ;
205+ }
206+ //bottom box
207+ context .fill (boxX + 3 , boxY + boxHeight - 5 , boxX + boxWidth -3 , boxY + boxHeight , 0xFF20FFFF );
208+ if (state == EditState .HEIGHT ){
209+ boxHeight = Math .max ((int )(mouseY /guiScaleFactor ), minBoxHeight + boxY ) - boxY + 2 ;
210+ }
211+ }
212+
141213 }
142214 public static <T > void reverseList (List <T > list ) {
143215 // base condition when the list size is 0
@@ -155,15 +227,25 @@ public static <T> void reverseList(List<T> list) {
155227 // add the first value at the end
156228 list .add (value );
157229 }
158- public void addMessage (Text message , MessageIndicator messageIndicator ) {
159- messages .addFirst (new ChatMessage (message , client .inGameHud .getTicks (), 0 ));
230+ public void addMessage (Text message , @ Nullable MessageSignatureData signatureData , @ Nullable MessageIndicator indicator ) {
231+ messages .addFirst (new ChatMessage (new ChatHudLine ( client .inGameHud .getTicks (), message , signatureData , indicator ) ));
160232 while (messages .size () > MAX_MESSAGES ) {
161233 messages .removeLast ();
162234 }
163235 }
164236
165-
166- public void scroll (int amount ) {
237+ public boolean WithinBounds (double min , double value , double max ){
238+ return (value > min && value < max );
239+ }
240+
241+ public boolean MouseWithinBox (double mouseX , double mouseY ){
242+ return (client .inGameHud .getChatHud ().isChatFocused ()
243+ && WithinBounds (boxX , mouseX /guiScaleFactor , boxX + boxWidth )
244+ && WithinBounds (boxY , mouseY /guiScaleFactor , boxY + boxHeight ));
245+ }
246+
247+ public void scroll (int amount ){
248+ amount *= linesPerScroll ;
167249 if (focused ) {
168250 scrollOffset = MathHelper .clamp (scrollOffset + amount , 0 , Math .max (0 , messages .size () - maxVisibleMessages ));
169251 }
@@ -172,15 +254,12 @@ public void scroll(int amount) {
172254 public void mouseClicked (double mouseX , double mouseY , int button ) {
173255 updateGuiScale ();
174256
175- // Get scaled coordinates for accurate detection
176- double scaledMouseX = mouseX / guiScaleFactor ;
177- double scaledMouseY = mouseY / guiScaleFactor ;
178-
179257 // Update location and get island number
180258 assert client .player != null ;
181259 location .updateLocation (client .player .getX (), client .player .getY (), client .player .getZ ());
182260 int island = location .getIslandNumber ();
183- islandText = island > 0 ? "i" + island : "" ;
261+ //For islandText
262+ String islandText = island > 0 ? "i" + island : "" ;
184263
185264 // Format coordinates with island
186265 String cords = "" ;
@@ -192,23 +271,66 @@ public void mouseClicked(double mouseX, double mouseY, int button) {
192271
193272 // Check clipboard icon click
194273 int iconX = boxX + boxWidth - 10 ; //place icon position from right border instead of left
195- if (scaledMouseX >= iconX && scaledMouseX <= iconX + client .textRenderer .getWidth (COPY_ICON ) &&
196- scaledMouseY >= boxY + 5 && scaledMouseY <= boxY + 5 + 9 && button == 0 ) {
197- client .keyboard .setClipboard (cords );
198- // Optional: Add visual feedback
199- MCCFishingMessagesMod .LOGGER .info ("Copied coordinates to clipboard" ); // Debug log
200- return ;
274+ if (button == 0
275+ && WithinBounds (iconX ,mouseX /guiScaleFactor ,iconX +client .textRenderer .getWidth (COPY_ICON ))
276+ && WithinBounds (boxY +5 , mouseY /guiScaleFactor , boxY + 14 )) {
277+ client .keyboard .setClipboard (cords );
278+ // Optional: Add visual feedback
279+ MCCFishingMessagesMod .LOGGER .info ("Copied coordinates to clipboard" ); // Debug log
280+ return ;
281+ }
282+ // Edit mode stuff
283+ if (editMode && focused && button == 0 ){
284+ //check top box area
285+ if (WithinBounds (boxX + 5 , (mouseX /guiScaleFactor ),boxX + boxWidth - 20 )
286+ && WithinBounds (boxY + 2 , (mouseY /guiScaleFactor ),boxY + 17 )){
287+ if (state == EditState .BOX ){
288+ EndEdit ();
289+ }else {
290+ //store the mouse offset
291+ xDisplacement = (int )(mouseX /guiScaleFactor ) - boxX ;
292+ yDisplacement = (int )(mouseY /guiScaleFactor ) - boxY ;
293+ //enable edit mode
294+ backupX = boxX ;
295+ backupY = boxY ;
296+ state = EditState .BOX ;
297+ }
298+ } else if (WithinBounds (boxX + boxWidth - 5 , (mouseX /guiScaleFactor ),boxX + boxWidth )
299+ && WithinBounds (boxY + 10 , (mouseY /guiScaleFactor ),boxY + boxHeight - 8 )) {
300+ if (state == EditState .WIDTH ){
301+ EndEdit ();
302+ }else {
303+ backupWidth = boxWidth ;
304+ state = EditState .WIDTH ;
305+ }
306+
307+ }else if (WithinBounds (boxX + 3 , (mouseX /guiScaleFactor ),boxX + boxWidth - 3 )
308+ && WithinBounds (boxY + boxHeight - 5 , (mouseY /guiScaleFactor ),boxY + boxHeight )){
309+ if (state == EditState .HEIGHT ){
310+ EndEdit ();
311+ }else {
312+ backupHeight = boxHeight ;
313+ state = EditState .HEIGHT ;
314+ }
315+ }
201316 }
202-
203317 // Original focus check
204- focused = visible && mouseX >= boxX && mouseX <= ( boxX + boxWidth )* guiScaleFactor &&
205- mouseY >= boxY * guiScaleFactor && mouseY <= ( boxY + boxHeight )* guiScaleFactor &&
318+ focused = visible &&
319+ MouseWithinBox ( mouseX , mouseY ) &&
206320 button == 0 && client .inGameHud .getChatHud ().isChatFocused ();
207321 if (!focused ){
208322 scrollOffset = 0 ;
323+ state = EditState .NONE ;
209324 }
210325 }
326+ public void Save (){
327+ ConfigManager .instance ().SetNewValues (boxX ,boxWidth ,boxY ,boxHeight ,fontSize );
328+ }
211329
330+ public void EndEdit (){
331+ state = EditState .NONE ;
332+ Save ();
333+ }
212334
213335 public boolean isFocused () {
214336 return focused ;
@@ -225,21 +347,38 @@ public boolean isVisible() {
225347 public void changeFontSize (float changeAmt ){
226348 float i = this .fontSize ;
227349 this .fontSize = Math .max (0.2f , Math .min (1.5f , i +changeAmt ));
350+ Save ();
351+ }
352+
353+ public void ToggleEditMode (){
354+ editMode = !editMode ;
355+ if (state != EditState .NONE ){
356+ state = EditState .NONE ;
357+ boxX = backupX ;
358+ boxY = backupY ;
359+ boxHeight = backupHeight ;
360+ boxWidth = backupWidth ;
361+ }
228362 }
229363
230364 public void updateGuiScale (){
231365 this .guiScaleFactor = client .options .getGuiScale ().getValue ();
232366 }
233367
368+ private enum EditState {
369+ NONE ,
370+ BOX ,
371+ WIDTH ,
372+ HEIGHT
373+ }
374+
234375 private static class ChatMessage {
235- public final Text text ;
236- public final int timestamp ;
376+ public ChatHudLine chathudline ;
237377 public int size ;
238378
239- public ChatMessage (Text text , int timestamp , int size ) {
240- this .text = text ;
241- this .timestamp = timestamp ;
242- this .size = size ;
379+ public ChatMessage (ChatHudLine text ) {
380+ this .chathudline = text ;
381+ this .size = 0 ;
243382 }
244383 }
245384}
0 commit comments