3939import net .minecraft .commands .Commands ;
4040import net .minecraft .network .chat .Component ;
4141import net .minecraft .network .chat .MutableComponent ;
42+ import net .minecraft .util .Mth ;
4243import net .minecraft .world .entity .player .Player ;
4344import net .minecraft .world .level .ChunkPos ;
4445import org .lwjgl .glfw .GLFW ;
@@ -60,6 +61,7 @@ public class ChunkScreenPanel extends Panel {
6061 private static final ImageIcon CHECKERED_ICON = new ImageIcon (FTBChunksAPI .rl ("textures/checkered.png" ));
6162
6263 private final List <ChunkButton > chunkButtons = new ArrayList <>();
64+ private XZ firstSelectedChunk = null ;
6365 private final Set <XZ > selectedChunks = new HashSet <>();
6466 private final List <ChunkButtonPos > chunkedPosList = new ArrayList <>();
6567 public boolean isAdminEnabled ;
@@ -129,11 +131,11 @@ public void alignWidgets() {
129131
130132 this .tileSizeX = maxWidth / FTBChunks .TILES ;
131133 this .tileSizeY = maxHeight / FTBChunks .TILES ;
132- for (ChunkButtonPos chunkedPos : chunkedPosList ) {
133- chunkedPos .button .setPos (xPos + tileSizeX * chunkedPos .x , yPos + tileSizeY * chunkedPos .y );
134- chunkedPos .button .setSize (tileSizeX , tileSizeY );
135- }
136- }
134+ for (ChunkButtonPos chunkedPos : chunkedPosList ) {
135+ chunkedPos .button .setPos (xPos + tileSizeX * chunkedPos .x , yPos + tileSizeY * chunkedPos .y );
136+ chunkedPos .button .setSize (tileSizeX , tileSizeY );
137+ }
138+ }
137139
138140 @ Override
139141 public void mouseReleased (MouseButton button ) {
@@ -143,16 +145,17 @@ public void mouseReleased(MouseButton button) {
143145 Optional <UUID > teamId = Optional .ofNullable (chunkScreen .getOpenedAs ()).map (Team ::getTeamId );
144146 NetworkManager .sendToServer (new RequestChunkChangePacket (ChunkChangeOp .create (button .isLeft (), isShiftKeyDown ()), selectedChunks , canChangeAsAdmin (), teamId ));
145147 selectedChunks .clear ();
148+ firstSelectedChunk = null ;
146149 playClickSound ();
147150 }
148151 }
149152
150153 public void removeAllClaims () {
151154 Optional <UUID > teamId = Optional .ofNullable (chunkScreen .getOpenedAs ()).map (Team ::getTeamId );
152155 Set <XZ > allChunks = chunkedPosList .stream ()
153- .map (ChunkButtonPos ::button )
154- .map (ChunkButton ::getChunkPos )
155- .collect (Collectors .toSet ());
156+ .map (ChunkButtonPos ::button )
157+ .map (ChunkButton ::getChunkPos )
158+ .collect (Collectors .toSet ());
156159 NetworkManager .sendToServer (new RequestChunkChangePacket (ChunkChangeOp .UNCLAIM , allChunks , canChangeAsAdmin (), teamId ));
157160 }
158161
@@ -226,6 +229,10 @@ public ChunkButton(Panel panel, XZ xz) {
226229
227230 @ Override
228231 public void onClicked (MouseButton mouseButton ) {
232+ if (selectedChunks .isEmpty ()) {
233+ firstSelectedChunk = chunkPos ;
234+ }
235+
229236 selectedChunks .add (chunkPos );
230237 }
231238
@@ -248,12 +255,39 @@ public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int
248255
249256 @ Override
250257 public boolean mouseDragged (int button , double dragX , double dragY ) {
251- if (isMouseOver () && (isMouseButtonDown (MouseButton .LEFT ) || isMouseButtonDown (MouseButton .RIGHT ))) {
252- selectedChunks .add (chunkPos );
253- }
258+ if (isMouseOver () && (isMouseButtonDown (MouseButton .LEFT ) || isMouseButtonDown (MouseButton .RIGHT ))) {
259+ if (ChunkScreen .claimMode != ChunkScreen .ClaimMode .FREEHAND && firstSelectedChunk != null ) {
260+ addChunksToSelection ();
261+ } else {
262+ selectedChunks .add (chunkPos );
263+ }
264+ }
254265 return super .mouseDragged (button , dragX , dragY );
255266 }
256267
268+ private void addChunksToSelection () {
269+ int x1 = Math .min (firstSelectedChunk .x (), chunkPos .x ());
270+ int x2 = Math .max (firstSelectedChunk .x (), chunkPos .x ());
271+ int z1 = Math .min (firstSelectedChunk .z (), chunkPos .z ());
272+ int z2 = Math .max (firstSelectedChunk .z (), chunkPos .z ());
273+ XZ centre = new XZ ((x1 + x2 ) / 2 , (z1 + z2 ) / 2 );
274+ selectedChunks .clear ();
275+ for (int x = x1 ; x <= x2 ; x ++) {
276+ for (int z = z1 ; z <= z2 ; z ++) {
277+ XZ xz = new XZ (x , z );
278+ if (ChunkScreen .claimMode == ChunkScreen .ClaimMode .RECTANGLE
279+ || distance (xz , centre ) - 0.5f <= Math .min (centre .x () - x1 , centre .z () - z1 ))
280+ {
281+ selectedChunks .add (xz );
282+ }
283+ }
284+ }
285+ }
286+
287+ private float distance (XZ xz1 , XZ xz2 ) {
288+ return Mth .sqrt ((xz2 .x () - xz1 .x ()) * (xz2 .x () - xz1 .x ()) + (xz2 .z () - xz1 .z ()) * (xz2 .z () - xz1 .z ()));
289+ }
290+
257291 @ Override
258292 @ SuppressWarnings ("deprecation" )
259293 public void addMouseOverText (TooltipList list ) {
@@ -265,8 +299,10 @@ public void addMouseOverText(TooltipList list) {
265299
266300 Date date = new Date ();
267301
302+ boolean altPressed = Screen .hasAltDown ();
303+
268304 chunk .getClaimedDate ().ifPresent (claimedDate -> {
269- if (Screen . hasAltDown () ) {
305+ if (altPressed ) {
270306 list .add (Component .literal (claimedDate .toLocaleString ()).withStyle (ChatFormatting .GRAY ));
271307 } else {
272308 list .add (Component .literal (TimeUtils .prettyTimeString ((date .getTime () - claimedDate .getTime ()) / 1000L ) + " ago" ).withStyle (ChatFormatting .GRAY ));
@@ -276,26 +312,30 @@ public void addMouseOverText(TooltipList list) {
276312 chunk .getForceLoadedDate ().ifPresent (forceLoadedDate -> {
277313 list .add (Component .translatable ("ftbchunks.gui.force_loaded" ).withStyle (ChatFormatting .YELLOW ));
278314
279- String loadStr = Screen . hasAltDown () ?
315+ String loadStr = altPressed ?
280316 " " + forceLoadedDate .toLocaleString () :
281317 " " + TimeUtils .prettyTimeString ((date .getTime () - forceLoadedDate .getTime ()) / 1000L ) + " ago" ;
282318 list .add (Component .literal (loadStr ).withStyle (ChatFormatting .GRAY ));
283319
284320 chunk .getForceLoadExpiryDate ().ifPresent (expiryDate -> {
285321 list .add (Component .translatable ("ftbchunks.gui.force_load_expires" ).withStyle (ChatFormatting .GOLD ));
286- String expireStr = Screen . hasAltDown () ?
322+ String expireStr = altPressed ?
287323 " " + expiryDate .toLocaleString () :
288324 " " + TimeUtils .prettyTimeString ((expiryDate .getTime () - date .getTime ()) / 1000L ) + " from now" ;
289325 list .add (Component .literal (expireStr ).withStyle (ChatFormatting .GRAY ));
290326 });
291327
292- if (!Screen . hasAltDown () ) {
328+ if (!altPressed ) {
293329 list .add (Component .translatable ("ftbchunks.gui.hold_alt_for_dates" ).withStyle (ChatFormatting .DARK_GRAY ));
294330 }
295331 if (team .getRankForPlayer (Minecraft .getInstance ().player .getUUID ()).isMemberOrBetter ()){
296332 list .add (Component .translatable ("ftbchunks.gui.mouse_wheel_expiry" ).withStyle (ChatFormatting .DARK_GRAY ));
297333 }
298334 });
335+
336+ if (!altPressed && (chunk .getClaimedDate ().isPresent () || chunk .getForceLoadedDate ().isPresent ())) {
337+ list .add (Component .translatable ("ftbchunks.gui.hold_alt_for_dates" ).withStyle (ChatFormatting .DARK_GRAY ));
338+ }
299339 });
300340 }
301341
0 commit comments