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.google.inject.Inject; 022import com.plotsquared.core.PlotSquared; 023import com.plotsquared.core.configuration.Settings; 024import com.plotsquared.core.configuration.caption.TranslatableCaption; 025import com.plotsquared.core.events.PlotChangeOwnerEvent; 026import com.plotsquared.core.events.PlotUnlinkEvent; 027import com.plotsquared.core.events.Result; 028import com.plotsquared.core.permissions.Permission; 029import com.plotsquared.core.player.MetaDataAccess; 030import com.plotsquared.core.player.PlayerMetaDataKeys; 031import com.plotsquared.core.player.PlotPlayer; 032import com.plotsquared.core.plot.Plot; 033import com.plotsquared.core.util.EventDispatcher; 034import com.plotsquared.core.util.PlayerManager; 035import com.plotsquared.core.util.TabCompletions; 036import com.plotsquared.core.util.task.TaskManager; 037import net.kyori.adventure.text.minimessage.Template; 038import org.checkerframework.checker.nullness.qual.NonNull; 039import org.checkerframework.checker.nullness.qual.Nullable; 040 041import java.util.Collection; 042import java.util.Collections; 043import java.util.Set; 044import java.util.UUID; 045import java.util.function.Consumer; 046 047@CommandDeclaration(command = "setowner", 048 permission = "plots.admin.command.setowner", 049 usage = "/plot setowner <player>", 050 aliases = {"owner", "so", "seto"}, 051 category = CommandCategory.CLAIMING, 052 requiredType = RequiredType.NONE, 053 confirmation = true) 054public class Owner extends SetCommand { 055 056 private final EventDispatcher eventDispatcher; 057 058 @Inject 059 public Owner(final @NonNull EventDispatcher eventDispatcher) { 060 this.eventDispatcher = eventDispatcher; 061 } 062 063 @Override 064 public boolean set(final PlotPlayer<?> player, final Plot plot, String value) { 065 if (value == null || value.isEmpty()) { 066 player.sendMessage( 067 TranslatableCaption.of("commandconfig.command_syntax"), 068 Template.of("value", "/plot setowner <owner>") 069 ); 070 return false; 071 } 072 @Nullable final UUID oldOwner = plot.getOwnerAbs(); 073 Set<Plot> plots = plot.getConnectedPlots(); 074 075 final Consumer<UUID> uuidConsumer = uuid -> { 076 if (uuid == null && !value.equalsIgnoreCase("none") && !value.equalsIgnoreCase("null") 077 && !value.equalsIgnoreCase("-")) { 078 player.sendMessage( 079 TranslatableCaption.of("errors.invalid_player"), 080 Template.of("value", value) 081 ); 082 return; 083 } 084 PlotChangeOwnerEvent event = this.eventDispatcher.callOwnerChange( 085 player, 086 plot, 087 plot.hasOwner() ? plot.getOwnerAbs() : null, 088 uuid, 089 plot.hasOwner() 090 ); 091 if (event.getEventResult() == Result.DENY) { 092 player.sendMessage( 093 TranslatableCaption.of("events.event_denied"), 094 Template.of("value", "Owner change") 095 ); 096 return; 097 } 098 uuid = event.getNewOwner(); 099 boolean force = event.getEventResult() == Result.FORCE; 100 if (uuid == null) { 101 if (!force && !player.hasPermission( 102 Permission.PERMISSION_ADMIN_COMMAND_SET_OWNER, 103 true 104 )) { 105 return; 106 } 107 PlotUnlinkEvent unlinkEvent = this.eventDispatcher.callUnlink( 108 plot.getArea(), 109 plot, 110 false, 111 false, 112 PlotUnlinkEvent.REASON.NEW_OWNER 113 ); 114 if (unlinkEvent.getEventResult() == Result.DENY) { 115 player.sendMessage( 116 TranslatableCaption.of("events.event_denied"), 117 Template.of("value", "Unlink on owner change") 118 ); 119 return; 120 } 121 if (plot.getPlotModificationManager().unlinkPlot(unlinkEvent.isCreateRoad(), unlinkEvent.isCreateRoad())) { 122 eventDispatcher.callPostUnlink(plot, PlotUnlinkEvent.REASON.NEW_OWNER); 123 } 124 Set<Plot> connected = plot.getConnectedPlots(); 125 for (Plot current : connected) { 126 current.unclaim(); 127 current.getPlotModificationManager().removeSign(); 128 } 129 eventDispatcher.callPostOwnerChange(player, plot, oldOwner); 130 player.sendMessage(TranslatableCaption.of("owner.set_owner")); 131 return; 132 } 133 final PlotPlayer<?> other = PlotSquared.platform().playerManager().getPlayerIfExists(uuid); 134 if (plot.isOwner(uuid)) { 135 player.sendMessage( 136 TranslatableCaption.of("member.already_owner"), 137 Template.of("player", PlayerManager.resolveName(uuid, false).getComponent(player)) 138 ); 139 return; 140 } 141 if (!force && !player.hasPermission(Permission.PERMISSION_ADMIN_COMMAND_SET_OWNER)) { 142 if (other == null) { 143 player.sendMessage( 144 TranslatableCaption.of("errors.invalid_player_offline"), 145 Template.of("player", PlayerManager.resolveName(uuid).getComponent(player)) 146 ); 147 return; 148 } 149 int size = plots.size(); 150 int currentPlots = (Settings.Limit.GLOBAL ? 151 other.getPlotCount() : 152 other.getPlotCount(plot.getWorldName())) + size; 153 try (final MetaDataAccess<Integer> metaDataAccess = player.accessPersistentMetaData(PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { 154 int grants; 155 if (currentPlots >= other.getAllowedPlots()) { 156 if (metaDataAccess.isPresent()) { 157 grants = metaDataAccess.get().orElse(0); 158 if (grants <= 0) { 159 metaDataAccess.remove(); 160 player.sendMessage(TranslatableCaption.of("permission.cant_transfer_more_plots")); 161 return; 162 } 163 } 164 } 165 } 166 } 167 final UUID finalUUID = uuid; 168 PlotSquared.get().getImpromptuUUIDPipeline().getSingle(uuid, (finalName, throwable) -> { 169 final boolean removeDenied = plot.isDenied(finalUUID); 170 Runnable run = () -> { 171 if (plot.setOwner(finalUUID, player)) { 172 if (removeDenied) { 173 plot.removeDenied(finalUUID); 174 } 175 plot.getPlotModificationManager().setSign(finalName); 176 player.sendMessage(TranslatableCaption.of("owner.set_owner")); 177 eventDispatcher.callPostOwnerChange(player, plot, oldOwner); 178 if (other != null) { 179 other.sendMessage( 180 TranslatableCaption.of("owner.now_owner"), 181 Template.of("plot", plot.getArea() + ";" + plot.getId()) 182 ); 183 } 184 } else { 185 player.sendMessage(TranslatableCaption.of("owner.set_owner_cancelled")); 186 } 187 }; 188 if (hasConfirmation(player)) { 189 CmdConfirm.addPending(player, "/plot setowner " + value, run); 190 } else { 191 TaskManager.runTask(run); 192 } 193 }); 194 }; 195 196 if (value.length() == 36) { 197 try { 198 uuidConsumer.accept(UUID.fromString(value)); 199 } catch (Exception ignored) { 200 } 201 } else { 202 PlotSquared.get().getImpromptuUUIDPipeline().getSingle(value, (uuid, throwable) -> uuidConsumer.accept(uuid)); 203 } 204 return true; 205 } 206 207 @Override 208 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 209 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 210 } 211 212}