001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.command; 020 021import com.plotsquared.core.PlotSquared; 022import com.plotsquared.core.configuration.Settings; 023import com.plotsquared.core.configuration.caption.Caption; 024import com.plotsquared.core.configuration.caption.TranslatableCaption; 025import com.plotsquared.core.database.DBFunc; 026import com.plotsquared.core.events.TeleportCause; 027import com.plotsquared.core.location.BlockLoc; 028import com.plotsquared.core.location.Location; 029import com.plotsquared.core.permissions.Permission; 030import com.plotsquared.core.player.PlotPlayer; 031import com.plotsquared.core.plot.Plot; 032import com.plotsquared.core.plot.PlotArea; 033import com.plotsquared.core.plot.PlotCluster; 034import com.plotsquared.core.plot.PlotId; 035import com.plotsquared.core.util.TabCompletions; 036import com.plotsquared.core.util.query.PlotQuery; 037import net.kyori.adventure.text.minimessage.Template; 038 039import java.util.Collection; 040import java.util.Collections; 041import java.util.HashSet; 042import java.util.LinkedList; 043import java.util.List; 044import java.util.Set; 045import java.util.UUID; 046import java.util.concurrent.TimeoutException; 047import java.util.stream.Collectors; 048 049@CommandDeclaration(command = "cluster", 050 aliases = "clusters", 051 category = CommandCategory.ADMINISTRATION, 052 requiredType = RequiredType.NONE, 053 permission = "plots.cluster") 054public class Cluster extends SubCommand { 055 056 @Override 057 public boolean onCommand(PlotPlayer<?> player, String[] args) { 058 059 // list, create, delete, resize, invite, kick, leave, helpers, tp, sethome 060 if (args.length == 0) { 061 // return arguments 062 player.sendMessage( 063 TranslatableCaption.of("cluster.cluster_available_args"), 064 Template.of( 065 "list", 066 "<dark_aqua>list</dark_aqua><gray>, </gray><dark_aqua>create</dark_aqua><gray>, </gray><dark_aqua>delete</dark_aqua><gray>, </gray><dark_aqua>resize</dark_aqua><gray>, </gray><dark_aqua>invite</dark_aqua><gray>, </gray><dark_aqua>kick</dark_aqua><gray>, </gray><dark_aqua>leave</dark_aqua><gray>, </gray><dark_aqua>members</dark_aqua><gray>, </gray><dark_aqua>info</dark_aqua><gray>, </gray><dark_aqua>tp</dark_aqua><gray>, </gray><dark_aqua>sethome</dark_aqua>" 067 ) 068 ); 069 return false; 070 } 071 String sub = args[0].toLowerCase(); 072 switch (sub) { 073 case "l": 074 case "list": { 075 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_LIST)) { 076 player.sendMessage( 077 TranslatableCaption.of("permission.no_permission"), 078 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_LIST)) 079 ); 080 return false; 081 } 082 if (args.length != 1) { 083 player.sendMessage( 084 TranslatableCaption.of("commandconfig.command_syntax"), 085 Template.of("value", "/plot cluster list") 086 ); 087 return false; 088 } 089 PlotArea area = player.getApplicablePlotArea(); 090 if (area == null) { 091 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 092 return false; 093 } 094 Set<PlotCluster> clusters = area.getClusters(); 095 player.sendMessage( 096 TranslatableCaption.of("cluster.cluster_list_heading"), 097 Template.of("amount", clusters.size() + "") 098 ); 099 for (PlotCluster cluster : clusters) { 100 // Ignore unmanaged clusters 101 String name = "'" + cluster.getName() + "' : " + cluster; 102 if (player.getUUID().equals(cluster.owner)) { 103 player.sendMessage( 104 TranslatableCaption.of("cluster.cluster_list_element_owner"), 105 Template.of("cluster", name) 106 ); 107 } else if (cluster.helpers.contains(player.getUUID())) { 108 player.sendMessage( 109 TranslatableCaption.of("cluster.cluster_list_element_helpers"), 110 Template.of("cluster", name) 111 ); 112 } else if (cluster.invited.contains(player.getUUID())) { 113 player.sendMessage( 114 TranslatableCaption.of("cluster.cluster_list_element_invited"), 115 Template.of("cluster", name) 116 ); 117 } else { 118 player.sendMessage( 119 TranslatableCaption.of("cluster.cluster_list_element"), 120 Template.of("cluster", cluster.toString()) 121 ); 122 } 123 } 124 return true; 125 } 126 case "c": 127 case "create": { 128 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_CREATE)) { 129 player.sendMessage( 130 TranslatableCaption.of("permission.no_permission"), 131 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_CREATE)) 132 ); 133 return false; 134 } 135 PlotArea area = player.getApplicablePlotArea(); 136 if (area == null) { 137 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 138 return false; 139 } 140 if (args.length != 4) { 141 player.sendMessage( 142 TranslatableCaption.of("commandconfig.command_syntax"), 143 Template.of("value", "/plot cluster create <name> <id-bot> <id-top>") 144 ); 145 return false; 146 } 147 int currentClusters = Settings.Limit.GLOBAL ? 148 player.getClusterCount() : 149 player.getPlotCount(player.getLocation().getWorldName()); 150 if (currentClusters >= player.getAllowedPlots()) { 151 player.sendMessage( 152 TranslatableCaption.of("permission.cant_claim_more_clusters"), 153 Template.of("amount", String.valueOf(player.getAllowedPlots())) 154 ); 155 } 156 PlotId pos1; 157 PlotId pos2; 158 // check pos1 / pos2 159 try { 160 pos1 = PlotId.fromString(args[2]); 161 pos2 = PlotId.fromString(args[3]); 162 } catch (IllegalArgumentException ignored) { 163 player.sendMessage(TranslatableCaption.of("invalid.not_valid_plot_id")); 164 return false; 165 } 166 // check if name is taken 167 String name = args[1]; 168 if (area.getCluster(name) != null) { 169 player.sendMessage( 170 TranslatableCaption.of("alias.alias_is_taken"), 171 Template.of("alias", name) 172 ); 173 return false; 174 } 175 if (pos2.getX() < pos1.getX() || pos2.getY() < pos1.getY()) { 176 PlotId tmp = PlotId.of(Math.min(pos1.getX(), pos2.getX()), Math.min(pos1.getY(), pos2.getY())); 177 pos2 = PlotId.of(Math.max(pos1.getX(), pos2.getX()), Math.max(pos1.getY(), pos2.getY())); 178 pos1 = tmp; 179 } 180 //check if overlap 181 PlotCluster cluster = area.getFirstIntersectingCluster(pos1, pos2); 182 if (cluster != null) { 183 player.sendMessage( 184 TranslatableCaption.of("cluster.cluster_intersection"), 185 Template.of("cluster", cluster.getName()) 186 ); 187 return false; 188 } 189 // Check if it occupies existing plots 190 if (!area.contains(pos1) || !area.contains(pos2)) { 191 player.sendMessage( 192 TranslatableCaption.of("cluster.cluster_outside"), 193 Template.of("area", String.valueOf(area)) 194 ); 195 return false; 196 } 197 Set<Plot> plots = area.getPlotSelectionOwned(pos1, pos2); 198 if (!plots.isEmpty()) { 199 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_CREATE_OTHER)) { 200 UUID uuid = player.getUUID(); 201 for (Plot plot : plots) { 202 if (!plot.isOwner(uuid)) { 203 player.sendMessage( 204 TranslatableCaption.of("permission.no_permission"), 205 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_CREATE_OTHER)) 206 ); 207 return false; 208 } 209 } 210 } 211 } 212 // Check allowed cluster size 213 cluster = new PlotCluster(area, pos1, pos2, player.getUUID()); 214 int current; 215 if (Settings.Limit.GLOBAL) { 216 current = player.getPlayerClusterCount(); 217 } else { 218 current = player.getPlayerClusterCount(player.getLocation().getWorldName()); 219 } 220 int allowed = player.hasPermissionRange( 221 Permission.PERMISSION_CLUSTER_SIZE, 222 Settings.Limit.MAX_PLOTS 223 ); 224 if (current + cluster.getArea() > allowed) { 225 player.sendMessage( 226 TranslatableCaption.of("permission.no_permission"), 227 Template.of("node", Permission.PERMISSION_CLUSTER_SIZE + "." + (current + cluster.getArea())) 228 ); 229 return false; 230 } 231 // create cluster 232 cluster.settings.setAlias(name); 233 area.addCluster(cluster); 234 DBFunc.createCluster(cluster); 235 // Add any existing plots to the current cluster 236 for (Plot plot : plots) { 237 if (plot.hasOwner()) { 238 if (!cluster.isAdded(plot.getOwner())) { 239 cluster.invited.add(plot.getOwner()); 240 DBFunc.setInvited(cluster, plot.getOwner()); 241 } 242 } 243 } 244 player.sendMessage( 245 TranslatableCaption.of("cluster.cluster_created"), 246 Template.of("name", name) 247 ); 248 return true; 249 } 250 case "disband": 251 case "del": 252 case "delete": { 253 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_DELETE)) { 254 player.sendMessage( 255 TranslatableCaption.of("permission.no_permission"), 256 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_DELETE)) 257 ); 258 return false; 259 } 260 if (args.length != 1 && args.length != 2) { 261 player.sendMessage( 262 TranslatableCaption.of("commandconfig.command_syntax"), 263 Template.of("value", "/plot cluster delete [name]") 264 ); 265 return false; 266 } 267 PlotArea area = player.getApplicablePlotArea(); 268 if (area == null) { 269 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 270 return false; 271 } 272 PlotCluster cluster; 273 if (args.length == 2) { 274 cluster = area.getCluster(args[1]); 275 if (cluster == null) { 276 player.sendMessage( 277 TranslatableCaption.of("cluster.invalid_cluster_name"), 278 Template.of("cluster", args[1]) 279 ); 280 return false; 281 } 282 } else { 283 cluster = area.getCluster(player.getLocation()); 284 if (cluster == null) { 285 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 286 return false; 287 } 288 } 289 if (!cluster.owner.equals(player.getUUID())) { 290 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_DELETE_OTHER)) { 291 player.sendMessage( 292 TranslatableCaption.of("permission.no_permission"), 293 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_DELETE_OTHER)) 294 ); 295 return false; 296 } 297 } 298 DBFunc.delete(cluster); 299 player.sendMessage(TranslatableCaption.of("cluster.cluster_deleted"), Template.of( 300 "cluster", 301 String.valueOf(cluster) 302 )); 303 return true; 304 } 305 case "res": 306 case "resize": { 307 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_RESIZE)) { 308 player.sendMessage( 309 TranslatableCaption.of("permission.no_permission"), 310 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_RESIZE)) 311 ); 312 return false; 313 } 314 if (args.length != 3) { 315 player.sendMessage( 316 TranslatableCaption.of("commandconfig.command_syntax"), 317 Template.of("value", "/plot cluster resize [name]") 318 ); 319 return false; 320 } 321 PlotId pos1; 322 PlotId pos2; 323 // check pos1 / pos2 324 try { 325 pos1 = PlotId.fromString(args[2]); 326 pos2 = PlotId.fromString(args[3]); 327 } catch (IllegalArgumentException ignored) { 328 player.sendMessage(TranslatableCaption.of("invalid.not_valid_plot_id")); 329 return false; 330 } 331 if (pos2.getX() < pos1.getX() || pos2.getY() < pos1.getY()) { 332 pos1 = PlotId.of(Math.min(pos1.getX(), pos2.getX()), Math.min(pos1.getY(), pos2.getY())); 333 pos2 = PlotId.of(Math.max(pos1.getX(), pos2.getX()), Math.max(pos1.getY(), pos2.getY())); 334 } 335 // check if in cluster 336 PlotArea area = player.getApplicablePlotArea(); 337 if (area == null) { 338 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 339 return false; 340 } 341 PlotCluster cluster = area.getCluster(player.getLocation()); 342 if (cluster == null) { 343 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 344 return false; 345 } 346 if (!cluster.hasHelperRights(player.getUUID())) { 347 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_RESIZE_OTHER)) { 348 player.sendMessage( 349 TranslatableCaption.of("permission.no_permission"), 350 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_RESIZE_OTHER)) 351 ); 352 return false; 353 } 354 } 355 //check if overlap 356 PlotCluster intersect = area.getFirstIntersectingCluster(pos1, pos2); 357 if (intersect != null) { 358 player.sendMessage( 359 TranslatableCaption.of("cluster.cluster_intersection"), 360 Template.of("cluster", intersect.getName()) 361 ); 362 return false; 363 } 364 Set<Plot> existing = area.getPlotSelectionOwned(cluster.getP1(), cluster.getP2()); 365 Set<Plot> newPlots = area.getPlotSelectionOwned(pos1, pos2); 366 // Set<Plot> removed = (HashSet<Plot>) existing.clone(); 367 Set<Plot> removed = new HashSet<>(existing); 368 369 removed.removeAll(newPlots); 370 // Check expand / shrink 371 if (!removed.isEmpty()) { 372 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_RESIZE_SHRINK)) { 373 player.sendMessage( 374 TranslatableCaption.of("permission.no_permission"), 375 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_RESIZE_SHRINK)) 376 ); 377 return false; 378 } 379 } 380 newPlots.removeAll(existing); 381 if (!newPlots.isEmpty()) { 382 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_RESIZE_EXPAND)) { 383 player.sendMessage( 384 TranslatableCaption.of("permission.no_permission"), 385 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_RESIZE_EXPAND)) 386 ); 387 return false; 388 } 389 } 390 // Check allowed cluster size 391 int current; 392 if (Settings.Limit.GLOBAL) { 393 current = player.getPlayerClusterCount(); 394 } else { 395 current = player.getPlayerClusterCount(player.getLocation().getWorldName()); 396 } 397 current -= cluster.getArea() + (1 + pos2.getX() - pos1.getX()) * (1 + pos2.getY() - pos1.getY()); 398 int allowed = player.hasPermissionRange( 399 Permission.PERMISSION_CLUSTER, 400 Settings.Limit.MAX_PLOTS 401 ); 402 if (current + cluster.getArea() > allowed) { 403 player.sendMessage( 404 TranslatableCaption.of("permission.no_permission"), 405 Template.of("node", Permission.PERMISSION_CLUSTER + "." + (current + cluster.getArea())) 406 ); 407 return false; 408 } 409 // resize cluster 410 DBFunc.resizeCluster(cluster, pos1, pos2); 411 player.sendMessage(TranslatableCaption.of("cluster.cluster_resized")); 412 return true; 413 } 414 case "add": 415 case "inv": 416 case "invite": { 417 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_INVITE)) { 418 player.sendMessage( 419 TranslatableCaption.of("permission.no_permission"), 420 Template.of("node", String.valueOf(Permission.PERMISSION_CLUSTER_INVITE)) 421 ); 422 return false; 423 } 424 if (args.length != 2) { 425 player.sendMessage( 426 TranslatableCaption.of("commandconfig.command_syntax"), 427 Template.of("value", "/plot cluster invite <player>") 428 ); 429 return false; 430 } 431 // check if in cluster 432 PlotArea area = player.getApplicablePlotArea(); 433 if (area == null) { 434 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 435 } 436 PlotCluster cluster = area.getCluster(player.getLocation()); 437 if (cluster == null) { 438 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 439 return false; 440 } 441 if (!cluster.hasHelperRights(player.getUUID())) { 442 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_INVITE_OTHER)) { 443 player.sendMessage( 444 TranslatableCaption.of("permission.no_permission"), 445 Template.of("node", Permission.PERMISSION_CLUSTER_INVITE_OTHER.toString()) 446 ); 447 return false; 448 } 449 } 450 451 PlotSquared.get().getImpromptuUUIDPipeline() 452 .getSingle(args[1], (uuid, throwable) -> { 453 if (throwable instanceof TimeoutException) { 454 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 455 } else if (throwable != null) { 456 player.sendMessage( 457 TranslatableCaption.of("errors.invalid_player"), 458 Template.of("value", args[1]) 459 ); 460 } else { 461 if (!cluster.isAdded(uuid)) { 462 // add the user if not added 463 cluster.invited.add(uuid); 464 DBFunc.setInvited(cluster, uuid); 465 final PlotPlayer<?> otherPlayer = 466 PlotSquared.platform().playerManager().getPlayerIfExists(uuid); 467 if (otherPlayer != null) { 468 player.sendMessage( 469 TranslatableCaption.of("cluster.cluster_invited"), 470 Template.of("cluster", cluster.getName()) 471 ); 472 } 473 } 474 player.sendMessage(TranslatableCaption.of("cluster.cluster_added_user")); 475 } 476 }); 477 return true; 478 } 479 case "k": 480 case "remove": 481 case "kick": { 482 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_KICK)) { 483 player.sendMessage( 484 TranslatableCaption.of("permission.no_permission"), 485 Template.of("node", Permission.PERMISSION_CLUSTER_KICK.toString()) 486 ); 487 return false; 488 } 489 if (args.length != 2) { 490 player.sendMessage( 491 TranslatableCaption.of("commandconfig.command_syntax"), 492 Template.of("value", "/plot cluster kick <player>") 493 ); 494 return false; 495 } 496 PlotArea area = player.getApplicablePlotArea(); 497 if (area == null) { 498 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 499 } 500 PlotCluster cluster = area.getCluster(player.getLocation()); 501 if (cluster == null) { 502 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 503 return false; 504 } 505 if (!cluster.hasHelperRights(player.getUUID())) { 506 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_KICK_OTHER)) { 507 player.sendMessage( 508 TranslatableCaption.of("permission.no_permission"), 509 Template.of("node", Permission.PERMISSION_CLUSTER_KICK_OTHER.toString()) 510 ); 511 return false; 512 } 513 } 514 // check uuid 515 PlotSquared.get().getImpromptuUUIDPipeline() 516 .getSingle(args[1], (uuid, throwable) -> { 517 if (throwable instanceof TimeoutException) { 518 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 519 } else if (throwable != null) { 520 player.sendMessage( 521 TranslatableCaption.of("errors.invalid_player"), 522 Template.of("value", args[1]) 523 ); 524 } else { 525 // Can't kick if the player is yourself, the owner, or not added to the cluster 526 if (uuid.equals(player.getUUID()) || uuid.equals(cluster.owner) 527 || !cluster.isAdded(uuid)) { 528 player.sendMessage( 529 TranslatableCaption.of("cluster.cannot_kick_player"), 530 Template.of("value", cluster.getName()) 531 ); 532 } else { 533 if (cluster.helpers.contains(uuid)) { 534 cluster.helpers.remove(uuid); 535 DBFunc.removeHelper(cluster, uuid); 536 } 537 cluster.invited.remove(uuid); 538 DBFunc.removeInvited(cluster, uuid); 539 540 final PlotPlayer<?> player2 = 541 PlotSquared.platform().playerManager().getPlayerIfExists(uuid); 542 if (player2 != null) { 543 player.sendMessage( 544 TranslatableCaption.of("cluster.cluster_removed"), 545 Template.of("cluster", cluster.getName()) 546 ); 547 } 548 removePlayerPlots(cluster, uuid, player2.getLocation().getWorldName()); 549 player.sendMessage(TranslatableCaption.of("cluster.cluster_kicked_user")); 550 } 551 } 552 }); 553 return true; 554 } 555 case "quit": 556 case "leave": { 557 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_LEAVE)) { 558 player.sendMessage( 559 TranslatableCaption.of("permission.no_permission"), 560 Template.of("node", Permission.PERMISSION_CLUSTER_LEAVE.toString()) 561 ); 562 return false; 563 } 564 if (args.length != 1 && args.length != 2) { 565 player.sendMessage( 566 TranslatableCaption.of("commandconfig.command_syntax"), 567 Template.of("value", "/plot cluster leave [name]") 568 ); 569 return false; 570 } 571 PlotArea area = player.getApplicablePlotArea(); 572 if (area == null) { 573 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 574 } 575 PlotCluster cluster; 576 if (args.length == 2) { 577 cluster = area.getCluster(args[1]); 578 if (cluster == null) { 579 player.sendMessage( 580 TranslatableCaption.of("cluster.invalid_cluster_name"), 581 Template.of("cluster", args[1]) 582 ); 583 return false; 584 } 585 } else { 586 cluster = area.getCluster(player.getLocation()); 587 if (cluster == null) { 588 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 589 return false; 590 } 591 } 592 UUID uuid = player.getUUID(); 593 if (!cluster.isAdded(uuid)) { 594 player.sendMessage(TranslatableCaption.of("cluster.cluster_not_added")); 595 return false; 596 } 597 if (uuid.equals(cluster.owner)) { 598 player.sendMessage(TranslatableCaption.of("cluster.cluster_cannot_leave")); 599 return false; 600 } 601 if (cluster.helpers.contains(uuid)) { 602 cluster.helpers.remove(uuid); 603 DBFunc.removeHelper(cluster, uuid); 604 } 605 cluster.invited.remove(uuid); 606 DBFunc.removeInvited(cluster, uuid); 607 player.sendMessage( 608 TranslatableCaption.of("cluster.cluster_removed"), 609 Template.of("cluster", cluster.getName()) 610 ); 611 removePlayerPlots(cluster, uuid, player.getLocation().getWorldName()); 612 return true; 613 } 614 case "members": { 615 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_HELPERS)) { 616 player.sendMessage( 617 TranslatableCaption.of("permission.no_permission"), 618 Template.of("node", Permission.PERMISSION_CLUSTER_HELPERS.toString()) 619 ); 620 return false; 621 } 622 if (args.length != 3) { 623 player.sendMessage( 624 TranslatableCaption.of("commandconfig.command_syntax"), 625 Template.of("value", "/plot cluster members <add | remove> <player>") 626 ); 627 return false; 628 } 629 PlotArea area = player.getApplicablePlotArea(); 630 if (area == null) { 631 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 632 } 633 PlotCluster cluster = area.getCluster(player.getLocation()); 634 if (cluster == null) { 635 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 636 return false; 637 } 638 639 PlotSquared.get().getImpromptuUUIDPipeline() 640 .getSingle(args[2], (uuid, throwable) -> { 641 if (throwable instanceof TimeoutException) { 642 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 643 } else if (throwable != null) { 644 player.sendMessage( 645 TranslatableCaption.of("errors.invalid_player"), 646 Template.of("value", args[2]) 647 ); 648 } else { 649 if (args[1].equalsIgnoreCase("add")) { 650 cluster.helpers.add(uuid); 651 DBFunc.setHelper(cluster, uuid); 652 player.sendMessage(TranslatableCaption.of("cluster.cluster_added_helper")); 653 } else if (args[1].equalsIgnoreCase("remove")) { 654 cluster.helpers.remove(uuid); 655 DBFunc.removeHelper(cluster, uuid); 656 player.sendMessage(TranslatableCaption.of("cluster.cluster_removed_helper")); 657 } else { 658 player.sendMessage( 659 TranslatableCaption.of("commandconfig.command_syntax"), 660 Template.of("value", "/plot cluster members <add | remove> <player>") 661 ); 662 } 663 } 664 }); 665 return true; 666 } 667 case "spawn": 668 case "home": 669 case "tp": { 670 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_TP)) { 671 player.sendMessage( 672 TranslatableCaption.of("permission.no_permission"), 673 Template.of("node", Permission.PERMISSION_CLUSTER_TP.toString()) 674 ); 675 return false; 676 } 677 if (args.length != 2) { 678 player.sendMessage( 679 TranslatableCaption.of("commandconfig.command_syntax"), 680 Template.of("value", "/plot cluster tp <name>") 681 ); 682 return false; 683 } 684 PlotArea area = player.getApplicablePlotArea(); 685 if (area == null) { 686 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 687 return false; 688 } 689 PlotCluster cluster = area.getCluster(args[1]); 690 if (cluster == null) { 691 player.sendMessage( 692 TranslatableCaption.of("cluster.invalid_cluster_name"), 693 Template.of("cluster", args[1]) 694 ); 695 return false; 696 } 697 UUID uuid = player.getUUID(); 698 if (!cluster.isAdded(uuid)) { 699 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_TP_OTHER)) { 700 player.sendMessage( 701 TranslatableCaption.of("permission.no_permission"), 702 Template.of("node", Permission.PERMISSION_CLUSTER_TP_OTHER.toString()) 703 ); 704 return false; 705 } 706 } 707 cluster.getHome(home -> player.teleport(home, TeleportCause.COMMAND_CLUSTER_TELEPORT)); 708 player.sendMessage(TranslatableCaption.of("cluster.cluster_teleporting")); 709 return true; 710 } 711 case "i": 712 case "info": 713 case "show": 714 case "information": { 715 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_INFO)) { 716 player.sendMessage( 717 TranslatableCaption.of("permission.no_permission"), 718 Template.of("node", Permission.PERMISSION_CLUSTER_TP.toString()) 719 ); 720 return false; 721 } 722 if (args.length != 1 && args.length != 2) { 723 player.sendMessage( 724 TranslatableCaption.of("commandconfig.command_syntax"), 725 Template.of("value", "/plot cluster info [name]") 726 ); 727 } 728 PlotArea area = player.getApplicablePlotArea(); 729 if (area == null) { 730 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 731 return false; 732 } 733 PlotCluster cluster; 734 if (args.length == 2) { 735 cluster = area.getCluster(args[1]); 736 if (cluster == null) { 737 player.sendMessage( 738 TranslatableCaption.of("cluster.invalid_cluster_name"), 739 Template.of("cluster", args[1]) 740 ); 741 return false; 742 } 743 } else { 744 cluster = area.getCluster(player.getLocation()); 745 if (cluster == null) { 746 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 747 return false; 748 } 749 } 750 String id = cluster.toString(); 751 752 PlotSquared.get().getImpromptuUUIDPipeline() 753 .getSingle(cluster.owner, (username, throwable) -> { 754 if (throwable instanceof TimeoutException) { 755 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 756 } else { 757 final String owner; 758 if (username == null) { 759 owner = "unknown"; 760 } else { 761 owner = username; 762 } 763 String name = cluster.getName(); 764 String size = (cluster.getP2().getX() - cluster.getP1().getX() + 1) + "x" + ( 765 cluster.getP2().getY() - cluster.getP1().getY() + 1); 766 String rights = cluster.isAdded(player.getUUID()) + ""; 767 Caption message = TranslatableCaption.of("cluster.cluster_info"); 768 Template idTemplate = Template.of("id", id); 769 Template ownerTemplate = Template.of("owner", owner); 770 Template nameTemplate = Template.of("name", name); 771 Template sizeTemplate = Template.of("size", size); 772 Template rightsTemplate = Template.of("rights", rights); 773 player.sendMessage( 774 message, 775 idTemplate, 776 ownerTemplate, 777 nameTemplate, 778 sizeTemplate, 779 rightsTemplate 780 ); 781 } 782 }); 783 return true; 784 } 785 case "sh": 786 case "setspawn": 787 case "sethome": { 788 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_SETHOME)) { 789 player.sendMessage( 790 TranslatableCaption.of("permission.no_permission"), 791 Template.of("node", Permission.PERMISSION_CLUSTER_SETHOME.toString()) 792 ); 793 return false; 794 } 795 if (args.length != 1 && args.length != 2) { 796 player.sendMessage( 797 TranslatableCaption.of("commandconfig.command_syntax"), 798 Template.of("value", "/plot cluster sethome") 799 ); 800 return false; 801 } 802 PlotArea area = player.getApplicablePlotArea(); 803 if (area == null) { 804 player.sendMessage(TranslatableCaption.of("errors.not_in_plot_world")); 805 } 806 PlotCluster cluster = area.getCluster(player.getLocation()); 807 if (cluster == null) { 808 player.sendMessage(TranslatableCaption.of("errors.not_in_cluster")); 809 return false; 810 } 811 if (!cluster.hasHelperRights(player.getUUID())) { 812 if (!player.hasPermission(Permission.PERMISSION_CLUSTER_SETHOME_OTHER)) { 813 player.sendMessage( 814 TranslatableCaption.of("permission.no_permission"), 815 Template.of("node", Permission.PERMISSION_CLUSTER_SETHOME_OTHER.toString()) 816 ); 817 return false; 818 } 819 } 820 Location base = cluster.getClusterBottom(); 821 Location relative = player.getLocation().subtract(base.getX(), 0, base.getZ()); 822 BlockLoc blockloc = new BlockLoc(relative.getX(), relative.getY(), relative.getZ()); 823 cluster.settings.setPosition(blockloc); 824 DBFunc.setPosition( 825 cluster, 826 relative.getX() + "," + relative.getY() + "," + relative.getZ() 827 ); 828 player.sendMessage(TranslatableCaption.of("position.position_set")); 829 return true; 830 } 831 } 832 player.sendMessage( 833 TranslatableCaption.of("cluster.cluster_available_args"), 834 Template.of( 835 "list", 836 "<dark_aqua>list</dark_aqua><gray>, </gray><dark_aqua>create</dark_aqua><gray>, </gray><dark_aqua>delete</dark_aqua><gray>, </gray><dark_aqua>resize</dark_aqua><gray>, </gray><dark_aqua>invite</dark_aqua><gray>, </gray><dark_aqua>kick</dark_aqua><gray>, </gray><dark_aqua>leave</dark_aqua><gray>, </gray><dark_aqua>members</dark_aqua><gray>, </gray><dark_aqua>info</dark_aqua><gray>, </gray><dark_aqua>tp</dark_aqua><gray>, </gray><dark_aqua>sethome</dark_aqua>" 837 ) 838 ); 839 return false; 840 } 841 842 private void removePlayerPlots(final PlotCluster cluster, final UUID uuid, final String world) { 843 for (final Plot plot : PlotQuery.newQuery().inWorld(world).ownedBy(uuid)) { 844 PlotCluster current = plot.getCluster(); 845 if (current != null && current.equals(cluster)) { 846 if (plot.getOwners().size() == 1) { 847 plot.unclaim(); 848 } else { 849 for (UUID newOwner : plot.getOwners()) { 850 if (!newOwner.equals(uuid)) { 851 plot.setOwner(newOwner); 852 break; 853 } 854 } 855 } 856 } 857 } 858 } 859 860 @Override 861 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 862 if (args.length == 1) { 863 final List<String> completions = new LinkedList<>(); 864 if (player.hasPermission(Permission.PERMISSION_CLUSTER_LIST)) { 865 completions.add("list"); 866 } 867 if (player.hasPermission(Permission.PERMISSION_CLUSTER_CREATE)) { 868 completions.add("create"); 869 } 870 if (player.hasPermission(Permission.PERMISSION_CLUSTER_DELETE)) { 871 completions.add("delete"); 872 } 873 if (player.hasPermission(Permission.PERMISSION_CLUSTER_RESIZE)) { 874 completions.add("resize"); 875 } 876 if (player.hasPermission(Permission.PERMISSION_CLUSTER_INVITE)) { 877 completions.add("invite"); 878 } 879 if (player.hasPermission(Permission.PERMISSION_CLUSTER_KICK)) { 880 completions.add("kick"); 881 } 882 if (player.hasPermission(Permission.PERMISSION_CLUSTER_KICK)) { 883 completions.add("leave"); 884 } 885 if (player.hasPermission(Permission.PERMISSION_CLUSTER_HELPERS)) { 886 completions.add("members"); 887 } 888 if (player.hasPermission(Permission.PERMISSION_CLUSTER_INFO)) { 889 completions.add("info"); 890 } 891 if (player.hasPermission(Permission.PERMISSION_CLUSTER_TP)) { 892 completions.add("tp"); 893 } 894 if (player.hasPermission(Permission.PERMISSION_CLUSTER_SETHOME)) { 895 completions.add("sethome"); 896 } 897 final List<Command> commands = completions.stream().filter(completion -> completion 898 .toLowerCase() 899 .startsWith(args[0].toLowerCase())) 900 .map(completion -> new Command( 901 null, 902 true, 903 completion, 904 "", 905 RequiredType.NONE, 906 CommandCategory.ADMINISTRATION 907 ) { 908 }).collect(Collectors.toCollection(LinkedList::new)); 909 if (player.hasPermission(Permission.PERMISSION_CLUSTER) && args[0].length() > 0) { 910 commands.addAll(TabCompletions.completePlayers(player, args[0], Collections.emptyList())); 911 } 912 return commands; 913 } 914 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 915 } 916 917}