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.common.primitives.Ints; 022import com.plotsquared.core.PlotSquared; 023import com.plotsquared.core.configuration.caption.TranslatableCaption; 024import com.plotsquared.core.database.DBFunc; 025import com.plotsquared.core.permissions.Permission; 026import com.plotsquared.core.player.MetaDataAccess; 027import com.plotsquared.core.player.PlayerMetaDataKeys; 028import com.plotsquared.core.player.PlotPlayer; 029import com.plotsquared.core.util.PlayerManager; 030import com.plotsquared.core.util.TabCompletions; 031import com.plotsquared.core.util.task.RunnableVal; 032import com.plotsquared.core.util.task.RunnableVal2; 033import com.plotsquared.core.util.task.RunnableVal3; 034import net.kyori.adventure.text.minimessage.Template; 035 036import java.util.Collection; 037import java.util.Collections; 038import java.util.LinkedList; 039import java.util.List; 040import java.util.Map; 041import java.util.UUID; 042import java.util.concurrent.CompletableFuture; 043import java.util.concurrent.TimeoutException; 044import java.util.stream.Collectors; 045 046@CommandDeclaration(command = "grant", 047 category = CommandCategory.CLAIMING, 048 usage = "/plot grant <check | add> [player]", 049 permission = "plots.grant", 050 requiredType = RequiredType.NONE) 051public class Grant extends Command { 052 053 public Grant() { 054 super(MainCommand.getInstance(), true); 055 } 056 057 @Override 058 public CompletableFuture<Boolean> execute( 059 final PlotPlayer<?> player, String[] args, 060 RunnableVal3<Command, Runnable, Runnable> confirm, 061 RunnableVal2<Command, CommandResult> whenDone 062 ) throws CommandException { 063 checkTrue( 064 args.length >= 1 && args.length <= 2, 065 TranslatableCaption.of("commandconfig.command_syntax"), 066 Template.of("value", "/plot grant <check | add> [player]") 067 ); 068 final String arg0 = args[0].toLowerCase(); 069 switch (arg0) { 070 case "add", "check" -> { 071 if (!player.hasPermission(Permission.PERMISSION_GRANT.format(arg0))) { 072 player.sendMessage( 073 TranslatableCaption.of("permission.no_permission"), 074 Template.of("node", Permission.PERMISSION_GRANT.format(arg0)) 075 ); 076 return CompletableFuture.completedFuture(false); 077 } 078 if (args.length != 2) { 079 break; 080 } 081 PlayerManager.getUUIDsFromString(args[1], (uuids, throwable) -> { 082 if (throwable instanceof TimeoutException) { 083 player.sendMessage(TranslatableCaption.of("players.fetching_players_timeout")); 084 } else if (throwable != null || uuids.size() != 1) { 085 player.sendMessage( 086 TranslatableCaption.of("errors.invalid_player"), 087 Template.of("value", String.valueOf(uuids)) 088 ); 089 } else { 090 final UUID uuid = uuids.iterator().next(); 091 PlotPlayer<?> pp = PlotSquared.platform().playerManager().getPlayerIfExists(uuid); 092 if (pp != null) { 093 try (final MetaDataAccess<Integer> access = pp.accessPersistentMetaData( 094 PlayerMetaDataKeys.PERSISTENT_GRANTED_PLOTS)) { 095 if (args[0].equalsIgnoreCase("check")) { 096 player.sendMessage( 097 TranslatableCaption.of("grants.granted_plots"), 098 Template.of("amount", String.valueOf(access.get().orElse(0))) 099 ); 100 } else { 101 access.set(access.get().orElse(0) + 1); 102 } 103 } 104 } else { 105 DBFunc.getPersistentMeta(uuid, new RunnableVal<>() { 106 @Override 107 public void run(Map<String, byte[]> value) { 108 final byte[] array = value.get("grantedPlots"); 109 if (arg0.equals("check")) { // check 110 int granted; 111 if (array == null) { 112 granted = 0; 113 } else { 114 granted = Ints.fromByteArray(array); 115 } 116 player.sendMessage( 117 TranslatableCaption.of("grants.granted_plots"), 118 Template.of("amount", String.valueOf(granted)) 119 ); 120 } else { // add 121 int amount; 122 if (array == null) { 123 amount = 1; 124 } else { 125 amount = 1 + Ints.fromByteArray(array); 126 } 127 boolean replace = array != null; 128 String key = "grantedPlots"; 129 byte[] rawData = Ints.toByteArray(amount); 130 DBFunc.addPersistentMeta(uuid, key, rawData, replace); 131 player.sendMessage( 132 TranslatableCaption.of("grants.added"), 133 Template.of("grants", String.valueOf(amount)) 134 ); 135 } 136 } 137 }); 138 } 139 } 140 }); 141 return CompletableFuture.completedFuture(true); 142 } 143 } 144 sendUsage(player); 145 return CompletableFuture.completedFuture(true); 146 } 147 148 @Override 149 public Collection<Command> tab(final PlotPlayer<?> player, final String[] args, final boolean space) { 150 if (args.length == 1) { 151 final List<String> completions = new LinkedList<>(); 152 if (player.hasPermission(Permission.PERMISSION_GRANT_ADD)) { 153 completions.add("add"); 154 } 155 if (player.hasPermission(Permission.PERMISSION_GRANT_CHECK)) { 156 completions.add("check"); 157 } 158 final List<Command> commands = completions.stream().filter(completion -> completion 159 .toLowerCase() 160 .startsWith(args[0].toLowerCase())) 161 .map(completion -> new Command( 162 null, 163 true, 164 completion, 165 "", 166 RequiredType.NONE, 167 CommandCategory.ADMINISTRATION 168 ) { 169 }).collect(Collectors.toCollection(LinkedList::new)); 170 if (player.hasPermission(Permission.PERMISSION_GRANT_SINGLE) && args[0].length() > 0) { 171 commands.addAll(TabCompletions.completePlayers(player, args[0], Collections.emptyList())); 172 } 173 return commands; 174 } 175 return TabCompletions.completePlayers(player, String.join(",", args).trim(), Collections.emptyList()); 176 } 177 178}