3939import net .minecraft .network .chat .Component ;
4040import net .minecraft .network .chat .MutableComponent ;
4141import net .minecraft .server .permissions .Permissions ;
42+ import net .minecraft .util .Mth ;
4243import net .minecraft .world .entity .player .Player ;
4344import net .minecraft .world .level .ChunkPos ;
4445import org .lwjgl .glfw .GLFW ;
@@ -54,6 +55,7 @@ public class ChunkScreenPanel extends Panel {
5455 private static final ImageIcon CHECKERED_ICON = new ImageIcon (FTBChunksAPI .id ("textures/checkered.png" ));
5556
5657 private final List <ChunkButton > chunkButtons = new ArrayList <>();
58+ private XZ firstSelectedChunk = null ;
5759 private final Set <XZ > selectedChunks = new HashSet <>();
5860 private final List <ChunkButtonPos > chunkedPosList = new ArrayList <>();
5961 public boolean isAdminEnabled ;
@@ -124,11 +126,11 @@ public void alignWidgets() {
124126
125127 this .tileSizeX = maxWidth / FTBChunks .TILES ;
126128 this .tileSizeY = maxHeight / FTBChunks .TILES ;
127- for (ChunkButtonPos chunkedPos : chunkedPosList ) {
128- chunkedPos .button .setPos (xPos + tileSizeX * chunkedPos .x , yPos + tileSizeY * chunkedPos .y );
129- chunkedPos .button .setSize (tileSizeX , tileSizeY );
130- }
131- }
129+ for (ChunkButtonPos chunkedPos : chunkedPosList ) {
130+ chunkedPos .button .setPos (xPos + tileSizeX * chunkedPos .x , yPos + tileSizeY * chunkedPos .y );
131+ chunkedPos .button .setSize (tileSizeX , tileSizeY );
132+ }
133+ }
132134
133135 @ Override
134136 public void mouseReleased (MouseButton button ) {
@@ -138,16 +140,17 @@ public void mouseReleased(MouseButton button) {
138140 Optional <UUID > teamId = Optional .ofNullable (chunkScreen .getOpenedAs ()).map (Team ::getTeamId );
139141 NetworkManager .sendToServer (new RequestChunkChangePacket (ChunkChangeOp .create (button .isLeft (), isShiftKeyDown ()), selectedChunks , canChangeAsAdmin (), teamId ));
140142 selectedChunks .clear ();
143+ firstSelectedChunk = null ;
141144 playClickSound ();
142145 }
143146 }
144147
145148 public void removeAllClaims () {
146149 Optional <UUID > teamId = Optional .ofNullable (chunkScreen .getOpenedAs ()).map (Team ::getTeamId );
147150 Set <XZ > allChunks = chunkedPosList .stream ()
148- .map (ChunkButtonPos ::button )
149- .map (ChunkButton ::getChunkPos )
150- .collect (Collectors .toSet ());
151+ .map (ChunkButtonPos ::button )
152+ .map (ChunkButton ::getChunkPos )
153+ .collect (Collectors .toSet ());
151154 NetworkManager .sendToServer (new RequestChunkChangePacket (ChunkChangeOp .UNCLAIM , allChunks , canChangeAsAdmin (), teamId ));
152155 }
153156
@@ -223,6 +226,10 @@ public ChunkButton(Panel panel, XZ xz) {
223226
224227 @ Override
225228 public void onClicked (MouseButton mouseButton ) {
229+ if (selectedChunks .isEmpty ()) {
230+ firstSelectedChunk = chunkPos ;
231+ }
232+
226233 selectedChunks .add (chunkPos );
227234 }
228235
@@ -244,12 +251,39 @@ public void drawBackground(GuiGraphics graphics, Theme theme, int x, int y, int
244251
245252 @ Override
246253 public boolean mouseDragged (int button , double dragX , double dragY ) {
247- if (isMouseOver () && (isMouseButtonDown (MouseButton .LEFT ) || isMouseButtonDown (MouseButton .RIGHT ))) {
248- selectedChunks .add (chunkPos );
249- }
254+ if (isMouseOver () && (isMouseButtonDown (MouseButton .LEFT ) || isMouseButtonDown (MouseButton .RIGHT ))) {
255+ if (ChunkScreen .claimMode != ChunkScreen .ClaimMode .FREEHAND && firstSelectedChunk != null ) {
256+ addChunksToSelection ();
257+ } else {
258+ selectedChunks .add (chunkPos );
259+ }
260+ }
250261 return super .mouseDragged (button , dragX , dragY );
251262 }
252263
264+ private void addChunksToSelection () {
265+ int x1 = Math .min (firstSelectedChunk .x (), chunkPos .x ());
266+ int x2 = Math .max (firstSelectedChunk .x (), chunkPos .x ());
267+ int z1 = Math .min (firstSelectedChunk .z (), chunkPos .z ());
268+ int z2 = Math .max (firstSelectedChunk .z (), chunkPos .z ());
269+ XZ centre = new XZ ((x1 + x2 ) / 2 , (z1 + z2 ) / 2 );
270+ selectedChunks .clear ();
271+ for (int x = x1 ; x <= x2 ; x ++) {
272+ for (int z = z1 ; z <= z2 ; z ++) {
273+ XZ xz = new XZ (x , z );
274+ if (ChunkScreen .claimMode == ChunkScreen .ClaimMode .RECTANGLE
275+ || distance (xz , centre ) - 0.5f <= Math .min (centre .x () - x1 , centre .z () - z1 ))
276+ {
277+ selectedChunks .add (xz );
278+ }
279+ }
280+ }
281+ }
282+
283+ private float distance (XZ xz1 , XZ xz2 ) {
284+ return Mth .sqrt ((xz2 .x () - xz1 .x ()) * (xz2 .x () - xz1 .x ()) + (xz2 .z () - xz1 .z ()) * (xz2 .z () - xz1 .z ()));
285+ }
286+
253287 @ Override
254288 public void addMouseOverText (TooltipList list ) {
255289 chunk .getTeam ().ifPresent (team -> {
@@ -287,9 +321,9 @@ public void addMouseOverText(TooltipList list) {
287321 }
288322 });
289323
290- if (!altPressed && (chunk .getClaimedDate ().isPresent () || chunk .getForceLoadedDate ().isPresent ())) {
291- list .add (Component .translatable ("ftbchunks.gui.hold_alt_for_dates" ).withStyle (ChatFormatting .DARK_GRAY ));
292- }
324+ if (!altPressed && (chunk .getClaimedDate ().isPresent () || chunk .getForceLoadedDate ().isPresent ())) {
325+ list .add (Component .translatable ("ftbchunks.gui.hold_alt_for_dates" ).withStyle (ChatFormatting .DARK_GRAY ));
326+ }
293327 });
294328 }
295329
0 commit comments