Add bukkit source.

This commit is contained in:
bloodshot 2019-07-23 23:31:17 -04:00
parent 782b6ccad9
commit 8a8d4dd08c
211 changed files with 48268 additions and 0 deletions

View File

@ -0,0 +1,202 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import com.griefdefender.util.BootstrapUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class GDBootstrap extends JavaPlugin {
private Map<String, File> jarMap = new HashMap<>();
private List<String> relocateList = new ArrayList<>();
private static GDBootstrap instance;
private static final String LIB_ROOT_PATH = "./plugins/GriefDefender/lib/";
private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7";
public static GDBootstrap getInstance() {
return instance;
}
@Override
public void onEnable() {
instance = this;
final JSONParser parser = new JSONParser();
String bukkitJsonVersion = null;
this.getLogger().info("Loading libraries...");
if (Bukkit.getVersion().contains("1.8.8")) {
bukkitJsonVersion = "1.8.8";
} else if (Bukkit.getVersion().contains("1.12.2")) {
bukkitJsonVersion = "1.12.2";
} else if (Bukkit.getVersion().contains("1.13.2")) {
bukkitJsonVersion = "1.13.2";
} else if (Bukkit.getVersion().contains("1.14.2")) {
bukkitJsonVersion = "1.14.2";
} else if (Bukkit.getVersion().contains("1.14.3")) {
bukkitJsonVersion = "1.14.3";
} else if (Bukkit.getVersion().contains("1.14.4")) {
bukkitJsonVersion = "1.14.4";
} else {
this.getLogger().severe("Detected unsupported version '" + Bukkit.getVersion() + "'. GriefDefender only supports 1.8.8, 1.12.2, 1.13.2, and 1.14.2. GriefDefender will NOT load.");
return;
}
try {
final InputStream in = getClass().getResourceAsStream("/" + bukkitJsonVersion + ".json");
final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
final JSONObject a = (JSONObject) parser.parse(reader);
final JSONArray libraries = (JSONArray) a.get("libraries");
if (libraries == null) {
this.getLogger().severe("Resource " + bukkitJsonVersion + ".json is corrupted!. Please contact author for assistance.");
return;
}
final Iterator<JSONObject> iterator = libraries.iterator();
while (iterator.hasNext()) {
JSONObject lib = iterator.next();
final String name = (String) lib.get("name");
final String sha1 = (String) lib.get("sha1");
final String path = (String) lib.get("path");
final String relocate = (String) lib.get("relocate");
final String url = (String) lib.get("url");
final Path libPath = Paths.get(LIB_ROOT_PATH).resolve(path);
final File file = libPath.toFile();
downloadLibrary(name, relocate, sha1, url, libPath);
}
} catch (Throwable t) {
t.printStackTrace();
}
// Inject jar-relocator and asm debug
injectRelocatorDeps();
// Relocate all GD dependencies and inject
GDRelocator.getInstance().relocateJars(this.jarMap);
// Boot GD
GriefDefenderPlugin.getInstance().onEnable();
}
public List<String> getRelocateList() {
return this.relocateList;
}
@Override
public void onDisable() {
GriefDefenderPlugin.getInstance().onDisable();
}
private void injectRelocatorDeps() {
String name = "org.ow2.asm:asm-debug-all:5.2";
File file = this.jarMap.get(name);
BootstrapUtil.addUrlToClassLoader(name, file);
name = "me.lucko:jar-relocator:1.3";
file = this.jarMap.get(name);
BootstrapUtil.addUrlToClassLoader(name, file);
}
public void downloadLibrary(String name, String relocate, String sha1, String url, Path libPath) {
final File file = libPath.toFile();
this.jarMap.put(name, file);
if (relocate != null && !relocate.isEmpty() && relocate.contains(":")) {
this.relocateList.add(relocate);
}
if (!Files.exists(libPath)) {
this.getLogger().info("Downloading library " + name + " ...");
try {
URL website = new URL(url);
URLConnection urlConnection = website.openConnection();
// Some maven repos like nexus require a user agent so we just pass one to satisfy it
urlConnection.setRequestProperty("User-Agent", USER_AGENT);
ReadableByteChannel rbc = Channels.newChannel(urlConnection.getInputStream());
if (!Files.exists(libPath)) {
file.getParentFile().mkdirs();
}
FileOutputStream fos = new FileOutputStream(file);
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
fos.close();
} catch (IOException e) {
this.getLogger().severe("An error occured while downloading library '" + name + "'. Skipping...");
e.printStackTrace();
return;
}
final String hash = getLibraryHash(file);
if (hash == null || !sha1.equals(hash)) {
this.getLogger().severe("Detected invalid hash '" + hash + "' for file '" + libPath + "'. Expected '" + sha1 + "'. Skipping...");
try {
Files.delete(libPath);
return;
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
this.jarMap.put(name, file);
}
private String getLibraryHash(File file) {
try {
final MessageDigest md = MessageDigest.getInstance("SHA-1");
final byte[] data = Files.readAllBytes(file.toPath());
final byte[] b = md.digest(data);
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < b.length; i++) {
if ((0xff & b[i]) < 0x10) {
buffer.append("0" + Integer.toHexString((0xFF & b[i])));
} else {
buffer.append(Integer.toHexString(0xFF & b[i]));
}
}
return buffer.toString();
} catch (Throwable t) {
t.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,76 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.StringJoiner;
import com.griefdefender.api.CatalogType;
public abstract class GDCatalogType implements CatalogType {
private final String id;
public GDCatalogType(String id) {
this.id = checkNotNull(id, "id");
}
@Override
public final String getId() {
return this.id;
}
@Override
public String getName() {
return getId();
}
@Override
public final int hashCode() {
return this.id.hashCode();
}
@Override
public final boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final CatalogType other = (CatalogType) obj;
return getId().equals(other.getId());
}
@Override
public String toString() {
return new StringJoiner(", ", GDCatalogType.class.getSimpleName() + "[", "]")
.add("id=" + getId())
.add("name=" + getName())
.toString();
}
}

View File

@ -0,0 +1,85 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import com.google.common.collect.ImmutableList;
import com.google.inject.Singleton;
import com.griefdefender.api.Core;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimBlockSystem;
import com.griefdefender.api.claim.ClaimManager;
import com.griefdefender.api.data.PlayerData;
import com.griefdefender.api.permission.flag.Flag;
import org.bukkit.Bukkit;
import org.bukkit.World;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
@Singleton
public class GDCore implements Core {
@Override
public boolean isEnabled(UUID worldUniqueId) {
return GriefDefenderPlugin.getInstance().claimsEnabledForWorld(worldUniqueId);
}
@Override
public ClaimBlockSystem getClaimBlockSystem() {
return GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.claimBlockSystem;
}
@Override
public boolean isEconomyModeEnabled() {
return GriefDefenderPlugin.getInstance().isEconomyModeEnabled();
}
@Override
public boolean isProtectionModuleEnabled(Flag flag) {
return GriefDefenderPlugin.getGlobalConfig().getConfig().modules.isProtectionModuleEnabled(flag.toString());
}
@Override
public ClaimManager getClaimManager(UUID worldUniqueId) {
return GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(worldUniqueId);
}
@Override
public Optional<PlayerData> getPlayerData(UUID worldUniqueId, UUID playerUniqueId) {
return Optional.ofNullable(GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(worldUniqueId, playerUniqueId));
}
@Override
public List<Claim> getAllPlayerClaims(UUID playerUniqueId) {
List<Claim> claimList = new ArrayList<>();
for (World world : Bukkit.getServer().getWorlds()) {
claimList.addAll(this.getClaimManager(world.getUID()).getPlayerClaims(playerUniqueId));
}
return ImmutableList.copyOf(claimList);
}
}

View File

@ -0,0 +1,206 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.griefdefender.api.Tristate;
import com.griefdefender.util.HttpClient;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.format.TextColor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.GZIPOutputStream;
public class GDDebugData {
private static final String BYTEBIN_ENDPOINT = "https://bytebin.lucko.me/post";
private static final String DEBUG_VIEWER_URL = "https://griefprevention.github.io/debug/?";
private static final MediaType PLAIN_TYPE = MediaType.parse("text/plain; charset=utf-8");
private static final int MAX_LINES = 5000;
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
private static final Component GD_TEXT = TextComponent.builder("").append("[", TextColor.WHITE).append("GD", TextColor.AQUA).append("] ", TextColor.WHITE).build();
private final CommandSender source;
private final List<String> header;
private final List<String> records;
private final long startTime = System.currentTimeMillis();
private boolean verbose;
private OfflinePlayer target;
public GDDebugData(CommandSender source, OfflinePlayer target, boolean verbose) {
this.source = source;
this.target = target;
this.verbose = verbose;
this.records = new ArrayList<>();
this.header = new ArrayList<>();
this.header.add("# GriefDefender Debug Log");
this.header.add("#### This file was automatically generated by [GriefDefender](https://github.com/MinecraftPortCentral/GriefDefender) ");
this.header.add("");
this.header.add("### Metadata");
this.header.add("| Key | Value |");
this.header.add("|-----|-------|");
this.header.add("| GD Version | " + GriefDefenderPlugin.IMPLEMENTATION_VERSION + "|");
this.header.add("| Bukkit Version | " + Bukkit.getVersion() + "|");
final Plugin lpContainer = Bukkit.getPluginManager().getPlugin("luckperms");
if (lpContainer != null) {
final String version = lpContainer.getDescription().getVersion();
if (version != null) {
this.header.add("| LuckPerms Version | " + version);
}
}
this.header.add("| User | " + (this.target == null ? "ALL" : this.target.getName()) + "|");
this.header.add("| Record start | " + DATE_FORMAT.format(new Date(this.startTime)) + "|");
}
public void addRecord(String flag, String trust, String source, String target, String location, String user, String permission, Tristate result) {
if (this.records.size() < MAX_LINES) {
this.records.add("| " + flag + " | " + trust + " | " + source + " | " + target + " | " + location + " | " + user + " | " + permission + " | " + result + " | ");
} else {
TextAdapter.sendComponent(this.source, TextComponent.builder("").append("MAX DEBUG LIMIT REACHED!").append("\n")
.append("Pasting output...", TextColor.GREEN).build());
this.pasteRecords();
this.records.clear();
GriefDefenderPlugin.debugActive = false;
TextAdapter.sendComponent(this.source, TextComponent.builder("").append(GD_TEXT).append("Debug ", TextColor.GRAY).append("OFF", TextColor.RED).build());
}
}
public CommandSender getSource() {
return this.source;
}
public OfflinePlayer getTarget() {
return this.target;
}
public boolean isRecording() {
return !this.verbose;
}
public void setTarget(OfflinePlayer user) {
this.target = user;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
public void pasteRecords() {
if (this.records.isEmpty()) {
TextAdapter.sendComponent(this.source, TextComponent.of("No debug records to paste!", TextColor.RED));
return;
}
final long endTime = System.currentTimeMillis();
List<String> debugOutput = new ArrayList<>(this.header);
debugOutput.add("| Record end | " + DATE_FORMAT.format(new Date(endTime)) + "|");
long elapsed = (endTime - startTime) / 1000L;
debugOutput.add("| Time elapsed | " + elapsed + " seconds" + "|");
debugOutput.add("");
debugOutput.add("### Output") ;
debugOutput.add("| Flag | Trust | Source | Target | Location | User | Permission | Result |");
debugOutput.add("|------|-------|--------|--------|----------|------|------------|--------|");
debugOutput.addAll(this.records);
String content = String.join("\n", debugOutput);
String pasteId;
try {
pasteId = postContent(content);
} catch (Exception e) {
TextAdapter.sendComponent(this.source, TextComponent.builder("").append("Error uploading content : ", TextColor.RED).append(e.getMessage(), TextColor.WHITE).build());
return;
}
String url = DEBUG_VIEWER_URL + pasteId;
URL jUrl;
try {
jUrl = new URL(url);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
TextAdapter.sendComponent(this.source, TextComponent.builder("").append("Paste success! : " + url, TextColor.GREEN)
.clickEvent(ClickEvent.openUrl(jUrl.toString())).build());
}
private static String postContent(String content) throws IOException {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
try (GZIPOutputStream writer = new GZIPOutputStream(byteOut)) {
writer.write(content.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
throw new RuntimeException(e);
}
RequestBody body = RequestBody.create(PLAIN_TYPE, byteOut.toByteArray());
Request.Builder requestBuilder = new Request.Builder()
.url(BYTEBIN_ENDPOINT)
.header("Content-Encoding", "gzip")
.post(body);
Request request = requestBuilder.build();
try (Response response = HttpClient.makeCall(request)) {
try (ResponseBody responseBody = response.body()) {
if (responseBody == null) {
throw new RuntimeException("No response");
}
try (InputStream inputStream = responseBody.byteStream()) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
JsonObject object = new Gson().fromJson(reader, JsonObject.class);
return object.get("key").getAsString();
}
}
}
}
}
}

View File

@ -0,0 +1,67 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import com.google.inject.Singleton;
import com.griefdefender.api.event.Event;
import com.griefdefender.api.event.EventManager;
import net.kyori.event.EventBus;
import net.kyori.event.SimpleEventBus;
import net.kyori.event.method.MethodSubscriptionAdapter;
import net.kyori.event.method.SimpleMethodSubscriptionAdapter;
import net.kyori.event.method.asm.ASMEventExecutorFactory;
@Singleton
public class GDEventManager implements EventManager {
private final EventBus<Event> bus;
private final MethodSubscriptionAdapter<Object> adapter;
public GDEventManager() {
this.bus = new SimpleEventBus<Event>(Event.class);
this.adapter = new SimpleMethodSubscriptionAdapter<>(bus, new ASMEventExecutorFactory<>());
}
@Override
public EventBus<Event> getBus() {
return this.bus;
}
@Override
public void post(Event event) {
this.bus.post(event);
}
@Override
public void register(Object listener) {
this.adapter.register(listener);
}
@Override
public void unregister(Object listener) {
this.adapter.unregister(listener);
}
}

View File

@ -0,0 +1,601 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ShovelType;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.api.data.PlayerData;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.configuration.GriefDefenderConfig;
import com.griefdefender.configuration.PlayerStorageData;
import com.griefdefender.internal.block.BlockSnapshot;
import com.griefdefender.internal.block.BlockTransaction;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.provider.VaultProvider;
import com.griefdefender.util.PermissionUtil;
import me.lucko.luckperms.api.context.MutableContextSet;
import net.kyori.text.Component;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class GDPlayerData implements PlayerData {
public UUID playerID;
public UUID worldUniqueId;
private WeakReference<GDPermissionUser> playerSubject;
private Set<Claim> claimList;
private PlayerStorageData playerStorage;
public Location lastAfkCheckLocation;
public Location lastShovelLocation;
public Location endShovelLocation;
public Location lastValidInspectLocation;
public ShovelType shovelMode = ShovelTypes.BASIC;
public GDClaim claimResizing;
public GDClaim claimSubdividing;
public List<BlockTransaction> visualBlocks;
public UUID visualClaimId;
public BukkitTask visualRevertTask;
private final VaultProvider vaultProvider = GriefDefenderPlugin.getInstance().getVaultProvider();
public boolean ignoreClaims = false;
public boolean debugClaimPermissions = false;
public WeakReference<GDClaim> lastClaim = new WeakReference<>(null);
public boolean inTown = false;
public boolean townChat = false;
// Always ignore active contexts by default
// This prevents protection issues when other plugins call getActiveContext
public boolean ignoreActiveContexts = true;
public boolean lastInteractResult = false;
public int lastTickCounter = 0;
public UUID lastInteractClaim = GriefDefenderPlugin.PUBLIC_UUID;
// collide event cache
public int lastCollideEntityId = 0;
public boolean lastCollideEntityResult = false;
private String playerName;
// cached global option values
public int minClaimLevel;
private Integer optionClaimCreateMode;
private Integer optionMaxAccruedBlocks;
// cached permission values
public boolean canManageAdminClaims = false;
public boolean canManageWilderness = false;
public boolean ignoreBorderCheck = false;
public boolean ignoreAdminClaims = false;
public boolean ignoreBasicClaims = false;
public boolean ignoreTowns = false;
public boolean ignoreWilderness = false;
public boolean dataInitialized = false;
public boolean showVisualFillers = true;
private boolean checkedDimensionHeight = false;
public GDPlayerData(UUID worldUniqueId, UUID playerUniqueId, PlayerStorageData playerStorage, GriefDefenderConfig<?> activeConfig, Set<Claim> claims) {
this.worldUniqueId = worldUniqueId;
this.playerID = playerUniqueId;
this.playerStorage = playerStorage;
this.claimList = claims;
this.refreshPlayerOptions();
}
// Run async
public void refreshPlayerOptions() {
//final GriefDefenderConfig<?> activeConfig = GriefDefenderPlugin.getActiveConfig(this.worldUniqueId);
GriefDefenderPlugin.getInstance().executor.execute(() -> {
if (this.playerSubject == null || this.playerSubject.get() == null) {
GDPermissionUser subject = PermissionHolderCache.getInstance().getOrCreateUser(this.playerID);
this.playerSubject = new WeakReference<>(subject);
}
final GDPermissionUser subject = this.playerSubject.get();
final MutableContextSet activeContexts = PermissionUtil.getInstance().getActiveContexts(subject);
// permissions
this.ignoreBorderCheck = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_BORDER_CHECK, activeContexts).asBoolean();
this.ignoreAdminClaims = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_ADMIN, activeContexts).asBoolean();
this.ignoreTowns = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_TOWN, activeContexts).asBoolean();
this.ignoreWilderness = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_WILDERNESS, activeContexts).asBoolean();
this.ignoreBasicClaims = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.IGNORE_CLAIMS_BASIC, activeContexts).asBoolean();
this.canManageAdminClaims = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.COMMAND_ADMIN_CLAIMS, activeContexts).asBoolean();
this.canManageWilderness = PermissionUtil.getInstance().getPermissionValue(subject, GDPermissions.MANAGE_WILDERNESS, activeContexts).asBoolean();
this.playerID = subject.getUniqueId();
/*if (this.optionMaxClaimLevel > 255 || this.optionMaxClaimLevel <= 0 || this.optionMaxClaimLevel < this.optionMinClaimLevel) {
this.optionMaxClaimLevel = 255;
}
if (this.optionMinClaimLevel < 0 || this.optionMinClaimLevel >= 255 || this.optionMinClaimLevel > this.optionMaxClaimLevel) {
this.optionMinClaimLevel = 0;
}*/
this.dataInitialized = true;
this.checkedDimensionHeight = false;
});
}
public String getPlayerName() {
if (this.playerName == null) {
GDPermissionUser user = this.playerSubject.get();
if (user == null) {
user = PermissionHolderCache.getInstance().getOrCreateUser(this.playerID);
}
if (user != null) {
this.playerName = user.getFriendlyName();
}
if (this.playerName == null) {
this.playerName = "[unknown]";
}
}
return this.playerName;
}
public void revertActiveVisual(Player player) {
if (this.visualRevertTask != null) {
this.visualRevertTask.cancel();
this.visualRevertTask = null;
}
if (this.visualClaimId != null) {
GDClaim claim = (GDClaim) GriefDefenderPlugin.getInstance().dataStore.getClaim(this.worldUniqueId, this.visualClaimId);
if (claim != null) {
claim.playersWatching.remove(this.playerID);
}
}
this.visualClaimId = null;
if (this.visualBlocks == null || !player.getWorld().equals(this.visualBlocks.get(0).getFinal().getLocation().getWorld())) {
return;
}
for (int i = 0; i < this.visualBlocks.size(); i++) {
BlockSnapshot snapshot = this.visualBlocks.get(i).getOriginal();
NMSUtil.getInstance().sendBlockChange(player, snapshot);
}
}
@Override
public int getBlocksAccruedPerHour() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.BLOCKS_ACCRUED_PER_HOUR, this).intValue();
}
@Override
public int getChestClaimExpiration() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.CHEST_EXPIRATION, this).intValue();
}
@Override
public int getCreateClaimLimit(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.CREATE_LIMIT, type, this).intValue();
}
@Override
public int getInitialClaimBlocks() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.INITIAL_BLOCKS, this).intValue();
}
@Override
public int getRemainingClaimBlocks() {
final int initialClaimBlocks = GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.INITIAL_BLOCKS, this).intValue();
int remainingBlocks = initialClaimBlocks + this.getAccruedClaimBlocks() + this.getBonusClaimBlocks();
if (GriefDefenderPlugin.getGlobalConfig().getConfig().economy.economyMode) {
if (!this.vaultProvider.getApi().hasAccount(this.getSubject().getOfflinePlayer())) {
return 0;
}
final double currentFunds = this.vaultProvider.getApi().getBalance(this.getSubject().getOfflinePlayer());
final Double economyBlockCost = GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.ECONOMY_BLOCK_COST, this);
remainingBlocks = (int) Math.round((currentFunds / economyBlockCost));
} else {
for (Claim claim : this.claimList) {
if (claim.isSubdivision()) {
continue;
}
GDClaim gpClaim = (GDClaim) claim;
if ((gpClaim.parent == null || gpClaim.parent.isAdminClaim()) && claim.getData().requiresClaimBlocks()) {
remainingBlocks -= claim.getClaimBlocks();
}
}
}
return remainingBlocks;
}
public int getTotalClaimsCost() {
int totalCost = 0;
for (Claim claim : this.claimList) {
if (claim.isSubdivision()) {
continue;
}
final GDClaim gpClaim = (GDClaim) claim;
if ((gpClaim.parent == null || gpClaim.parent.isAdminClaim()) && claim.getData().requiresClaimBlocks()) {
totalCost += claim.getClaimBlocks();
}
}
return totalCost;
}
public double getRemainingChunks() {
final double remainingChunks = this.getRemainingClaimBlocks() / 65536.0;
return Math.round(remainingChunks * 100.0)/100.0;
}
@Override
public int getAccruedClaimBlocks() {
return this.playerStorage.getConfig().getAccruedClaimBlocks();
}
public boolean addAccruedClaimBlocks(int newAccruedClaimBlocks) {
int currentTotal = this.getAccruedClaimBlocks();
if ((currentTotal + newAccruedClaimBlocks) > this.getMaxAccruedClaimBlocks()) {
return false;
}
this.playerStorage.getConfig().setAccruedClaimBlocks(currentTotal + newAccruedClaimBlocks);
return true;
}
public boolean setAccruedClaimBlocks(int newAccruedClaimBlocks) {
if (newAccruedClaimBlocks > this.getMaxAccruedClaimBlocks()) {
return false;
}
this.playerStorage.getConfig().setAccruedClaimBlocks(newAccruedClaimBlocks);
return true;
}
public int getBonusClaimBlocks() {
return this.playerStorage.getConfig().getBonusClaimBlocks();
}
public void setBonusClaimBlocks(int bonusClaimBlocks) {
this.playerStorage.getConfig().setBonusClaimBlocks(bonusClaimBlocks);
}
public int getClaimCreateMode() {
if (this.optionClaimCreateMode == null) {
int mode = GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.CREATE_MODE, this).intValue();
// default to 0 if invalid
if (mode != 0 && mode != 1) {
mode = 0;
}
this.optionClaimCreateMode = mode;
}
return this.optionClaimCreateMode;
}
public void setClaimCreateMode(int mode) {
// default to 0 if invalid
if (mode != 0 && mode != 1) {
mode = 0;
}
this.optionClaimCreateMode = mode;
}
public boolean canCreateClaim(Player player) {
return canCreateClaim(player, false);
}
public boolean canCreateClaim(Player player, boolean sendMessage) {
final int createMode = this.getClaimCreateMode();
if (this.shovelMode == ShovelTypes.BASIC) {
if (createMode == 0 && !player.hasPermission(GDPermissions.CLAIM_CREATE_BASIC)) {
if (sendMessage) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionClaimCreate.toText());
}
return false;
}
if (createMode == 1 && !player.hasPermission(GDPermissions.CLAIM_CUBOID_BASIC)) {
if (sendMessage) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionCuboid.toText());
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimCuboidDisabled.toText());
}
return false;
}
} else if (this.shovelMode == ShovelTypes.SUBDIVISION) {
if (createMode == 0 && !player.hasPermission(GDPermissions.CLAIM_CREATE_SUBDIVISION)) {
if (sendMessage) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionClaimCreate.toText());
}
return false;
} else if (!player.hasPermission(GDPermissions.CLAIM_CUBOID_SUBDIVISION)) {
if (sendMessage) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionCuboid.toText());
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimCuboidDisabled.toText());
}
return false;
}
} else if (this.shovelMode == ShovelTypes.ADMIN) {
if (createMode == 0 && !player.hasPermission(GDPermissions.COMMAND_ADMIN_CLAIMS)) {
return false;
} else if (!player.hasPermission(GDPermissions.CLAIM_CUBOID_ADMIN)) {
return false;
}
} else if (this.shovelMode == ShovelTypes.TOWN) {
if (createMode == 0 && !player.hasPermission(GDPermissions.CLAIM_CREATE_TOWN)) {
return false;
} else if (!player.hasPermission(GDPermissions.CLAIM_CUBOID_TOWN)) {
return false;
}
}
return true;
}
public void saveAllData() {
this.playerStorage.save();
}
public PlayerStorageData getStorageData() {
return this.playerStorage;
}
public Set<Claim> getClaims() {
return ImmutableSet.copyOf(this.claimList);
}
public Set<Claim> getInternalClaims() {
return this.claimList;
}
public int getClaimTypeCount(ClaimType type) {
int count = 0;
for (Claim claim : this.claimList) {
if (claim.getType() == type) {
count++;
}
}
return count;
}
public void setLastCollideEntityData(int entityId, boolean result) {
this.lastCollideEntityId = entityId;
this.lastCollideEntityResult = result;
}
public void setLastInteractData(GDClaim claim) {
this.lastInteractResult = true;
this.lastInteractClaim = claim.getUniqueId();
this.lastTickCounter = NMSUtil.getInstance().getRunningServerTicks();
}
public boolean checkLastInteraction(GDClaim claim, GDPermissionUser user) {
if (this.lastInteractResult && user != null && (NMSUtil.getInstance().getRunningServerTicks() - this.lastTickCounter) <= 2) {
if (claim.getUniqueId().equals(this.lastInteractClaim) || claim.isWilderness()) {
return true;
}
}
return false;
}
public void setIgnoreClaims(boolean flag) {
this.ignoreClaims = flag;
}
@Override
public boolean canIgnoreClaim(Claim claim) {
if (claim == null || this.ignoreClaims == false) {
return false;
}
if (claim.isAdminClaim()) {
return this.ignoreAdminClaims;
} else if (claim.isWilderness()) {
return this.ignoreWilderness;
} else if (claim.isTown()) {
return this.ignoreTowns;
}
return this.ignoreBasicClaims;
}
public boolean canManageOption(Player player, GDClaim claim, boolean isGroup) {
if (claim.allowEdit(player) != null) {
return false;
}
if (claim.isWilderness()) {
return player.hasPermission(GDPermissions.MANAGE_WILDERNESS);
}
if (isGroup) {
if (claim.isTown() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_GROUP_TOWN)) {
return true;
}
if (claim.isAdminClaim() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_GROUP_ADMIN)) {
return true;
}
if (claim.isBasicClaim() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_GROUP_BASIC)) {
return true;
}
if (claim.isSubdivision() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_GROUP_SUBDIVISION)) {
return true;
}
} else {
if (claim.isTown() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_PLAYER_TOWN)) {
return true;
}
if (claim.isAdminClaim() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_PLAYER_ADMIN)) {
return true;
}
if (claim.isBasicClaim() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_PLAYER_BASIC)) {
return true;
}
if (claim.isSubdivision() && player.hasPermission(GDPermissions.COMMAND_OPTIONS_PLAYER_SUBDIVISION)) {
return true;
}
}
return false;
}
@Override
public int getMaxAccruedClaimBlocks() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.MAX_ACCRUED_BLOCKS, this).intValue();
}
@Override
public double getAbandonedReturnRatio(ClaimType type) {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.ABANDON_RETURN_RATIO, this);
}
@Override
public int getMaxClaimX(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.MAX_SIZE_X, type, this).intValue();
}
@Override
public int getMaxClaimY(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.MAX_SIZE_Y, type, this).intValue();
}
@Override
public int getMaxClaimZ(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.MAX_SIZE_Z, type, this).intValue();
}
@Override
public int getMinClaimX(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.MIN_SIZE_X, type, this).intValue();
}
@Override
public int getMinClaimY(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.MIN_SIZE_Y, type, this).intValue();
}
@Override
public int getMinClaimZ(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.MIN_SIZE_Z, type, this).intValue();
}
@Override
public int getMaxClaimLevel() {
int maxClaimLevel = GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.MAX_LEVEL, this).intValue();
if (!this.checkedDimensionHeight) {
final World world = Bukkit.getServer().getWorld(this.worldUniqueId);
if (world != null) {
final int buildHeight = world.getMaxHeight() - 1;
if (buildHeight < maxClaimLevel) {
maxClaimLevel = buildHeight;
}
}
this.checkedDimensionHeight = true;
}
return maxClaimLevel;
}
@Override
public int getMinClaimLevel() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.MIN_LEVEL, this).intValue();
}
@Override
public double getEconomyClaimBlockCost() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.ECONOMY_BLOCK_COST, this);
}
@Override
public double getEconomyClaimBlockReturn() {
return GDPermissionManager.getInstance().getGlobalInternalOptionValue(this.getSubject(), Options.ECONOMY_BLOCK_SELL_RETURN, this);
}
@Override
public double getTaxRate(ClaimType type) {
return GDPermissionManager.getInstance().getInternalOptionValue(this.getSubject(), Options.TAX_RATE, type, this);
}
@Override
public String getSubjectId() {
return this.getSubject().getIdentifier();
}
public GDPermissionUser getSubject() {
this.playerSubject = null;
if (this.playerSubject == null || this.playerSubject.get() == null) {
GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(this.playerID);
this.playerSubject = new WeakReference<>(user);
}
return this.playerSubject.get();
}
public void sendTaxExpireMessage(Player player, GDClaim claim) {
final double taxRate = GDPermissionManager.getInstance().getInternalOptionValue(player, Options.TAX_RATE, claim, this);
final double taxOwed = claim.getClaimBlocks() * taxRate;
final double remainingDays = GDPermissionManager.getInstance().getInternalOptionValue(player, Options.TAX_EXPIRATION_DAYS_KEEP, claim, this).intValue();
final Component message = GriefDefenderPlugin.getInstance().messageData.taxClaimExpired
.apply(ImmutableMap.of(
"remaining_days", remainingDays,
"tax_owed", taxOwed)).build();
GriefDefenderPlugin.sendClaimDenyMessage(claim, player, message);
}
public double getTotalTax() {
double totalTax = 0;
final GDPermissionUser subject = this.getSubject();
for (Claim claim : this.getInternalClaims()) {
double playerTaxRate = GDPermissionManager.getInstance().getInternalOptionValue(subject, Options.TAX_RATE, claim, this);
totalTax += (claim.getClaimBlocks() / 256) * playerTaxRate;
}
return totalTax;
}
public void onDisconnect() {
this.visualBlocks = null;
this.lastInteractClaim = null;
this.claimResizing = null;
this.claimSubdividing = null;
if (this.visualRevertTask != null) {
this.visualRevertTask.cancel();
this.visualRevertTask = null;
}
}
}

View File

@ -0,0 +1,79 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.griefdefender.util.BootstrapUtil;
import me.lucko.jarrelocator.JarRelocator;
import me.lucko.jarrelocator.Relocation;
public class GDRelocator {
private static GDRelocator instance;
private List<Relocation> rules;
public static GDRelocator getInstance() {
if (instance == null) {
instance = new GDRelocator();
}
return instance;
}
public GDRelocator() {
this.rules = new ArrayList<>();
for (String name : GDBootstrap.getInstance().getRelocateList()) {
final String[] parts = name.split(":");
final String key = parts[0];
final String relocated = parts[1];
this.rules.add(new Relocation(key, "com.griefdefender.lib." + relocated));
}
}
public void relocateJars(Map<String, File> jarMap) {
for (Map.Entry<String, File> mapEntry : jarMap.entrySet()) {
final String name = mapEntry.getKey();
final File input = mapEntry.getValue();
final File output = Paths.get(input.getParentFile().getPath()).resolve(input.getName().replace(".jar", "") + "-shaded.jar").toFile();
if (!output.exists()) {
// Relocate
JarRelocator relocator = new JarRelocator(input, output, this.rules);
try {
relocator.run();
} catch (IOException e) {
throw new RuntimeException("Unable to relocate", e);
}
}
BootstrapUtil.addUrlToClassLoader(name, output);
}
}
}

View File

@ -0,0 +1,79 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import co.aikar.timings.lib.MCTiming;
public class GDTimings {
public static final MCTiming BLOCK_BREAK_EVENT = GriefDefenderPlugin.timing("onBlockBreak");
public static final MCTiming BLOCK_COLLIDE_EVENT = GriefDefenderPlugin.timing("onBlockCollide");
public static final MCTiming BLOCK_NOTIFY_EVENT = GriefDefenderPlugin.timing("onBlockNotify");
public static final MCTiming BLOCK_PLACE_EVENT = GriefDefenderPlugin.timing("onBlockPlace");
public static final MCTiming BLOCK_POST_EVENT = GriefDefenderPlugin.timing("onBlockPost");
public static final MCTiming BLOCK_PRE_EVENT = GriefDefenderPlugin.timing("onBlockPre");
public static final MCTiming ENTITY_EXPLOSION_PRE_EVENT = GriefDefenderPlugin.timing("onEntityExplosionPre");
public static final MCTiming ENTITY_EXPLOSION_DETONATE_EVENT = GriefDefenderPlugin.timing("onEntityExplosionDetonate");
public static final MCTiming ENTITY_ATTACK_EVENT = GriefDefenderPlugin.timing("onEntityAttack");
public static final MCTiming ENTITY_COLLIDE_EVENT = GriefDefenderPlugin.timing("onEntityCollide");
public static final MCTiming ENTITY_DAMAGE_EVENT = GriefDefenderPlugin.timing("onEntityDamage");
public static final MCTiming ENTITY_DAMAGE_MONITOR_EVENT = GriefDefenderPlugin.timing("onEntityDamageMonitor");
public static final MCTiming ENTITY_DEATH_EVENT = GriefDefenderPlugin.timing("onEntityDeath");
public static final MCTiming ENTITY_DROP_ITEM_DEATH_EVENT = GriefDefenderPlugin.timing("onEntityDropDeathItem");
public static final MCTiming ENTITY_MOUNT_EVENT = GriefDefenderPlugin.timing("onEntityMount");
public static final MCTiming ENTITY_MOVE_EVENT = GriefDefenderPlugin.timing("onEntityMove");
public static final MCTiming ENTITY_SPAWN_PRE_EVENT = GriefDefenderPlugin.timing("onEntitySpawnPre");
public static final MCTiming ENTITY_SPAWN_EVENT = GriefDefenderPlugin.timing("onEntitySpawn");
public static final MCTiming ENTITY_TELEPORT_EVENT = GriefDefenderPlugin.timing("onEntityTeleport");
public static final MCTiming PLAYER_CHANGE_HELD_ITEM_EVENT = GriefDefenderPlugin.timing("onPlayerChangeHeldItem");
public static final MCTiming PLAYER_CHAT_EVENT = GriefDefenderPlugin.timing("onPlayerChat");
public static final MCTiming PLAYER_COMMAND_EVENT = GriefDefenderPlugin.timing("onPlayerCommand");
public static final MCTiming PLAYER_DEATH_EVENT = GriefDefenderPlugin.timing("onPlayerDeath");
public static final MCTiming PLAYER_DISPENSE_ITEM_EVENT = GriefDefenderPlugin.timing("onPlayerDispenseItem");
public static final MCTiming PLAYER_LOGIN_EVENT = GriefDefenderPlugin.timing("onPlayerLogin");
public static final MCTiming PLAYER_HANDLE_SHOVEL_ACTION = GriefDefenderPlugin.timing("onPlayerHandleShovelAction");
public static final MCTiming PLAYER_INTERACT_BLOCK_PRIMARY_EVENT = GriefDefenderPlugin.timing("onPlayerInteractBlockPrimary");
public static final MCTiming PLAYER_INTERACT_BLOCK_SECONDARY_EVENT = GriefDefenderPlugin.timing("onPlayerInteractBlockSecondary");
public static final MCTiming PLAYER_INTERACT_ENTITY_PRIMARY_EVENT = GriefDefenderPlugin.timing("onPlayerInteractEntityPrimary");
public static final MCTiming PLAYER_INTERACT_ENTITY_SECONDARY_EVENT = GriefDefenderPlugin.timing("onPlayerInteractEntitySecondary");
public static final MCTiming PLAYER_INTERACT_INVENTORY_CLICK_EVENT = GriefDefenderPlugin.timing("onPlayerInteractInventoryClick");
public static final MCTiming PLAYER_INTERACT_INVENTORY_CLOSE_EVENT = GriefDefenderPlugin.timing("onPlayerInteractInventoryClose");
public static final MCTiming PLAYER_INTERACT_INVENTORY_OPEN_EVENT = GriefDefenderPlugin.timing("onPlayerInteractInventoryOpen");
public static final MCTiming PLAYER_INVESTIGATE_CLAIM = GriefDefenderPlugin.timing("onPlayerInvestigateClaim");
public static final MCTiming PLAYER_JOIN_EVENT = GriefDefenderPlugin.timing("onPlayerJoin");
public static final MCTiming PLAYER_KICK_EVENT = GriefDefenderPlugin.timing("onPlayerKick");
public static final MCTiming PLAYER_PICKUP_ITEM_EVENT = GriefDefenderPlugin.timing("onPlayerPickupItem");
public static final MCTiming PLAYER_QUIT_EVENT = GriefDefenderPlugin.timing("onPlayerQuit");
public static final MCTiming PLAYER_RESPAWN_EVENT = GriefDefenderPlugin.timing("onPlayerRespawn");
public static final MCTiming PLAYER_USE_ITEM_EVENT = GriefDefenderPlugin.timing("onPlayerUseItem");
public static final MCTiming SIGN_CHANGE_EVENT = GriefDefenderPlugin.timing("onSignChange");
public static final MCTiming PROJECTILE_IMPACT_BLOCK_EVENT = GriefDefenderPlugin.timing("onProjectileImpactBlock");
public static final MCTiming PROJECTILE_IMPACT_ENTITY_EVENT = GriefDefenderPlugin.timing("onProjectileImpactEntity");
public static final MCTiming EXPLOSION_EVENT = GriefDefenderPlugin.timing("onExplosion");
public static final MCTiming CLAIM_GETCLAIM = GriefDefenderPlugin.timing("getClaimAt");
public static final MCTiming WORLD_LOAD_EVENT = GriefDefenderPlugin.timing("onWorldSave");
public static final MCTiming WORLD_SAVE_EVENT = GriefDefenderPlugin.timing("onWorldSave");
public static final MCTiming WORLD_UNLOAD_EVENT = GriefDefenderPlugin.timing("onWorldSave");
}

View File

@ -0,0 +1,44 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import com.google.inject.Singleton;
import com.griefdefender.api.Version;
@Singleton
public class GDVersion implements Version {
public static final double API_VERSION = 0.91;
@Override
public double getApiVersion() {
return API_VERSION;
}
@Override
public String getImplementationVersion() {
return GriefDefenderPlugin.IMPLEMENTATION_VERSION;
}
}

View File

@ -0,0 +1,931 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.PaperCommandManager;
import co.aikar.commands.RegisteredCommand;
import co.aikar.commands.RootCommand;
import co.aikar.timings.lib.MCTiming;
import co.aikar.timings.lib.TimingManager;
import com.google.common.reflect.TypeToken;
import com.google.inject.Guice;
import com.google.inject.Stage;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.ClaimBlockSystem;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.permission.flag.Flag;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.command.CommandAdjustBonusClaimBlocks;
import com.griefdefender.command.CommandCallback;
import com.griefdefender.command.CommandClaimAbandon;
import com.griefdefender.command.CommandClaimAbandonAll;
import com.griefdefender.command.CommandClaimAbandonTop;
import com.griefdefender.command.CommandClaimAdmin;
import com.griefdefender.command.CommandClaimBank;
import com.griefdefender.command.CommandClaimBasic;
import com.griefdefender.command.CommandClaimBuy;
import com.griefdefender.command.CommandClaimBuyBlocks;
import com.griefdefender.command.CommandClaimClear;
import com.griefdefender.command.CommandClaimCuboid;
import com.griefdefender.command.CommandClaimDelete;
import com.griefdefender.command.CommandClaimDeleteAll;
import com.griefdefender.command.CommandClaimDeleteAllAdmin;
import com.griefdefender.command.CommandClaimDeleteTop;
import com.griefdefender.command.CommandClaimFarewell;
import com.griefdefender.command.CommandClaimFlag;
import com.griefdefender.command.CommandClaimFlagDebug;
import com.griefdefender.command.CommandClaimFlagGroup;
import com.griefdefender.command.CommandClaimFlagPlayer;
import com.griefdefender.command.CommandClaimGreeting;
import com.griefdefender.command.CommandClaimIgnore;
import com.griefdefender.command.CommandClaimInfo;
import com.griefdefender.command.CommandClaimInherit;
import com.griefdefender.command.CommandClaimList;
import com.griefdefender.command.CommandClaimName;
import com.griefdefender.command.CommandClaimOption;
import com.griefdefender.command.CommandClaimPermissionGroup;
import com.griefdefender.command.CommandClaimPermissionPlayer;
import com.griefdefender.command.CommandClaimSchematic;
import com.griefdefender.command.CommandClaimSell;
import com.griefdefender.command.CommandClaimSellBlocks;
import com.griefdefender.command.CommandClaimSetSpawn;
import com.griefdefender.command.CommandClaimSpawn;
import com.griefdefender.command.CommandClaimSubdivide;
import com.griefdefender.command.CommandClaimTown;
import com.griefdefender.command.CommandClaimTransfer;
import com.griefdefender.command.CommandClaimWorldEdit;
import com.griefdefender.command.CommandDebug;
import com.griefdefender.command.CommandGDReload;
import com.griefdefender.command.CommandGDVersion;
import com.griefdefender.command.CommandHelp;
import com.griefdefender.command.CommandPagination;
import com.griefdefender.command.CommandPlayerInfo;
import com.griefdefender.command.CommandRestoreClaim;
import com.griefdefender.command.CommandRestoreNature;
import com.griefdefender.command.CommandSetAccruedClaimBlocks;
import com.griefdefender.command.CommandTownChat;
import com.griefdefender.command.CommandTownTag;
import com.griefdefender.command.CommandTrustGroup;
import com.griefdefender.command.CommandTrustGroupAll;
import com.griefdefender.command.CommandTrustList;
import com.griefdefender.command.CommandTrustPlayer;
import com.griefdefender.command.CommandTrustPlayerAll;
import com.griefdefender.command.CommandUntrustGroup;
import com.griefdefender.command.CommandUntrustGroupAll;
import com.griefdefender.command.CommandUntrustPlayer;
import com.griefdefender.command.CommandUntrustPlayerAll;
import com.griefdefender.configuration.ClaimTypeSerializer;
import com.griefdefender.configuration.GriefDefenderConfig;
import com.griefdefender.configuration.MessageDataConfig;
import com.griefdefender.configuration.MessageStorage;
import com.griefdefender.configuration.category.BlacklistCategory;
import com.griefdefender.configuration.type.ConfigBase;
import com.griefdefender.configuration.type.GlobalConfig;
import com.griefdefender.inject.GriefDefenderImplModule;
import com.griefdefender.internal.material.GDMaterials;
import com.griefdefender.internal.provider.WorldEditProvider;
import com.griefdefender.internal.provider.WorldGuardProvider;
import com.griefdefender.internal.registry.BlockTypeRegistryModule;
import com.griefdefender.internal.registry.EntityTypeRegistryModule;
import com.griefdefender.internal.registry.ItemTypeRegistryModule;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.listener.BlockEventHandler;
import com.griefdefender.listener.BlockEventTracker;
import com.griefdefender.listener.CommandEventHandler;
import com.griefdefender.listener.EntityEventHandler;
import com.griefdefender.listener.PlayerEventHandler;
import com.griefdefender.listener.WorldEventHandler;
import com.griefdefender.permission.GDFlags;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.provider.LuckPermsProvider;
import com.griefdefender.provider.VaultProvider;
import com.griefdefender.registry.ClaimTypeRegistryModule;
import com.griefdefender.registry.FlagRegistryModule;
import com.griefdefender.registry.OptionRegistryModule;
import com.griefdefender.registry.ResultTypeRegistryModule;
import com.griefdefender.registry.ShovelTypeRegistryModule;
import com.griefdefender.registry.TrustTypeRegistryModule;
import com.griefdefender.storage.BaseStorage;
import com.griefdefender.storage.FileStorage;
import com.griefdefender.task.ClaimBlockTask;
import com.griefdefender.task.ClaimCleanupTask;
import com.griefdefender.text.ComponentConfigSerializer;
import com.griefdefender.text.TextTemplate;
import com.griefdefender.text.TextTemplateConfigSerializer;
import me.lucko.luckperms.api.LuckPermsApi;
import me.lucko.luckperms.api.User;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.serializer.plain.PlainComponentSerializer;
import ninja.leaping.configurate.objectmapping.serialize.TypeSerializers;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.LocaleUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Monster;
import org.bukkit.event.Event;
import org.bukkit.plugin.RegisteredServiceProvider;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class GriefDefenderPlugin {
private static GriefDefenderPlugin instance;
public static final String MOD_ID = "GriefDefender";
public static final String API_VERSION = GriefDefenderPlugin.class.getPackage().getSpecificationVersion();
public static final String IMPLEMENTATION_NAME = GriefDefenderPlugin.class.getPackage().getImplementationTitle();
public static final String IMPLEMENTATION_VERSION = GriefDefenderPlugin.class.getPackage().getImplementationVersion();
public static String VERSION = "1.0.0";
private Path configPath = Paths.get(".", "plugins", "GriefDefender");
public MessageStorage messageStorage;
public MessageDataConfig messageData;
public Map<UUID, Random> worldGeneratorRandoms = new HashMap<>();
public static ClaimBlockSystem CLAIM_BLOCK_SYSTEM;
public static final String CONFIG_HEADER = "1.0.0\n"
+ "# If you need help with the configuration or have any issues related to GriefDefender,\n"
+ "# create a ticket on https://github.com/bloodmc/GriefDefender/issues.\n"
+ "# Note: If you have not purchased GriefDefender, please consider doing so to get \n"
+ "# exclusive access to Discord for prompt support.\n";
// GP Public user info
public static final UUID PUBLIC_UUID = UUID.fromString("41C82C87-7AfB-4024-BA57-13D2C99CAE77");
public static final UUID WORLD_USER_UUID = UUID.fromString("00000000-0000-0000-0000-000000000000");
public static final UUID ADMIN_USER_UUID = UUID.fromString("11111111-1111-1111-1111-111111111111");
public static GDPermissionUser PUBLIC_USER;
public static GDPermissionUser WORLD_USER;
public static final String PUBLIC_NAME = "[GDPublic]";
public static final String WORLD_USER_NAME = "[GDWorld]";
public static GDPermissionHolder DEFAULT_HOLDER;
private PaperCommandManager commandManager;
private static TimingManager timingManager;
public BaseStorage dataStore;
private LuckPermsProvider luckPermsProvider;
private WorldEditProvider worldEditProvider;
private WorldGuardProvider worldGuardProvider;
private VaultProvider vaultProvider;
public Executor executor;
private boolean isEconomyModeEnabled = false;
public Material modificationTool;
public Material investigationTool;
public int maxInspectionDistance = 100;
public static boolean debugLogging = false;
public static boolean debugActive = false;
private Map<String, GDDebugData> debugUserMap = new HashMap<>();
public static final Component GD_TEXT = TextComponent.builder("").append("[").append("GD", TextColor.AQUA).append("] ").build();
public static final List<String> ID_MAP = new ArrayList<>();
public static List<Component> helpComponents = new ArrayList<>();
public static GriefDefenderPlugin getInstance() {
if (instance == null) {
instance = new GriefDefenderPlugin();
}
return instance;
}
public Path getConfigPath() {
return this.configPath;
}
public static void addEventLogEntry(Event event, Location location, String sourceId, String targetId, GDPermissionHolder permissionSubject, String permission, String trust, Tristate result) {
final String eventName = event.getClass().getSimpleName().replace('$', '.').replace(".Impl", "");
final String eventLocation = location == null ? "none" : VecHelper.toVector3i(location).toString();
for (GDDebugData debugEntry : GriefDefenderPlugin.getInstance().getDebugUserMap().values()) {
final CommandSender debugSource = debugEntry.getSource();
final OfflinePlayer debugUser = debugEntry.getTarget();
if (debugUser != null) {
if (permissionSubject == null) {
continue;
}
// Check event source user
if (!permissionSubject.getFriendlyName().equals(debugUser.getName())) {
continue;
}
}
String messageUser = permissionSubject.getFriendlyName();
if (permissionSubject instanceof User) {
messageUser = ((User) permissionSubject).getName();
}
// record
if (debugEntry.isRecording()) {
permission = permission.replace("griefdefender.flag.", "");
String messageFlag = permission;
final Flag flag = FlagRegistryModule.getInstance().getById(permission).orElse(null);
if (flag != null) {
messageFlag = flag.toString();
}
String messageSource = sourceId == null ? "none" : sourceId;
String messageTarget = targetId == null ? "none" : targetId;
if (messageTarget.endsWith(".0")) {
messageTarget = messageTarget.substring(0, messageTarget.length() - 2);
}
if (trust == null) {
trust = "none";
}
// Strip minecraft id on bukkit
String[] parts = messageSource.split(":");
if (parts.length > 1) {
messageSource = parts[1];
}
parts = messageTarget.split(":");
if (parts.length > 1) {
messageTarget = parts[1];
}
debugEntry.addRecord(messageFlag, trust, messageSource, messageTarget, eventLocation, messageUser, permission, result);
continue;
}
final Component textEvent = TextComponent.builder("")
.append(GD_TEXT)
.append("Event: ", TextColor.GRAY)
.append(eventName == null ? TextComponent.of("Plugin").color(TextColor.GRAY) : TextComponent.of(eventName).color(TextColor.GRAY))
.append("\n").build();
final Component textCause = TextComponent.builder("")
.append(GD_TEXT)
.append("Cause: ", TextColor.GRAY)
.append(sourceId, TextColor.LIGHT_PURPLE)
.append("\n").build();
final Component textLocation = TextComponent.builder("")
.append(GD_TEXT)
.append("Location: ", TextColor.GRAY)
.append(eventLocation == null ? "NONE" : eventLocation).build();
final Component textUser = TextComponent.builder("")
.append("User: ", TextColor.GRAY)
.append(messageUser, TextColor.GOLD)
.append("\n").build();
final Component textLocationAndUser = TextComponent.builder("")
.append(textLocation)
.append(" ")
.append(textUser).build();
Component textContext = null;
Component textPermission = null;
if (targetId != null) {
textContext = TextComponent.builder("")
.append(GD_TEXT)
.append("Target: ", TextColor.GRAY)
.append(GDPermissionManager.getInstance().getPermissionIdentifier(targetId), TextColor.YELLOW)
.append("\n").build();
}
if (permission != null) {
textPermission = TextComponent.builder("")
.append(GD_TEXT)
.append("Permission: ", TextColor.GRAY)
.append(permission, TextColor.RED)
.append("\n").build();
}
TextComponent.Builder textBuilder = TextComponent.builder("").append(textEvent);
if (textContext != null) {
textBuilder.append(textContext);
} else {
textBuilder.append(textCause);
}
if (textPermission != null) {
textBuilder.append(textPermission);
}
textBuilder.append(textLocationAndUser);
TextAdapter.sendComponent(debugSource, textBuilder.build());
}
}
public void onEnable() {
this.getLogger().info("GriefDefender boot start.");
RegisteredServiceProvider<LuckPermsApi> provider = Bukkit.getServicesManager().getRegistration(LuckPermsApi.class);
if (provider == null) {
this.getLogger().severe("Unable to initialize plugin. GriefDefender requires LuckPerms to be installed."
+ "\nSee https://github.com/lucko/LuckPerms/wiki/Migration on how to migrate from other permission plugins.");
return;
}
this.luckPermsProvider = new LuckPermsProvider();
instance = this;
timingManager = TimingManager.of(GDBootstrap.getInstance());
DEFAULT_HOLDER = new GDPermissionHolder(this.luckPermsProvider.getApi().getGroup("default"));
PUBLIC_USER = new GDPermissionUser(PUBLIC_UUID, PUBLIC_NAME);
WORLD_USER = new GDPermissionUser(WORLD_USER_UUID, WORLD_USER_NAME);
Guice.createInjector(Stage.PRODUCTION, new GriefDefenderImplModule());
ClaimTypeRegistryModule.getInstance().registerDefaults();
ShovelTypeRegistryModule.getInstance().registerDefaults();
TrustTypeRegistryModule.getInstance().registerDefaults();
FlagRegistryModule.getInstance().registerDefaults();
OptionRegistryModule.getInstance().registerDefaults();
ResultTypeRegistryModule.getInstance().registerDefaults();
EntityTypeRegistryModule.getInstance().registerDefaults();
BlockTypeRegistryModule.getInstance().registerDefaults();
ItemTypeRegistryModule.getInstance().registerDefaults();
this.loadConfig();
this.executor = Executors.newFixedThreadPool(GriefDefenderPlugin.getGlobalConfig().getConfig().thread.numExecutorThreads);
if (Bukkit.getPluginManager().getPlugin("Vault") != null) {
this.vaultProvider = new VaultProvider();
this.getLogger().info("Detected Vault. Checking for compatible economy plugin...");
if (this.vaultProvider.getApi() != null) {
this.getLogger().info("Found economy plugin '" + this.vaultProvider.getApi().getName() + "'. GriefDefender economy integration is now enabled.");
} else {
this.getLogger().info("Could not locate a compatible economy plugin for Vault. Please check with your server administrator.");
}
if (GriefDefenderPlugin.getGlobalConfig().getConfig().economy.economyMode) {
this.getLogger().info("Economy mode enabled!. Claimblocks will be disabled...");
}
} else if (GriefDefenderPlugin.getGlobalConfig().getConfig().economy.economyMode) {
this.getLogger().severe("No economy plugin found! Unable to initialize economy plugin.");
return;
}
if (Bukkit.getPluginManager().getPlugin("WorldEdit") != null || Bukkit.getPluginManager().getPlugin("FastAsyncWorldEdit") != null) {
this.worldEditProvider = new WorldEditProvider();
}
if (Bukkit.getPluginManager().getPlugin("WorldGuard") != null) {
this.worldGuardProvider = new WorldGuardProvider();
}
if (this.dataStore == null) {
try {
this.dataStore = new FileStorage();
this.dataStore.initialize();
} catch (Exception e) {
this.getLogger().info("Unable to initialize file storage.");
this.getLogger().info(e.getMessage());
e.printStackTrace();
return;
}
}
//this.registerBaseCommands();
Bukkit.getPluginManager().registerEvents(new BlockEventHandler(dataStore), GDBootstrap.getInstance());
Bukkit.getPluginManager().registerEvents(new BlockEventTracker(), GDBootstrap.getInstance());
Bukkit.getPluginManager().registerEvents(new CommandEventHandler(dataStore), GDBootstrap.getInstance());
Bukkit.getPluginManager().registerEvents(new PlayerEventHandler(dataStore), GDBootstrap.getInstance());
Bukkit.getPluginManager().registerEvents(new EntityEventHandler(dataStore), GDBootstrap.getInstance());
Bukkit.getPluginManager().registerEvents(new WorldEventHandler(), GDBootstrap.getInstance());
Bukkit.getPluginManager().registerEvents(new NMSUtil(), GDBootstrap.getInstance());
/*PUBLIC_USER = Sponge.getServiceManager().provide(UserStorageService.class).get()
.getOrCreate(GameProfile.of(GriefDefenderPlugin.PUBLIC_UUID, GriefDefenderPlugin.PUBLIC_NAME));
WORLD_USER = Sponge.getServiceManager().provide(UserStorageService.class).get()
.getOrCreate(GameProfile.of(GriefDefenderPlugin.WORLD_USER_UUID, GriefDefenderPlugin.WORLD_USER_NAME));*/
// run cleanup task
int cleanupTaskInterval = GriefDefenderPlugin.getGlobalConfig().getConfig().claim.expirationCleanupInterval;
if (cleanupTaskInterval > 0) {
new ClaimCleanupTask(cleanupTaskInterval);
}
/*if (this.permissionService == null) {
this.getLogger().severe("Unable to initialize plugin. GriefDefender requires a permissions plugin such as LuckPerms.");
return;
}*/
final boolean resetMigration = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.resetMigrations;
final boolean resetClaimData = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.resetAccruedClaimBlocks;
final int migration2dRate = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.migrateAreaRate;
final int migration3dRate = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.migrateVolumeRate;
boolean migrate = false;
if (resetMigration || resetClaimData || (migration2dRate > -1 && GriefDefenderPlugin.CLAIM_BLOCK_SYSTEM == ClaimBlockSystem.AREA)
|| (migration3dRate > -1 && GriefDefenderPlugin.CLAIM_BLOCK_SYSTEM == ClaimBlockSystem.VOLUME)) {
migrate = true;
}
if (migrate) {
List<GDPlayerData> playerDataList = new ArrayList<>();
if (BaseStorage.USE_GLOBAL_PLAYER_STORAGE) {
final GDClaimManager claimWorldManager = this.dataStore.getClaimWorldManager(Bukkit.getServer().getWorlds().get(0).getUID());
claimWorldManager.resetPlayerData();
playerDataList = new ArrayList<>(claimWorldManager.getPlayerDataMap().values());
for (GDPlayerData playerData : playerDataList) {
if (Bukkit.getServer().getPlayer(playerData.playerID) != null && playerData.getClaims().isEmpty()) {
playerData.onDisconnect();
claimWorldManager.removePlayer(playerData.playerID);
}
}
}
if (!BaseStorage.USE_GLOBAL_PLAYER_STORAGE) {
for (World world : Bukkit.getServer().getWorlds()) {
final GDClaimManager claimWorldManager = this.dataStore.getClaimWorldManager(world.getUID());
playerDataList = new ArrayList<>(claimWorldManager.getPlayerDataMap().values());
for (GDPlayerData playerData : playerDataList) {
if (Bukkit.getServer().getPlayer(playerData.playerID) != null && playerData.getClaims().isEmpty()) {
playerData.onDisconnect();
claimWorldManager.removePlayer(playerData.playerID);
}
}
}
}
GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.resetMigrations = false;
GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.resetAccruedClaimBlocks = false;
GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.migrateAreaRate = -1;
GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.migrateVolumeRate = -1;
GriefDefenderPlugin.getGlobalConfig().save();
}
new ClaimBlockTask();
registerBaseCommands();
this.getLogger().info("Loaded successfully.");
}
public void onDisable() {
// Spigot disables plugins before calling world save on shutdown so we need to manually save here
for (World world : Bukkit.getServer().getWorlds()) {
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(world.getUID())) {
continue;
}
GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(world.getUID());
if (claimWorldManager == null) {
continue;
}
claimWorldManager.save();
claimWorldManager.playerIndexStorage.savePlayerDatData();
}
}
public void registerBaseCommands() {
PaperCommandManager manager = new PaperCommandManager(GDBootstrap.getInstance());
this.commandManager = manager;
manager.getCommandReplacements().addReplacement("griefdefender", "gd|griefdefender");
manager.registerCommand(new CommandAdjustBonusClaimBlocks());
manager.registerCommand(new CommandCallback());
manager.registerCommand(new CommandClaimAbandon());
manager.registerCommand(new CommandClaimAbandonAll());
manager.registerCommand(new CommandClaimAbandonTop());
manager.registerCommand(new CommandClaimAdmin());
manager.registerCommand(new CommandClaimBank());
manager.registerCommand(new CommandClaimBasic());
manager.registerCommand(new CommandClaimBuy());
manager.registerCommand(new CommandClaimBuyBlocks());
manager.registerCommand(new CommandClaimClear());
manager.registerCommand(new CommandClaimCuboid());
manager.registerCommand(new CommandClaimDelete());
manager.registerCommand(new CommandClaimDeleteAll());
manager.registerCommand(new CommandClaimDeleteAllAdmin());
manager.registerCommand(new CommandClaimDeleteTop());
manager.registerCommand(new CommandClaimFarewell());
manager.registerCommand(new CommandClaimFlag());
manager.registerCommand(new CommandClaimFlagDebug());
manager.registerCommand(new CommandClaimFlagGroup());
manager.registerCommand(new CommandClaimFlagPlayer());
manager.registerCommand(new CommandClaimGreeting());
manager.registerCommand(new CommandClaimIgnore());
manager.registerCommand(new CommandClaimInfo());
manager.registerCommand(new CommandClaimInherit());
manager.registerCommand(new CommandClaimList());
manager.registerCommand(new CommandClaimName());
manager.registerCommand(new CommandClaimOption());
manager.registerCommand(new CommandClaimPermissionGroup());
manager.registerCommand(new CommandClaimPermissionPlayer());
manager.registerCommand(new CommandClaimSchematic());
manager.registerCommand(new CommandClaimSell());
manager.registerCommand(new CommandClaimSellBlocks());
manager.registerCommand(new CommandClaimSetSpawn());
manager.registerCommand(new CommandClaimSpawn());
manager.registerCommand(new CommandClaimSubdivide());
manager.registerCommand(new CommandClaimTown());
manager.registerCommand(new CommandClaimTransfer());
manager.registerCommand(new CommandClaimWorldEdit());
manager.registerCommand(new CommandDebug());
manager.registerCommand(new CommandGDReload());
manager.registerCommand(new CommandGDVersion());
manager.registerCommand(new CommandHelp());
manager.registerCommand(new CommandPagination());
manager.registerCommand(new CommandPlayerInfo());
manager.registerCommand(new CommandRestoreClaim());
manager.registerCommand(new CommandRestoreNature());
manager.registerCommand(new CommandSetAccruedClaimBlocks());
manager.registerCommand(new CommandTownChat());
manager.registerCommand(new CommandTownTag());
manager.registerCommand(new CommandTrustGroup());
manager.registerCommand(new CommandTrustPlayer());
manager.registerCommand(new CommandTrustGroupAll());
manager.registerCommand(new CommandTrustPlayerAll());
manager.registerCommand(new CommandUntrustGroup());
manager.registerCommand(new CommandUntrustPlayer());
manager.registerCommand(new CommandUntrustGroupAll());
manager.registerCommand(new CommandUntrustPlayerAll());
manager.registerCommand(new CommandTrustList());
manager.enableUnstableAPI("help");
final Map<String, Component> helpMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
// Generate help text
RootCommand rootCommand = getCommandManager().getRootCommand("gd");
for (BaseCommand child : rootCommand.getChildren()) {
for (RegisteredCommand registeredCommand : child.getRegisteredCommands()) {
if (helpMap.get(registeredCommand.getPrefSubCommand()) != null) {
continue;
}
TextComponent permissionText = TextComponent.builder("")
.append("Permission: ", TextColor.GOLD)
.append(registeredCommand.getRequiredPermissions() == null ? "None" : String.join(",", registeredCommand.getRequiredPermissions()), TextColor.GRAY)
.build();
TextComponent argumentsText = TextComponent.builder("")
//.append("Arguments: ", TextColor.AQUA)
.append(registeredCommand.getSyntaxText() == null ? "Arguments: None" : registeredCommand.getSyntaxText(), TextColor.GREEN)
.build();
final TextComponent hoverText = TextComponent.builder("")
.append("Command: ", TextColor.AQUA)
.append(registeredCommand.getPrefSubCommand() + "\n", TextColor.GREEN)
.append("Description: ", TextColor.AQUA)
.append(registeredCommand.getHelpText() + "\n", TextColor.GREEN)
.append("Arguments: ", TextColor.AQUA)
.append(argumentsText)
.append("\n")
.append(permissionText)
.build();
final TextComponent commandText = TextComponent.builder("")
.append("/gd " + registeredCommand.getPrefSubCommand(), TextColor.GREEN)
.hoverEvent(HoverEvent.showText(hoverText))
.clickEvent(ClickEvent.suggestCommand("/gd " + registeredCommand.getPrefSubCommand()))
.build();
helpMap.put(registeredCommand.getPrefSubCommand(), commandText);
}
}
helpComponents = new ArrayList<>(helpMap.values());
NMSUtil.getInstance().populateTabComplete();
ID_MAP.add("any");
ID_MAP.add("ambient");
ID_MAP.add("animal");
ID_MAP.add("aquatic");
ID_MAP.add("monster");
// commands
ID_MAP.add("griefdefender:cf");
ID_MAP.add("griefdefender:cfg");
ID_MAP.add("griefdefender:cfp");
ID_MAP.add("griefdefender:cog");
ID_MAP.add("griefdefender:cop");
ID_MAP.add("griefdefender:cpg");
ID_MAP.add("griefdefender:cpp");
ID_MAP.add("griefdefender:claimflag");
ID_MAP.add("griefdefender:claimflaggroup");
ID_MAP.add("griefdefender:claimflagplayer");
//ID_MAP.add("unknown");
}
public PaperCommandManager getCommandManager() {
return this.commandManager;
}
public void loadConfig() {
this.getLogger().info("Loading configuration...");
try {
TypeSerializers.getDefaultSerializers().registerType(TypeToken.of(Component.class), new ComponentConfigSerializer());
TypeSerializers.getDefaultSerializers().registerType(TypeToken.of(TextTemplate.class), new TextTemplateConfigSerializer());
TypeSerializers.getDefaultSerializers().registerType(TypeToken.of(ClaimType.class), new ClaimTypeSerializer());
if (Files.notExists(BaseStorage.dataLayerFolderPath)) {
Files.createDirectories(BaseStorage.dataLayerFolderPath);
}
Path rootConfigPath = this.getConfigPath().resolve("worlds");
BaseStorage.globalConfig = new GriefDefenderConfig<>(GlobalConfig.class, this.getConfigPath().resolve("global.conf"), null);
BaseStorage.globalConfig.getConfig().permissionCategory.refreshFlags();
String localeString = BaseStorage.globalConfig.getConfig().message.locale;
try {
LocaleUtils.toLocale(localeString);
} catch (IllegalArgumentException e) {
e.printStackTrace();
this.getLogger().severe("Could not validate the locale '" + localeString + "'. Defaulting to 'en_US'...");
localeString = "en_US";
}
final Path localePath = this.getConfigPath().resolve("lang").resolve(localeString + ".conf");
if (!localePath.toFile().exists()) {
// Check for a default locale asset and copy to lang folder
try {
final InputStream in = getClass().getResourceAsStream("/assets/lang/" + localeString + ".conf");
FileUtils.copyInputStreamToFile(in, localePath.toFile());
} catch (Throwable t) {
t.printStackTrace();
}
}
messageStorage = new MessageStorage(localePath);
messageData = messageStorage.getConfig();
BaseStorage.USE_GLOBAL_PLAYER_STORAGE = BaseStorage.globalConfig.getConfig().playerdata.useGlobalPlayerDataStorage;
GDFlags.populateFlagStatus();
PermissionHolderCache.getInstance().getOrCreatePermissionCache(GriefDefenderPlugin.DEFAULT_HOLDER).invalidateAll();
CLAIM_BLOCK_SYSTEM = BaseStorage.globalConfig.getConfig().playerdata.claimBlockSystem;
final Material modTool = Material.getMaterial(BaseStorage.globalConfig.getConfig().claim.modificationTool);
final Material invTool = Material.getMaterial(BaseStorage.globalConfig.getConfig().claim.investigationTool);
this.modificationTool = modTool == null ? GDMaterials.GOLDEN_SHOVEL : modTool;
this.investigationTool = invTool == null? Material.STICK : invTool;
this.maxInspectionDistance = BaseStorage.globalConfig.getConfig().general.maxClaimInspectionDistance;
if (this.dataStore != null) {
for (World world : Bukkit.getServer().getWorlds()) {
final String dimType = world.getEnvironment().name().toLowerCase();
final Path dimPath = rootConfigPath.resolve(dimType);
if (Files.notExists(dimPath.resolve(world.getName()))) {
try {
Files.createDirectories(rootConfigPath.resolve(dimType).resolve(world.getName()));
} catch (IOException e) {
e.printStackTrace();
}
}
GriefDefenderConfig<ConfigBase> dimConfig = new GriefDefenderConfig<>(ConfigBase.class, dimPath.resolve("dimension.conf"), BaseStorage.globalConfig);
GriefDefenderConfig<ConfigBase> worldConfig = new GriefDefenderConfig<>(ConfigBase.class, dimPath.resolve(world.getName()).resolve("world.conf"), dimConfig);
BaseStorage.dimensionConfigMap.put(world.getUID(), dimConfig);
BaseStorage.worldConfigMap.put(world.getUID(), worldConfig);
// refresh player data
final GDClaimManager claimManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(world.getUID());
for (GDPlayerData playerData : claimManager.getPlayerDataMap().values()) {
if (playerData.playerID.equals(WORLD_USER_UUID) || playerData.playerID.equals(ADMIN_USER_UUID) || playerData.playerID.equals(PUBLIC_UUID)) {
continue;
}
playerData.refreshPlayerOptions();
}
if (GriefDefenderPlugin.getGlobalConfig().getConfig().migrator.classicMigrator) {
GriefDefenderPlugin.getGlobalConfig().getConfig().migrator.classicMigrator = false;
GriefDefenderPlugin.getGlobalConfig().save();
}
if (this.worldEditProvider != null) {
this.getLogger().info("Loading schematics for world " + world.getName() + "...");
this.worldEditProvider.loadSchematics(world);
}
}
// refresh default permissions
this.dataStore.setDefaultGlobalPermissions();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void sendClaimDenyMessage(GDClaim claim, CommandSender source, Component message) {
if (claim.getData() != null && !claim.getData().allowDenyMessages()) {
return;
}
sendMessage(source, message);
}
public static void sendMessage(CommandSender src, String messageKey, TextTemplate template, Map<String, ?> params) {
Component message = null;
//try {
message = template.apply(params).build();
/*} catch (TextTemplateArgumentException e) {
// fix message data
GriefDefenderPlugin.getInstance().messageStorage.resetMessageData(messageKey);
}*/
if (message != null) {
sendMessage(src, message);
}
}
public static void sendMessage(CommandSender source, Component message) {
if (message == TextComponent.empty() || message == null) {
return;
}
if (source == null) {
GriefDefenderPlugin.getInstance().getLogger().warning(PlainComponentSerializer.INSTANCE.serialize(message));
} else {
TextAdapter.sendComponent(source, message);
}
}
public static GriefDefenderConfig<?> getActiveConfig(World world) {
return getActiveConfig(world.getUID());
}
public static GriefDefenderConfig<? extends ConfigBase> getActiveConfig(UUID worldUniqueId) {
GriefDefenderConfig<ConfigBase> config = BaseStorage.worldConfigMap.get(worldUniqueId);
if (config != null) {
return config;
}
config = BaseStorage.dimensionConfigMap.get(worldUniqueId);
if (config != null) {
return config;
}
return BaseStorage.globalConfig;
}
public static GriefDefenderConfig<GlobalConfig> getGlobalConfig() {
return BaseStorage.globalConfig;
}
public boolean claimsEnabledForWorld(UUID worldUniqueId) {
return GriefDefenderPlugin.getActiveConfig(worldUniqueId).getConfig().claim.claimsEnabled != 0;
}
public int getSeaLevel(World world) {
return world.getSeaLevel();
}
public Map<String, GDDebugData> getDebugUserMap() {
return this.debugUserMap;
}
public static boolean isEntityProtected(Entity entity) {
// ignore monsters
if (entity instanceof Monster) {
return false;
}
return true;
}
public static GDPermissionUser getOrCreateUser(UUID uuid) {
if (uuid == null) {
return null;
}
if (uuid == PUBLIC_UUID) {
return PUBLIC_USER;
}
if (uuid == WORLD_USER_UUID) {
return WORLD_USER;
}
// check the cache
return PermissionHolderCache.getInstance().getOrCreateUser(uuid);
}
public static boolean isSourceIdBlacklisted(String flag, Object source, UUID worldUniqueId) {
final List<String> flagList = GriefDefenderPlugin.getGlobalConfig().getConfig().blacklist.flagIdBlacklist.get(flag);
final boolean checkFlag = flagList != null && !flagList.isEmpty();
final boolean checkGlobal = !GriefDefenderPlugin.getGlobalConfig().getConfig().blacklist.globalSourceBlacklist.isEmpty();
if (!checkFlag && !checkGlobal) {
return false;
}
final GriefDefenderConfig<?> activeConfig = GriefDefenderPlugin.getActiveConfig(worldUniqueId);
final String id = GDPermissionManager.getInstance().getPermissionIdentifier(source);
final String idNoMeta = GDPermissionManager.getInstance().getIdentifierWithoutMeta(id);
// Check global
if (checkGlobal) {
final BlacklistCategory blacklistCategory = activeConfig.getConfig().blacklist;
final List<String> globalSourceBlacklist = blacklistCategory.getGlobalSourceBlacklist();
if (globalSourceBlacklist == null) {
return false;
}
for (String str : globalSourceBlacklist) {
if (FilenameUtils.wildcardMatch(id, str)) {
return true;
}
if (FilenameUtils.wildcardMatch(idNoMeta, str)) {
return true;
}
}
}
// Check flag
if (checkFlag) {
for (String str : flagList) {
if (FilenameUtils.wildcardMatch(id, str)) {
return true;
}
if (FilenameUtils.wildcardMatch(idNoMeta, str)) {
return true;
}
}
}
return false;
}
public static boolean isTargetIdBlacklisted(String flag, Object target, UUID worldUniqueId) {
final List<String> flagList = GriefDefenderPlugin.getGlobalConfig().getConfig().blacklist.flagIdBlacklist.get(flag);
final boolean checkFlag = flagList != null && !flagList.isEmpty();
final boolean checkGlobal = !GriefDefenderPlugin.getGlobalConfig().getConfig().blacklist.globalTargetBlacklist.isEmpty();
if (!checkFlag && !checkGlobal) {
return false;
}
final GriefDefenderConfig<?> activeConfig = GriefDefenderPlugin.getActiveConfig(worldUniqueId);
final String id = GDPermissionManager.getInstance().getPermissionIdentifier(target);
final String idNoMeta = GDPermissionManager.getInstance().getIdentifierWithoutMeta(id);
// Check global
if (checkGlobal) {
final BlacklistCategory blacklistCategory = activeConfig.getConfig().blacklist;
final List<String> globalTargetBlacklist = blacklistCategory.getGlobalTargetBlacklist();
if (globalTargetBlacklist == null) {
return false;
}
for (String str : globalTargetBlacklist) {
if (FilenameUtils.wildcardMatch(id, str)) {
return true;
}
if (FilenameUtils.wildcardMatch(idNoMeta, str)) {
return true;
}
}
}
// Check flag
if (checkFlag) {
for (String str : flagList) {
if (FilenameUtils.wildcardMatch(id, str)) {
return true;
}
if (FilenameUtils.wildcardMatch(idNoMeta, str)) {
return true;
}
}
}
return false;
}
public boolean isEconomyModeEnabled() {
return this.isEconomyModeEnabled;
}
public LuckPermsProvider getLuckPermsProvider() {
return this.luckPermsProvider;
}
public WorldEditProvider getWorldEditProvider() {
return this.worldEditProvider;
}
public WorldGuardProvider getWorldGuardProvider() {
return this.worldGuardProvider;
}
public VaultProvider getVaultProvider() {
return this.vaultProvider;
}
public Logger getLogger() {
return GDBootstrap.getInstance().getLogger();
}
public static MCTiming timing(String name) {
return timingManager.of(name);
}
}

View File

@ -0,0 +1,181 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.cache;
import com.github.benmanes.caffeine.cache.AsyncCache;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.griefdefender.api.Tristate;
import com.griefdefender.permission.GDPermissionGroup;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.util.PermissionUtil;
import me.lucko.luckperms.api.Group;
import me.lucko.luckperms.api.User;
import org.bukkit.OfflinePlayer;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class PermissionHolderCache {
private static PermissionHolderCache instance;
private final AsyncCache<String, GDPermissionHolder> holderCache = Caffeine.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES)
.buildAsync();
private final ConcurrentHashMap<GDPermissionHolder, Cache<Integer, Tristate>> permissionCache = new ConcurrentHashMap<>();
public GDPermissionUser getOrCreateUser(OfflinePlayer player) {
if (player == null) {
return null;
}
return getOrCreateUser(player.getUniqueId());
}
public GDPermissionUser getOrCreateUser(UUID uuid) {
GDPermissionUser user = null;
CompletableFuture<GDPermissionHolder> future = holderCache.getIfPresent(uuid.toString());
if (future != null) {
try {
user = (GDPermissionUser) future.get();
if (user != null) {
return user;
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
user = new GDPermissionUser(uuid);
final GDPermissionHolder holder = user;
future = CompletableFuture.supplyAsync(() -> holder);
holderCache.put(user.getIdentifier(), future);
return user;
}
public GDPermissionUser getOrCreateUser(String username) {
final User luckPermsUser = PermissionUtil.getInstance().getUserSubject(username);
if (luckPermsUser != null) {
return this.getOrCreateUser(luckPermsUser.getUuid());
}
return null;
}
public GDPermissionGroup getOrCreateGroup(String groupName) {
GDPermissionGroup permissionHolder = null;
CompletableFuture<GDPermissionHolder> future = holderCache.getIfPresent(groupName);
if (future != null) {
try {
permissionHolder = (GDPermissionGroup) future.get();
if (permissionHolder != null) {
return permissionHolder;
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
final Group luckPermsGroup = PermissionUtil.getInstance().getGroupSubject(groupName);
if (luckPermsGroup == null) {
return null;
}
permissionHolder = new GDPermissionGroup(luckPermsGroup);
final GDPermissionGroup holder = permissionHolder;
future = CompletableFuture.supplyAsync(() -> holder);
holderCache.put(groupName, future);
return holder;
}
public GDPermissionGroup getOrCreateGroup(Group group) {
GDPermissionGroup permissionHolder = null;
CompletableFuture<GDPermissionHolder> future = holderCache.getIfPresent(group.getName());
if (future != null) {
try {
permissionHolder = (GDPermissionGroup) future.get();
if (permissionHolder != null) {
return permissionHolder;
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
permissionHolder = new GDPermissionGroup(group);
final GDPermissionGroup holder = permissionHolder;
future = CompletableFuture.supplyAsync(() -> holder);
holderCache.put(group.getName(), future);
return holder;
}
public GDPermissionHolder getOrCreateHolder(String identifier) {
GDPermissionHolder permissionHolder = null;
CompletableFuture<GDPermissionHolder> future = holderCache.getIfPresent(identifier);
if (future != null) {
try {
permissionHolder = future.get();
if (permissionHolder != null) {
return permissionHolder;
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
permissionHolder = new GDPermissionHolder(identifier);
final GDPermissionHolder holder = permissionHolder;
future = CompletableFuture.supplyAsync(() -> holder);
holderCache.put(identifier, future);
return holder;
}
public Cache<Integer, Tristate> getOrCreatePermissionCache(GDPermissionHolder holder) {
Cache<Integer, Tristate> cache = this.permissionCache.get(holder);
if (cache == null) {
cache = Caffeine.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES).build();
this.permissionCache.put(holder, cache);
}
return cache;
}
public void invalidateAllPermissionCache() {
for (Cache<Integer, Tristate> cache : this.permissionCache.values()) {
cache.invalidateAll();
}
}
static {
instance = new PermissionHolderCache();
}
public static PermissionHolderCache getInstance() {
return instance;
}
}

View File

@ -0,0 +1,87 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.claim;
import me.lucko.luckperms.api.PermissionHolder;
import me.lucko.luckperms.api.context.ContextCalculator;
public abstract class ClaimContextCalculator implements ContextCalculator<PermissionHolder> {
/*@Override
public void accumulateContexts(PermissionHolder calculable, Set<Context> accumulator) {
if (calculable.getCommandSource().isPresent() && calculable.getCommandSource().get() instanceof Player) {
Player player = (Player) calculable.getCommandSource().get();
GPPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getPlayerData(player.getWorld(), player.getUniqueId());
if (playerData == null) {
return;
}
if (playerData.ignoreActiveContexts) {
playerData.ignoreActiveContexts = false;
return;
}
GPClaim sourceClaim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (sourceClaim != null) {
if (playerData == null || playerData.canIgnoreClaim(sourceClaim)) {
return;
}
if (sourceClaim.parent != null && sourceClaim.getData().doesInheritParent()) {
accumulator.add(sourceClaim.parent.getContext());
} else {
accumulator.add(sourceClaim.getContext());
}
}
}
}
@Override
public boolean matches(Context context, Subject subject) {
if (context.equals("gd_claim")) {
if (subject.getCommandSource().isPresent() && subject.getCommandSource().get() instanceof Player) {
Player player = (Player) subject.getCommandSource().get();
GPPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getPlayerData(player.getWorld(), player.getUniqueId());
if (playerData == null) {
return false;
}
GPClaim playerClaim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (playerClaim != null && playerClaim.id.equals(UUID.fromString(context.getValue()))) {
return true;
}
}
}
return false;
}
@Override
public @NonNull MutableContextSet giveApplicableContext(@NonNull PermissionHolder arg0,
@NonNull MutableContextSet arg1) {
// TODO Auto-generated method stub
return null;
}*/
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,663 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.claim;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimBlockSystem;
import com.griefdefender.api.claim.ClaimManager;
import com.griefdefender.api.claim.ClaimResult;
import com.griefdefender.api.claim.ClaimResultType;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.configuration.ClaimDataConfig;
import com.griefdefender.configuration.ClaimStorageData;
import com.griefdefender.configuration.GriefDefenderConfig;
import com.griefdefender.configuration.PlayerStorageData;
import com.griefdefender.event.GDDeleteClaimEvent;
import com.griefdefender.internal.tracking.PlayerIndexStorage;
import com.griefdefender.internal.tracking.chunk.GDChunk;
import com.griefdefender.internal.util.BlockUtil;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.storage.BaseStorage;
import com.griefdefender.util.Direction;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.serializer.plain.PlainComponentSerializer;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import javax.annotation.Nullable;
public class GDClaimManager implements ClaimManager {
private static final BaseStorage DATASTORE = GriefDefenderPlugin.getInstance().dataStore;
private UUID worldUniqueId;
private GriefDefenderConfig<?> activeConfig;
// Player UUID -> player data
private Map<UUID, GDPlayerData> playerDataList = Maps.newHashMap();
// World claim list
private Set<Claim> worldClaims = new HashSet<>();
// Claim UUID -> Claim
private Map<UUID, Claim> claimUniqueIdMap = Maps.newHashMap();
// String -> Claim
private Map<Long, Set<Claim>> chunksToClaimsMap = new Long2ObjectOpenHashMap<>(4096);
// Entity Index
public PlayerIndexStorage playerIndexStorage;
private Map<Long, GDChunk> chunksToGpChunks = new Long2ObjectOpenHashMap<>(4096);
private GDClaim theWildernessClaim;
public GDClaimManager(World world) {
this.worldUniqueId = world.getUID();
this.activeConfig = GriefDefenderPlugin.getActiveConfig(this.worldUniqueId);
this.playerIndexStorage = new PlayerIndexStorage(world);
}
public GDPlayerData getOrCreatePlayerData(UUID playerUniqueId) {
GDPlayerData playerData = this.getPlayerDataMap().get(playerUniqueId);
if (playerData == null) {
return createPlayerData(playerUniqueId);
} else {
return playerData;
}
}
private GDPlayerData createPlayerData(UUID playerUniqueId) {
Path playerFilePath = null;
if (BaseStorage.USE_GLOBAL_PLAYER_STORAGE) {
playerFilePath = BaseStorage.globalPlayerDataPath.resolve(playerUniqueId.toString());
} else {
playerFilePath = BaseStorage.worldConfigMap.get(this.worldUniqueId).getPath().getParent().resolve("PlayerData").resolve(playerUniqueId.toString());
}
PlayerStorageData playerStorage = new PlayerStorageData(playerFilePath);
Set<Claim> claimList = this.createPlayerClaimList(playerUniqueId);
GDPlayerData playerData = new GDPlayerData(this.worldUniqueId, playerUniqueId, playerStorage, this.activeConfig, claimList);
this.getPlayerDataMap().put(playerUniqueId, playerData);
return playerData;
}
private Set<Claim> createPlayerClaimList(UUID playerUniqueId) {
Set<Claim> claimList = new HashSet<>();
if (BaseStorage.USE_GLOBAL_PLAYER_STORAGE) {
for (World world : Bukkit.getServer().getWorlds()) {
GDClaimManager claimmanager = DATASTORE.getClaimWorldManager(world.getUID());
for (Claim claim : claimmanager.worldClaims) {
GDClaim gpClaim = (GDClaim) claim;
if (gpClaim.isAdminClaim()) {
continue;
}
if (gpClaim.parent != null) {
if (gpClaim.parent.getOwnerUniqueId().equals(playerUniqueId)) {
claimList.add(claim);
}
} else {
if (gpClaim.getOwnerUniqueId().equals(playerUniqueId)) {
claimList.add(claim);
}
}
}
}
} else {
for (Claim claim : this.worldClaims) {
GDClaim gpClaim = (GDClaim) claim;
if (gpClaim.isAdminClaim()) {
continue;
}
if (gpClaim.parent != null) {
if (gpClaim.parent.getOwnerUniqueId().equals(playerUniqueId)) {
claimList.add(claim);
}
} else {
if (gpClaim.getOwnerUniqueId().equals(playerUniqueId)) {
claimList.add(claim);
}
}
}
}
return claimList;
}
public void removePlayer(UUID playerUniqueId) {
this.getPlayerDataMap().remove(playerUniqueId);
}
public ClaimResult addClaim(Claim claim) {
GDClaim newClaim = (GDClaim) claim;
// ensure this new claim won't overlap any existing claims
ClaimResult result = newClaim.checkArea(false);
if (!result.successful()) {
return result;
}
// validate world
if (!this.worldUniqueId.equals(newClaim.getWorld().getUID())) {
World world = Bukkit.getServer().getWorld(this.worldUniqueId);
newClaim.setWorld(world);
}
// otherwise add this new claim to the data store to make it effective
this.addClaim(newClaim, true);
if (result.getClaims().size() > 1) {
newClaim.migrateClaims(new ArrayList<>(result.getClaims()));
}
return result;
}
public void addClaim(Claim claimToAdd, boolean writeToStorage) {
GDClaim claim = (GDClaim) claimToAdd;
if (claim.parent == null && this.worldClaims.contains(claimToAdd)) {
return;
}
if (writeToStorage) {
DATASTORE.writeClaimToStorage(claim);
}
// We need to keep track of all claims so they can be referenced by children during server startup
this.claimUniqueIdMap.put(claim.getUniqueId(), claim);
if (claim.isWilderness()) {
this.theWildernessClaim = claim;
return;
}
if (claim.parent != null) {
claim.parent.children.add(claim);
this.worldClaims.remove(claim);
this.deleteChunkHashes((GDClaim) claim);
if (!claim.isAdminClaim() && (!claim.isInTown() || !claim.getTownClaim().getOwnerUniqueId().equals(claim.getOwnerUniqueId()))) {
final GDPlayerData playerData = this.getPlayerDataMap().get(claim.getOwnerUniqueId());
Set<Claim> playerClaims = playerData.getInternalClaims();
if (!playerClaims.contains(claim)) {
playerClaims.add(claim);
}
}
return;
}
if (!this.worldClaims.contains(claim)) {
this.worldClaims.add(claim);
}
final UUID ownerId = claim.getOwnerUniqueId();
final GDPlayerData playerData = this.getPlayerDataMap().get(ownerId);
if (playerData != null) {
Set<Claim> playerClaims = playerData.getInternalClaims();
if (!playerClaims.contains(claim)) {
playerClaims.add(claim);
}
} else if (!claim.isAdminClaim()) {
this.createPlayerData(ownerId);
}
this.updateChunkHashes(claim);
return;
}
public void updateChunkHashes(GDClaim claim) {
this.deleteChunkHashes(claim);
Set<Long> chunkHashes = claim.getChunkHashes(true);
for (Long chunkHash : chunkHashes) {
Set<Claim> claimsInChunk = this.getInternalChunksToClaimsMap().get(chunkHash);
if (claimsInChunk == null) {
claimsInChunk = new HashSet<Claim>();
this.getInternalChunksToClaimsMap().put(chunkHash, claimsInChunk);
}
claimsInChunk.add(claim);
}
}
// Used when parent claims becomes children
public void removeClaimData(Claim claim) {
this.worldClaims.remove(claim);
this.deleteChunkHashes((GDClaim) claim);
}
@Override
public ClaimResult deleteClaim(Claim claim, boolean deleteChildren) {
GDDeleteClaimEvent event = new GDDeleteClaimEvent(claim);
GriefDefender.getEventManager().post(event);
if (event.cancelled()) {
return new GDClaimResult(claim, ClaimResultType.CLAIM_EVENT_CANCELLED, event.getMessage().orElse(null));
}
this.deleteClaimInternal(claim, deleteChildren);
return new GDClaimResult(claim, ClaimResultType.SUCCESS);
}
public void deleteClaimInternal(Claim claim, boolean deleteChildren) {
final GDClaim gpClaim = (GDClaim) claim;
Set<Claim> subClaims = claim.getChildren(false);
for (Claim child : subClaims) {
if (deleteChildren || (gpClaim.parent == null && child.isSubdivision())) {
this.deleteClaimInternal(child, true);
continue;
}
final GDClaim parentClaim = (GDClaim) claim;
final GDClaim childClaim = (GDClaim) child;
if (parentClaim.parent != null) {
migrateChildToNewParent(parentClaim.parent, childClaim);
} else {
// move child to parent folder
migrateChildToNewParent(null, childClaim);
}
}
resetPlayerClaimVisuals(claim);
// transfer bank balance to owner
final UUID bankAccount = claim.getEconomyAccountId().orElse(null);
if (bankAccount != null) {
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();
final GDPlayerData playerData = ((GDClaim) claim).getOwnerPlayerData();
if (playerData != null) {
final OfflinePlayer vaultPlayer = playerData.getSubject().getOfflinePlayer();
if (vaultPlayer != null && !economy.hasAccount(vaultPlayer)) {
final double bankBalance = economy.bankBalance(claim.getUniqueId().toString()).amount;
economy.depositPlayer(vaultPlayer, bankBalance);
}
}
economy.deleteBank(claim.getUniqueId().toString());
}
this.worldClaims.remove(claim);
this.claimUniqueIdMap.remove(claim.getUniqueId());
this.deleteChunkHashes((GDClaim) claim);
if (gpClaim.parent != null) {
gpClaim.parent.children.remove(claim);
}
DATASTORE.deleteClaimFromStorage((GDClaim) claim);
}
// Migrates children to new parent
private void migrateChildToNewParent(GDClaim parentClaim, GDClaim childClaim) {
childClaim.parent = parentClaim;
String fileName = childClaim.getClaimStorage().filePath.getFileName().toString();
Path newPath = null;
if (parentClaim == null) {
newPath = childClaim.getClaimStorage().folderPath.getParent().getParent().resolve(childClaim.getType().getName().toLowerCase()).resolve(fileName);
} else {
// Only store in same claim type folder if not admin.
// Admin claims are currently the only type that can hold children of same type within
if (childClaim.getType().equals(parentClaim.getType()) && (!parentClaim.isAdminClaim())) {
newPath = parentClaim.getClaimStorage().folderPath.resolve(fileName);
} else {
newPath = parentClaim.getClaimStorage().folderPath.resolve(childClaim.getType().getName().toLowerCase()).resolve(fileName);
}
}
try {
if (Files.notExists(newPath.getParent())) {
Files.createDirectories(newPath.getParent());
}
Files.move(childClaim.getClaimStorage().filePath, newPath);
if (childClaim.getClaimStorage().folderPath.toFile().listFiles().length == 0) {
Files.delete(childClaim.getClaimStorage().folderPath);
}
childClaim.setClaimStorage(new ClaimStorageData(newPath, this.worldUniqueId, (ClaimDataConfig) childClaim.getInternalClaimData()));
} catch (IOException e) {
e.printStackTrace();
}
// Make sure to update new parent in storage
final UUID parentUniqueId = parentClaim == null ? null : parentClaim.getUniqueId();
childClaim.getInternalClaimData().setParent(parentUniqueId);
this.addClaim(childClaim, true);
for (Claim child : childClaim.children) {
migrateChildToNewParent(childClaim, (GDClaim) child);
}
}
private void resetPlayerClaimVisuals(Claim claim) {
// player may be offline so check is needed
GDPlayerData playerData = this.getPlayerDataMap().get(claim.getOwnerUniqueId());
if (playerData != null) {
playerData.getInternalClaims().remove(claim);
if (playerData.lastClaim != null) {
playerData.lastClaim.clear();
}
}
// revert visuals for all players watching this claim
List<UUID> playersWatching = new ArrayList<>(((GDClaim) claim).playersWatching);
for (UUID playerUniqueId : playersWatching) {
Player player = Bukkit.getServer().getPlayer(playerUniqueId);
if (player != null) {
playerData = this.getOrCreatePlayerData(playerUniqueId);
playerData.revertActiveVisual(player);
if (playerData.lastClaim != null) {
playerData.lastClaim.clear();
}
if (GriefDefenderPlugin.getInstance().getWorldEditProvider() != null) {
GriefDefenderPlugin.getInstance().getWorldEditProvider().revertVisuals(player, playerData, claim.getUniqueId());
}
}
}
}
private void deleteChunkHashes(GDClaim claim) {
Set<Long> chunkHashes = claim.getChunkHashes(false);
if (chunkHashes == null) {
return;
}
for (Long chunkHash : chunkHashes) {
Set<Claim> claimsInChunk = this.getInternalChunksToClaimsMap().get(chunkHash);
if (claimsInChunk != null) {
claimsInChunk.remove(claim);
}
}
}
@Nullable
public Optional<Claim> getClaimByUUID(UUID claimUniqueId) {
return Optional.ofNullable(this.claimUniqueIdMap.get(claimUniqueId));
}
public Set<Claim> getInternalPlayerClaims(UUID playerUniqueId) {
final GDPlayerData playerData = this.getPlayerDataMap().get(playerUniqueId);
if (playerData == null) {
return new HashSet<>();
}
return playerData.getInternalClaims();
}
@Nullable
public Set<Claim> getPlayerClaims(UUID playerUniqueId) {
final GDPlayerData playerData = this.getPlayerDataMap().get(playerUniqueId);
if (playerData == null) {
return ImmutableSet.of();
}
return ImmutableSet.copyOf(this.getPlayerDataMap().get(playerUniqueId).getInternalClaims());
}
public void createWildernessClaim(World world) {
final Vector3i lesserCorner = new Vector3i(-30000000, 0, -30000000);
final Vector3i greaterCorner = new Vector3i(29999999, 255, 29999999);
// Use world UUID as wilderness claim ID
GDClaim wilderness = new GDClaim(world, lesserCorner, greaterCorner, world.getUID(), ClaimTypes.WILDERNESS, null, false);
wilderness.setOwnerUniqueId(GriefDefenderPlugin.WORLD_USER_UUID);
wilderness.initializeClaimData(null);
wilderness.claimData.save();
wilderness.claimStorage.save();
this.theWildernessClaim = wilderness;
this.claimUniqueIdMap.put(wilderness.getUniqueId(), wilderness);
}
@Override
public GDClaim getWildernessClaim() {
if (this.theWildernessClaim == null) {
World world = Bukkit.getServer().getWorld(this.worldUniqueId);
this.createWildernessClaim(world);
}
return this.theWildernessClaim;
}
@Override
public Set<Claim> getWorldClaims() {
return this.worldClaims;
}
public Map<UUID, GDPlayerData> getPlayerDataMap() {
if (BaseStorage.USE_GLOBAL_PLAYER_STORAGE) {
return BaseStorage.GLOBAL_PLAYER_DATA;
}
return this.playerDataList;
}
@Override
public Map<Long, Set<Claim>> getChunksToClaimsMap() {
return ImmutableMap.copyOf(this.chunksToClaimsMap);
}
public Map<Long, Set<Claim>> getInternalChunksToClaimsMap() {
return this.chunksToClaimsMap;
}
public void save() {
for (Claim claim : this.worldClaims) {
GDClaim gpClaim = (GDClaim) claim;
gpClaim.save();
}
this.theWildernessClaim.save();
for (GDPlayerData playerData : this.getPlayerDataMap().values()) {
playerData.getStorageData().save();
}
}
public void unload() {
this.playerDataList.clear();
this.worldClaims.clear();
this.claimUniqueIdMap.clear();
this.chunksToClaimsMap.clear();
if (this.theWildernessClaim != null) {
this.theWildernessClaim.unload();
this.theWildernessClaim = null;
}
this.worldUniqueId = null;
}
public Claim getClaimAt(Location location, boolean useBorderBlockRadius) {
return this.getClaimAt(VecHelper.toVector3i(location), null, null, useBorderBlockRadius);
}
public Claim getClaimAtPlayer(Location location, GDPlayerData playerData) {
return this.getClaimAt(VecHelper.toVector3i(location), (GDClaim) playerData.lastClaim.get(), playerData, false);
}
public Claim getClaimAtPlayer(Location location, GDPlayerData playerData, boolean useBorderBlockRadius) {
return this.getClaimAt(VecHelper.toVector3i(location), (GDClaim) playerData.lastClaim.get(), playerData, useBorderBlockRadius);
}
@Override
public Claim getClaimAt(Vector3i pos) {
return this.getClaimAt(pos, null, null, false);
}
public Claim getClaimAt(Vector3i pos, GDClaim cachedClaim, GDPlayerData playerData, boolean useBorderBlockRadius) {
if (cachedClaim != null && !cachedClaim.isWilderness() && cachedClaim.contains(pos, true)) {
return cachedClaim;
}
Set<Claim> claimsInChunk = this.getInternalChunksToClaimsMap().get(BlockUtil.getInstance().asLong(pos.getX() >> 4, pos.getZ() >> 4));
if (useBorderBlockRadius && (playerData != null && !playerData.ignoreBorderCheck)) {
final int borderBlockRadius = GriefDefenderPlugin.getActiveConfig(this.worldUniqueId).getConfig().claim.borderBlockRadius;
// if borderBlockRadius > 0, check surrounding chunks
if (borderBlockRadius > 0) {
for (Direction direction : BlockUtil.getInstance().ORDINAL_SET) {
Vector3i currentPos = pos;
for (int i = 0; i < borderBlockRadius; i++) { // Handle depth
currentPos = BlockUtil.getInstance().getBlockRelative(currentPos, direction);
Set<Claim> relativeClaims = this.getInternalChunksToClaimsMap().get(BlockUtil.getInstance().asLong(currentPos.getX() >> 4, currentPos.getZ() >> 4));
if (relativeClaims != null) {
if (claimsInChunk == null) {
claimsInChunk = new HashSet<>();
}
claimsInChunk.addAll(relativeClaims);
}
}
}
}
}
if (claimsInChunk == null) {
return this.getWildernessClaim();
}
for (Claim claim : claimsInChunk) {
GDClaim foundClaim = findClaim((GDClaim) claim, pos, playerData, useBorderBlockRadius);
if (foundClaim != null) {
return foundClaim;
}
}
// if no claim found, return the world claim
return this.getWildernessClaim();
}
private GDClaim findClaim(GDClaim claim, Vector3i pos, GDPlayerData playerData, boolean useBorderBlockRadius) {
if (claim.contains(pos, playerData, useBorderBlockRadius)) {
// when we find a top level claim, if the location is in one of its children,
// return the child claim, not the top level claim
for (Claim childClaim : claim.children) {
GDClaim child = (GDClaim) childClaim;
if (!child.children.isEmpty()) {
GDClaim innerChild = findClaim(child, pos, playerData, useBorderBlockRadius);
if (innerChild != null) {
return innerChild;
}
}
// check if child has children (Town -> Basic -> Subdivision)
if (child.contains(pos, playerData, useBorderBlockRadius)) {
return child;
}
}
return claim;
}
return null;
}
@Override
public List<Claim> getClaimsByName(String name) {
List<Claim> claimList = new ArrayList<>();
for (Claim worldClaim : this.getWorldClaims()) {
Component claimName = worldClaim.getName().orElse(null);
if (claimName != null && claimName != TextComponent.empty()) {
if (PlainComponentSerializer.INSTANCE.serialize(claimName).equalsIgnoreCase(name)) {
claimList.add(worldClaim);
}
}
// check children
for (Claim child : ((GDClaim) worldClaim).getChildren(true)) {
if (child.getUniqueId().toString().equals(name)) {
claimList.add(child);
}
}
}
return claimList;
}
public void resetPlayerData() {
// check migration reset
if (GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.resetMigrations) {
for (GDPlayerData playerData : this.getPlayerDataMap().values()) {
final PlayerStorageData playerStorage = playerData.getStorageData();
playerStorage.getConfig().setMigratedBlocks(false);
playerStorage.save();
}
}
// migrate playerdata to new claim block system
final int migration3dRate = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.migrateVolumeRate;
final int migration2dRate = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.migrateAreaRate;
final boolean resetClaimBlockData = GriefDefenderPlugin.getGlobalConfig().getConfig().playerdata.resetAccruedClaimBlocks;
if (migration3dRate <= -1 && migration2dRate <= -1 && !resetClaimBlockData) {
return;
}
if (GriefDefenderPlugin.CLAIM_BLOCK_SYSTEM == ClaimBlockSystem.VOLUME && migration2dRate >= 0) {
return;
}
if (GriefDefenderPlugin.CLAIM_BLOCK_SYSTEM == ClaimBlockSystem.AREA && migration3dRate >= 0) {
return;
}
for (GDPlayerData playerData : this.getPlayerDataMap().values()) {
final PlayerStorageData playerStorage = playerData.getStorageData();
final int accruedBlocks = playerStorage.getConfig().getAccruedClaimBlocks();
int newAccruedBlocks = accruedBlocks;
// first check reset
if (resetClaimBlockData) {
newAccruedBlocks = playerData.getTotalClaimsCost();
playerStorage.getConfig().setBonusClaimBlocks(0);
} else if (migration3dRate > -1 && !playerStorage.getConfig().hasMigratedBlocks()) {
newAccruedBlocks = accruedBlocks * migration3dRate;
playerStorage.getConfig().setMigratedBlocks(true);
} else if (migration2dRate > -1 && !playerStorage.getConfig().hasMigratedBlocks()) {
newAccruedBlocks = accruedBlocks / migration2dRate;
playerStorage.getConfig().setMigratedBlocks(true);
}
if (newAccruedBlocks < 0) {
newAccruedBlocks = 0;
}
final int maxAccruedBlocks = GDPermissionManager.getInstance().getGlobalInternalOptionValue(playerData.getSubject(), Options.MAX_ACCRUED_BLOCKS, playerData).intValue();
if (newAccruedBlocks > maxAccruedBlocks) {
newAccruedBlocks = maxAccruedBlocks;
}
playerStorage.getConfig().setAccruedClaimBlocks(newAccruedBlocks);
playerStorage.save();
}
}
@Override
public UUID getWorldId() {
return this.worldUniqueId;
}
public GDChunk getChunk(Chunk chunk) {
GDChunk gpChunk = this.chunksToGpChunks.get(getChunkKey(chunk));
if (gpChunk == null) {
gpChunk = new GDChunk(chunk);
this.chunksToGpChunks.put(getChunkKey(chunk), gpChunk);
}
return gpChunk;
}
public void removeChunk(Chunk chunk) {
this.chunksToGpChunks.remove(getChunkKey(chunk));
}
private long getChunkKey(Chunk chunk) {
return (long) chunk.getX() & 0xffffffffL | ((long) chunk.getZ() & 0xffffffffL) << 32;
}
}

View File

@ -0,0 +1,89 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.claim;
import com.google.common.collect.ImmutableList;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimResult;
import com.griefdefender.api.claim.ClaimResultType;
import net.kyori.text.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class GDClaimResult implements ClaimResult {
private final Component eventMessage;
private final List<Claim> claims;
private final ClaimResultType resultType;
public GDClaimResult(ClaimResultType type) {
this(type, null);
}
public GDClaimResult(ClaimResultType type, Component message) {
this.claims = ImmutableList.of();
this.resultType = type;
this.eventMessage = message;
}
public GDClaimResult(Claim claim, ClaimResultType type) {
this(claim, type, null);
}
public GDClaimResult(Claim claim, ClaimResultType type, Component message) {
List<Claim> claimList = new ArrayList<>();
claimList.add(claim);
this.claims = ImmutableList.copyOf(claimList);
this.resultType = type;
this.eventMessage = message;
}
public GDClaimResult(List<Claim> claims, ClaimResultType type) {
this(claims, type, null);
}
public GDClaimResult(List<Claim> claims, ClaimResultType type, Component message) {
this.claims = ImmutableList.copyOf(claims);
this.resultType = type;
this.eventMessage = message;
}
@Override
public ClaimResultType getResultType() {
return this.resultType;
}
@Override
public Optional<Component> getMessage() {
return Optional.ofNullable(this.eventMessage);
}
@Override
public List<Claim> getClaims() {
return this.claims;
}
}

View File

@ -0,0 +1,92 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.claim;
import com.griefdefender.api.claim.ClaimContexts;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.permission.Context;
public class GDClaimType implements ClaimType {
private final String id;
private final String name;
private final Context context;
private final Context defaultContext;
private final Context overrideContext;
public GDClaimType(String id, String name) {
this.id = id;
this.name = name;
this.context = new Context("gd_claim_type", name.toLowerCase());
if (name.equalsIgnoreCase("any")) {
this.defaultContext = ClaimContexts.GLOBAL_DEFAULT_CONTEXT;
this.overrideContext = ClaimContexts.GLOBAL_OVERRIDE_CONTEXT;
} else if (name.equalsIgnoreCase("admin")) {
this.defaultContext = ClaimContexts.ADMIN_DEFAULT_CONTEXT;
this.overrideContext = ClaimContexts.ADMIN_OVERRIDE_CONTEXT;
} else if (name.equalsIgnoreCase("basic")) {
this.defaultContext = ClaimContexts.BASIC_DEFAULT_CONTEXT;
this.overrideContext = ClaimContexts.BASIC_OVERRIDE_CONTEXT;
} else if (name.equalsIgnoreCase("subdivision")) {
this.defaultContext = ClaimContexts.SUBDIVISION_DEFAULT_CONTEXT;
this.overrideContext = ClaimContexts.SUBDIVISION_OVERRIDE_CONTEXT;
} else if (name.equalsIgnoreCase("town")) {
this.defaultContext = ClaimContexts.TOWN_DEFAULT_CONTEXT;
this.overrideContext = ClaimContexts.TOWN_OVERRIDE_CONTEXT;
} else {
this.defaultContext = ClaimContexts.WILDERNESS_DEFAULT_CONTEXT;
this.overrideContext = ClaimContexts.WILDERNESS_OVERRIDE_CONTEXT;
}
}
@Override
public String getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
public String toString() {
return this.name;
}
@Override
public Context getContext() {
return this.context;
}
@Override
public Context getDefaultContext() {
return this.defaultContext;
}
@Override
public Context getOverrideContext() {
return this.overrideContext;
}
}

View File

@ -0,0 +1,49 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.claim;
import com.griefdefender.api.claim.ShovelType;
public class GDShovelType implements ShovelType {
private final String id;
private final String name;
public GDShovelType(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
}

View File

@ -0,0 +1,21 @@
package com.griefdefender.claim;
import com.flowpowered.math.vector.Vector3i;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.Town;
import com.griefdefender.api.data.TownData;
import org.bukkit.World;
import java.util.UUID;
public class GDTown extends GDClaim implements Town {
public GDTown(World world, Vector3i point1, Vector3i point2, ClaimType type, UUID ownerUniqueId, boolean cuboid) {
super(world, point1, point2, type, ownerUniqueId, cuboid);
}
@Override
public TownData getData() {
return (TownData) this.claimData;
}
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.claim;
import com.griefdefender.api.claim.TrustType;
public class GDTrustType implements TrustType {
private final String id;
private final String name;
public GDTrustType(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String getId() {
return this.id;
}
@Override
public String getName() {
return this.name;
}
@Override
public String toString() {
return this.id + ":" + this.name;
}
}

View File

@ -0,0 +1,998 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.Maps;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimContexts;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.permission.Context;
import com.griefdefender.api.permission.PermissionResult;
import com.griefdefender.api.permission.flag.Flag;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDFlagClaimEvent;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.registry.FlagRegistryModule;
import com.griefdefender.storage.BaseStorage;
import com.griefdefender.text.action.GDCallbackHolder;
import com.griefdefender.util.CauseContextHelper;
import com.griefdefender.util.ClaimClickData;
import com.griefdefender.util.PaginationUtil;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public abstract class ClaimFlagBase extends BaseCommand {
public enum FlagType {
DEFAULT,
CLAIM,
OVERRIDE,
INHERIT,
GROUP,
PLAYER
}
protected ClaimSubjectType subjectType;
protected GDPermissionHolder subject;
protected String friendlySubjectName;
protected boolean isAdmin = false;
protected GDPlayerData sourcePlayerData;
private final Cache<UUID, FlagType> lastActiveFlagTypeMap = Caffeine.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES)
.build();
protected ClaimFlagBase(ClaimSubjectType type) {
this.subjectType = type;
}
public void execute(Player player, String[] args) throws InvalidCommandArgument {
String commandFlag = null;
String target = null;
String value = null;
String contexts = null;
final String arguments = String.join(" ", args);
int index = arguments.indexOf("context[");
if (index != -1) {
contexts = arguments.substring(index, arguments.length());
}
if (args.length > 0) {
if (args.length < 3) {
throw new InvalidCommandArgument();
}
commandFlag = args[0];
target = args[1];
value = args[2];
}
final Flag flag = FlagRegistryModule.getInstance().getById(commandFlag).orElse(null);
if (commandFlag != null && flag == null) {
TextAdapter.sendComponent(player, TextComponent.of("Flag not found.", TextColor.RED));
return;
}
if (flag != null && !player.hasPermission(GDPermissions.USER_CLAIM_FLAGS + flag.getPermission().replace(GDPermissions.FLAG_BASE, ""))) {
TextAdapter.sendComponent(player, TextComponent.of("You do not have permission to change this flag.", TextColor.RED));
return;
}
if (target != null && target.equalsIgnoreCase("hand")) {
ItemStack stack = NMSUtil.getInstance().getActiveItem(player);
if (stack != null) {
target = GDPermissionManager.getInstance().getPermissionIdentifier(stack);
}
}
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final Claim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Set<Context> contextSet = CauseContextHelper.generateContexts(player, claim, contexts);
if (contextSet == null) {
return;
}
if (claim != null) {
if (flag == null && value == null && player.hasPermission(GDPermissions.COMMAND_LIST_CLAIM_FLAGS)) {
showFlagPermissions(player, (GDClaim) claim, FlagType.CLAIM);
return;
} else if (flag != null && value != null) {
// if (context != null) {
/*claimContext = CommandHelper.validateCustomContext(src, claim, context);
if (claimContext == null) {
final Text message = GriefDefenderPlugin.getInstance().messageData.flagInvalidContext
.apply(ImmutableMap.of(
"context", context,
"flag", flag)).build();
GriefDefenderPlugin.sendMessage(src, message);
return CommandResult.success();
}*/
//}
GDCauseStackManager.getInstance().pushCause(player);
((GDPermissionManager) GriefDefender.getPermissionManager()).setPermission(claim, this.subject, this.friendlySubjectName, flag, target, PermissionUtil.getInstance().getTristateFromString(value.toUpperCase()), contextSet);
GDCauseStackManager.getInstance().popCause();
return;
}
GriefDefenderPlugin.sendMessage(player, TextComponent.of("Usage: /cf [<flag> <target> <value> [subject|context]]"));
} else {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotFound.toText());
}
}
protected void showFlagPermissions(CommandSender src, GDClaim claim, FlagType flagType) {
boolean isAdmin = false;
if (src.hasPermission(GDPermissions.DELETE_CLAIM_ADMIN)) {
isAdmin = true;
}
if (src instanceof Player) {
final Player player = (Player) src;
final FlagType lastFlagType = this.lastActiveFlagTypeMap.getIfPresent(player.getUniqueId());
if (lastFlagType != null && lastFlagType != flagType) {
PaginationUtil.getInstance().resetActivePage(player.getUniqueId());
}
}
final Component whiteOpenBracket = TextComponent.of("[", TextColor.AQUA);
final Component whiteCloseBracket = TextComponent.of("]", TextColor.AQUA);
final Component showOverrideText = TextComponent.builder("")
.append("Click here to filter by ")
.append("OVERRIDE ", TextColor.RED)
.append("permissions.").build();
final Component showDefaultText = TextComponent.builder("")
.append("Click here to filter by ")
.append("DEFAULT ", TextColor.LIGHT_PURPLE)
.append("permissions.").build();
final Component showClaimText = TextComponent.builder("")
.append("Click here to filter by ")
.append("CLAIM ", TextColor.GOLD)
.append("permissions.").build();
final Component showInheritText = TextComponent.builder("")
.append("Click here to filter by ")
.append("INHERIT ", TextColor.AQUA)
.append("permissions.").build();
Component defaultFlagText = TextComponent.empty();
if (isAdmin) {
defaultFlagText = TextComponent.builder("")
.append(flagType == FlagType.DEFAULT ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("DEFAULT", TextColor.LIGHT_PURPLE)
.append(whiteCloseBracket).build() : TextComponent.of("DEFAULT", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimFlagConsumer(src, claim, FlagType.DEFAULT))))
.hoverEvent(HoverEvent.showText(showDefaultText)).build();
}
final Component overrideFlagText = TextComponent.builder("")
.append(flagType == FlagType.OVERRIDE ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("OVERRIDE", TextColor.RED)
.append(whiteCloseBracket).build() : TextComponent.of("OVERRIDE", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimFlagConsumer(src, claim, FlagType.OVERRIDE))))
.hoverEvent(HoverEvent.showText(showOverrideText)).build();
final Component claimFlagText = TextComponent.builder("")
.append(flagType == FlagType.CLAIM ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("CLAIM", TextColor.YELLOW)
.append(whiteCloseBracket).build() : TextComponent.of("CLAIM", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimFlagConsumer(src, claim, FlagType.CLAIM))))
.hoverEvent(HoverEvent.showText(showClaimText)).build();
final Component inheritFlagText = TextComponent.builder("")
.append(flagType == FlagType.INHERIT ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("INHERIT", TextColor.AQUA)
.append(whiteCloseBracket).build() : TextComponent.of("INHERIT", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimFlagConsumer(src, claim, FlagType.INHERIT))))
.hoverEvent(HoverEvent.showText(showInheritText)).build();
Component claimFlagHead = TextComponent.empty();
if (this.subjectType == ClaimSubjectType.GLOBAL) {
if (isAdmin) {
claimFlagHead = TextComponent.builder("")
.append(" Displaying : ", TextColor.AQUA)
.append(defaultFlagText)
.append(" ")
.append(claimFlagText)
.append(" ")
.append(inheritFlagText)
.append(" ")
.append(overrideFlagText).build();
} else {
claimFlagHead = TextComponent.builder("")
.append(" Displaying : ", TextColor.AQUA)
.append(claimFlagText)
.append(" ")
.append(inheritFlagText)
.append(" ")
.append(overrideFlagText).build();
}
} else {
claimFlagHead = TextComponent.builder("")
.append(" " + this.subjectType.getFriendlyName() + " ", TextColor.AQUA)
.append(this.friendlySubjectName, TextColor.YELLOW)
.append(" : ", TextColor.AQUA)
.append(claimFlagText)
.append(" ")
.append(inheritFlagText)
.append(" ")
.append(overrideFlagText).build();
}
Map<Set<Context>, Map<String, Component>> contextMap = new HashMap<>();
List<Component> textList = new ArrayList<>();
Set<Context> defaultContexts = new HashSet<>();
Set<Context> overrideContexts = new HashSet<>();
//contexts.add(claim.world.getContext());
if (claim.isAdminClaim()) {
defaultContexts.add(ClaimContexts.ADMIN_DEFAULT_CONTEXT);
overrideContexts.add(ClaimContexts.ADMIN_OVERRIDE_CONTEXT);
} else if (claim.isBasicClaim() || claim.isSubdivision()) {
defaultContexts.add(ClaimContexts.BASIC_DEFAULT_CONTEXT);
overrideContexts.add(ClaimContexts.BASIC_OVERRIDE_CONTEXT);
} else if (claim.isTown()) {
defaultContexts.add(ClaimContexts.TOWN_DEFAULT_CONTEXT);
overrideContexts.add(ClaimContexts.TOWN_OVERRIDE_CONTEXT);
} else {
defaultContexts.add(ClaimContexts.WILDERNESS_DEFAULT_CONTEXT);
overrideContexts.add(ClaimContexts.WILDERNESS_OVERRIDE_CONTEXT);
}
defaultContexts.add(ClaimContexts.GLOBAL_DEFAULT_CONTEXT);
overrideContexts.add(ClaimContexts.GLOBAL_OVERRIDE_CONTEXT);
overrideContexts.add(claim.getOverrideClaimContext());
Map<Set<Context>, Map<String, Boolean>> defaultPermissionMap = new HashMap<>();
Map<Set<Context>, Map<String, Boolean>> defaultTransientPermissionMap = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : PermissionUtil.getInstance().getTransientPermissions(claim, this.subject).entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(claim.getDefaultTypeContext()) || contextSet.contains(ClaimContexts.GLOBAL_DEFAULT_CONTEXT)) {
defaultTransientPermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
}
Map<Set<Context>, Map<String, Boolean>> overridePermissionMap = new HashMap<>();
Map<Set<Context>, Map<String, Boolean>> claimPermissionMap = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : PermissionUtil.getInstance().getPermanentPermissions(claim, this.subject).entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(claim.getDefaultTypeContext())) {
defaultPermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
if (contextSet.contains(claim.getContext())) {
claimPermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
if (contextSet.contains(claim.getOverrideClaimContext())) {
overridePermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
} else if (contextSet.contains(claim.getOverrideTypeContext())) {
overridePermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
if (contextSet.contains(ClaimContexts.GLOBAL_DEFAULT_CONTEXT)) {
defaultPermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
if (contextSet.contains(ClaimContexts.GLOBAL_OVERRIDE_CONTEXT)) {
overridePermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
}
Map<Set<Context>, ClaimClickData> inheritPermissionMap = Maps.newHashMap();
final List<Claim> inheritParents = claim.getInheritedParents();
Collections.reverse(inheritParents);
for (Claim current : inheritParents) {
GDClaim currentClaim = (GDClaim) current;
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : PermissionUtil.getInstance().getPermanentPermissions(claim, this.subject).entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(currentClaim.getContext())) {
inheritPermissionMap.put(mapEntry.getKey(), new ClaimClickData(currentClaim, mapEntry.getValue()));
}
}
}
final Component denyText = claim.allowEdit((Player) src);
final boolean hasPermission = denyText == null;
if (flagType == FlagType.CLAIM) {
final Map<String, Set<Context>> permissionMap = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : defaultTransientPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Component> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Component>();
contextMap.put(contextSet, textMap);
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
Component flagText = null;
String flagPermission = permissionEntry.getKey();
/*if (textMap.containsKey(flagPermission)) {
// only display flags not overridden
continue;
}*/
Boolean flagValue = permissionEntry.getValue();
String baseFlagPerm = flagPermission.replace(GDPermissions.FLAG_BASE + ".", "").replace(".*", "");
final Flag baseFlag = FlagRegistryModule.getInstance().getById(flagPermission).orElse(null);
if (baseFlag == null) {
// invalid flag
continue;
}
boolean hasOverride = false;
for (Map.Entry<Set<Context>, Map<String, Boolean>> overrideEntry : overridePermissionMap.entrySet()) {
final Set<Context> overrideContextSet = overrideEntry.getKey();
for (Map.Entry<String, Boolean> overridePermissionEntry : overrideEntry.getValue().entrySet()) {
if (flagPermission.contains(overridePermissionEntry.getKey())) {
hasOverride = true;
Component undefinedText = null;
if (hasPermission) {
undefinedText = TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append(baseFlagPerm)
.append(" is currently being ")
.append("overridden", TextColor.RED)
.append(" by an administrator.\nClick here to remove this flag.").build()))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createFlagConsumer(src, claim, overrideContextSet, flagPermission, Tristate.UNDEFINED, flagType, FlagType.CLAIM, false)))).build();
} else {
undefinedText = TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.hoverEvent(HoverEvent.showText(denyText)).build();
}
flagText = TextComponent.builder("")
.append(undefinedText)
.append(" ")
.append("[", TextColor.AQUA)
.append(String.valueOf(overridePermissionEntry.getValue()), TextColor.RED)
.append("]", TextColor.AQUA)
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append("This flag has been overridden by an administrator and can ")
.append(TextComponent.of("NOT").color(TextColor.RED).decoration(TextDecoration.UNDERLINED, true))
.append(" be changed.").build()))
.build();
break;
}
}
}
if (!hasOverride) {
// check if transient default has been overridden and if so display that value instead
final Set<Context> claimContexts = createClaimContextSet(claim, contextSet);
final Map<String, Boolean> subjectPerms = PermissionUtil.getInstance().getPermissions(this.subject, claimContexts);
Boolean overriddenValue = subjectPerms.get(flagPermission);
if (overriddenValue == null && this.subject != GriefDefenderPlugin.DEFAULT_HOLDER) {
// Check claim
final Map<String, Boolean> claimPerms = claimPermissionMap.get(claimContexts);
if (claimPerms != null) {
overriddenValue = claimPerms.get(flagPermission);
}
}
final Tristate currentValue = overriddenValue == null ? Tristate.UNDEFINED : Tristate.fromBoolean(overriddenValue);
Component undefinedText = null;
if (hasPermission) {
undefinedText = TextComponent.builder("")
.append(currentValue == Tristate.UNDEFINED ?
TextComponent.builder("")
.append(whiteOpenBracket)
.append("undefined", TextColor.GOLD)
.append(whiteCloseBracket)
.build() :
TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.append(TextComponent.empty())
.build())
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append(baseFlagPerm)
.append(" is currently not set.\nThe default claim value of ")
.append(String.valueOf(flagValue), TextColor.LIGHT_PURPLE)
.append(" will be active until set.").build()))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createFlagConsumer(src, claim, claimContexts, flagPermission, Tristate.UNDEFINED, flagType, FlagType.CLAIM, false)))).build();
} else {
undefinedText = TextComponent.builder("").append(
TextComponent.builder("")
.append(currentValue == Tristate.UNDEFINED ?
TextComponent.builder("")
.append(whiteOpenBracket)
.append("undefined", TextColor.GOLD)
.append(whiteCloseBracket)
.build() :
TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.append(currentValue == Tristate.UNDEFINED ? whiteCloseBracket : TextComponent.empty())
.build())
.build())
.hoverEvent(HoverEvent.showText(denyText)).build();
}
final Component trueText = TextComponent.builder("")
.append(getClickableText(src, claim, claimContexts, flagPermission, currentValue, Tristate.TRUE, flagType, FlagType.CLAIM, false).color(TextColor.GRAY)).build();
final Component falseText = TextComponent.builder("")
.append(getClickableText(src, claim, claimContexts, flagPermission, currentValue, Tristate.FALSE, flagType, FlagType.CLAIM, false).color(TextColor.GRAY)).build();
flagText = TextComponent.builder("")
.append(undefinedText)
.append(" ")
.append(trueText)
.append(" ")
.append(falseText).build();
}
Component baseFlagText = getFlagText(defaultContexts, flagPermission, baseFlag.toString(), flagType);
flagText = TextComponent.builder("")
.append(baseFlagText)
.append(" ")
.append(flagText).build();
textMap.put(flagPermission, flagText);
permissionMap.put(flagPermission, contextSet);
textList.add(flagText);
}
}
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : claimPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Component> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Component>();
contextMap.put(contextSet, textMap);
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
String flagPermission = permissionEntry.getKey();
final Flag claimFlag = FlagRegistryModule.getInstance().getById(flagPermission).orElse(null);
if (claimFlag == null) {
// invalid flag
continue;
}
final String baseFlag = flagPermission.replace(GDPermissions.FLAG_BASE + ".", "").replace(".*", "");
final Set<Context> contexts = permissionMap.get(flagPermission);
if (this.ignoreFlagEntry(contextSet)) {
continue;
}
Boolean flagValue = permissionEntry.getValue();
Component flagText = null;
boolean hasOverride = false;
for (Map.Entry<Set<Context>, Map<String, Boolean>> overrideEntry : overridePermissionMap.entrySet()) {
final Set<Context> overrideContextSet = overrideEntry.getKey();
for (Map.Entry<String, Boolean> overridePermissionEntry : overrideEntry.getValue().entrySet()) {
if (flagPermission.contains(overridePermissionEntry.getKey())) {
hasOverride = true;
Component undefinedText = null;
if (hasPermission) {
undefinedText = TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append(baseFlag, TextColor.GREEN)
.append(" is currently being ")
.append("overridden", TextColor.RED)
.append(" by an administrator.\nClick here to remove this flag.").build()))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createFlagConsumer(src, claim, overrideContextSet, flagPermission, Tristate.UNDEFINED, flagType, FlagType.CLAIM, false)))).build();
} else {
undefinedText = TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.hoverEvent(HoverEvent.showText(denyText)).build();
}
flagText = TextComponent.builder("")
.append(undefinedText)
.append(" ")
.append("[", TextColor.AQUA)
.append(String.valueOf(overridePermissionEntry.getValue()), TextColor.RED)
.append("]", TextColor.AQUA)
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append("This flag has been overridden by an administrator and can ")
.append(TextComponent.of("NOT").color(TextColor.RED).decoration(TextDecoration.UNDERLINED, true))
.append(" be changed.").build()))
.build();
break;
}
}
}
if (!hasOverride) {
final Tristate currentValue = Tristate.fromBoolean(flagValue);
ClaimClickData claimClickData = inheritPermissionMap.get(flagPermission);
if (claimClickData != null) {
Set<Context> claimClickContexts = new HashSet<>(contextSet);
claimClickContexts.remove(claim.getContext());
claimClickContexts.add(claimClickData.claim.getContext());
final Component undefinedText = getClickableText(src, claimClickData.claim, claimClickContexts, flagPermission, currentValue, Tristate.UNDEFINED, flagType, FlagType.INHERIT, false);
final Component trueText = getClickableText(src, claimClickData.claim, claimClickContexts, flagPermission, currentValue, Tristate.TRUE, flagType, FlagType.INHERIT, false);
final Component falseText = getClickableText(src, claimClickData.claim, claimClickContexts, flagPermission, currentValue, Tristate.FALSE, flagType, FlagType.INHERIT, false);
flagText = TextComponent.builder("")
.append(undefinedText)
.append(" ")
.append(trueText)
.append(" ")
.append(falseText).build();
} else {
final Component undefinedText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.UNDEFINED, flagType, FlagType.CLAIM, false);
final Component trueText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.TRUE, flagType, FlagType.CLAIM, false);
final Component falseText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.FALSE, flagType, FlagType.CLAIM, false);
flagText = TextComponent.builder("")
.append(undefinedText)
.append(" ")
.append(trueText)
.append(" ")
.append(falseText).build();
}
}
Component currentText = textMap.get(flagPermission);
if (currentText == null) {
currentText = TextComponent.builder("")
.append(baseFlag, TextColor.GREEN)
.append(" ")
.hoverEvent(HoverEvent.showText(CommandHelper.getBaseFlagOverlayText(baseFlag))).build();
}
Component baseFlagText = getFlagText(defaultContexts, flagPermission, baseFlag.toString(), flagType);
flagText = TextComponent.builder("")
.append(baseFlagText)
.append(" ")
.append(flagText).build();
textMap.put(flagPermission, flagText);//Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText)));
textList.add(flagText);
}
}
} else if (flagType == FlagType.OVERRIDE) {
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : overridePermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Component> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Component>();
contextMap.put(contextSet, textMap);
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
String flagPermission = permissionEntry.getKey();
Boolean flagValue = permissionEntry.getValue();
Component flagText = TextComponent.builder("")
.append(getClickableText(src, claim, contextSet, flagPermission, Tristate.fromBoolean(flagValue), FlagType.OVERRIDE).color(TextColor.RED)).build();
// Text currentText = textMap.get(flagPermission);
String baseFlag = flagPermission.replace(GDPermissions.FLAG_BASE + ".", "").replace(".*", "");
//boolean customFlag = false;
//Text hover = CommandHelper.getBaseFlagOverlayText(baseFlag);
Component baseFlagText = getFlagText(contextSet, flagPermission, baseFlag, flagType);
flagText = TextComponent.builder("")
.append(baseFlagText)
.append(" ")
.append(flagText).build();
/*if (claim.isWilderness()) {
Text reason = GriefDefenderPlugin.getGlobalConfig().getConfig().bans.getReason(baseFlag);
if (reason != null && !reason.isEmpty()) {
hover = Text.of(TextColors.GREEN, "Ban Reason", TextColors.WHITE, " : ", reason);
}
}
if (currentText == null) {
customFlag = true;
// custom flag
currentText = TextComponent.builder("").append(Text.of(
TextColors.GREEN, baseFlag, " ",
TextColors.WHITE, "["))
.hoverEvent(HoverEvent.showText(hover)).build();
}
final Text text = Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText, TextColors.WHITE, "]"));*/
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
} else if (flagType == FlagType.INHERIT) {
for (Map.Entry<Set<Context>, ClaimClickData> mapEntry : inheritPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Component> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Component>();
contextMap.put(contextSet, textMap);
}
Map<String, Boolean> permissionMap = (Map<String, Boolean>) mapEntry.getValue().value;
for (Map.Entry<String, Boolean> permissionEntry : permissionMap.entrySet()) {
String flagPermission = permissionEntry.getKey();
final String baseFlagPerm = flagPermission.replace(GDPermissions.FLAG_BASE + ".", "").replace(".*", "");
final ClaimClickData claimClickData = mapEntry.getValue();
Component flagText = null;
final Flag baseFlag = FlagRegistryModule.getInstance().getById(flagPermission).orElse(null);
if (baseFlag == null) {
// invalid flag
continue;
}
boolean hasOverride = false;
for (Map.Entry<Set<Context>, Map<String, Boolean>> overrideEntry : overridePermissionMap.entrySet()) {
final Set<Context> overrideContextSet = overrideEntry.getKey();
for (Map.Entry<String, Boolean> overridePermissionEntry : overrideEntry.getValue().entrySet()) {
if (flagPermission.contains(overridePermissionEntry.getKey())) {
hasOverride = true;
final Component undefinedText = TextComponent.builder("")
.append("undefined", TextColor.GRAY)
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append(baseFlagPerm, TextColor.GREEN)
.append(" is currently being ")
.append("overridden", TextColor.RED)
.append(" by an administrator.\nClick here to remove this flag.").build()))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createFlagConsumer(src, claim, overrideContextSet, flagPermission, Tristate.UNDEFINED, flagType, FlagType.CLAIM, false)))).build();
flagText = TextComponent.builder("")
.append(undefinedText)
.append(" ")
.append("[", TextColor.AQUA)
.append(String.valueOf(overridePermissionEntry.getValue()))
.append("]", TextColor.AQUA)
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append("This flag has been overridden by an administrator and can ")
.append(TextComponent.of("NOT").color(TextColor.RED).decoration(TextDecoration.UNDERLINED, true))
.append(" be changed.").build()))
.build();
break;
}
}
}
if (!hasOverride) {
flagText = TextComponent.builder("")
.append(getClickableText(src, claimClickData.claim, contextSet, flagPermission, Tristate.fromBoolean(permissionEntry.getValue()), FlagType.INHERIT).color(TextColor.AQUA))
.build();
}
Component currentText = textMap.get(flagPermission);
if (currentText == null) {
currentText = TextComponent.builder("")
.append(baseFlagPerm, TextColor.GREEN)
.append(" ")
.hoverEvent(HoverEvent.showText(CommandHelper.getBaseFlagOverlayText(baseFlagPerm))).build();
}
Component baseFlagText = getFlagText(defaultContexts, flagPermission, baseFlag.toString(), flagType);
flagText = TextComponent.builder("")
.append(baseFlagText)
.append(" ")
.append(flagText).build();
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
} else if (flagType == FlagType.DEFAULT) {
final Map<String, Set<Context>> permissionMap = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : defaultTransientPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Component> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Component>();
contextMap.put(contextSet, textMap);
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
Component flagText = null;
String flagPermission = permissionEntry.getKey();
Boolean flagValue = permissionEntry.getValue();
String baseFlagPerm = flagPermission.replace(GDPermissions.FLAG_BASE + ".", "").replace(".*", "");
final Flag baseFlag = FlagRegistryModule.getInstance().getById(baseFlagPerm).orElse(null);
if (baseFlag == null) {
continue;
}
// check if transient default has been overridden and if so display that value instead
Tristate actualValue = PermissionUtil.getInstance().getPermissionValue(claim, this.subject, flagPermission, contextSet);
final Component trueText = getClickableText(src, claim, contextSet, flagPermission, actualValue, Tristate.TRUE, flagType, FlagType.DEFAULT, false).color(TextColor.GRAY);
final Component falseText = getClickableText(src, claim, contextSet, flagPermission, actualValue, Tristate.FALSE, flagType, FlagType.DEFAULT, false).color(TextColor.GRAY);
flagText = TextComponent.builder("")
.append(trueText)
.append(" ")
.append(falseText).build();
Component baseFlagText = getFlagText(defaultContexts, flagPermission, baseFlag.toString(), flagType);
flagText = TextComponent.builder("")
.append(baseFlagText)
.append(" ")
.append(flagText).build();
textMap.put(flagPermission, flagText);
permissionMap.put(flagPermission, contextSet);
textList.add(flagText);
}
}
// Handle custom defaults
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : defaultPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Component> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Component>();
contextMap.put(contextSet, textMap);
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
Component flagText = null;
String flagPermission = permissionEntry.getKey();
final Flag claimFlag = FlagRegistryModule.getInstance().getById(flagPermission).orElse(null);
if (claimFlag == null) {
// invalid flag
continue;
}
final String baseFlag = flagPermission.replace(GDPermissions.FLAG_BASE + ".", "").replace(".*", "");
final Set<Context> contexts = permissionMap.get(flagPermission);
if (this.ignoreFlagEntry(contexts)) {
continue;
}
Boolean flagValue = permissionEntry.getValue();
// check if transient default has been overridden and if so display that value instead
final Map<String, Boolean> subjectPerms = PermissionUtil.getInstance().getPermissions(this.subject, contextSet);
Boolean defaultTransientOverrideValue = subjectPerms.get(flagPermission);
if (defaultTransientOverrideValue != null) {
flagValue = defaultTransientOverrideValue;
}
final Tristate currentValue = Tristate.fromBoolean(flagValue);
final Component trueText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.TRUE, flagType, FlagType.DEFAULT, false).color(TextColor.GRAY);
final Component falseText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.FALSE, flagType, FlagType.DEFAULT, false).color(TextColor.GRAY);
final Component undefinedText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.UNDEFINED, flagType, FlagType.DEFAULT, false).color(TextColor.GRAY);
flagText = TextComponent.builder("")
.append(trueText)
.append(" ")
.append(falseText)
.append(" ")
.append(undefinedText).build();
Component baseFlagText = getFlagText(defaultContexts, flagPermission, baseFlag.toString(), flagType);
flagText = TextComponent.builder("")
.append(baseFlagText)
.append(" ")
.append(flagText).build();
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
}
//List<Text> textList = new ArrayList<>(contextMap.values());
Collections.sort(textList, CommandHelper.PLAIN_COMPARATOR);
int fillSize = 20 - (textList.size() + 2);
for (int i = 0; i < fillSize; i++) {
textList.add(TextComponent.of(" "));
}
//PaginationList.Builder paginationBuilder = paginationService.builder()
// .title(claimFlagHead).padding(Text.of(TextStyles.STRIKETHROUGH,"-")).contents(textList);
//final PaginationList paginationList = paginationBuilder.build();
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(claimFlagHead).padding(TextComponent.builder(" ").decoration(TextDecoration.STRIKETHROUGH, true).build()).contents(textList);
final PaginationList paginationList = paginationBuilder.build();
Integer activePage = 1;
if (src instanceof Player) {
final Player player = (Player) src;
activePage = PaginationUtil.getInstance().getActivePage(player.getUniqueId());
if (activePage == null) {
activePage = 1;
}
this.lastActiveFlagTypeMap.put(player.getUniqueId(), flagType);
}
paginationList.sendTo(src, activePage);
}
private static Set<Context> createClaimContextSet(GDClaim claim, Set<Context> contexts) {
Set<Context> claimContexts = new HashSet<>();
claimContexts.add(claim.getContext());
for (Context context : contexts) {
if (context.getKey().contains("world") || context.getKey().contains("gd_claim")) {
continue;
}
claimContexts.add(context);
}
return claimContexts;
}
private static Component getFlagText(Set<Context> contexts, String flagPermission, String baseFlag, FlagType type) {
//final String flagTarget = GPPermissionHandler.getTargetPermission(flagPermission);
TextComponent.Builder builder = TextComponent.builder("");
boolean customContext = false;
for (Context context : contexts) {
if (type != FlagType.INHERIT && type != FlagType.OVERRIDE && (context.getKey().contains("gd_") || context.getKey().contains("world"))) {
continue;
}
customContext = true;
builder.append(context.getKey() + "=", TextColor.GREEN).append(context.getValue() + "\n").build();
}
final Component hoverText = builder.build();
final Component baseFlagText = TextComponent.builder("").color(customContext ? TextColor.YELLOW : TextColor.GREEN).append(baseFlag.toString() + " ")
.hoverEvent(HoverEvent.showText(customContext ? hoverText : CommandHelper.getBaseFlagOverlayText(baseFlag))).build();
return baseFlagText;
}
private Consumer<CommandSender> createFlagConsumer(CommandSender src, GDClaim claim, Set<Context> contexts, String flagPermission, Tristate flagValue, FlagType displayType, FlagType flagType, boolean toggleType) {
return consumer -> {
// Toggle DEFAULT type
final String targetId = GDPermissionManager.getInstance().getTargetPermission(flagPermission);
final Flag claimFlag = FlagRegistryModule.getInstance().getById(flagPermission).orElse(null);
if (claimFlag == null) {
return;
}
//Context claimContext = claim.getContext();
Tristate newValue = Tristate.UNDEFINED;
if (flagType == FlagType.DEFAULT) {
if (toggleType) {
if (flagValue == Tristate.TRUE) {
newValue = Tristate.FALSE;
} else {
newValue = Tristate.TRUE;
}
ClaimType claimType = claim.getType();
if (claimType == ClaimTypes.SUBDIVISION) {
claimType = ClaimTypes.BASIC;
}
final Boolean defaultValue = BaseStorage.CLAIM_FLAG_DEFAULTS.get(claimType).get(claimFlag.getName());
if (defaultValue != null && defaultValue == newValue.asBoolean()) {
newValue = Tristate.UNDEFINED;
}
}
//claimContext = CommandHelper.validateCustomContext(src, claim, "default");
// Toggle CLAIM type
} else if (flagType == FlagType.CLAIM) {
if (flagValue == Tristate.TRUE) {
newValue = Tristate.FALSE;
} else if (flagValue == Tristate.UNDEFINED) {
newValue = Tristate.TRUE;
}
// Toggle OVERRIDE type
} else if (flagType == FlagType.OVERRIDE) {
if (flagValue == Tristate.TRUE) {
newValue = Tristate.FALSE;
} else if (flagValue == Tristate.UNDEFINED) {
newValue = Tristate.TRUE;
}
}
GDCauseStackManager.getInstance().pushCause(src);
GDFlagClaimEvent.Set event = new GDFlagClaimEvent.Set(claim, this.subject, claimFlag, targetId, toggleType ? newValue :flagValue, contexts);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
return;
}
PermissionResult result = CommandHelper.applyFlagPermission(src, this.subject, "ALL", claim, flagPermission, "any", toggleType ? newValue : flagValue, contexts, flagType, true);
if (result.successful()) {
showFlagPermissions(src, claim, displayType);
}
};
}
private Component getClickableText(CommandSender src, GDClaim claim, Set<Context> contexts, String flagPermission, Tristate flagValue, FlagType flagType) {
return getClickableText(src, claim, contexts, flagPermission, Tristate.UNDEFINED, flagValue, FlagType.CLAIM, flagType, true);
}
private Component getClickableText(CommandSender src, GDClaim claim, Set<Context> contexts, String flagPermission, Tristate currentValue, Tristate flagValue, FlagType displayType, FlagType flagType, boolean toggleType) {
Component hoverEventText = TextComponent.of("Click here to toggle " + flagType.name().toLowerCase() + " value.");
if (!toggleType) {
if (flagValue == Tristate.TRUE) {
hoverEventText = TextComponent.of("Click here to allow this flag.");
} else if (flagValue == Tristate.FALSE) {
hoverEventText = TextComponent.of("Click here to deny this flag.");
} else {
hoverEventText = TextComponent.of("Click here to remove this flag.");
}
}
TextColor flagColor = TextColor.GOLD;
boolean hasPermission = true;
if (flagType == FlagType.DEFAULT) {
flagColor = TextColor.LIGHT_PURPLE;
if (!src.hasPermission(GDPermissions.MANAGE_FLAG_DEFAULTS)) {
hoverEventText = TextComponent.of("You do not have permission to change flag defaults.").color(TextColor.RED);
hasPermission = false;
}
}
if (flagType == FlagType.OVERRIDE) {
flagColor = TextColor.RED;
if (!src.hasPermission(GDPermissions.MANAGE_FLAG_OVERRIDES)) {
hoverEventText = TextComponent.of("This flag has been forced by an admin and cannot be changed.").color(TextColor.RED);
hasPermission = false;
}
} else if (flagType == FlagType.INHERIT) {
flagColor = TextColor.AQUA;
hoverEventText = TextComponent.builder("This flag is inherited from parent claim ")
.append(claim.getName().orElse(claim.getFriendlyNameType()))
.append(" and ")
.append(TextComponent.of("cannot").decoration(TextDecoration.UNDERLINED, true))
.append(" be changed.").build();
hasPermission = false;
} else if (src instanceof Player) {
Component denyReason = claim.allowEdit((Player) src);
if (denyReason != null) {
hoverEventText = denyReason;
hasPermission = false;
} else {
// check flag perm
if (!src.hasPermission(GDPermissions.USER_CLAIM_FLAGS + flagPermission.replace(GDPermissions.FLAG_BASE, ""))) {
hoverEventText = TextComponent.of("You do not have permission to change this flag.").color(TextColor.RED);
hasPermission = false;
}
}
}
if (toggleType) {
TextComponent.Builder textBuilder = TextComponent.builder("")
.append(flagValue.toString().toLowerCase())
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append(hoverEventText)
.append("\n")
.append(CommandHelper.getFlagTypeHoverText(flagType)).build()));
if (hasPermission) {
textBuilder.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createFlagConsumer(src, claim, contexts, flagPermission, flagValue, displayType, flagType, true))));
}
return textBuilder.build();
}
TextComponent.Builder textBuilder = TextComponent.builder("")
.append(flagValue.toString().toLowerCase())
.hoverEvent(HoverEvent.showText(TextComponent.builder("")
.append(hoverEventText)
.append("\n")
.append(CommandHelper.getFlagTypeHoverText(flagType)).build()));
if (hasPermission) {
textBuilder.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createFlagConsumer(src, claim, contexts, flagPermission, flagValue, displayType, flagType, false))));
}
Component result = textBuilder.build();
if (currentValue == flagValue) {
final Component whiteOpenBracket = TextComponent.of("[", TextColor.AQUA);
final Component whiteCloseBracket = TextComponent.of("]", TextColor.AQUA);
result = TextComponent.builder("")
.append(whiteOpenBracket)
.append(result.color(flagColor))
.append(whiteCloseBracket).build();
} else {
result = result.color(TextColor.GRAY);
}
return result;
}
private Consumer<CommandSender> createClaimFlagConsumer(CommandSender src, GDClaim claim, FlagType flagType) {
return consumer -> {
showFlagPermissions(src, claim, flagType);
};
}
private boolean ignoreFlagEntry(Set<Context> contexts) {
if (contexts == null) {
return false;
}
for (Context context : contexts) {
if (!context.getKey().startsWith("gd_")) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,791 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.griefdefender.GDPlayerData;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.permission.option.Option;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDOptionEvent;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.registry.OptionRegistryModule;
import org.bukkit.command.CommandSender;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class ClaimOptionBase {
public enum OptionType {
ALL,
DEFAULT,
CLAIM,
//OVERRIDE,
INHERIT,
GROUP,
PLAYER
}
protected ClaimSubjectType subjectType;
protected GDPermissionHolder subject;
protected String friendlySubjectName;
protected boolean isAdmin = false;
protected GDPlayerData sourcePlayerData;
private final Cache<UUID, OptionType> lastActiveFlagTypeMap = Caffeine.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES)
.build();
protected ClaimOptionBase(ClaimSubjectType type) {
this.subjectType = type;
}
/*protected void showOptions(CommandSource src, GPClaim claim, OptionType optionType) {
boolean isAdmin = false;
if (src.hasPermission(GPPermissions.DELETE_CLAIM_ADMIN)) {
isAdmin = true;
}
if (src instanceof Player) {
final Player player = (Player) src;
final OptionType lastFlagType = this.lastActiveFlagTypeMap.getIfPresent(player.getUniqueId());
if (lastFlagType != null && lastFlagType != optionType) {
PaginationUtils.resetActivePage(player.getUniqueId());
}
}
final Text whiteOpenBracket = Text.of(TextColors.AQUA, "[");
final Text whiteCloseBracket = Text.of(TextColors.AQUA, "]");
final Text showAllText = Text.of("Click here to show all options for claim.");
//final Text showOverrideText = Text.of("Click here to filter by ", TextColors.RED, "OVERRIDE ", TextColors.RESET, "permissions.");
final Text showDefaultText = Text.of("Click here to filter by ", TextColors.LIGHT_PURPLE, "DEFAULT ", TextColors.RESET, "options.");
final Text showClaimText = Text.of("Click here to filter by ", TextColors.GOLD, "CLAIM ", TextColors.RESET, "options.");
final Text showInheritText = Text.of("Click here to filter by ", TextColors.AQUA, "INHERIT ", TextColors.RESET, "options.");
Text allTypeText = Text.EMPTY;
Text defaultFlagText = Text.EMPTY;
if (isAdmin) {
allTypeText = Text.builder()
.append(Text.of(optionType == OptionType.ALL ? Text.of(whiteOpenBracket, TextColors.GOLD, "ALL", whiteCloseBracket) : Text.of(TextColors.GRAY, "ALL")))
.onClick(TextActions.executeCallback(createClaimOptionConsumer(src, claim, OptionType.ALL)))
.onHover(TextActions.showText(showAllText)).build();
defaultFlagText = Text.builder()
.append(Text.of(optionType == OptionType.DEFAULT ? Text.of(whiteOpenBracket, TextColors.LIGHT_PURPLE, "DEFAULT", whiteCloseBracket) : Text.of(TextColors.GRAY, "DEFAULT")))
.onClick(TextActions.executeCallback(createClaimOptionConsumer(src, claim, OptionType.DEFAULT)))
.onHover(TextActions.showText(showDefaultText)).build();
}
// final Text overrideFlagText = Text.builder()
// .append(Text.of(flagType == OptionType.OVERRIDE ? Text.of(whiteOpenBracket, TextColors.RED, "OVERRIDE", whiteCloseBracket) : Text.of(TextColors.GRAY, "OVERRIDE")))
// .onClick(TextActions.executeCallback(createClaimFlagConsumer(src, claim, OptionType.OVERRIDE)))
// .onHover(TextActions.showText(showOverrideText)).build();
final Text claimFlagText = Text.builder()
.append(Text.of(optionType == OptionType.CLAIM ? Text.of(whiteOpenBracket, TextColors.YELLOW, "CLAIM", whiteCloseBracket) : Text.of(TextColors.GRAY, "CLAIM")))
.onClick(TextActions.executeCallback(createClaimOptionConsumer(src, claim, OptionType.CLAIM)))
.onHover(TextActions.showText(showClaimText)).build();
final Text inheritFlagText = Text.builder()
.append(Text.of(optionType == OptionType.INHERIT ? Text.of(whiteOpenBracket, TextColors.AQUA, "INHERIT", whiteCloseBracket) : Text.of(TextColors.GRAY, "INHERIT")))
.onClick(TextActions.executeCallback(createClaimOptionConsumer(src, claim, OptionType.INHERIT)))
.onHover(TextActions.showText(showInheritText)).build();
Text claimFlagHead = Text.of();
if (this.subjectType == ClaimSubjectType.GLOBAL) {
if (isAdmin) {
claimFlagHead = Text.builder().append(Text.of(
TextColors.AQUA," Displaying : ", allTypeText, " ", defaultFlagText, " ", claimFlagText, " ", inheritFlagText)).build();
} else {
claimFlagHead = Text.builder().append(Text.of(
TextColors.AQUA," Displaying : ", claimFlagText, " ", inheritFlagText)).build();
}
} else {
claimFlagHead = Text.builder().append(Text.of(
TextColors.AQUA," ", this.subjectType.getFriendlyName(), " ", TextColors.YELLOW, this.friendlySubjectName, TextColors.AQUA, " : ", allTypeText, " ", claimFlagText, " ", inheritFlagText)).build();
}
Map<Set<Context>, Map<String, Text>> contextMap = new HashMap<>();
List<Text> textList = new ArrayList<>();
Set<Context> contexts = new HashSet<>();
Set<Context> overrideContexts = new HashSet<>();
contexts.add(claim.world.getContext());
if (claim.isAdminClaim()) {
contexts.add(ClaimContexts.ADMIN_DEFAULT_CONTEXT);
//overrideContexts.add(ClaimContexts.ADMIN_OVERRIDE_CONTEXT);
//overrideContexts.add(claim.world.getContext());
} else if (claim.isBasicClaim() || claim.isSubdivision()) {
contexts.add(ClaimContexts.BASIC_DEFAULT_CONTEXT);
//overrideContexts.add(ClaimContexts.BASIC_OVERRIDE_CONTEXT);
//overrideContexts.add(claim.world.getContext());
} else if (claim.isTown()) {
contexts.add(ClaimContexts.TOWN_DEFAULT_CONTEXT);
//overrideContexts.add(ClaimContexts.TOWN_OVERRIDE_CONTEXT);
//overrideContexts.add(claim.world.getContext());
} else {
contexts.add(ClaimContexts.WILDERNESS_DEFAULT_CONTEXT);
// overrideContexts.add(ClaimContexts.WILDERNESS_OVERRIDE_CONTEXT);
}
Map<Set<Context>, Map<String, String>> defaultOptionMap = new HashMap<>();
Map<Set<Context>, Map<String, String>> defaultTransientOptionMap = new HashMap<>();
if (isAdmin) {
// defaultTransientPermissions = this.subject.getTransientSubjectData().getPermissions(contexts);
for (Map.Entry<Set<Context>, Map<String, String>> mapEntry : this.subject.getTransientSubjectData().getAllOptions().entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(claim.getDefaultContext()) { // && contextSet.contains(claim.world.getContext())
defaultTransientOptionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
}
for (Map.Entry<Set<Context>, Map<String, String>> mapEntry : this.subject.getSubjectData().getAllOptions().entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(claim.getDefaultContext()) { // && contextSet.contains(claim.world.getContext())
defaultOptionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
}
} else {
}
Map<Set<Context>, Map<String, String>> overridePermissionMap = new HashMap<>();
// Map<String, Boolean> claimPermissions = new HashMap<>();
Map<Set<Context>, Map<String, String>> claimPermissionMap = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, String>> mapEntry : this.subject.getSubjectData().getAllOptions().entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(claim.getContext())) {
claimPermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
if (contextSet.contains(claim.getOverrideContext()) { //&& contextSet.contains(claim.world.getContext())
overridePermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
}
Map<Set<Context>, ClaimClickData> inheritPermissionMap = Maps.newHashMap();
final List<Claim> inheritParents = claim.getInheritedParents();
Collections.reverse(inheritParents);
for (Claim current : inheritParents) {
GPClaim currentClaim = (GPClaim) current;
for (Map.Entry<Set<Context>, Map<String, String>> mapEntry : this.subject.getSubjectData().getAllOptions().entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
if (contextSet.contains(currentClaim.getContext())) {
if (this.subjectType == ClaimSubjectType.GLOBAL) {
//claimPermissions.put(mapEntry.getKey(), mapEntry.getValue());
} else {
// subjectPermissionMap.put(mapEntry.getKey(), mapEntry.getValue());
}
inheritPermissionMap.put(mapEntry.getKey(), new ClaimClickData(currentClaim, mapEntry.getValue()));
}
}
}
final Text denyText = claim.allowEdit((Player) src);
final boolean hasPermission = denyText == null;
if (optionType == OptionType.ALL) {
for (Map.Entry<Set<Context>, Map<String, String>> mapEntry : defaultTransientOptionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, String> permissionEntry : mapEntry.getValue().entrySet()) {
Text flagText = null;
String optionPermission = permissionEntry.getKey();
String baseFlagPerm = optionPermission.replace(GPPermissions.FLAG_BASE + ".", "");
final ClaimOption baseOption = GPOptionHandler.getOptionFromPermission(optionPermission);
if (baseOption == null) {
// invalid flag
continue;
}
// check if transient default has been overridden and if so display that value instead
String flagValue = permissionEntry.getValue();
final Map<String, String> subjectPerms = this.subject.getSubjectData().getOptions(contextSet);
final String overriddenValue = subjectPerms.get(optionPermission);
if (overriddenValue != null) {
flagValue = overriddenValue;
}
Text baseFlagText = getFlagText(contextSet, optionPermission, baseFlagPerm.toString());
//Text baseFlagText = Text.builder().append(Text.of(TextColors.GREEN, baseFlagPerm))
// .onHover(TextActions.showText(CommandHelper.getBaseFlagOverlayText(baseFlagPerm))).build();
flagText = Text.of(
baseFlagText, " ",
TextColors.WHITE, "[",
TextColors.LIGHT_PURPLE, getClickableText(src, claim, contextSet, optionPermission, flagValue, OptionType.DEFAULT));
final Set<Context> claimContexts = createClaimContextSet(claim, contextSet);
final Map<String, String> claimPermissions = claimPermissionMap.get(claimContexts);
String claimValue = claimPermissions == null ? null : claimPermissions.get(permissionEntry.getKey());
final String claimFinalValue = claimValue == null ? "undefined" : claimValue;
//if (claimPermissions == null || claimPermissions.get(permissionEntry.getKey()) == null) {
flagText = Text.join(flagText,
Text.of(
TextColors.WHITE, ", ",
TextColors.GOLD, getClickableText(src, claim, claimContexts, optionPermission, claimFinalValue, OptionType.CLAIM)));
if (overridePermissionMap.get(optionPermission) == null) {
flagText = Text.join(flagText, Text.of(TextColors.WHITE, "]"));
}
//}
textMap.put(optionPermission, flagText);
textList.add(flagText);
}
}
for (Map.Entry<Set<Context>, Map<String, String>> mapEntry : claimPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, String> permissionEntry : mapEntry.getValue().entrySet()) {
String flagPermission = permissionEntry.getKey();
final ClaimOption claimFlag = GPOptionHandler.getOptionFromPermission(flagPermission);
if (claimFlag == null) {
// invalid flag
continue;
}
final String baseFlag = flagPermission.replace("griefdefender.", "");
if (claimFlag.toString().equalsIgnoreCase(baseFlag)) {
// All base flag permissions are handled above in transient logic
continue;
}
String flagValue = permissionEntry.getValue();
Text flagText = null;
ClaimClickData claimClickData = inheritPermissionMap.get(flagPermission);
if (claimClickData != null) {
flagText = Text.of(TextColors.AQUA, getClickableText(src, claimClickData.claim, contextSet, flagPermission, Tristate.fromBoolean((boolean) claimClickData.value), OptionType.INHERIT));
} else {
flagText = Text.of(TextColors.GOLD, getClickableText(src, claim, contextSet, flagPermission, Tristate.fromBoolean(flagValue), OptionType.CLAIM));
}
Text currentText = textMap.get(flagPermission);
boolean customFlag = false;
if (currentText == null) {
customFlag = true;
// custom flag
Text baseFlagText = getFlagText(contextSet, flagPermission, baseFlag.toString());
currentText = Text.builder().append(Text.of(
TextColors.GREEN, baseFlagText, " ",
TextColors.WHITE, "[")).build();
//.onHover(TextActions.showText(CommandHelper.getBaseFlagOverlayText(baseFlagPerm))).build();
}
if (overridePermissionMap.get(flagPermission) == null) {
final Text text = Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText, TextColors.WHITE, "]"));
textMap.put(flagPermission, text);
textList.add(text);
} else {
final Text text = Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText));
textMap.put(flagPermission, text);
textList.add(text);
}
}
}
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : overridePermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
String flagPermission = permissionEntry.getKey();
Boolean flagValue = permissionEntry.getValue();
Text flagText = Text.of(TextColors.RED, getClickableText(src, claim, contextSet, flagPermission, Tristate.fromBoolean(flagValue), OptionType.OVERRIDE));
Text currentText = textMap.get(flagPermission);
boolean customFlag = false;
if (currentText == null) {
customFlag = true;
// custom flag
String baseFlagPerm = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
currentText = Text.builder().append(Text.of(
TextColors.GREEN, baseFlagPerm, " ",
TextColors.WHITE, "["))
.onHover(TextActions.showText(CommandHelper.getBaseFlagOverlayText(baseFlagPerm))).build();
}
final Text text = Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText, TextColors.WHITE, "]"));
textMap.put(flagPermission, text);
textList.add(text);
}
}
} else if (optionType == OptionType.CLAIM) {
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : defaultTransientOptionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
Text flagText = null;
String flagPermission = permissionEntry.getKey();
if (contextMap.containsKey(flagPermission)) {
// only display flags not overridden
continue;
}
Boolean flagValue = permissionEntry.getValue();
String baseFlagPerm = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
final ClaimFlag baseFlag = GPPermissionManager.getInstance().getFlagFromPermission(baseFlagPerm);
if (baseFlag == null) {
// invalid flag
continue;
}
boolean hasOverride = false;
for (Map.Entry<Set<Context>, Map<String, Boolean>> overrideEntry : overridePermissionMap.entrySet()) {
final Set<Context> overrideContextSet = overrideEntry.getKey();
for (Map.Entry<String, Boolean> overridePermissionEntry : overrideEntry.getValue().entrySet()) {
if (flagPermission.contains(overridePermissionEntry.getKey())) {
hasOverride = true;
flagText = Text.builder().append(
Text.of(TextColors.RED, mapEntry.getValue()))
.onHover(TextActions.showText(Text.of(TextColors.GREEN, baseFlagPerm, TextColors.WHITE, " is currently being ", TextColors.RED, "overridden", TextColors.WHITE, " by an administrator and can ", TextColors.RED, TextStyles.UNDERLINE, "NOT", TextStyles.RESET, TextColors.WHITE, " be changed.")))
.build();
break;
}
}
}
if (!hasOverride) {
// check if transient default has been overridden and if so display that value instead
final Set<Context> claimContexts = createClaimContextSet(claim, contextSet);
final Map<String, Boolean> subjectPerms = this.subject.getSubjectData().getPermissions(claimContexts);
Boolean overriddenValue = subjectPerms.get(flagPermission);
if (overriddenValue == null && this.subject != GriefDefenderPlugin.GLOBAL_SUBJECT) {
// Check claim
final Map<String, Boolean> claimPerms = claimPermissionMap.get(claimContexts);
if (claimPerms != null) {
overriddenValue = claimPerms.get(flagPermission);
}
}
final Tristate currentValue = overriddenValue == null ? Tristate.UNDEFINED : Tristate.fromBoolean(overriddenValue);
Text undefinedText = null;
if (hasPermission) {
undefinedText = Text.builder().append(
Text.of(currentValue == Tristate.UNDEFINED ? Text.of(whiteOpenBracket, TextColors.GOLD, "undefined") : Text.of(TextColors.GRAY, "undefined"), TextStyles.RESET, currentValue == Tristate.UNDEFINED ? whiteCloseBracket : ""))
.onHover(TextActions.showText(Text.of(TextColors.GREEN, baseFlagPerm, TextColors.WHITE, " is currently not set.\nThe default claim value of ", TextColors.LIGHT_PURPLE, flagValue, TextColors.WHITE, " will be active until set.")))
.onClick(TextActions.executeCallback(createFlagConsumer(src, claim, claimContexts, flagPermission, Tristate.UNDEFINED, optionType, OptionType.CLAIM, false))).build();
} else {
undefinedText = Text.builder().append(
Text.of(currentValue == Tristate.UNDEFINED ? Text.of(whiteOpenBracket, TextColors.GOLD, "undefined") : Text.of(TextColors.GRAY, "undefined"), TextStyles.RESET, currentValue == Tristate.UNDEFINED ? whiteCloseBracket : ""))
.onHover(TextActions.showText(denyText)).build();
}
final Text trueText = Text.of(TextColors.GRAY, getClickableText(src, claim, claimContexts, flagPermission, currentValue, Tristate.TRUE, optionType, OptionType.CLAIM, false));
final Text falseText = Text.of(TextColors.GRAY, getClickableText(src, claim, claimContexts, flagPermission, currentValue, Tristate.FALSE, optionType, OptionType.CLAIM, false));
flagText = Text.of(undefinedText, " ", trueText, " ", falseText);
}
Text baseFlagText = getFlagText(contexts, flagPermission, baseFlag.toString());
flagText = Text.of(
baseFlagText, " ",
flagText);
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : claimPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
String flagPermission = permissionEntry.getKey();
final ClaimFlag claimFlag = GPPermissionManager.getInstance().getFlagFromPermission(flagPermission);
if (claimFlag == null) {
// invalid flag
continue;
}
final String baseFlag = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
if (claimFlag.toString().equalsIgnoreCase(baseFlag)) {
// All base flag permissions are handled above in transient logic
continue;
}
Boolean flagValue = permissionEntry.getValue();
Text flagText = null;
boolean hasOverride = false;
for (Map.Entry<Set<Context>, Map<String, Boolean>> overrideEntry : overridePermissionMap.entrySet()) {
final Set<Context> overrideContextSet = overrideEntry.getKey();
for (Map.Entry<String, Boolean> overridePermissionEntry : overrideEntry.getValue().entrySet()) {
if (flagPermission.contains(overridePermissionEntry.getKey())) {
hasOverride = true;
Text undefinedText = null;
if (hasPermission) {
undefinedText = Text.builder().append(
Text.of(TextColors.GRAY, "undefined"))
.onHover(TextActions.showText(Text.of(TextColors.GREEN, baseFlag, TextColors.WHITE, " is currently being ", TextColors.RED, "overridden", TextColors.WHITE, " by an administrator", TextColors.WHITE, ".\nClick here to remove this flag.")))
.onClick(TextActions.executeCallback(createFlagConsumer(src, claim, overrideContextSet, flagPermission, Tristate.UNDEFINED, optionType, OptionType.CLAIM, false))).build();
} else {
undefinedText = Text.builder().append(
Text.of(TextColors.GRAY, "undefined"))
.onHover(TextActions.showText(denyText)).build();
}
flagText = Text.builder().append(
Text.of(undefinedText, " ", TextColors.AQUA, "[", TextColors.RED, mapEntry.getValue(), TextStyles.RESET, TextColors.AQUA, "]"))
.onHover(TextActions.showText(Text.of(TextColors.WHITE, "This flag has been overridden by an administrator and can ", TextColors.RED, TextStyles.UNDERLINE, "NOT", TextStyles.RESET, TextColors.WHITE, " be changed.")))
.build();
break;
}
}
}
if (!hasOverride) {
final Tristate currentValue = Tristate.fromBoolean(flagValue);
ClaimClickData claimClickData = inheritPermissionMap.get(flagPermission);
if (claimClickData != null) {
Set<Context> claimClickContexts = new HashSet<>(contextSet);
claimClickContexts.remove(claim.getContext());
claimClickContexts.add(claimClickData.claim.getContext());
final Text undefinedText = getClickableText(src, claimClickData.claim, claimClickContexts, flagPermission, currentValue, Tristate.UNDEFINED, optionType, OptionType.INHERIT, false);
final Text trueText = getClickableText(src, claimClickData.claim, claimClickContexts, flagPermission, currentValue, Tristate.TRUE, optionType, OptionType.INHERIT, false);
final Text falseText = getClickableText(src, claimClickData.claim, claimClickContexts, flagPermission, currentValue, Tristate.FALSE, optionType, OptionType.INHERIT, false);
flagText = Text.of(undefinedText, " ", trueText, " ", falseText);
} else {
final Text undefinedText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.UNDEFINED, optionType, OptionType.CLAIM, false);
final Text trueText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.TRUE, optionType, OptionType.CLAIM, false);
final Text falseText = getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.FALSE, optionType, OptionType.CLAIM, false);
flagText = Text.of(undefinedText, " ", trueText, " ", falseText);
}
}
Text currentText = textMap.get(flagPermission);
if (currentText == null) {
currentText = Text.builder().append(Text.of(
TextColors.GREEN, baseFlag, " "))
//TextColors.WHITE, "["))
.onHover(TextActions.showText(CommandHelper.getBaseFlagOverlayText(baseFlag))).build();
}
Text baseFlagText = getFlagText(contexts, flagPermission, baseFlag.toString());
flagText = Text.of(
baseFlagText, " ",
flagText);
textMap.put(flagPermission, flagText);//Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText)));
textList.add(flagText);
}
}
} else if (optionType == OptionType.OVERRIDE) {
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : overridePermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
String flagPermission = permissionEntry.getKey();
Boolean flagValue = permissionEntry.getValue();
Text flagText = Text.of(TextColors.RED, getClickableText(src, claim, contextSet, flagPermission, Tristate.fromBoolean(flagValue), OptionType.OVERRIDE));
Text currentText = textMap.get(flagPermission);
String baseFlagPerm = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
boolean customFlag = false;
Text hover = CommandHelper.getBaseFlagOverlayText(baseFlagPerm);
if (claim.isWilderness()) {
Text reason = GriefDefenderPlugin.getGlobalConfig().getConfig().bans.getReason(baseFlagPerm);
if (reason != null && !reason.isEmpty()) {
hover = Text.of(TextColors.GREEN, "Ban Reason", TextColors.WHITE, " : ", reason);
}
}
if (currentText == null) {
customFlag = true;
// custom flag
currentText = Text.builder().append(Text.of(
TextColors.GREEN, baseFlagPerm, " ",
TextColors.WHITE, "["))
.onHover(TextActions.showText(hover)).build();
}
final Text text = Text.join(currentText, Text.of(customFlag ? "" : ", ", flagText, TextColors.WHITE, "]"));
textMap.put(flagPermission, text);
textList.add(text);
}
}
} else if (optionType == OptionType.INHERIT) {
for (Map.Entry<Set<Context>, ClaimClickData> mapEntry : inheritPermissionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
Map<String, Boolean> permissionMap = (Map<String, Boolean>) mapEntry.getValue().value;
for (Map.Entry<String, Boolean> permissionEntry : permissionMap.entrySet()) {
String flagPermission = permissionEntry.getKey();
final String baseFlagPerm = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
final ClaimClickData claimClickData = mapEntry.getValue();
//final boolean flagValue = (boolean) claimClickData.value;
Text flagText = null;
final ClaimFlag baseFlag = GPPermissionManager.getInstance().getFlagFromPermission(flagPermission);
if (baseFlag == null) {
// invalid flag
continue;
}
boolean hasOverride = false;
for (Map.Entry<Set<Context>, Map<String, Boolean>> overrideEntry : overridePermissionMap.entrySet()) {
final Set<Context> overrideContextSet = overrideEntry.getKey();
for (Map.Entry<String, Boolean> overridePermissionEntry : overrideEntry.getValue().entrySet()) {
if (flagPermission.contains(overridePermissionEntry.getKey())) {
hasOverride = true;
final Text undefinedText = Text.builder().append(
Text.of(TextColors.GRAY, "undefined"))
.onHover(TextActions.showText(Text.of(TextColors.GREEN, baseFlagPerm, TextColors.WHITE, " is currently being ", TextColors.RED, "overridden", TextColors.WHITE, " by an administrator", TextColors.WHITE, ".\nClick here to remove this flag.")))
.onClick(TextActions.executeCallback(createFlagConsumer(src, claim, overrideContextSet, flagPermission, Tristate.UNDEFINED, optionType, OptionType.CLAIM, false))).build();
flagText = Text.builder().append(
Text.of(undefinedText, " ", TextColors.AQUA, "[", TextColors.RED, mapEntry.getValue(), TextStyles.RESET, TextColors.AQUA, "]"))
.onHover(TextActions.showText(Text.of(TextColors.WHITE, "This flag has been overridden by an administrator and can ", TextColors.RED, TextStyles.UNDERLINE, "NOT", TextStyles.RESET, TextColors.WHITE, " be changed.")))
.build();
break;
}
}
}
if (!hasOverride) {
//flagText = Text.of(TextColors.AQUA, getClickableText(src, claimClickData.claim, flagPermission, Tristate.fromBoolean(flagValue), FlagType.INHERIT));
}
Text currentText = textMap.get(flagPermission);
if (currentText == null) {
currentText = Text.builder().append(Text.of(
TextColors.GREEN, baseFlagPerm, " "))
.onHover(TextActions.showText(CommandHelper.getBaseFlagOverlayText(baseFlagPerm))).build();
}
Text baseFlagText = getFlagText(contexts, flagPermission, baseFlag.toString());
flagText = Text.of(
baseFlagText, " ",
flagText);
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
} else if (optionType == OptionType.DEFAULT) {
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : defaultTransientOptionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
Text flagText = null;
String flagPermission = permissionEntry.getKey();
Boolean flagValue = permissionEntry.getValue();
String baseFlagPerm = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
if (!ClaimFlag.contains(baseFlagPerm)) {
continue;
}
final ClaimFlag baseFlag = ClaimFlag.getEnum(baseFlagPerm);
// check if transient default has been overridden and if so display that value instead
final Map<String, Boolean> subjectPerms = this.subject.getSubjectData().getPermissions(contextSet);
Boolean defaultTransientOverrideValue = subjectPerms.get(flagPermission);
if (defaultTransientOverrideValue != null) {
flagValue = defaultTransientOverrideValue;
}
final Text trueText = Text.of(TextColors.GRAY, getClickableText(src, claim, contextSet, flagPermission, Tristate.fromBoolean(flagValue), Tristate.TRUE, optionType, OptionType.DEFAULT, false));
final Text falseText = Text.of(TextColors.GRAY, getClickableText(src, claim, contextSet, flagPermission, Tristate.fromBoolean(flagValue), Tristate.FALSE, optionType, OptionType.DEFAULT, false));
flagText = Text.of(trueText, " ", falseText);
Text baseFlagText = getFlagText(contexts, flagPermission, baseFlag.toString());
flagText = Text.of(
baseFlagText, " ",
flagText);
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
// Handle custom defaults
for (Map.Entry<Set<Context>, Map<String, Boolean>> mapEntry : defaultOptionMap.entrySet()) {
final Set<Context> contextSet = mapEntry.getKey();
Map<String, Text> textMap = contextMap.get(contextSet);
if (textMap == null) {
textMap = new HashMap<String, Text>();
contextMap.put(contextSet, new HashMap<String, Text>());
}
for (Map.Entry<String, Boolean> permissionEntry : mapEntry.getValue().entrySet()) {
Text flagText = null;
String flagPermission = permissionEntry.getKey();
final ClaimFlag claimFlag = GPPermissionManager.getInstance().getFlagFromPermission(flagPermission);
if (claimFlag == null) {
// invalid flag
continue;
}
final String baseFlag = flagPermission.replace(GPPermissions.FLAG_BASE + ".", "");
if (claimFlag.toString().equalsIgnoreCase(baseFlag)) {
// All base flag permissions are handled above in transient logic
continue;
}
Boolean flagValue = permissionEntry.getValue();
// check if transient default has been overridden and if so display that value instead
final Map<String, Boolean> subjectPerms = this.subject.getSubjectData().getPermissions(contextSet);
Boolean defaultTransientOverrideValue = subjectPerms.get(flagPermission);
if (defaultTransientOverrideValue != null) {
flagValue = defaultTransientOverrideValue;
}
final Tristate currentValue = Tristate.fromBoolean(flagValue);
final Text trueText = Text.of(TextColors.GRAY, getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.TRUE, optionType, OptionType.DEFAULT, false));
final Text falseText = Text.of(TextColors.GRAY, getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.FALSE, optionType, OptionType.DEFAULT, false));
final Text undefinedText = Text.of(TextColors.GRAY, getClickableText(src, claim, contextSet, flagPermission, currentValue, Tristate.UNDEFINED, optionType, OptionType.DEFAULT, false));
flagText = Text.of(trueText, " ", falseText, " ", undefinedText);
Text baseFlagText = getFlagText(contexts, flagPermission, baseFlag.toString());
flagText = Text.of(
baseFlagText, " ",
flagText);
textMap.put(flagPermission, flagText);
textList.add(flagText);
}
}
}
//List<Text> textList = new ArrayList<>(contextMap.values());
Collections.sort(textList);
int fillSize = 20 - (textList.size() + 2);
for (int i = 0; i < fillSize; i++) {
textList.add(Text.of(" "));
}
PaginationService paginationService = Sponge.getServiceManager().provide(PaginationService.class).get();
PaginationList.Builder paginationBuilder = paginationService.builder()
.title(claimFlagHead).padding(Text.of(TextStyles.STRIKETHROUGH,"-")).contents(textList);
final PaginationList paginationList = paginationBuilder.build();
Integer activePage = 1;
if (src instanceof Player) {
final Player player = (Player) src;
activePage = PaginationUtils.getActivePage(player.getUniqueId());
if (activePage == null) {
activePage = 1;
}
this.lastActiveFlagTypeMap.put(player.getUniqueId(), optionType);
}
paginationList.sendTo(src, activePage);
}
private static Set<Context> createClaimContextSet(GPClaim claim, Set<Context> contexts) {
Set<Context> claimContexts = new HashSet<>();
claimContexts.add(claim.getContext());
for (Context context : contexts) {
if (context.getKey().contains("world") || context.getKey().contains("gd_claim")) {
continue;
}
claimContexts.add(context);
}
return claimContexts;
}
private static Text getFlagText(Set<Context> contexts, String flagPermission, String baseFlag) {
//final String flagTarget = GPPermissionHandler.getTargetPermission(flagPermission);
Text.Builder builder = Text.builder();
boolean customContext = false;
for (Context context : contexts) {
if (context.getKey().contains("gd_claim") || context.getKey().contains("world")) {
continue;
}
customContext = true;
builder.append(Text.of(TextColors.WHITE, context.getKey() + "=", TextColors.GREEN, context.getValue(),"\n"));
}
//builder.append(Text.of("target=", TextColors.GREEN, flagTarget));
final Text hoverText = builder.build();
final Text baseFlagText = Text.builder().append(Text.of(customContext ? TextColors.YELLOW : TextColors.GREEN, baseFlag.toString(), " "))
.onHover(TextActions.showText(customContext ? hoverText : CommandHelper.getBaseFlagOverlayText(baseFlag))).build();
final Text baseText = Text.builder().append(Text.of(
baseFlagText)).build();
//sourceText,
//targetText)).build();
return baseText;
/*String flagSource = null;
String flagUsedItem = null;
for (Context context : contexts) {
if (context.getKey().equalsIgnoreCase("source")) {
flagSource = context.getValue();
}
if (context.getKey().equalsIgnoreCase("used_item")) {
flagUsedItem = context.getValue();
}
}
Text sourceText = flagSource == null ? null : Text.of(TextColors.WHITE, "source=",TextColors.GREEN, flagSource);
Text targetText = flagTarget == null ? null : Text.of(TextColors.WHITE, "target=",TextColors.GREEN, flagTarget);
Text usedItemText = flagUsedItem == null ? null : Text.of(TextColors.WHITE, "used_item=", TextColors.GREEN, flagUsedItem);
if (sourceText != null) {
sourceText = Text.of(sourceText, "\n");
//}
} else {
sourceText = Text.of();
}
if (targetText != null) {
targetText = Text.of(targetText);
} else {
targetText = Text.of();
}
Text baseFlagText = Text.of();
if (flagSource == null && flagTarget == null && flagUsedItem == null) {
baseFlagText = Text.builder().append(Text.of(TextColors.GREEN, baseFlag.toString(), " "))
.onHover(TextActions.showText(Text.of(sourceText, targetText))).build();
} else {
baseFlagText = Text.builder().append(Text.of(TextStyles.ITALIC, TextColors.YELLOW, baseFlag.toString(), " ", TextStyles.RESET))
.onHover(TextActions.showText(Text.of(sourceText, usedItemText))).build();
}
final Text baseText = Text.builder().append(Text.of(
baseFlagText)).build();
//sourceText,
//targetText)).build();
return baseText;
*/
//}
private Consumer<CommandSender> createFlagConsumer(CommandSender src, GDClaim claim, Set<com.griefdefender.api.permission.Context> contexts, String flagPermission, String flagValue, OptionType displayType, OptionType flagType, boolean toggleType) {
return consumer -> {
// Toggle DEFAULT type
//final String targetId = GPPermissionManager.getInstance().getTargetPermission(flagPermission);
final Option claimOption = OptionRegistryModule.getInstance().getById(flagPermission).orElse(null);
if (claimOption == null) {
return;
}
//Context claimContext = claim.getContext();
//final Set<Context> contexts = new HashSet<>();
//contexts.add(claimContext);
GDCauseStackManager.getInstance().pushCause(src);
GDOptionEvent.Set event = new GDOptionEvent.Set(this.subject, claimOption, flagValue == null ? "undefined" : flagValue, contexts);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
return;
}
// TODO
//OptionResult result = CommandHelper.applyFlagPermission(src, this.subject, "ALL", claim, flagPermission, flagValue == null ? "undefined" : flagValue, contexts, flagType, true);
//if (result.successful()) {
// showOptions(src, claim, displayType);
//}
};
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
public enum ClaimSubjectType {
GLOBAL("Global"),
GROUP("Group"),
PLAYER("Player");
private String friendlyName;
private ClaimSubjectType(String name) {
this.friendlyName = name;
}
public String getFriendlyName() {
return this.friendlyName;
}
}

View File

@ -0,0 +1,93 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SET_ACCRUED_CLAIM_BLOCKS)
public class CommandAdjustBonusClaimBlocks extends BaseCommand {
@CommandAlias("acb|adjustclaimblocks")
@Description("Updates a player's accrued claim block total")
@Syntax("<player> <amount>")
@Subcommand("player adjustbonusblocks")
public void execute(CommandSender src, OfflinePlayer user, int amount, @Optional String worldName) {
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
TextAdapter.sendComponent(src, TextComponent.of("This command is not available while server is in economy mode.", TextColor.RED));
return;
}
World world = worldName == null ? null : Bukkit.getServer().getWorld(worldName);
if (world == null) {
if (src instanceof Player) {
world = ((Player) src).getWorld();
} else {
world = Bukkit.getServer().getWorlds().get(0);
}
}
if (world == null || !GriefDefenderPlugin.getInstance().claimsEnabledForWorld(world.getUID())) {
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
// parse the adjustment amount
int adjustment = amount;
//User user = args.<User>getOne("user").get();
// give blocks to player
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(world.getUID(), user.getUniqueId());
playerData.setBonusClaimBlocks(playerData.getBonusClaimBlocks() + adjustment);
playerData.getStorageData().save();
final Component message = GriefDefenderPlugin.getInstance().messageData.adjustBlocksSuccess
.apply(ImmutableMap.of(
"player", user.getName(),
"adjustment", adjustment,
"total", playerData.getBonusClaimBlocks())).build();
TextAdapter.sendComponent(src, message);
GriefDefenderPlugin.getInstance().getLogger().info(
src.getName() + " adjusted " + user.getName() + "'s bonus claim blocks by " + adjustment + ".");
}
}

View File

@ -0,0 +1,23 @@
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.Description;
import com.griefdefender.text.action.GDCallbackHolder;
import org.bukkit.command.CommandSender;
import java.util.UUID;
import java.util.function.Consumer;
public class CommandCallback extends BaseCommand {
@CommandAlias("gp:callback")
@Description("Execute a callback registered as part of a Text object. Primarily for internal use")
public void execute(CommandSender src, String[] args) {
final UUID callbackId = UUID.fromString(args[0]);
Consumer<CommandSender> callback = GDCallbackHolder.getInstance().getCallbackForUUID(callbackId).orElse(null);
if (callback != null) {
callback.accept(src);
}
}
}

View File

@ -0,0 +1,165 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDDeleteClaimEvent;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_ABANDON_BASIC)
public class CommandClaimAbandon extends BaseCommand {
protected boolean abandonTopClaim = false;
@CommandAlias("abandonclaim")
@Description("Abandons a claim")
@Subcommand("abandon claim")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
final UUID ownerId = claim.getOwnerUniqueId();
final boolean isAdmin = playerData.canIgnoreClaim(claim);
final boolean isTown = claim.isTown();
if (claim.isWilderness()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandAbandonClaimMissing.toText());
return;
} else if (!isAdmin && !player.getUniqueId().equals(ownerId) && claim.isUserTrusted(player, TrustTypes.MANAGER)) {
if (claim.parent == null) {
// Managers can only abandon child claims
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotYours.toText());
return;
}
} else if (!isAdmin && (claim.allowEdit(player) != null || (!claim.isAdminClaim() && !player.getUniqueId().equals(ownerId)))) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotYours.toText());
return;
}
if (!claim.isTown() && !claim.isAdminClaim() && claim.children.size() > 0 && !this.abandonTopClaim) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandAbandonTopLevel.toText());
return;
} else {
if (this.abandonTopClaim && (claim.isTown() || claim.isAdminClaim()) && claim.children.size() > 0) {
Set<Claim> invalidClaims = new HashSet<>();
for (Claim child : claim.getChildren(true)) {
if (child.getOwnerUniqueId() == null || !child.getOwnerUniqueId().equals(ownerId)) {
//return CommandResult.empty();
invalidClaims.add(child);
}
}
if (!invalidClaims.isEmpty()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandAbandonTownChildren.toText());
CommandHelper.showClaims(player, invalidClaims, 0, true);
return;
}
}
GDCauseStackManager.getInstance().pushCause(player);
GDDeleteClaimEvent.Abandon event = new GDDeleteClaimEvent.Abandon(claim);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not abandon claim. A plugin has denied it.").color(TextColor.RED)));
return;
}
if (!claim.isSubdivision() && !claim.isAdminClaim()) {
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();
if (!economy.hasAccount(player)) {
return;
}
}
}
GDClaimManager claimManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(player.getWorld().getUID());
claimManager.deleteClaimInternal(claim, this.abandonTopClaim);
// remove all context permissions
PermissionUtil.getInstance().clearPermissions(player, claim.getContext());
PermissionUtil.getInstance().clearPermissions(GriefDefenderPlugin.DEFAULT_HOLDER, claim.getContext());
playerData.revertActiveVisual(player);
if (isTown) {
playerData.inTown = false;
playerData.townChat = false;
}
if (!claim.isSubdivision() && !claim.isAdminClaim()) {
final double abandonReturnRatio = GDPermissionManager.getInstance().getInternalOptionValue(player, Options.ABANDON_RETURN_RATIO, claim, playerData);
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();
final double requiredClaimBlocks = claim.getClaimBlocks() * abandonReturnRatio;
final double refund = requiredClaimBlocks * claim.getOwnerEconomyBlockCost();
final EconomyResponse result = economy.depositPlayer(player, refund);
if (result.transactionSuccess()) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyClaimAbandonSuccess
.apply(ImmutableMap.of(
"refund", refund
)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
} else {
int newAccruedClaimCount = playerData.getAccruedClaimBlocks() - ((int) Math.ceil(claim.getClaimBlocks() * (1 - abandonReturnRatio)));
playerData.setAccruedClaimBlocks(newAccruedClaimCount);
int remainingBlocks = playerData.getRemainingClaimBlocks();
final Component message = GriefDefenderPlugin.getInstance().messageData.claimAbandonSuccess
.apply(ImmutableMap.of(
"remaining-blocks", remainingBlocks
)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}
}
}
}

View File

@ -0,0 +1,123 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDDeleteClaimEvent;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_ABANDON_ALL_CLAIMS)
public class CommandClaimAbandonAll extends BaseCommand {
@CommandAlias("abandonall")
@Description("Abandons ALL your claims")
@Subcommand("abandon all")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
int originalClaimCount = playerData.getInternalClaims().size();
if (originalClaimCount == 0) {
try {
throw new CommandException(GriefDefenderPlugin.getInstance().messageData.claimNoClaims.toText());
} catch (CommandException e) {
TextAdapter.sendComponent(player, e.getText());
return;
}
}
GDCauseStackManager.getInstance().pushCause(player);
GDDeleteClaimEvent.Abandon event = new GDDeleteClaimEvent.Abandon(ImmutableList.copyOf(playerData.getInternalClaims()));
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not abandon claim. A plugin has denied it.").color(TextColor.RED)));
return;
}
double refund = 0;
// adjust claim blocks
for (Claim claim : playerData.getInternalClaims()) {
// remove all context permissions
PermissionUtil.getInstance().clearPermissions(player, claim.getContext());
if (claim.isSubdivision() || claim.isAdminClaim() || claim.isWilderness()) {
continue;
}
final double abandonReturnRatio = GDPermissionManager.getInstance().getInternalOptionValue(player, Options.ABANDON_RETURN_RATIO, claim, playerData);
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
refund += claim.getClaimBlocks() * abandonReturnRatio;
} else {
playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() - ((int) Math.ceil(claim.getClaimBlocks() * (1 - abandonReturnRatio))));
}
}
GriefDefenderPlugin.getInstance().dataStore.deleteClaimsForPlayer(player.getUniqueId());
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();
if (!economy.hasAccount(player)) {
return;
}
final EconomyResponse result = economy.depositPlayer(player, refund);
if (result.transactionSuccess()) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyClaimAbandonSuccess
.apply(ImmutableMap.of(
"refund", TextComponent.of(String.valueOf(refund))
)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
} else {
int remainingBlocks = playerData.getRemainingClaimBlocks();
final Component message = GriefDefenderPlugin.getInstance().messageData.claimAbandonSuccess
.apply(ImmutableMap.of(
"remaining-blocks", remainingBlocks
)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
playerData.revertActiveVisual(player);
}
}

View File

@ -0,0 +1,48 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_ABANDON_TOP_LEVEL_CLAIM)
public class CommandClaimAbandonTop extends CommandClaimAbandon {
public CommandClaimAbandonTop() {
this.abandonTopClaim = true;
}
@CommandAlias("abandontop")
@Description("Abandons top level claim")
@Subcommand("abandon top")
public void execute(Player player) {
super.execute(player);
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_ADMIN_CLAIMS)
public class CommandClaimAdmin extends BaseCommand {
@CommandAlias("modeadmin")
@Description("Switches the shovel tool to administrative claims mode")
@Subcommand("mode admin")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.shovelMode = ShovelTypes.ADMIN;
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimModeAdmin.toText());
}
}

View File

@ -0,0 +1,74 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_BANK)
public class CommandClaimBank extends BaseCommand {
protected boolean townOnly = false;
@CommandAlias("claimbank")
@Description("Used for claim bank queries")
@Syntax("<withdraw|deposit> <amount>")
@Subcommand("claim bank")
public void execute(Player player, @Optional String[] args) throws CommandException {
if (!GriefDefenderPlugin.getActiveConfig(player.getWorld().getUID()).getConfig().claim.bankTaxSystem) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimBankTaxSystemNotEnabled.toText());
return;
}
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
if (this.townOnly) {
if (!claim.isInTown()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.townNotIn.toText());
return;
}
claim = claim.getTownClaim();
} else {
if (claim.isSubdivision() || claim.isAdminClaim()) {
return;
}
}
if (args.length == 0 || args.length < 2) {
CommandHelper.displayClaimBankInfo(player, claim);
return;
}
CommandHelper.handleBankTransaction(player, args, claim);
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_BASIC_MODE)
public class CommandClaimBasic extends BaseCommand {
@CommandAlias("modebasic")
@Description("Switches the shovel tool back to basic claims mode")
@Subcommand("mode basic")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.shovelMode = ShovelTypes.BASIC;
playerData.claimSubdividing = null;
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimModeBasic.toText());
}
}

View File

@ -0,0 +1,97 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_BUY)
public class CommandClaimBuy extends BaseCommand {
@CommandAlias("claimbuy")
@Description("List all claims available for purchase.\nNote: Requires economy plugin.")
@Subcommand("buy claim")
public void execute(Player player) {
if (GriefDefenderPlugin.getInstance().getVaultProvider() == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyNotInstalled.toText());
return;
}
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();
if (!economy.hasAccount(player)) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyUserNotFound
.apply(ImmutableMap.of(
"user", player.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
Set<Claim> claimsForSale = new HashSet<>();
GDClaimManager claimManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(player.getWorld().getUID());
for (Claim worldClaim : claimManager.getWorldClaims()) {
if (worldClaim.isWilderness()) {
continue;
}
if (!worldClaim.isAdminClaim() && worldClaim.getEconomyData().isForSale() && worldClaim.getEconomyData().getSalePrice() > -1) {
claimsForSale.add(worldClaim);
}
for (Claim child : worldClaim.getChildren(true)) {
if (child.isAdminClaim()) {
continue;
}
if (child.getEconomyData().isForSale() && child.getEconomyData().getSalePrice() > -1) {
claimsForSale.add(child);
}
}
}
List<Component> claimsTextList = CommandHelper.generateClaimTextList(new ArrayList<Component>(), claimsForSale, player.getWorld().getName(), null, player, CommandHelper.createCommandConsumer(player, "claimbuy", ""), true, false);
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of("Claims for sale", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(claimsTextList);
paginationBuilder.sendTo(player);
return;
}
}

View File

@ -0,0 +1,137 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_BUY_CLAIM_BLOCKS)
public class CommandClaimBuyBlocks extends BaseCommand {
@CommandAlias("buyblocks")
@Description("Purchases additional claim blocks with server money.\nNote: Requires economy plugin.")
@Syntax("[<amount>]")
@Subcommand("buy blocks")
public void execute(Player player, @Optional Integer blockCount) {
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
TextAdapter.sendComponent(player, TextComponent.of("This command is not available while server is in economy mode.", TextColor.RED));
return;
}
if (GriefDefenderPlugin.getInstance().getVaultProvider() == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyNotInstalled.toText());
return;
}
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();
if (!economy.hasAccount(player)) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyUserNotFound
.apply(ImmutableMap.of(
"user", player.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
final double economyBlockCost = GDPermissionManager.getInstance().getGlobalInternalOptionValue(player, Options.ECONOMY_BLOCK_COST, playerData);
final double economyBlockSell = GDPermissionManager.getInstance().getGlobalInternalOptionValue(player, Options.ECONOMY_BLOCK_SELL_RETURN, playerData);
if (economyBlockCost == 0 && economyBlockSell == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyBuySellNotConfigured.toText());
return;
}
if (economyBlockCost == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyOnlySellBlocks.toText());
return;
}
final double balance = economy.getBalance(player);
if (blockCount == null) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyBlockPurchaseCost
.apply(ImmutableMap.of(
"cost", economyBlockCost,
"balance", balance)).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
} else {
if (blockCount <= 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyBuyInvalidBlockCount.toText());
return;
}
final double totalCost = blockCount * economyBlockCost;
final int newClaimBlockTotal = playerData.getAccruedClaimBlocks() + blockCount;
if (newClaimBlockTotal > playerData.getMaxAccruedClaimBlocks()) {
final Component message = GriefDefenderPlugin.getInstance().messageData.claimBlockPurchaseLimit
.apply(ImmutableMap.of(
"new_total", newClaimBlockTotal,
"block_limit", playerData.getMaxAccruedClaimBlocks())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
final EconomyResponse result = economy.withdrawPlayer(player, totalCost);
if (!result.transactionSuccess()) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyWithdrawError
.apply(ImmutableMap.of(
"reason", result.errorMessage)).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
playerData.addAccruedClaimBlocks(blockCount);
playerData.getStorageData().save();
final Component message = GriefDefenderPlugin.getInstance().messageData.economyBlocksPurchaseConfirmation
.apply(ImmutableMap.of(
"cost", totalCost,
"remaining-blocks", playerData.getRemainingClaimBlocks())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}
}

View File

@ -0,0 +1,139 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import org.bukkit.Chunk;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.entity.Tameable;
import org.bukkit.entity.Villager;
import java.util.UUID;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_CLEAR)
public class CommandClaimClear extends BaseCommand {
@CommandAlias("claimclear")
@Description("Allows clearing of entities within one or more claims.")
@Syntax("<entity_id> [claim_uuid]")
@Subcommand("claim clear")
public void execute(Player player, String target, @Optional String claimId) {
World world = player.getWorld();
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(world.getUID())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
UUID claimUniqueId = null;
GDClaim targetClaim = null;
if (claimId == null) {
targetClaim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
final Component result = targetClaim.allowEdit(player);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
claimUniqueId = targetClaim.getUniqueId();
} else {
if (!player.hasPermission(GDPermissions.COMMAND_DELETE_CLAIMS)) {
GriefDefenderPlugin.sendMessage(player, TextComponent.of("Only administrators may clear claims by UUID.", TextColor.RED));
return;
}
try {
claimUniqueId = UUID.fromString(claimId);
} catch (IllegalArgumentException e) {
return;
}
}
if (targetClaim.isWilderness()) {
GriefDefenderPlugin.sendMessage(player, TextComponent.of("This action is not available in the wilderness.", TextColor.RED));
return;
}
int count = 0;
String[] parts = target.split(":");
if (parts.length > 1) {
target = parts[1];
}
for (Chunk chunk : targetClaim.getChunks()) {
for (Entity entity : chunk.getEntities()) {
if (entity instanceof Player) {
continue;
}
if (entity instanceof Villager || !(entity instanceof LivingEntity)) {
continue;
}
if (entity instanceof Tameable) {
final UUID ownerUniqueId = NMSUtil.getInstance().getTameableOwnerUUID(entity);
if (ownerUniqueId != null && !ownerUniqueId.equals(player.getUniqueId())) {
continue;
}
}
LivingEntity livingEntity = (LivingEntity) entity;
String entityName = entity.getType().getName().toLowerCase();
if (target.equalsIgnoreCase("any") || target.equalsIgnoreCase("all") || target.equalsIgnoreCase("minecraft") || target.equalsIgnoreCase(entityName)) {
livingEntity.setHealth(0);
count++;
}
}
}
if (count == 0) {
GriefDefenderPlugin.sendMessage(player, TextComponent.builder("")
.append("Could not locate any entities of type ")
.append(target, TextColor.GREEN)
.append(".").build());
} else {
GriefDefenderPlugin.sendMessage(player, TextComponent.builder("")
.append("Killed ", TextColor.RED)
.append(String.valueOf(count), TextColor.AQUA)
.append(" entities of type ")
.append(target, TextColor.GREEN)
.append(".").build());
}
}
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CUBOID_CLAIMS)
public class CommandClaimCuboid extends BaseCommand {
@CommandAlias("cuboid")
@Description("Toggles cuboid claims mode.")
@Subcommand("cuboid")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
if (playerData.getClaimCreateMode() == 0) {
playerData.setClaimCreateMode(1);
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimCuboidEnabled.toText());
} else {
playerData.setClaimCreateMode(0);
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimCuboidDisabled.toText());
}
}
}

View File

@ -0,0 +1,99 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ClaimResult;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_DELETE_CLAIMS)
public class CommandClaimDelete extends BaseCommand {
protected boolean deleteTopLevelClaim = false;
@CommandAlias("deleteclaim")
@Description("Deletes the claim you're standing in, even if it's not your claim.")
@Subcommand("delete claim")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
final boolean isTown = claim.isTown();
if (claim.isWilderness()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotFound.toText());
return;
}
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimDelete
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
if (claim.isAdminClaim() && !player.hasPermission(GDPermissions.DELETE_CLAIM_ADMIN)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
if (claim.isBasicClaim() && !player.hasPermission(GDPermissions.DELETE_CLAIM_BASIC)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
if (!this.deleteTopLevelClaim && !claim.isTown() && claim.children.size() > 0 /*&& !playerData.warnedAboutMajorDeletion*/) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimChildrenWarning.toText());
return;
}
GDCauseStackManager.getInstance().pushCause(player);
ClaimResult claimResult = GriefDefenderPlugin.getInstance().dataStore.deleteClaim(claim, !this.deleteTopLevelClaim);
GDCauseStackManager.getInstance().popCause();
if (!claimResult.successful()) {
GriefDefenderPlugin.sendMessage(player, claimResult.getMessage().orElse(TextComponent.of("Could not delete claim. A plugin has denied it.").color(TextColor.RED)));
return;
}
PermissionUtil.getInstance().clearPermissions(GriefDefenderPlugin.DEFAULT_HOLDER, claim.getContext());
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDeleted.toText());
playerData.revertActiveVisual(player);
if (isTown) {
playerData.inTown = false;
playerData.townChat = false;
}
}
}

View File

@ -0,0 +1,84 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDDeleteClaimEvent;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_DELETE_CLAIMS)
public class CommandClaimDeleteAll extends BaseCommand {
@CommandAlias("deleteall")
@Description("Delete all of another player's claims.")
@Subcommand("delete all")
public void execute(Player player, OfflinePlayer otherPlayer) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
int originalClaimCount = playerData.getInternalClaims().size();
if (originalClaimCount == 0) {
TextAdapter.sendComponent(player, TextComponent.of("Player " + otherPlayer.getName() + " has no claims to delete.", TextColor.RED));
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDDeleteClaimEvent event = new GDDeleteClaimEvent(ImmutableList.copyOf(playerData.getInternalClaims()));
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
GriefDefenderPlugin.sendMessage(player, event.getMessage().orElse(TextComponent.of("Could not delete all claims. A plugin has denied it.").color(TextColor.RED)));
return;
}
GriefDefenderPlugin.getInstance().dataStore.deleteClaimsForPlayer(otherPlayer.getUniqueId());
final Component message = GriefDefenderPlugin.getInstance().messageData.claimDeleteAllSuccess
.apply(ImmutableMap.of(
"owner", otherPlayer.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
if (player != null) {
GriefDefenderPlugin.getInstance().getLogger().info(player.getName() + " deleted all claims belonging to " + otherPlayer.getName() + ".");
// revert any current visualization
playerData.revertActiveVisual(player);
}
}
}

View File

@ -0,0 +1,63 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ClaimResult;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_DELETE_ADMIN_CLAIMS)
public class CommandClaimDeleteAllAdmin extends BaseCommand {
@CommandAlias("deletealladmin")
@Description("Deletes all administrative claims.")
@Subcommand("delete alladmin")
public void execute(Player player) {
ClaimResult claimResult = GriefDefenderPlugin.getInstance().dataStore.deleteAllAdminClaims(player, player.getWorld());
if (!claimResult.successful()) {
final Component message = GriefDefenderPlugin.getInstance().messageData.claimTypeNotFound
.apply(ImmutableMap.of(
"type", ClaimTypes.ADMIN.getName().toLowerCase())).build();
GriefDefenderPlugin.sendMessage(player, claimResult.getMessage().orElse(message));
return;
}
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDeleteAllAdminSuccess.toText());
GriefDefenderPlugin.getInstance().getLogger().info(player.getName() + " deleted all administrative claims.");
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.revertActiveVisual(player);
}
}

View File

@ -0,0 +1,48 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_DELETE_CLAIMS)
public class CommandClaimDeleteTop extends CommandClaimDelete {
public CommandClaimDeleteTop() {
this.deleteTopLevelClaim = true;
}
@CommandAlias("deletetop")
@Description("Deletes the claim you're standing in, even if it's not your claim.")
@Subcommand("delete top")
public void execute(Player player) {
super.execute(player);
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SET_CLAIM_FAREWELL)
public class CommandClaimFarewell extends BaseCommand {
@CommandAlias("claimfarewell")
@Description("Sets the farewell message of your claim.")
@Syntax("<message>")
@Subcommand("claim farewell")
public void execute(Player player, String message) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (claim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionEditClaim.toText());
return;
}
TextComponent farewell = LegacyComponentSerializer.legacy().deserialize(message, '&');
if (farewell == TextComponent.empty() || farewell.content().equals("clear")) {
claim.getInternalClaimData().setFarewell(null);
} else {
claim.getInternalClaimData().setFarewell(farewell);
}
claim.getInternalClaimData().setRequiresSave(true);
Component resultMessage = null;
if (!claim.getInternalClaimData().getFarewell().isPresent()) {
resultMessage = GriefDefenderPlugin.getInstance().messageData.claimFarewellClear.toText();
} else {
resultMessage = GriefDefenderPlugin.getInstance().messageData.claimFarewell
.apply(ImmutableMap.of(
"farewell", farewell)).build();
}
TextAdapter.sendComponent(player, resultMessage);
}
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_FLAGS_CLAIM)
public class CommandClaimFlag extends ClaimFlagBase {
public CommandClaimFlag() {
super(ClaimSubjectType.GLOBAL);
}
@CommandAlias("cf|claimflag")
@Description("Gets/Sets claim flags in the claim you are standing in.")
@Syntax("<flag> <target> <value> [context[key=value]]")
@Subcommand("flag claim")
public void execute(Player player, @Optional String[] args) throws InvalidCommandArgument {
this.subject = GriefDefenderPlugin.DEFAULT_HOLDER;
this.friendlySubjectName = "ALL";
super.execute(player, args);
}
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_FLAGS_DEBUG)
public class CommandClaimFlagDebug extends BaseCommand {
@CommandAlias("cfd")
@Description("Toggles claim flag debug mode.")
@Subcommand("claim debug")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(player);
final Component result = claim.allowEdit(user, true);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
playerData.debugClaimPermissions = !playerData.debugClaimPermissions;
if (!playerData.debugClaimPermissions) {
GriefDefenderPlugin.sendMessage(player, TextComponent.builder("")
.append("Claim flags debug ")
.append("OFF", TextColor.RED).build());
} else {
GriefDefenderPlugin.sendMessage(player, TextComponent.builder("")
.append("Claim flags debug ")
.append("ON", TextColor.GREEN).build());
}
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_FLAGS_GROUP)
public class CommandClaimFlagGroup extends ClaimFlagBase {
public CommandClaimFlagGroup() {
super(ClaimSubjectType.GROUP);
}
@CommandAlias("cfg")
@Description("Gets/Sets flag permission for a group in claim you are standing in.")
@Syntax("<group> <flag> <target> <value> [context[key=value]]")
@Subcommand("flag group")
public void execute(Player player, String group, @Optional String[] args) throws InvalidCommandArgument {
if (args.length < 2 || args.length > 3) {
throw new InvalidCommandArgument();
}
if (!PermissionUtil.getInstance().hasGroupSubject(group)) {
final Component message = GriefDefenderPlugin.getInstance().messageData.commandGroupInvalid
.apply(ImmutableMap.of(
"group", group)).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
/*String reason = ctx.<String>getOne("reason").orElse(null);
Text reasonText = null;
if (reason != null) {
reasonText = TextSerializers.FORMATTING_CODE.deserialize(reason);
}*/
this.subject = PermissionHolderCache.getInstance().getOrCreateHolder(group);
this.friendlySubjectName = group;
super.execute(player, args);
}
}

View File

@ -0,0 +1,65 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.Tristate;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_FLAGS_PLAYER)
public class CommandClaimFlagPlayer extends ClaimFlagBase {
public CommandClaimFlagPlayer() {
super(ClaimSubjectType.PLAYER);
}
@CommandAlias("cfp")
@Description("Gets/Sets flag permission for a player in claim you are standing in.")
@Syntax("<player> <flag> <target> <value> [context[key=value]]")
@Subcommand("flag player")
public void execute(Player src, OfflinePlayer player, @Optional String[] args) throws InvalidCommandArgument {
this.subject = PermissionHolderCache.getInstance().getOrCreateUser(player);
this.friendlySubjectName = player.getName();
if (PermissionUtil.getInstance().getPermissionValue(this.subject, GDPermissions.COMMAND_ADMIN_CLAIMS) == Tristate.TRUE && !src.hasPermission(GDPermissions.SET_ADMIN_FLAGS)) {
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.permissionSetAdminFlags.toText());
return;
}
super.execute(src, args);
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.permission.Context;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import org.bukkit.entity.Player;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_FLAGS_RESET)
public class CommandClaimFlagReset extends BaseCommand {
@CommandAlias("cfr")
@Description("Resets a claim to flag defaults.")
@Subcommand("flag reset")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimResetFlags
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
if (claim.isWilderness()) {
if (!player.hasPermission(GDPermissions.MANAGE_WILDERNESS)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
} else if (claim.isAdminClaim()) {
if (!player.getUniqueId().equals(claim.getOwnerUniqueId()) && !player.hasPermission(GDPermissions.COMMAND_ADMIN_CLAIMS)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
} else if (!player.hasPermission(GDPermissions.COMMAND_ADMIN_CLAIMS) && (claim.isBasicClaim() || claim.isSubdivision()) && !player.getUniqueId().equals(claim.getOwnerUniqueId())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionClaimResetFlagsSelf.toText());
return;
}
// Remove persisted data
for (Set<Context> contextSet : PermissionUtil.getInstance().getAllPermissions(claim, GriefDefenderPlugin.DEFAULT_HOLDER).keySet()) {
if (contextSet.contains(claim.getContext())) {
PermissionUtil.getInstance().clearPermissions(GriefDefenderPlugin.DEFAULT_HOLDER, contextSet);
}
}
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.flagResetSuccess.toText());
}
}

View File

@ -0,0 +1,79 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SET_CLAIM_GREETING)
public class CommandClaimGreeting extends BaseCommand {
@CommandAlias("claimgreeting")
@Description("Sets the greeting message of your claim.")
@Syntax("<message>")
@Subcommand("claim greeting")
public void execute(Player player, String message) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component result = claim.allowEdit(player);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
final TextComponent greeting = LegacyComponentSerializer.legacy().deserialize(message, '&');
if (greeting == TextComponent.empty() || greeting.content().equals("clear")) {
claim.getInternalClaimData().setGreeting(null);
} else {
claim.getInternalClaimData().setGreeting(greeting);
}
claim.getInternalClaimData().setRequiresSave(true);
Component resultMessage = null;
if (!claim.getInternalClaimData().getGreeting().isPresent()) {
resultMessage = GriefDefenderPlugin.getInstance().messageData.claimGreetingClear.toText();
} else {
resultMessage = GriefDefenderPlugin.getInstance().messageData.claimGreeting
.apply(ImmutableMap.of(
"greeting", greeting)).build();
}
TextAdapter.sendComponent(player, resultMessage);
}
}

View File

@ -0,0 +1,66 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_IGNORE_CLAIMS)
public class CommandClaimIgnore extends BaseCommand {
@CommandAlias("claimignore|ignoreclaims|ic")
@Description("Toggles ignore claims mode.")
@Subcommand("claim ignore")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
if (claim.isBasicClaim() && !playerData.ignoreBasicClaims || claim.isWilderness() && !playerData.ignoreWilderness || claim.isAdminClaim() && !playerData.ignoreAdminClaims) {
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimIgnore
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
playerData.ignoreClaims = !playerData.ignoreClaims;
if (!playerData.ignoreClaims) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimRespecting.toText());
} else {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimIgnore.toText());
}
}
}

View File

@ -0,0 +1,840 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.flowpowered.math.vector.Vector3i;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimResult;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.text.action.GDCallbackHolder;
import com.griefdefender.util.PlayerUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Consumer;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_INFO_BASE)
public class CommandClaimInfo extends BaseCommand {
private static final Component NONE = TextComponent.of("none", TextColor.GRAY);
private static final String ADMIN_SETTINGS = "Admin Settings";
private static final String CLAIM_EXPIRATION = "ClaimExpiration";
private static final String DENY_MESSAGES = "DenyMessages";
private static final String FLAG_OVERRIDES = "FlagOverrides";
private static final String INHERIT_PARENT = "InheritParent";
private static final String PVP_OVERRIDE = "PvPOverride";
private static final String RESIZABLE = "Resizable";
private static final String REQUIRES_CLAIM_BLOCKS = "RequiresClaimBlocks";
private static final String SIZE_RESTRICTIONS = "SizeRestrictions";
private static final String FOR_SALE = "ForSale";
private boolean useTownInfo = false;
public CommandClaimInfo() {
}
public CommandClaimInfo(boolean useTownInfo) {
this.useTownInfo = useTownInfo;
}
@CommandAlias("claiminfo")
@Syntax("[claim_uuid]")
@Subcommand("claim info")
public void execute(CommandSender src, String[] args) {
String claimIdentifier = null;
if (args.length > 0) {
claimIdentifier = args[0];
}
Player player = null;
if (src instanceof Player) {
player = (Player) src;
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(player.getWorld().getUID())) {
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
}
if (player == null && claimIdentifier == null) {
TextAdapter.sendComponent(src, TextComponent.of("No valid player or claim UUID found.", TextColor.RED));
return;
}
boolean isAdmin = src.hasPermission(GDPermissions.COMMAND_ADMIN_CLAIMS);
final GDPlayerData playerData = player != null ? GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId()) : null;
Claim claim = null;
if (claimIdentifier == null) {
if (player != null) {
claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
} else {
TextAdapter.sendComponent(src, TextComponent.of("Claim UUID is required if executing from non-player source.", TextColor.RED));
return;
}
} else {
for (World world : Bukkit.getServer().getWorlds()) {
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(world.getUID())) {
continue;
}
final GDClaimManager claimManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(world.getUID());
UUID uuid = null;
try {
uuid = UUID.fromString(claimIdentifier);
claim = claimManager.getClaimByUUID(uuid).orElse(null);
if (claim != null) {
break;
}
} catch (IllegalArgumentException e) {
}
if (uuid == null) {
final List<Claim> claimList = claimManager.getClaimsByName(claimIdentifier);
if (!claimList.isEmpty()) {
claim = claimList.get(0);
}
}
}
}
if (claim == null) {
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.claimNotFound.toText());
return;
}
if (this.useTownInfo) {
if (!claim.isInTown()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.townNotIn.toText());
return;
}
claim = claim.getTown().get();
}
final GDClaim gpClaim = (GDClaim) claim;
UUID ownerUniqueId = claim.getOwnerUniqueId();
if (!isAdmin) {
isAdmin = playerData.canIgnoreClaim(gpClaim);
}
// if not owner of claim, validate perms
if (!isAdmin && !player.getUniqueId().equals(claim.getOwnerUniqueId())) {
if (!gpClaim.getInternalClaimData().getContainers().contains(player.getUniqueId())
&& !gpClaim.getInternalClaimData().getBuilders().contains(player.getUniqueId())
&& !gpClaim.getInternalClaimData().getManagers().contains(player.getUniqueId())
&& !player.hasPermission(GDPermissions.COMMAND_CLAIM_INFO_OTHERS)) {
TextAdapter.sendComponent(player, GriefDefenderPlugin.getInstance().messageData.claimNotYours.toText());
return;
}
}
final Component allowEdit = gpClaim.allowEdit(player);
List<Component> textList = new ArrayList<>();
Component name = claim.getName().orElse(null);
Component greeting = claim.getData().getGreeting().orElse(null);
Component farewell = claim.getData().getFarewell().orElse(null);
String accessors = "";
String builders = "";
String containers = "";
String managers = "";
String accessorGroups = "";
String builderGroups = "";
String containerGroups = "";
String managerGroups = "";
final int minClaimLevel = gpClaim.getOwnerMinClaimLevel();
double claimY = gpClaim.getOwnerPlayerData() == null ? 65.0D : (minClaimLevel > 65.0D ? minClaimLevel : 65);
if (gpClaim.isCuboid()) {
claimY = gpClaim.lesserBoundaryCorner.getY();
}
Location southWest = new Location(gpClaim.getWorld(), gpClaim.lesserBoundaryCorner.getX(), claimY, gpClaim.greaterBoundaryCorner.getZ());
Location northWest = new Location(gpClaim.getWorld(), gpClaim.lesserBoundaryCorner.getX(), claimY, gpClaim.lesserBoundaryCorner.getZ());
Location southEast = new Location(gpClaim.getWorld(), gpClaim.greaterBoundaryCorner.getX(), claimY, gpClaim.greaterBoundaryCorner.getZ());
Location northEast = new Location(gpClaim.getWorld(), gpClaim.greaterBoundaryCorner.getX(), claimY, gpClaim.lesserBoundaryCorner.getZ());
// String southWestCorner =
Date created = null;
Date lastActive = null;
try {
Instant instant = claim.getData().getDateCreated();
created = Date.from(instant);
} catch(DateTimeParseException ex) {
// ignore
}
try {
Instant instant = claim.getData().getDateLastActive();
lastActive = Date.from(instant);
} catch(DateTimeParseException ex) {
// ignore
}
final int sizeX = Math.abs(claim.getGreaterBoundaryCorner().getX() - claim.getLesserBoundaryCorner().getX()) + 1;
final int sizeY = Math.abs(claim.getGreaterBoundaryCorner().getY() - claim.getLesserBoundaryCorner().getY()) + 1;
final int sizeZ = Math.abs(claim.getGreaterBoundaryCorner().getZ() - claim.getLesserBoundaryCorner().getZ()) + 1;
Component claimSize = TextComponent.empty();
if (claim.isCuboid()) {
claimSize = TextComponent.builder(" ")
.append("Area: ", TextColor.YELLOW)
.append(sizeX + "x" + sizeY + "x" + sizeZ, TextColor.GRAY).build();
} else {
claimSize = TextComponent.builder(" ")
.append("Area: ", TextColor.YELLOW)
.append(sizeX + "x" + sizeZ, TextColor.GRAY).build();
}
final Component claimCost = TextComponent.builder(" ")
.append("Blocks: ", TextColor.YELLOW)
.append(String.valueOf(claim.getClaimBlocks()), TextColor.GRAY).build();
if (claim.isWilderness() && name == null) {
name = TextComponent.of("Wilderness", TextColor.GREEN);
}
Component claimName = TextComponent.builder("")
.append("Name", TextColor.YELLOW)
.append(" : ")
.append(name == null ? NONE : name).build();
if (!claim.isWilderness() && !claim.isAdminClaim()) {
claimName = TextComponent.builder("")
.append(claimName)
.append(claimSize)
.append(claimCost).build();
}
// users
final List<UUID> accessorList = gpClaim.getUserTrustList(TrustTypes.ACCESSOR, true);
final List<UUID> builderList = gpClaim.getUserTrustList(TrustTypes.BUILDER, true);
final List<UUID> containerList = gpClaim.getUserTrustList(TrustTypes.CONTAINER, true);
final List<UUID> managerList = gpClaim.getUserTrustList(TrustTypes.MANAGER, true);
for (UUID uuid : accessorList) {
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName != null) {
accessors += PlayerUtil.getInstance().getUserName(uuid) + " ";
}
}
for (UUID uuid : builderList) {
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName != null) {
builders += PlayerUtil.getInstance().getUserName(uuid) + " ";
}
}
for (UUID uuid : containerList) {
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName != null) {
containers += PlayerUtil.getInstance().getUserName(uuid) + " ";
}
}
for (UUID uuid : managerList) {
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName != null) {
managers += PlayerUtil.getInstance().getUserName(uuid) + " ";
}
}
// groups
for (String group : gpClaim.getInternalClaimData().getAccessorGroups()) {
accessorGroups += group + " ";
}
for (String group : gpClaim.getInternalClaimData().getBuilderGroups()) {
builderGroups += group + " ";
}
for (String group : gpClaim.getInternalClaimData().getContainerGroups()) {
containerGroups += group + " ";
}
for (String group : gpClaim.getInternalClaimData().getManagerGroups()) {
managerGroups += group + " ";
}
/*if (gpClaim.isInTown()) {
Text returnToClaimInfo = Text.builder().append(Text.of(
TextColors.WHITE, "\n[", TextColors.AQUA, "Return to standard settings", TextColors.WHITE, "]\n"))
.onClick(TextActions.executeCallback(CommandHelper.createCommandConsumer(src, "claiminfo", ""))).build();
Text townName = Text.of(TextColors.YELLOW, "Name", TextColors.WHITE, " : ", TextColors.RESET,
gpClaim.getTownClaim().getTownData().getName().orElse(NONE));
Text townTag = Text.of(TextColors.YELLOW, "Tag", TextColors.WHITE, " : ", TextColors.RESET,
gpClaim.getTownClaim().getTownData().getTownTag().orElse(NONE));
townTextList.add(returnToClaimInfo);
townTextList.add(townName);
townTextList.add(townTag);
Text townSettings = Text.builder()
.append(Text.of(TextStyles.ITALIC, TextColors.GREEN, TOWN_SETTINGS))
.onClick(TextActions.executeCallback(createSettingsConsumer(src, claim, townTextList, ClaimTypes.TOWN)))
.onHover(TextActions.showText(Text.of("Click here to view town settings")))
.build();
textList.add(townSettings);
}*/
if (isAdmin) {
Component adminSettings = TextComponent.builder("")
.append(TextComponent.of(ADMIN_SETTINGS, TextColor.RED).decoration(TextDecoration.ITALIC, true))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createSettingsConsumer(src, claim, generateAdminSettings(src, gpClaim), ClaimTypes.ADMIN))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Click here to view admin settings")))
.build();
textList.add(adminSettings);
}
Component bankInfo = null;
Component forSaleText = null;
if (GriefDefenderPlugin.getInstance().getVaultProvider() != null) {
if (GriefDefenderPlugin.getActiveConfig(gpClaim.getWorld().getUID()).getConfig().claim.bankTaxSystem) {
bankInfo = TextComponent.builder("")
.append("Bank Info", TextColor.GOLD, TextDecoration.ITALIC)
.hoverEvent(HoverEvent.showText(TextComponent.of("Click to check bank information")))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(Consumer -> { CommandHelper.displayClaimBankInfo(src, gpClaim, gpClaim.isTown() ? true : false, true); })))
.build();
}
forSaleText = TextComponent.builder("")
.append("ForSale", TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, FOR_SALE, claim.getEconomyData().isForSale() ? TextComponent.of("YES", TextColor.GREEN) : TextComponent.of("NO", TextColor.GRAY))).build();
if (claim.getEconomyData().isForSale()) {
forSaleText = TextComponent.builder("")
.append(forSaleText)
.append(" ")
.append("Price", TextColor.YELLOW)
.append(" : ")
.append(String.valueOf(claim.getEconomyData().getSalePrice()), TextColor.GOLD)
.build();
}
}
Component claimId = TextComponent.builder("")
.append("UUID", TextColor.YELLOW)
.append(" : ")
.append(TextComponent.builder("")
.append(claim.getUniqueId().toString(), TextColor.GRAY)
.insertion(claim.getUniqueId().toString()).build()).build();
final String ownerName = PlayerUtil.getInstance().getUserName(ownerUniqueId);
Component ownerLine = TextComponent.builder("")
.append("Owner", TextColor.YELLOW)
.append(" : ")
.append(ownerName != null && !claim.isAdminClaim() ? ownerName : "administrator", TextColor.GOLD).build();
Component adminShowText = TextComponent.empty();
Component basicShowText = TextComponent.empty();
Component subdivisionShowText = TextComponent.empty();
Component townShowText = TextComponent.empty();
Component claimType = TextComponent.empty();
final Component whiteOpenBracket = TextComponent.of("[");
final Component whiteCloseBracket = TextComponent.of("]");
Component defaultTypeText = TextComponent.builder("")
.append(whiteOpenBracket)
.append(gpClaim.getFriendlyNameType(true))
.append(whiteCloseBracket).build();
if (allowEdit != null && !isAdmin) {
adminShowText = allowEdit;
basicShowText = allowEdit;
subdivisionShowText = allowEdit;
townShowText = allowEdit;
Component adminTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.ADMIN ?
defaultTypeText : TextComponent.of("ADMIN", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(adminShowText)).build();
Component basicTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.BASIC ?
defaultTypeText : TextComponent.of("BASIC", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(basicShowText)).build();
Component subTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.SUBDIVISION ?
defaultTypeText : TextComponent.of("SUBDIVISION", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(subdivisionShowText)).build();
Component townTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.TOWN ?
defaultTypeText : TextComponent.of("TOWN", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(townShowText)).build();
claimType = TextComponent.builder("")
.append(claim.isCuboid() ? "3D " : "2D ", TextColor.GREEN)
.append(adminTypeText)
.append(" ")
.append(basicTypeText)
.append(" ")
.append(subTypeText)
.append(" ")
.append(townTypeText)
.build();
} else {
Component adminTypeText = defaultTypeText;
Component basicTypeText = defaultTypeText;
Component subTypeText = defaultTypeText;
Component townTypeText = defaultTypeText;
if (!claim.isAdminClaim()) {
final Component message = ((GDClaim) claim).validateClaimType(ClaimTypes.ADMIN, ownerUniqueId, playerData).getMessage().orElse(null);
adminShowText = message != null ? message : TextComponent.builder("")
.append("Click here to change claim to ")
.append("ADMIN ", TextColor.RED)
.append("type.").build();
if (message == null) {
adminTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.ADMIN ?
defaultTypeText : TextComponent.of("ADMIN", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimTypeConsumer(src, claim, ClaimTypes.ADMIN, isAdmin))))
.hoverEvent(HoverEvent.showText(adminShowText)).build();
} else {
adminTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.ADMIN ?
defaultTypeText : TextComponent.of("ADMIN", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(adminShowText)).build();
}
}
if (!claim.isBasicClaim()) {
final Component message = ((GDClaim) claim).validateClaimType(ClaimTypes.BASIC, ownerUniqueId, playerData).getMessage().orElse(null);
basicShowText = message != null ? message : TextComponent.builder("")
.append("Click here to change claim to ")
.append("BASIC ", TextColor.YELLOW)
.append("type.").build();
if (message == null) {
basicTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.BASIC ? defaultTypeText : TextComponent.of("BASIC", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimTypeConsumer(src, claim, ClaimTypes.BASIC, isAdmin))))
.hoverEvent(HoverEvent.showText(basicShowText)).build();
} else {
basicTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.BASIC ? defaultTypeText : TextComponent.of("BASIC", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(basicShowText)).build();
}
}
if (!claim.isSubdivision()) {
final Component message = ((GDClaim) claim).validateClaimType(ClaimTypes.SUBDIVISION, ownerUniqueId, playerData).getMessage().orElse(null);
subdivisionShowText = message != null ? message : TextComponent.builder("")
.append("Click here to change claim to ")
.append("SUBDIVISION ", TextColor.AQUA)
.append("type.").build();
if (message == null) {
subTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.SUBDIVISION ? defaultTypeText : TextComponent.of("SUBDIVISION", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimTypeConsumer(src, claim, ClaimTypes.SUBDIVISION, isAdmin))))
.hoverEvent(HoverEvent.showText(subdivisionShowText)).build();
} else {
subTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.SUBDIVISION ? defaultTypeText : TextComponent.of("SUBDIVISION", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(subdivisionShowText)).build();
}
}
if (!claim.isTown()) {
final Component message = ((GDClaim) claim).validateClaimType(ClaimTypes.TOWN, ownerUniqueId, playerData).getMessage().orElse(null);
townShowText = message != null ? message : TextComponent.builder("")
.append("Click here to change claim to ")
.append("TOWN ", TextColor.GREEN)
.append("type.").build();
if (message == null) {
townTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.TOWN ? defaultTypeText : TextComponent.of("TOWN", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimTypeConsumer(src, claim, ClaimTypes.TOWN, isAdmin))))
.hoverEvent(HoverEvent.showText(townShowText)).build();
} else {
townTypeText = TextComponent.builder("")
.append(claim.getType() == ClaimTypes.TOWN ? defaultTypeText : TextComponent.of("TOWN", TextColor.GRAY))
.hoverEvent(HoverEvent.showText(townShowText)).build();
}
}
claimType = TextComponent.builder("")
.append(claim.isCuboid() ? "3D " : "2D ", TextColor.GREEN)
.append(adminTypeText)
.append(" ")
.append(basicTypeText)
.append(" ")
.append(subTypeText)
.append(" ")
.append(townTypeText)
.build();
}
Component claimTypeInfo = TextComponent.builder("")
.append("Type", TextColor.YELLOW)
.append(" : ")
.append(claimType).build();
Component claimInherit = TextComponent.builder("")
.append(INHERIT_PARENT, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, INHERIT_PARENT, claim.getData().doesInheritParent() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component claimExpired = TextComponent.builder("")
.append("Expired", TextColor.YELLOW)
.append(" : ")
.append(claim.getData().isExpired() ? TextComponent.of("YES", TextColor.RED) : TextComponent.of("NO", TextColor.GRAY)).build();
Component claimFarewell = TextComponent.builder("")
.append("Farewell", TextColor.YELLOW)
.append(" : ")
.append(farewell == null ? NONE : farewell).build();
Component claimGreeting = TextComponent.builder("")
.append("Greeting", TextColor.YELLOW)
.append(" : ")
.append(greeting == null ? NONE : greeting).build();
Component claimSpawn = null;
if (claim.getData().getSpawnPos().isPresent()) {
Vector3i spawnPos = claim.getData().getSpawnPos().get();
Location spawnLoc = new Location(gpClaim.getWorld(), spawnPos.getX(), spawnPos.getY(), spawnPos.getZ());
claimSpawn = TextComponent.builder("")
.append("Spawn", TextColor.GREEN)
.append(" : ")
.append(spawnPos.toString(), TextColor.GRAY)
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createTeleportConsumer(player, spawnLoc, claim))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Click here to teleport to claim spawn.")))
.build();
}
Component southWestCorner = TextComponent.builder("")
.append("SW", TextColor.LIGHT_PURPLE)
.append(" : ")
.append(VecHelper.toVector3i(southWest).toString(), TextColor.GRAY)
.append(" ")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createTeleportConsumer(player, southWest, claim))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Click here to teleport to SW corner of claim.")))
.build();
Component southEastCorner = TextComponent.builder("")
.append("SE", TextColor.LIGHT_PURPLE)
.append(" : ")
.append(VecHelper.toVector3i(southEast).toString(), TextColor.GRAY)
.append(" ")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createTeleportConsumer(player, southEast, claim))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Click here to teleport to SE corner of claim.")))
.build();
Component southCorners = TextComponent.builder("")
.append("SouthCorners", TextColor.YELLOW)
.append(" : ")
.append(southWestCorner)
.append(southEastCorner).build();
Component northWestCorner = TextComponent.builder("")
.append("NW", TextColor.LIGHT_PURPLE)
.append(" : ")
.append(VecHelper.toVector3i(northWest).toString(), TextColor.GRAY)
.append(" ")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createTeleportConsumer(player, northWest, claim))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Click here to teleport to NW corner of claim.")))
.build();
Component northEastCorner = TextComponent.builder("")
.append("NE", TextColor.LIGHT_PURPLE)
.append(" : ")
.append(VecHelper.toVector3i(northEast).toString(), TextColor.GRAY)
.append(" ")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createTeleportConsumer(player, northEast, claim))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Click here to teleport to NE corner of claim.")))
.build();
Component northCorners = TextComponent.builder("")
.append("NorthCorners", TextColor.YELLOW)
.append(" : ")
.append(northWestCorner)
.append(northEastCorner).build();
Component claimAccessors = TextComponent.builder("")
.append("Accessors", TextColor.YELLOW)
.append(" : ")
.append(accessors.equals("") ? NONE : TextComponent.of(accessors, TextColor.BLUE))
.append(" ")
.append(accessorGroups, TextColor.LIGHT_PURPLE).build();
Component claimBuilders = TextComponent.builder("")
.append("Builders", TextColor.YELLOW)
.append(" : ")
.append(builders.equals("") ? NONE : TextComponent.of(builders, TextColor.BLUE))
.append(" ")
.append(builderGroups, TextColor.LIGHT_PURPLE).build();
Component claimContainers = TextComponent.builder("")
.append("Containers", TextColor.YELLOW)
.append(" : ")
.append(containers.equals("") ? NONE : TextComponent.of(containers, TextColor.BLUE))
.append(" ")
.append(containerGroups, TextColor.LIGHT_PURPLE).build();
Component claimCoowners = TextComponent.builder("")
.append("Managers", TextColor.YELLOW)
.append(" : ")
.append(managers.equals("") ? NONE : TextComponent.of(managers, TextColor.BLUE))
.append(" ")
.append(managerGroups, TextColor.LIGHT_PURPLE).build();
Component dateCreated = TextComponent.builder("")
.append("Created", TextColor.YELLOW)
.append(" : ")
.append(created != null ? created.toString() : "Unknown", TextColor.GRAY).build();
Component dateLastActive = TextComponent.builder("")
.append("LastActive", TextColor.YELLOW)
.append(" : ")
.append(lastActive != null ? lastActive.toString() : "Unknown", TextColor.GRAY).build();
Component worldName = TextComponent.builder("")
.append("World", TextColor.YELLOW)
.append(" : ")
.append(gpClaim.getWorld().getName(), TextColor.GRAY).build();
if (claimSpawn != null) {
textList.add(claimSpawn);
}
if (bankInfo != null) {
textList.add(bankInfo);
}
textList.add(claimName);
textList.add(ownerLine);
textList.add(claimTypeInfo);
if (!claim.isAdminClaim() && !claim.isWilderness()) {
textList.add(TextComponent.builder("")
.append(claimInherit)
.append(" ")
.append(claimExpired).build());
if (forSaleText != null) {
textList.add(forSaleText);
}
}
textList.add(claimAccessors);
textList.add(claimBuilders);
textList.add(claimContainers);
textList.add(claimCoowners);
textList.add(claimGreeting);
textList.add(claimFarewell);
textList.add(worldName);
textList.add(dateCreated);
textList.add(dateLastActive);
textList.add(claimId);
textList.add(northCorners);
textList.add(southCorners);
if (!claim.getParent().isPresent()) {
textList.remove(claimInherit);
}
if (claim.isAdminClaim()) {
textList.remove(bankInfo);
textList.remove(dateLastActive);
}
if (claim.isWilderness()) {
textList.remove(bankInfo);
textList.remove(claimInherit);
textList.remove(claimTypeInfo);
textList.remove(dateLastActive);
textList.remove(northCorners);
textList.remove(southCorners);
}
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of("Claim Info", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(textList);
paginationBuilder.sendTo(src);
}
public static Consumer<CommandSender> createSettingsConsumer(CommandSender src, Claim claim, List<Component> textList, ClaimType type) {
return settings -> {
String name = type == ClaimTypes.TOWN ? "Town Settings" : "Admin Settings";
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of(name, TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(textList);
paginationBuilder.sendTo(src);
};
}
private static List<Component> generateAdminSettings(CommandSender src, GDClaim claim) {
List<Component> textList = new ArrayList<>();
Component returnToClaimInfo = TextComponent.builder("")
.append("\n[")
.append("Return to standard settings", TextColor.AQUA)
.append("]\n")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(CommandHelper.createCommandConsumer(src, "claiminfo", claim.getUniqueId().toString())))).build();
Component claimDenyMessages = TextComponent.builder("")
.append(DENY_MESSAGES, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, DENY_MESSAGES, claim.getInternalClaimData().allowDenyMessages() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component claimResizable = TextComponent.builder("")
.append(RESIZABLE, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, RESIZABLE, claim.getInternalClaimData().isResizable() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component claimRequiresClaimBlocks = TextComponent.builder("")
.append(REQUIRES_CLAIM_BLOCKS, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, REQUIRES_CLAIM_BLOCKS, claim.getInternalClaimData().requiresClaimBlocks() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component claimSizeRestrictions = TextComponent.builder("")
.append(SIZE_RESTRICTIONS, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, SIZE_RESTRICTIONS, claim.getInternalClaimData().hasSizeRestrictions() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component claimExpiration = TextComponent.builder("")
.append(CLAIM_EXPIRATION, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, CLAIM_EXPIRATION, claim.getInternalClaimData().allowExpiration() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component claimFlagOverrides = TextComponent.builder("")
.append(FLAG_OVERRIDES, TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, FLAG_OVERRIDES, claim.getInternalClaimData().allowFlagOverrides() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))).build();
Component pvp = TextComponent.builder("")
.append("PvP", TextColor.YELLOW)
.append(" : ")
.append(getClickableInfoText(src, claim, PVP_OVERRIDE, claim.getInternalClaimData().getPvpOverride() == Tristate.TRUE ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of(claim.getInternalClaimData().getPvpOverride().name(), TextColor.RED))).build();
textList.add(returnToClaimInfo);
textList.add(claimDenyMessages);
if (!claim.isAdminClaim() && !claim.isWilderness()) {
textList.add(claimRequiresClaimBlocks);
textList.add(claimExpiration);
textList.add(claimResizable);
textList.add(claimSizeRestrictions);
}
textList.add(claimFlagOverrides);
textList.add(pvp);
int fillSize = 20 - (textList.size() + 4);
for (int i = 0; i < fillSize; i++) {
textList.add(TextComponent.of(" "));
}
return textList;
}
private static void executeAdminSettings(CommandSender src, GDClaim claim) {
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of("Admin Settings", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(generateAdminSettings(src, claim));
paginationBuilder.sendTo(src);
}
public static Component getClickableInfoText(CommandSender src, Claim claim, String title, Component infoText) {
Component onClickText = TextComponent.of("Click here to toggle value.");
boolean hasPermission = true;
if (src instanceof Player) {
Component denyReason = ((GDClaim) claim).allowEdit((Player) src);
if (denyReason != null) {
onClickText = denyReason;
hasPermission = false;
}
}
TextComponent.Builder textBuilder = TextComponent.builder("")
.append(infoText)
.hoverEvent(HoverEvent.showText(onClickText));
if (hasPermission) {
textBuilder.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimInfoConsumer(src, claim, title))));
}
return textBuilder.build();
}
private static Consumer<CommandSender> createClaimInfoConsumer(CommandSender src, Claim claim, String title) {
GDClaim gpClaim = (GDClaim) claim;
return info -> {
switch (title) {
case INHERIT_PARENT :
if (!src.hasPermission(GDPermissions.COMMAND_CLAIM_INHERIT)) {
return;
}
gpClaim.getInternalClaimData().setInheritParent(!gpClaim.getInternalClaimData().doesInheritParent());
gpClaim.getInternalClaimData().setRequiresSave(true);
claim.getData().save();
CommandHelper.executeCommand(src, "claiminfo", gpClaim.getUniqueId().toString());
return;
case CLAIM_EXPIRATION :
gpClaim.getInternalClaimData().setExpiration(!gpClaim.getInternalClaimData().allowExpiration());
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case DENY_MESSAGES :
gpClaim.getInternalClaimData().setDenyMessages(!gpClaim.getInternalClaimData().allowDenyMessages());
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case FLAG_OVERRIDES :
gpClaim.getInternalClaimData().setFlagOverrides(!gpClaim.getInternalClaimData().allowFlagOverrides());
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case PVP_OVERRIDE :
Tristate value = gpClaim.getInternalClaimData().getPvpOverride();
if (value == Tristate.UNDEFINED) {
gpClaim.getInternalClaimData().setPvpOverride(Tristate.TRUE);
} else if (value == Tristate.TRUE) {
gpClaim.getInternalClaimData().setPvpOverride(Tristate.FALSE);
} else {
gpClaim.getInternalClaimData().setPvpOverride(Tristate.UNDEFINED);
}
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case RESIZABLE :
boolean resizable = gpClaim.getInternalClaimData().isResizable();
gpClaim.getInternalClaimData().setResizable(!resizable);
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case REQUIRES_CLAIM_BLOCKS :
boolean requiresClaimBlocks = gpClaim.getInternalClaimData().requiresClaimBlocks();
gpClaim.getInternalClaimData().setRequiresClaimBlocks(!requiresClaimBlocks);
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case SIZE_RESTRICTIONS :
boolean sizeRestrictions = gpClaim.getInternalClaimData().hasSizeRestrictions();
gpClaim.getInternalClaimData().setSizeRestrictions(!sizeRestrictions);
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
break;
case FOR_SALE :
boolean forSale = gpClaim.getEconomyData().isForSale();
gpClaim.getEconomyData().setForSale(!forSale);
gpClaim.getInternalClaimData().setRequiresSave(true);
gpClaim.getClaimStorage().save();
CommandHelper.executeCommand(src, "claiminfo", gpClaim.getUniqueId().toString());
return;
default:
}
executeAdminSettings(src, gpClaim);
};
}
private static Consumer<CommandSender> createClaimTypeConsumer(CommandSender src, Claim gpClaim, ClaimType clicked, boolean isAdmin) {
GDClaim claim = (GDClaim) gpClaim;
return type -> {
if (!(src instanceof Player)) {
// ignore
return;
}
final Player player = (Player) src;
if (!isAdmin && ((GDClaim) gpClaim).allowEdit(player) != null) {
TextAdapter.sendComponent(src, GriefDefenderPlugin.getInstance().messageData.claimNotYours.toText());
return;
}
final ClaimResult result = claim.changeType(clicked, Optional.of(player.getUniqueId()), src);
if (result.successful()) {
CommandHelper.executeCommand(src, "claiminfo", gpClaim.getUniqueId().toString());
} else {
TextAdapter.sendComponent(src, result.getMessage().get());
}
};
}
}

View File

@ -0,0 +1,74 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_INHERIT)
public class CommandClaimInherit extends BaseCommand {
@CommandAlias("claiminherit")
@Description("Toggles subdivision inherit mode.")
@Subcommand("claim inherit")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component result = claim.allowEdit(player);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
if (claim.parent == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandInherit.toText());
return;
}
claim.getData().setInheritParent(!claim.getData().doesInheritParent());
claim.getInternalClaimData().setRequiresSave(true);
if (!claim.getData().doesInheritParent()) {
GriefDefenderPlugin.sendMessage(player, TextComponent.builder("")
.append("Parent claim inheritance ")
.append("OFF", TextColor.RED).build());
} else {
GriefDefenderPlugin.sendMessage(player, TextComponent.builder("")
.append("Parent claim inheritance ")
.append("ON", TextColor.GREEN).build());
}
}
}

View File

@ -0,0 +1,273 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaimManager;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.internal.util.BlockUtil;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.text.action.GDCallbackHolder;
import com.griefdefender.util.PaginationUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_LIST)
public class CommandClaimList extends BaseCommand {
private final ClaimType forcedType;
private boolean canListOthers;
private boolean canListAdmin;
private boolean displayOwned = true;
private final Cache<UUID, String> lastActiveClaimTypeMap = Caffeine.newBuilder().expireAfterAccess(10, TimeUnit.MINUTES)
.build();
public CommandClaimList() {
this.forcedType = null;
}
public CommandClaimList(ClaimType type) {
this.forcedType = type;
}
@CommandAlias("claimlist")
@Syntax("[<player>|<player> <world>]")
@Subcommand("claim list")
public void execute(Player src, @Optional String[] args) {
OfflinePlayer user = null;
World world = null;
if (args.length > 0) {
user = Bukkit.getServer().getOfflinePlayer(args[0]);
if (user == null) {
TextAdapter.sendComponent(src, TextComponent.of("User ' " + args[0] + "' could not be found.", TextColor.RED));
return;
}
if (args.length > 1) {
world = Bukkit.getServer().getWorld(args[1]);
if (world == null) {
TextAdapter.sendComponent(src, TextComponent.of("World ' " + args[1] + "' could not be found.", TextColor.RED));
return;
}
}
}
if (user == null) {
user = (OfflinePlayer) src;
if (world == null) {
world = ((Player) user).getWorld();
}
}
if (world == null) {
world = Bukkit.getServer().getWorlds().get(0);
}
this.canListOthers = src.hasPermission(GDPermissions.LIST_OTHER_CLAIMS);
this.canListAdmin = src.hasPermission(GDPermissions.LIST_OTHER_CLAIMS);
showClaimList(src, PermissionHolderCache.getInstance().getOrCreateUser(user), this.forcedType, world.getUID());
}
private void showClaimList(Player src, GDPermissionUser user, ClaimType type, UUID worldUniqueId) {
List<Component> claimsTextList = new ArrayList<>();
Set<Claim> claims = new HashSet<>();
final String worldName = worldUniqueId == null ? "" : Bukkit.getWorld(worldUniqueId).getName();
for (World world : Bukkit.getServer().getWorlds()) {
if (!this.displayOwned && !world.getUID().equals(worldUniqueId)) {
continue;
}
final GDClaimManager claimWorldManager = GriefDefenderPlugin.getInstance().dataStore.getClaimWorldManager(world.getUID());
// load the target player's data
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(world, user.getUniqueId());
Set<Claim> claimList = null;
if (this.displayOwned) {
claimList = playerData.getClaims();
} else {
claimList = BlockUtil.getInstance().getNearbyClaims(src.getLocation(), 100);
}
for (Claim claim : claimList) {
if (claims.contains(claim)) {
continue;
}
if (user != null && this.displayOwned) {
if (user.getUniqueId().equals(claim.getOwnerUniqueId())) {
claims.add(claim);
}
} else if (type != null) {
if (claim.getType() == type) {
claims.add(claim);
}
} else {
claims.add(claim);
}
}
}
if (src instanceof Player) {
final Player player = (Player) src;
final String lastClaimType = this.lastActiveClaimTypeMap.getIfPresent(player.getUniqueId());
String currentType = type == null ? "ALL" : type.toString();
if (lastClaimType != null && !lastClaimType.equals(currentType.toString())) {
PaginationUtil.getInstance().resetActivePage(player.getUniqueId());
}
}
claimsTextList = CommandHelper.generateClaimTextList(claimsTextList, claims, worldName, user, src, createClaimListConsumer(src, user, type, worldUniqueId), this.canListOthers, false);
final Component whiteOpenBracket = TextComponent.of("[");
final Component whiteCloseBracket = TextComponent.of("]");
Component ownedShowText = TextComponent.of("Click here to view the claims you own.");
Component adminShowText = TextComponent.builder("")
.append("Click here to filter by ")
.append("ADMIN ", TextColor.RED)
.append("type.").build();
Component basicShowText = TextComponent.builder("")
.append("Click here to filter by ")
.append("BASIC ", TextColor.YELLOW)
.append("type.").build();
Component subdivisionShowText = TextComponent.builder("")
.append("Click here to filter by ")
.append("SUBDIVISION ", TextColor.AQUA)
.append("type.").build();
Component townShowText = TextComponent.builder("")
.append("Click here to filter by ")
.append("TOWN ", TextColor.GREEN)
.append("type.").build();
Component ownedTypeText = TextComponent.builder("")
.append(this.displayOwned && type == null ?
TextComponent.builder("")
.append(whiteOpenBracket)
.append("OWN", TextColor.GOLD)
.append(whiteCloseBracket).build() : TextComponent.of("OWN", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimListConsumer(src, user, "OWN", worldUniqueId))))
.hoverEvent(HoverEvent.showText(ownedShowText)).build();
Component adminTypeText = TextComponent.builder("")
.append(type == ClaimTypes.ADMIN ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("ADMIN", TextColor.RED)
.append(whiteCloseBracket).build() : TextComponent.of("ADMIN", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimListConsumer(src, user, ClaimTypes.ADMIN, worldUniqueId))))
.hoverEvent(HoverEvent.showText(adminShowText)).build();
Component basicTypeText = TextComponent.builder("")
.append(type == ClaimTypes.BASIC ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("BASIC", TextColor.YELLOW)
.append(whiteCloseBracket).build() : TextComponent.of("BASIC", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimListConsumer(src, user, ClaimTypes.BASIC, worldUniqueId))))
.hoverEvent(HoverEvent.showText(basicShowText)).build();
Component subTypeText = TextComponent.builder("")
.append(type == ClaimTypes.SUBDIVISION ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("SUBDIVISION", TextColor.AQUA)
.append(whiteCloseBracket).build() : TextComponent.of("SUBDIVISION", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimListConsumer(src, user, ClaimTypes.SUBDIVISION, worldUniqueId))))
.hoverEvent(HoverEvent.showText(subdivisionShowText)).build();
Component townTypeText = TextComponent.builder("")
.append(type == ClaimTypes.TOWN ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("TOWN", TextColor.GREEN)
.append(whiteCloseBracket).build() : TextComponent.of("TOWN", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createClaimListConsumer(src, user, ClaimTypes.TOWN, worldUniqueId))))
.hoverEvent(HoverEvent.showText(townShowText)).build();
Component claimListHead = TextComponent.builder("")
.append(" Displaying : ", TextColor.AQUA)
.append(ownedTypeText)
.append(" ")
.append(adminTypeText)
.append(" ")
.append(basicTypeText)
.append(" ")
.append(subTypeText)
.append(" ")
.append(townTypeText).build();
final int fillSize = 20 - (claimsTextList.size() + 2);
for (int i = 0; i < fillSize; i++) {
claimsTextList.add(TextComponent.of(" "));
}
PaginationList paginationList = PaginationList.builder()
.title(claimListHead).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(claimsTextList).build();
Integer activePage = 1;
if (src instanceof Player) {
final Player player = (Player) src;
activePage = PaginationUtil.getInstance().getActivePage(player.getUniqueId());
if (activePage == null) {
activePage = 1;
}
this.lastActiveClaimTypeMap.put(player.getUniqueId(), type == null ? "ALL" : type.toString());
}
paginationList.sendTo(src, activePage);
}
private Consumer<CommandSender> createClaimListConsumer(Player src, GDPermissionUser user, String type, UUID worldUniqueId) {
return consumer -> {
if (type.equalsIgnoreCase("ALL")) {
this.displayOwned = false;
} else {
this.displayOwned = true;
}
showClaimList(src, user, null, worldUniqueId);
};
}
private Consumer<CommandSender> createClaimListConsumer(Player src, GDPermissionUser user, ClaimType type, UUID worldUniqueId) {
return consumer -> {
this.displayOwned = false;
showClaimList(src, user, type, worldUniqueId);
};
}
}

View File

@ -0,0 +1,72 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SET_CLAIM_NAME)
public class CommandClaimName extends BaseCommand {
@CommandAlias("claimname")
@Syntax("<name>")
@Subcommand("claim name")
public void execute(Player player, String name) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component result = claim.allowEdit(player);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
final Component text = LegacyComponentSerializer.legacy().deserialize(name, '&');
if (text == TextComponent.empty()) {
claim.getInternalClaimData().setName(null);
} else {
claim.getInternalClaimData().setName(text);
}
claim.getInternalClaimData().setRequiresSave(true);
final Component message = GriefDefenderPlugin.getInstance().messageData.commandClaimName
.apply(ImmutableMap.of(
"name", text)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,251 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ClaimContexts;
import com.griefdefender.api.permission.Context;
import com.griefdefender.api.permission.option.Option;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.registry.OptionRegistryModule;
import com.griefdefender.util.CauseContextHelper;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.entity.Player;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_OPTIONS_BASE)
public class CommandClaimOption extends BaseCommand {
private GDPermissionHolder subject = GriefDefenderPlugin.DEFAULT_HOLDER;
private ClaimSubjectType subjectType = ClaimSubjectType.GLOBAL;
private String friendlySubjectName;
@CommandAlias("cop|claimoption")
@Description("Gets/Sets claim options in the claim you are standing in.")
@Syntax("[<option> <value> [context[key=value]]")
@Subcommand("option claim")
public void execute(Player player, @Optional String[] args) throws CommandException, InvalidCommandArgument {
this.subject = PermissionHolderCache.getInstance().getOrCreateUser(player);
String commandOption = null;
Double optionValue = null;
String contexts = null;
Option option = null;
if (args.length > 0) {
if (args.length < 2) {
throw new InvalidCommandArgument();
}
commandOption = args[0];
option = OptionRegistryModule.getInstance().getById(commandOption).orElse(null);
// Check if global option
if (option != null && option.isGlobal() && !player.hasPermission(GDPermissions.MANAGE_GLOBAL_OPTIONS)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionGlobalOption.toText());
return;
}
try {
optionValue = Double.parseDouble(args[1]);
} catch (NumberFormatException e) {
TextAdapter.sendComponent(player, TextComponent.of("Invalid number ' " + args[1] + "' entered.", TextColor.RED));
throw new InvalidCommandArgument();
}
if (args.length == 3) {
contexts = args[2];
}
}
/*if (contexts != null && !contexts.equalsIgnoreCase("default")) {
final Text message = GriefDefenderPlugin.getInstance().messageData.contextInvalid
.apply(ImmutableMap.of(
"context", context)).build();
GriefDefenderPlugin.sendMessage(src, message);
return CommandResult.success();
}*/
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Set<Context> contextSet = CauseContextHelper.generateContexts(player, claim, contexts, true);
if (contextSet == null) {
return;
}
boolean isClaimContext = true;
if (!contextSet.isEmpty()) {
Iterator<Context> iter = contextSet.iterator();
while (iter.hasNext()) {
final Context context = iter.next();
if (context.getKey().equals("player")) {
final String playerName = context.getValue();
final GDPermissionHolder user = PermissionHolderCache.getInstance().getOrCreateUser(playerName);
if (user == null) {
TextAdapter.sendComponent(player, TextComponent.of("Could not locate player with name '" + playerName + "'."));
return;
}
this.subject = user;
this.subjectType = ClaimSubjectType.PLAYER;
this.friendlySubjectName = playerName;
iter.remove();
} else if (context.getKey().equals("group")) {
final String groupName = context.getValue();
final GDPermissionHolder group = PermissionHolderCache.getInstance().getOrCreateHolder(groupName);
if (group == null) {
TextAdapter.sendComponent(player, TextComponent.of("Could not locate group with name '" + groupName + "'."));
return;
}
this.subject = group;
this.subjectType = ClaimSubjectType.GROUP;
this.friendlySubjectName = groupName;
iter.remove();
} else if (context.getKey().equals("default")) {
isClaimContext = false;
}
}
}
if (option != null && !option.isGlobal()) {
if (claim.isSubdivision()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandOptionInvalidClaim.toText());
return;
}
if (!playerData.canManageOption(player, claim, true)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionGroupOption.toText());
return;
}
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimManage
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
if (claim.isWilderness() && !player.hasPermission(GDPermissions.MANAGE_WILDERNESS)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
} else if (claim.isAdminClaim() && !player.hasPermission(GDPermissions.COMMAND_ADMIN_CLAIMS)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
// Validate new value against admin set value
if (option != null && optionValue != null && isClaimContext) {
Double tempValue = GDPermissionManager.getInstance().getInternalOptionValue(player, option, claim, playerData);
if (tempValue > optionValue || tempValue < optionValue) {
final Component message2 = GriefDefenderPlugin.getInstance().messageData.commandOptionExceedsAdmin
.apply(ImmutableMap.of(
"original_value", optionValue,
"admin_value", tempValue)).build();
GriefDefenderPlugin.sendMessage(player, message2);
return;
}
contextSet.add(claim.getContext());
}
}
if (option == null || optionValue == null) {
List<Component> optionList = Lists.newArrayList();
contextSet.add(ClaimContexts.GLOBAL_DEFAULT_CONTEXT);
Map<String, String> options = PermissionUtil.getInstance().getTransientOptions(claim, GriefDefenderPlugin.DEFAULT_HOLDER, contextSet);
for (Map.Entry<String, String> optionEntry : options.entrySet()) {
String value = optionEntry.getValue();
Component optionText = TextComponent.builder("")
.append(optionEntry.getKey(), TextColor.GREEN)
.append(" ")
.append(value, TextColor.GOLD).build();
optionList.add(optionText);
}
List<Component> finalTexts = CommandHelper.stripeText(optionList);
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of("Claim Options")).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(finalTexts);
paginationBuilder.sendTo(player);
return;
}
final Option subjectOption = option;
final Double subjectOptionValue = optionValue;
boolean result = PermissionUtil.getInstance().setOptionValue(this.subject, option.getPermission(), optionValue.toString(), contextSet);
if (!result) {
TextAdapter.sendComponent(player, TextComponent.of("The permission plugin failed to set the option.", TextColor.RED));
return;
}
if (contextSet.isEmpty()) {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append("Set ")
.append("default", TextColor.LIGHT_PURPLE)
.append(" option ")
.append(subjectOption.getName().toLowerCase(), TextColor.AQUA)
.append(" to ")
.append(String.valueOf(subjectOptionValue), TextColor.GREEN).build());
} else {
if (this.subjectType == ClaimSubjectType.GROUP) {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append("Set option ")
.append(subjectOption.getName().toLowerCase(), TextColor.AQUA)
.append(" to ")
.append(String.valueOf(subjectOptionValue), TextColor.GREEN)
.append(" on group ")
.append(this.subject.getFriendlyName(), TextColor.GOLD)
.append(".").build());
} else {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append("Set option ")
.append(subjectOption.getName().toLowerCase(), TextColor.AQUA)
.append(" to ")
.append(String.valueOf(subjectOptionValue), TextColor.GREEN)
.append(" on user ")
.append(this.subject.getFriendlyName(), TextColor.GOLD)
.append(".").build());
}
}
}
}

View File

@ -0,0 +1,141 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.permission.Context;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_PERMISSION_GROUP)
public class CommandClaimPermissionGroup extends BaseCommand {
@CommandAlias("cpg")
@Description("Sets a permission on a group with a claim context.")
@Syntax("<group> [<permission> <value>]")
@Subcommand("permission group")
public void execute(Player player, String group, @Optional String[] args) throws CommandException, InvalidCommandArgument {
String permission = null;
String value = null;
if (args.length > 0) {
if (args.length < 2) {
throw new InvalidCommandArgument();
}
permission = args[0];
if (permission != null && !player.hasPermission(permission)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionAssignWithoutHaving.toText());
return;
}
value = args[1];
}
if (!PermissionUtil.getInstance().hasGroupSubject(group)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandGroupInvalid.toText());
return;
}
final GDPermissionHolder subj = PermissionHolderCache.getInstance().getOrCreateHolder(group);
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimManage
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
if (claim.isWilderness() && !playerData.canManageWilderness) {
GriefDefenderPlugin.sendMessage(player, message);
return;
} else if (claim.isAdminClaim() && !playerData.canManageAdminClaims) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
Set<Context> contexts = new HashSet<>();
contexts.add(claim.getContext());
if (permission == null || value == null) {
List<Component> permList = Lists.newArrayList();
Map<String, Boolean> permissions = PermissionUtil.getInstance().getPermissions(subj, contexts);
for (Map.Entry<String, Boolean> permissionEntry : permissions.entrySet()) {
Boolean permValue = permissionEntry.getValue();
Component permText = TextComponent.builder("")
.append(permissionEntry.getKey(), TextColor.GREEN)
.append(" ")
.append(permValue.toString(), TextColor.GOLD).build();
permList.add(permText);
}
List<Component> finalTexts = CommandHelper.stripeText(permList);
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of(subj.getFriendlyName() + " Permissions", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(finalTexts);
paginationBuilder.sendTo(player);
}
Tristate tristateValue = PermissionUtil.getInstance().getTristateFromString(value);
if (tristateValue == null) {
TextAdapter.sendComponent(player, TextComponent.of("Invalid value entered. '" + value + "' is not a valid value. Valid values are : true, false, undefined, 1, -1, or 0.", TextColor.RED));
return;
}
PermissionUtil.getInstance().setPermissionValue((GDClaim) claim, subj, permission, tristateValue, contexts);
TextAdapter.sendComponent(player, TextComponent.builder("")
.append("Set permission ")
.append(permission, TextColor.AQUA)
.append(" to ")
.append(value, TextColor.GREEN)
.append(" on group ")
.append(subj.getFriendlyName(), TextColor.GOLD)
.append(".").build());
}
}

View File

@ -0,0 +1,138 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.permission.Context;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_PERMISSION_PLAYER)
public class CommandClaimPermissionPlayer extends BaseCommand {
@CommandAlias("cpp")
@Description("Sets a permission on a player with a claim context.")
@Syntax("<player> [<permission> <value>]")
@Subcommand("permission player")
public void execute(Player player, OfflinePlayer otherPlayer, @Optional String[] args) throws CommandException, InvalidCommandArgument {
String permission = null;
String value = null;
if (args.length > 0) {
if (args.length < 2) {
throw new InvalidCommandArgument();
}
permission = args[0];
if (permission != null && !player.hasPermission(permission)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionAssignWithoutHaving.toText());
return;
}
value = args[1];
}
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimManage
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
if (claim.isWilderness() && !playerData.canManageWilderness) {
GriefDefenderPlugin.sendMessage(player, message);
return;
} else if (claim.isAdminClaim() && !playerData.canManageAdminClaims) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
final GDPermissionHolder holder = PermissionHolderCache.getInstance().getOrCreateUser(player);
Set<Context> contexts = new HashSet<>();
contexts.add(claim.getContext());
if (permission == null || value == null) {
// display current permissions for user
List<Component> permList = Lists.newArrayList();
Map<String, Boolean> permissions = PermissionUtil.getInstance().getPermissions(holder, contexts);
for (Map.Entry<String, Boolean> permissionEntry : permissions.entrySet()) {
Boolean permValue = permissionEntry.getValue();
Component permText = TextComponent.builder("")
.append(permissionEntry.getKey(), TextColor.GREEN)
.append(" ")
.append(permValue.toString(), TextColor.GOLD).build();
permList.add(permText);
}
List<Component> finalTexts = CommandHelper.stripeText(permList);
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of(otherPlayer.getName() + " Permissions", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(finalTexts);
paginationBuilder.sendTo(player);
}
Tristate tristateValue = PermissionUtil.getInstance().getTristateFromString(value);
if (tristateValue == null) {
TextAdapter.sendComponent(player, TextComponent.of("Invalid value entered. '" + value + "' is not a valid value. Valid values are : true, false, undefined, 1, -1, or 0.", TextColor.RED));
return;
}
PermissionUtil.getInstance().setPermissionValue((GDClaim) claim, holder, permission, tristateValue, contexts);
TextAdapter.sendComponent(player, TextComponent.builder("")
.append("Set permission ")
.append(permission, TextColor.AQUA)
.append(" to ")
.append(value, TextColor.GREEN)
.append(" on user ")
.append(otherPlayer.getName(), TextColor.GOLD)
.append(".").build());
}
}

View File

@ -0,0 +1,158 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimSchematic;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.text.action.GDCallbackHolder;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.sql.Date;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_SCHEMATIC)
public class CommandClaimSchematic extends BaseCommand {
@CommandAlias("claimschematic")
@Description("Manages claim schematics. Use '/claimschematic create <name>' to create a live backup of claim.")
@Syntax("<create|delete> <name>")
@Subcommand("schematic")
public void execute(Player player, @Optional String[] args) throws CommandException, InvalidCommandArgument {
if (GriefDefenderPlugin.getInstance().getWorldEditProvider() == null) {
TextAdapter.sendComponent(player, TextComponent.of("This command requires WorldEdit to be running on server.", TextColor.RED));
return;
}
String action = null;
String name = null;
if (args.length > 0) {
action = args[0];
if (args.length < 2) {
throw new InvalidCommandArgument();
}
name = args[1];
}
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component denyMessage = claim.allowEdit(player);
if (denyMessage != null) {
GriefDefenderPlugin.sendMessage(player, denyMessage);
return;
}
if (action == null) {
if (claim.schematics.isEmpty()) {
TextAdapter.sendComponent(player, TextComponent.of("There are no schematic backups for this claim.", TextColor.RED));
return;
}
List<Component> schematicTextList = new ArrayList<>();
for (ClaimSchematic schematic : claim.schematics.values()) {
final String schematicName = schematic.getName();
final Instant schematicDate = schematic.getDateCreated();
schematicTextList.add(
TextComponent.builder("")
.append(schematicName, TextColor.GREEN)
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(displayConfirmationConsumer(player, claim, schematic))))
.hoverEvent(HoverEvent.showText(
TextComponent.builder("")
.append("Click here to restore claim schematic.\n")
.append("Name", TextColor.YELLOW)
.append(": ")
.append(schematicName, TextColor.GREEN)
.append("\n")
.append("Created", TextColor.YELLOW)
.append(": ")
.append(Date.from(schematicDate).toString(), TextColor.AQUA).build()))
.build());
}
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of("Schematics", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(schematicTextList);
paginationBuilder.sendTo(player);
} else if (action.equalsIgnoreCase("create")) {
TextAdapter.sendComponent(player, TextComponent.of("Creating schematic backup...", TextColor.GREEN));
final ClaimSchematic schematic = ClaimSchematic.builder().claim(claim).name(name).build().orElse(null);
if (schematic != null) {
TextAdapter.sendComponent(player, TextComponent.of("Schematic backup complete.", TextColor.GREEN));
} else {
TextAdapter.sendComponent(player, TextComponent.of("Schematic could not be created.", TextColor.GREEN));
}
} else if (action.equalsIgnoreCase("delete")) {
claim.deleteSchematic(name);
TextAdapter.sendComponent(player, TextComponent.of("Schematic '" + name + "' has been deleted.", TextColor.GREEN));
}
}
private static Consumer<CommandSender> displayConfirmationConsumer(CommandSender src, Claim claim, ClaimSchematic schematic) {
return confirm -> {
final Component schematicConfirmationText = TextComponent.builder("")
.append("\n[")
.append("Confirm", TextColor.GREEN)
.append("]\n")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createConfirmationConsumer(src, claim, schematic))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Clicking confirm will restore ALL claim data with schematic. Use cautiously!"))).build();
TextAdapter.sendComponent(src, schematicConfirmationText);
};
}
private static Consumer<CommandSender> createConfirmationConsumer(CommandSender src, Claim claim, ClaimSchematic schematic) {
return confirm -> {
schematic.apply();
final Component message = GriefDefenderPlugin.getInstance().messageData.schematicRestoreConfirmed
.apply(ImmutableMap.of(
"schematic_name", schematic.getName())).build();
GriefDefenderPlugin.sendMessage(src, message);
};
}
}

View File

@ -0,0 +1,133 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.configuration.MessageStorage;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.text.action.GDCallbackHolder;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.format.TextColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Map;
import java.util.function.Consumer;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_SELL)
public class CommandClaimSell extends BaseCommand {
@CommandAlias("claimsell")
@Description("Puts your claim up for sale. Use /claimsell amount.\nNote: Requires economy plugin.")
@Syntax("<amount> | cancel")
@Subcommand("sell claim")
public void execute(Player player, String arg) throws InvalidCommandArgument {
// if economy is disabled, don't do anything
if (GriefDefenderPlugin.getInstance().getVaultProvider() == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyNotInstalled.toText());
return;
}
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
if (claim.isAdminClaim() || claim.isWilderness()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyClaimNotForSale.toText());
return;
}
if (!playerData.canIgnoreClaim(claim) && !player.getUniqueId().equals(claim.getOwnerUniqueId())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionClaimSale.toText());
return;
}
Double salePrice = null;
if (!claim.getEconomyData().isForSale()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyClaimNotForSale.toText());
return;
}
if (arg.equalsIgnoreCase("cancel")) {
claim.getEconomyData().setForSale(false);
claim.getEconomyData().setSalePrice(-1);
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyClaimSaleCancelled.toText());
return;
} else {
try {
salePrice = Double.parseDouble(arg);
} catch (NumberFormatException e) {
throw new InvalidCommandArgument();
}
}
if (salePrice == null || salePrice < 0) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyClaimSaleInvalidPrice
.apply(ImmutableMap.of(
"sale_price", salePrice)).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
final Component message = GriefDefenderPlugin.getInstance().messageData.economyClaimSaleConfirmation
.apply(ImmutableMap.of(
"sale_price", salePrice)).build();
GriefDefenderPlugin.sendMessage(player, message);
final Component saleConfirmationText = TextComponent.builder("")
.append("\n[")
.append("Confirm", TextColor.GREEN)
.append("]\n")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createSaleConfirmationConsumer(player, claim, salePrice))))
.build();
GriefDefenderPlugin.sendMessage(player, saleConfirmationText);
return;
}
private static Consumer<CommandSender> createSaleConfirmationConsumer(CommandSender src, Claim claim, double price) {
return confirm -> {
claim.getEconomyData().setSalePrice(price);
claim.getEconomyData().setForSale(true);
claim.getData().save();
Map<String, ?> params = ImmutableMap.of(
"sale_price", price);
GriefDefenderPlugin.sendMessage(src, MessageStorage.ECONOMY_CLAIM_SALE_CONFIRMED, GriefDefenderPlugin.getInstance().messageData.economyClaimSaleConfirmed, params);
};
}
}

View File

@ -0,0 +1,122 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SELL_CLAIM_BLOCKS)
public class CommandClaimSellBlocks extends BaseCommand {
@CommandAlias("sellblocks")
@Description("Sell your claim blocks for server money.\nNote: Requires economy plugin.")
@Syntax("[<amount>]")
@Subcommand("sell blocks")
public void execute(Player player, @Optional Integer blockCount) {
if (GriefDefenderPlugin.getGlobalConfig().getConfig().economy.economyMode) {
TextAdapter.sendComponent(player, TextComponent.of("This command is not available while server is in economy mode.", TextColor.RED));
return;
}
// if economy is disabled, don't do anything
if (GriefDefenderPlugin.getInstance().getVaultProvider() == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyNotInstalled.toText());
return;
}
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
if (playerData.getEconomyClaimBlockCost() == 0 && playerData.getEconomyClaimBlockReturn() == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyBuySellNotConfigured.toText());
return;
}
// if selling disabled, send error message
if (playerData.getEconomyClaimBlockReturn() == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyOnlyBuyBlocks.toText());
return;
}
int availableBlocks = playerData.getRemainingClaimBlocks();
if (blockCount == null) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyBlockPurchaseCost
.apply(ImmutableMap.of(
"cost", playerData.getEconomyClaimBlockReturn(),
"balance", availableBlocks)).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
} else {
// try to parse number of blocks
if (blockCount <= 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyBuyInvalidBlockCount.toText());
return;
} else if (blockCount > availableBlocks) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.economyBlocksNotAvailable.toText());
return;
}
// attempt to compute value and deposit it
double totalValue = blockCount * playerData.getEconomyClaimBlockReturn();
/*TransactionResult
transactionResult =
GriefDefenderPlugin.getInstance().economyService.get().getOrCreateAccount(player.getUniqueId()).get().deposit
(GriefDefenderPlugin.getInstance().economyService.get().getDefaultCurrency(), BigDecimal.valueOf(totalValue),
Sponge.getCauseStackManager().getCurrentCause());
if (transactionResult.getResult() != ResultType.SUCCESS) {
final Component message = GriefDefenderPlugin.getInstance().messageData.economyBlockSellError
.apply(ImmutableMap.of(
"reason", transactionResult.getResult().name())).build();
GriefDefenderPlugin.sendMessage(player, message);
return CommandResult.success();
}
// subtract blocks
playerData.setBonusClaimBlocks(playerData.getBonusClaimBlocks() - blockCount);
playerData.getStorageData().save();*/
final Component message = GriefDefenderPlugin.getInstance().messageData.economyBlockSaleConfirmation
.apply(ImmutableMap.of(
"deposit", totalValue,
"remaining-blocks", playerData.getRemainingClaimBlocks())).build();
// inform player
GriefDefenderPlugin.sendMessage(player, message);
}
}
}

View File

@ -0,0 +1,64 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Subcommand;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.util.VecHelper;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_SET_SPAWN)
public class CommandClaimSetSpawn extends BaseCommand {
@CommandAlias("claimsetspawn")
@Subcommand("claim setspawn")
public void execute(Player player, String[] args) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
final Component result = claim.allowEdit(player);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
final Vector3i pos = VecHelper.toVector3i(player.getLocation());
claim.getInternalClaimData().setSpawnPos(pos);
final Component message = GriefDefenderPlugin.getInstance().messageData.commandSpawnSet
.apply(ImmutableMap.of(
"location", pos)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,69 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.flowpowered.math.vector.Vector3i;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import org.bukkit.Location;
import org.bukkit.entity.Player;
@CommandAlias("gd|griefdefender")
public class CommandClaimSpawn extends BaseCommand {
@CommandAlias("claimspawn")
@Description("Teleports you to claim spawn if available.")
@Subcommand("claim spawn")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (!playerData.canIgnoreClaim(claim) && !claim.isUserTrusted(player, TrustTypes.ACCESSOR) && !player.hasPermission(GDPermissions.COMMAND_DELETE_CLAIMS)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionAccess.toText());
return;
}
final Vector3i spawnPos = claim.getData().getSpawnPos().orElse(null);
if (spawnPos == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandSpawnNotSet.toText());
return;
}
final Location spawnLocation = new Location(claim.getWorld(), spawnPos.getX(), spawnPos.getY(), spawnPos.getZ());
player.teleport(spawnLocation);
final Component message = GriefDefenderPlugin.getInstance().messageData.commandSpawnTeleport
.apply(ImmutableMap.of(
"location", spawnPos)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SUBDIVIDE_CLAIMS)
public class CommandClaimSubdivide extends BaseCommand {
@CommandAlias("modesubdivide")
@Description("Switches the shovel tool to subdivision mode, used to subdivide your claims.")
@Subcommand("mode subdivide")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.shovelMode = ShovelTypes.SUBDIVISION;
playerData.claimSubdividing = null;
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimModeSubdivision.toText());
}
}

View File

@ -0,0 +1,52 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TOWN_MODE)
public class CommandClaimTown extends BaseCommand {
@CommandAlias("modetown")
@Description("Switches the shovel tool to town claims mode.")
@Subcommand("mode town")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.shovelMode = ShovelTypes.TOWN;
playerData.claimSubdividing = null;
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimModeTown.toText());
}
}

View File

@ -0,0 +1,77 @@
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ClaimResult;
import com.griefdefender.api.claim.ClaimResultType;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.api.data.PlayerData;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import java.util.UUID;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TRANSFER_CLAIM)
public class CommandClaimTransfer extends BaseCommand {
@CommandAlias("claimtransfer|transferclaim")
@Description("Transfers a basic or admin claim to another player.")
@Subcommand("claim transfer")
public void execute(Player player, OfflinePlayer otherPlayer) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (claim == null || claim.isWilderness()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotFound.toText());
return;
}
final UUID ownerId = claim.getOwnerUniqueId();
final boolean isAdmin = playerData.canIgnoreClaim(claim);
// check permission
if (!isAdmin && claim.isAdminClaim() && !player.hasPermission(GDPermissions.COMMAND_ADMIN_CLAIMS)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionClaimTransferAdmin.toText());
return;
} else if (!isAdmin && !player.getUniqueId().equals(ownerId) && claim.isUserTrusted(player, TrustTypes.MANAGER)) {
if (claim.parent == null) {
// Managers can only transfer child claims
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotYours.toText());
return;
}
} else if (!isAdmin && !claim.isAdminClaim() && !player.getUniqueId().equals(ownerId)) {
// verify ownership
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotYours.toText());
return;
}
// change ownership
final ClaimResult claimResult = claim.transferOwner(otherPlayer.getUniqueId());
if (!claimResult.successful()) {
PlayerData targetPlayerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), otherPlayer.getUniqueId());
if (claimResult.getResultType() == ClaimResultType.INSUFFICIENT_CLAIM_BLOCKS) {
TextAdapter.sendComponent(player, TextComponent.of("Could not transfer claim to player with UUID " + otherPlayer.getUniqueId() + "."
+ " Player only has " + targetPlayerData.getRemainingClaimBlocks() + " claim blocks remaining."
+ " The claim requires a total of " + claim.getClaimBlocks() + " claim blocks to own.", TextColor.RED));
} else if (claimResult.getResultType() == ClaimResultType.WRONG_CLAIM_TYPE) {
TextAdapter.sendComponent(player, TextComponent.of("The wilderness claim cannot be transferred.", TextColor.RED));
} else if (claimResult.getResultType() == ClaimResultType.CLAIM_EVENT_CANCELLED) {
TextAdapter.sendComponent(player, TextComponent.of("Could not transfer the claim. A plugin has cancelled the TransferClaimEvent.", TextColor.RED));
} else {
TextAdapter.sendComponent(player, TextComponent.of("Could not transfer the claim. " + claimResult.getResultType().name(), TextColor.RED));
}
} else {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimTransferSuccess.toText());
}
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_CLAIM_WORLDEDIT)
public class CommandClaimWorldEdit extends BaseCommand {
@CommandAlias("claim")
@Description("Uses the worldedit selection to create a claim.")
@Subcommand("claim worldedit|claim we")
public void execute(Player player) {
if (GriefDefenderPlugin.getInstance().getWorldEditProvider() == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandCreateWorldEdit.toText());
return;
}
GriefDefenderPlugin.getInstance().getWorldEditProvider().createClaim(player);
}
}

View File

@ -0,0 +1,116 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.griefdefender.GDDebugData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_ADMIN_DEBUG)
public class CommandDebug extends BaseCommand {
@CommandAlias("gddebug")
@Description("Captures all GD actions for debugging purposes.")
@Syntax("<record|paste|on|off> [filter]")
@Subcommand("debug")
public void execute(CommandSender src, String target, @Optional OfflinePlayer targetPlayer) {
GDDebugData debugData = null;
boolean paste = false;
if (target.equalsIgnoreCase("on")) {
debugData = getOrCreateDebugUser(src, targetPlayer, true);
} else if (target.equalsIgnoreCase("record")) {
debugData = getOrCreateDebugUser(src, targetPlayer, false);
} else if (target.equalsIgnoreCase("paste")) {
paste = true;
} else if (target.equalsIgnoreCase("off")) {
GriefDefenderPlugin.getInstance().getDebugUserMap().remove(src.getName());
if (GriefDefenderPlugin.getInstance().getDebugUserMap().isEmpty()) {
GriefDefenderPlugin.debugActive = false;
}
}
if (debugData == null) {
if (paste) {
debugData = GriefDefenderPlugin.getInstance().getDebugUserMap().get(src.getName());
if (debugData == null) {
TextAdapter.sendComponent(src, TextComponent.of("Nothing to paste!", TextColor.RED));
} else {
debugData.pasteRecords();
}
}
TextAdapter.sendComponent(src, TextComponent.builder("")
.append(GriefDefenderPlugin.GD_TEXT)
.append("Debug ", TextColor.GRAY)
.append("OFF", TextColor.RED)
.build());
GriefDefenderPlugin.getInstance().getDebugUserMap().remove(src.getName());
if (GriefDefenderPlugin.getInstance().getDebugUserMap().isEmpty()) {
GriefDefenderPlugin.debugActive = false;
}
} else {
TextAdapter.sendComponent(src, TextComponent.builder("")
.append(GriefDefenderPlugin.GD_TEXT)
.append("Debug: ", TextColor.GRAY)
.append("ON", TextColor.GREEN)
.append(" | ")
.append("Verbose: ", TextColor.GRAY)
.append(!debugData.isRecording() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))
.append(" | ")
.append("Record: ", TextColor.GRAY)
.append(debugData.isRecording() ? TextComponent.of("ON", TextColor.GREEN) : TextComponent.of("OFF", TextColor.RED))
.append(" | ")
.append("User: ", TextColor.GRAY)
.append(targetPlayer == null ? "ALL" : targetPlayer.getName(), TextColor.GOLD)
.build());
GriefDefenderPlugin.getInstance().getDebugUserMap().put(src.getName(), debugData);
}
}
private GDDebugData getOrCreateDebugUser(CommandSender src, OfflinePlayer user, boolean verbose) {
GDDebugData debugData = GriefDefenderPlugin.getInstance().getDebugUserMap().get(src.getName());
if (debugData == null) {
debugData = new GDDebugData(src, user, verbose);
GriefDefenderPlugin.getInstance().getDebugUserMap().put(src.getName(), debugData);
} else {
debugData.setTarget(user);
debugData.setVerbose(verbose);
}
GriefDefenderPlugin.debugActive = true;
return debugData;
}
}

View File

@ -0,0 +1,92 @@
/*
* This file is part of SpongeAPI, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import net.kyori.text.Component;
/**
* Thrown when an executed command raises an error or when execution of
* the command failed.
*/
public class CommandException extends ComponentMessageException {
private static final long serialVersionUID = 4626722485860074825L;
private final boolean includeUsage;
/**
* Constructs a new {@link CommandException} with the given message.
*
* @param message The detail message
*/
public CommandException(Component message) {
this(message, false);
}
/**
* Constructs a new {@link CommandException} with the given message and
* the given cause.
*
* @param message The detail message
* @param cause The cause
*/
public CommandException(Component message, Throwable cause) {
this(message, cause, false);
}
/**
* Constructs a new {@link CommandException} with the given message.
*
* @param message The detail message
* @param includeUsage Whether to include usage in the exception
*/
public CommandException(Component message, boolean includeUsage) {
super(message);
this.includeUsage = includeUsage;
}
/**
* Constructs a new {@link CommandException} with the given message and
* the given cause.
*
* @param message The detail message
* @param cause The cause
* @param includeUsage Whether to include the usage in the exception
*/
public CommandException(Component message, Throwable cause, boolean includeUsage) {
super(message, cause);
this.includeUsage = includeUsage;
}
/**
* Gets whether the exception should include usage in
* the presentation of the exception/stack-trace.
*
* @return Whether to include usage in the exception
*/
public boolean shouldIncludeUsage() {
return this.includeUsage;
}
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.command.CommandSender;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_RELOAD)
public class CommandGDReload extends BaseCommand {
@CommandAlias("gdreload")
@Description("Reloads GriefDefender's configuration settings.")
@Subcommand("reload")
public void execute(CommandSender src) {
GriefDefenderPlugin.getInstance().loadConfig();
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.pluginReload.toText());
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_VERSION)
public class CommandGDVersion extends BaseCommand {
@CommandAlias("gdversion")
@Description("Displays GriefDefender's version information.")
@Subcommand("version")
public void execute(CommandSender src) {
String version = GriefDefenderPlugin.IMPLEMENTATION_VERSION;
if (version == null) {
version = "unknown";
}
Component gpVersion = TextComponent.builder("")
.append(GriefDefenderPlugin.GD_TEXT)
.append("Running ")
// TODO : Use version from manifest
.append("GriefDefender " + GriefDefenderPlugin.VERSION, TextColor.AQUA)
.build();
Component bukkitVersion = TextComponent.builder("")
.append(GriefDefenderPlugin.GD_TEXT)
.append("Running ")
.append(Bukkit.getVersion(), TextColor.YELLOW)
.build();
String permissionPlugin = Bukkit.getPluginManager().getPlugin("LuckPerms").getDescription().getFullName();
Component permVersion = TextComponent.builder("")
.append(GriefDefenderPlugin.GD_TEXT)
.append("Running ")
.append(permissionPlugin, TextColor.GREEN)
.build();
TextAdapter.sendComponent(src, TextComponent.builder("")
.append(gpVersion)
.append("\n")
.append(bukkitVersion)
.append("\n")
.append(permVersion)
.build());
}
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.HelpCommand;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.command.CommandSender;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_HELP)
public class CommandHelp extends BaseCommand {
@HelpCommand
@Description("Displays GriefDefender command help.")
public void execute(CommandSender src) {
PaginationList.Builder paginationBuilder =
PaginationList.builder().title(TextComponent.of("Showing GriefDefender Help", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(GriefDefenderPlugin.helpComponents);
paginationBuilder.sendTo(src);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,37 @@
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.Description;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import org.bukkit.command.CommandSender;
import com.griefdefender.internal.pagination.ActivePagination;
import com.griefdefender.internal.pagination.GDPaginationHolder;
public class CommandPagination extends BaseCommand {
@CommandAlias("gd:pagination")
@Description("Used internally by GD for pagination purposes.")
public void execute(CommandSender src, String[] args) throws CommandException {
String id = args[0];
final ActivePagination activePagination = GDPaginationHolder.getInstance().getActivePagination(src, id);
if (activePagination == null) {
throw new CommandException(TextComponent.of("Source " + src.getName() + " has no paginations!", TextColor.RED));
}
String action = args[1];
if (action.equals("page")) {
activePagination.currentPage();
} else if (action.equals("next")) {
activePagination.nextPage();
} else if (action.equals("prev")) {
activePagination.previousPage();
} else {
int page = Integer.parseInt(action);
activePagination.specificPage(page);
}
}
}

View File

@ -0,0 +1,307 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.Lists;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimBlockSystem;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.storage.BaseStorage;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_PLAYER_INFO_BASE)
public class CommandPlayerInfo extends BaseCommand {
@CommandAlias("playerinfo")
@Description("Gets information about a player.")
@Syntax("[<player>|<player> <world>]")
@Subcommand("player info")
public void execute(CommandSender src, @Optional String[] args) throws InvalidCommandArgument {
OfflinePlayer user = null;
World world = null;
if (args.length > 0) {
user = Bukkit.getServer().getOfflinePlayer(args[0]);
if (user == null) {
TextAdapter.sendComponent(src, TextComponent.of("User ' " + args[0] + "' could not be found.", TextColor.RED));
throw new InvalidCommandArgument();
}
if (args.length > 1) {
world = Bukkit.getServer().getWorld(args[1]);
if (world == null) {
TextAdapter.sendComponent(src, TextComponent.of("World ' " + args[1] + "' could not be found.", TextColor.RED));
throw new InvalidCommandArgument();
}
}
}
if (user == null) {
if (!(src instanceof Player)) {
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.commandPlayerInvalid.toText());
return;
}
user = (OfflinePlayer) src;
if (world == null) {
world = ((Player) user).getWorld();
}
}
if (world == null) {
world = Bukkit.getServer().getWorlds().get(0);
}
// otherwise if no permission to delve into another player's claims data or self
if ((user != null && user != src && !src.hasPermission(GDPermissions.COMMAND_PLAYER_INFO_OTHERS))) {
TextAdapter.sendComponent(src, TextComponent.of("No permission to view other players.", TextColor.RED));
}
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(world.getUID(), user.getUniqueId());
boolean useGlobalData = BaseStorage.USE_GLOBAL_PLAYER_STORAGE;
List<Claim> claimList = new ArrayList<>();
for (Claim claim : playerData.getInternalClaims()) {
if (useGlobalData) {
claimList.add(claim);
} else {
if (claim.getWorldUniqueId().equals(world.getUID())) {
claimList.add(claim);
}
}
}
Component claimSizeLimit = TextComponent.of("none", TextColor.GRAY);
if (playerData.getMaxClaimX(ClaimTypes.BASIC) != 0 || playerData.getMaxClaimY(ClaimTypes.BASIC) != 0 || playerData.getMaxClaimZ(ClaimTypes.BASIC) != 0) {
claimSizeLimit = TextComponent.of(playerData.getMaxClaimX(ClaimTypes.BASIC) + "," + playerData.getMaxClaimY(ClaimTypes.BASIC) + "," + playerData.getMaxClaimZ(ClaimTypes.BASIC), TextColor.GRAY);
}
final Component WHITE_SEMI_COLON = TextComponent.of(" : ");
final double claimableChunks = GriefDefenderPlugin.CLAIM_BLOCK_SYSTEM == ClaimBlockSystem.VOLUME ? (playerData.getRemainingClaimBlocks() / 65536.0) : (playerData.getRemainingClaimBlocks() / 256.0);
final Component uuidText = TextComponent.builder("")
.append("UUID", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(user.getUniqueId().toString(), TextColor.GRAY)
.build();
final Component worldText = TextComponent.builder("")
.append("World", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(world.getName(), TextColor.GRAY)
.build();
final Component sizeLimitText = TextComponent.builder("")
.append("Claim Size Limits", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(claimSizeLimit)
.build();
final Component initialBlockText = TextComponent.builder("")
.append("Initial Blocks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getInitialClaimBlocks()), TextColor.GREEN)
.build();
final Component accruedBlockText = TextComponent.builder("")
.append("Accrued Blocks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getAccruedClaimBlocks()), TextColor.GREEN)
.append(" (", TextColor.GRAY)
.append(String.valueOf(playerData.getBlocksAccruedPerHour()), TextColor.LIGHT_PURPLE)
.append(" per hour")
.append(")", TextColor.GRAY).build();
final Component maxAccruedBlockText = TextComponent.builder("")
.append("Max Accrued Blocks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getMaxAccruedClaimBlocks()), TextColor.GREEN)
.build();
final Component bonusBlockText = TextComponent.builder("")
.append("Bonus Blocks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getBonusClaimBlocks()), TextColor.GREEN)
.build();
final Component remainingBlockText = TextComponent.builder("")
.append("Remaining Blocks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getRemainingClaimBlocks()), TextColor.GREEN)
.build();
final Component minMaxLevelText = TextComponent.builder("")
.append("Min/Max Claim Level", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getMinClaimLevel() + "-" + playerData.getMaxClaimLevel()), TextColor.GREEN)
.build();
final Component abandonRatioText = TextComponent.builder("")
.append("Abandoned Return Ratio", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getAbandonedReturnRatio(ClaimTypes.BASIC)), TextColor.GREEN)
.build();
final Component totalTaxText = TextComponent.builder("")
.append("Total Tax", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getTotalTax()), TextColor.GREEN)
.build();
final Component totalBlockText = TextComponent.builder("")
.append("Total Blocks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(playerData.getInitialClaimBlocks() + playerData.getAccruedClaimBlocks() + playerData.getBonusClaimBlocks()), TextColor.GREEN)
.build();
final Component totalClaimableChunkText = TextComponent.builder("")
.append("Total Claimable Chunks", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(Math.round(claimableChunks * 100.0)/100.0), TextColor.GREEN)
.build();
final Component totalClaimText = TextComponent.builder("")
.append("Total Claims", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(String.valueOf(claimList.size()), TextColor.GREEN)
.build();
List<Component> claimsTextList = Lists.newArrayList();
claimsTextList.add(uuidText);
claimsTextList.add(worldText);
claimsTextList.add(sizeLimitText);
claimsTextList.add(initialBlockText);
claimsTextList.add(accruedBlockText);
claimsTextList.add(maxAccruedBlockText);
claimsTextList.add(bonusBlockText);
claimsTextList.add(remainingBlockText);
claimsTextList.add(minMaxLevelText);
claimsTextList.add(abandonRatioText);
final int townLimit = playerData.getCreateClaimLimit(ClaimTypes.TOWN);
final int basicLimit = playerData.getCreateClaimLimit(ClaimTypes.BASIC);
final int subLimit = playerData.getCreateClaimLimit(ClaimTypes.SUBDIVISION);
Component claimCreateLimits = TextComponent.builder("")
.append("TOWN", TextColor.GRAY)
.append(" : ")
.append(String.valueOf(townLimit), TextColor.GREEN)
.append(" BASIC", TextColor.GRAY)
.append(" : ")
.append(String.valueOf(basicLimit), TextColor.GREEN)
.append(" SUB", TextColor.GRAY)
.append(" : ")
.append(String.valueOf(subLimit), TextColor.GREEN)
.build();
claimsTextList.add(claimCreateLimits);
if (GriefDefenderPlugin.getGlobalConfig().getConfig().claim.bankTaxSystem) {
Component townTaxRate = TextComponent.builder("")
.append("TOWN", TextColor.GRAY)
.append(" : ")
.append(String.valueOf(playerData.getTaxRate(ClaimTypes.TOWN)), TextColor.GREEN)
.build();
// TODO
//TextColors.GRAY, " BASIC", TextColors.WHITE, " : ", TextColors.GREEN, playerData.optionTaxRateTownBasic,
//TextColors.GRAY, " SUB", TextColors.WHITE, " : ", TextColors.GREEN, playerData.getTaxRate(type));
Component claimTaxRate = TextComponent.builder("")
.append("BASIC", TextColor.GRAY)
.append(" : ")
.append(String.valueOf(playerData.getTaxRate(ClaimTypes.BASIC)), TextColor.GREEN)
.append(" SUB", TextColor.GRAY)
.append(" : ")
.append(String.valueOf(playerData.getTaxRate(ClaimTypes.SUBDIVISION)), TextColor.GREEN)
.build();
Component currentTaxRateText = TextComponent.builder("")
.append("Current Claim Tax Rate", TextColor.YELLOW)
.append(" : ")
.append("N/A", TextColor.RED)
.build();
if (src instanceof Player) {
Player player = (Player) src;
if (player.getUniqueId().equals(user.getUniqueId())) {
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
if (claim != null && !claim.isWilderness()) {
final double playerTaxRate = GDPermissionManager.getInstance().getInternalOptionValue(user, Options.TAX_RATE, claim, playerData);
currentTaxRateText = TextComponent.builder("")
.append("Current Claim Tax Rate", TextColor.YELLOW)
.append(" : ")
.append(String.valueOf(playerTaxRate), TextColor.GREEN)
.build();
}
}
}
final Component globalTownTaxText = TextComponent.builder("")
.append("Global Town Tax Rate", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(townTaxRate)
.build();
final Component globalClaimTaxText = TextComponent.builder("")
.append("Global Claim Tax Rate", TextColor.YELLOW)
.append(WHITE_SEMI_COLON)
.append(claimTaxRate)
.build();
claimsTextList.add(currentTaxRateText);
claimsTextList.add(globalTownTaxText);
claimsTextList.add(globalClaimTaxText);
claimsTextList.add(totalTaxText);
}
claimsTextList.add(totalBlockText);
claimsTextList.add(totalClaimableChunkText);
claimsTextList.add(totalClaimText);
if (NMSUtil.getInstance().getLastLogin(user) != 0) {
Date lastActive = null;
try {
lastActive = new Date(NMSUtil.getInstance().getLastLogin(user));
} catch(DateTimeParseException ex) {
// ignore
}
if (lastActive != null) {
claimsTextList.add(TextComponent.builder("")
.append("Last Active", TextColor.YELLOW)
.append(" : ")
.append(lastActive.toString(), TextColor.GRAY)
.build());
}
}
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(TextComponent.of("Player Info", TextColor.AQUA)).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(claimsTextList);
paginationBuilder.sendTo(src);
}
}

View File

@ -0,0 +1,97 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.util.BlockUtil;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.text.action.GDCallbackHolder;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import java.util.function.Consumer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_RESTORE_CLAIM)
public class CommandRestoreClaim extends BaseCommand {
@CommandAlias("restoreclaim|claimrestore")
@Description("Restores claim to its natural state. Use with caution.")
@Subcommand("claim restore")
public void execute(Player player) {
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
if (claim.isWilderness()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimNotFound.toText());
return;
}
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionClaimDelete
.apply(ImmutableMap.of(
"type", claim.getType().getName())).build();
if (!player.hasPermission(GDPermissions.DELETE_CLAIM_ADMIN)) {
GriefDefenderPlugin.sendMessage(player, message);
return;
}
displayConfirmationConsumer(player, claim);
}
private static void displayConfirmationConsumer(CommandSender src, GDClaim claim) {
final Component schematicConfirmationText = TextComponent.builder("")
.append("Are you sure you want to restore this claim?")
.append("\n[")
.append("Confirm", TextColor.GREEN)
.append("]\n")
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createConfirmationConsumer(src, claim))))
.hoverEvent(HoverEvent.showText(TextComponent.of("Clicking confirm will restore ENTIRE claim back to default world gen state. Use cautiously!"))).build();
TextAdapter.sendComponent(src, schematicConfirmationText);
}
private static Consumer<CommandSender> createConfirmationConsumer(CommandSender src, GDClaim claim) {
return confirm -> {
BlockUtil.getInstance().restoreClaim(claim);
final Component message = GriefDefenderPlugin.getInstance().messageData.claimRestoreSuccess.toText();
GriefDefenderPlugin.sendMessage(src, message);
};
}
}

View File

@ -0,0 +1,67 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_RESTORE_NATURE)
public class CommandRestoreNature extends BaseCommand {
@CommandAlias("modenature")
@Description("Switches the shovel tool to restoration mode.")
@Subcommand("mode nature")
public void execute(Player player) {
if (true) {
GriefDefenderPlugin.sendMessage(player, TextComponent.of("This mode is currently being worked on and will be available in a future build.", TextColor.RED));
return;
}
if (!NMSUtil.getInstance().hasItemInOneHand(player, GriefDefenderPlugin.getInstance().modificationTool)) {
TextAdapter.sendComponent(player, TextComponent.builder("")
.append("You do not have ", TextColor.RED)
.append(GriefDefenderPlugin.getInstance().modificationTool.name().toLowerCase(), TextColor.GREEN)
.append(" equipped.", TextColor.RED).build());
return;
}
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.shovelMode = ShovelTypes.RESTORE;
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.restoreNatureActivate.toText());
}
}

View File

@ -0,0 +1,96 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.InvalidCommandArgument;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_SET_ACCRUED_CLAIM_BLOCKS)
public class CommandSetAccruedClaimBlocks extends BaseCommand {
@CommandAlias("setaccruedblocks")
@Description("Updates a player's accrued claim block total.")
@Syntax("<amount>")
@Subcommand("player setaccruedblocks")
public void execute(CommandSender src, String[] args) throws InvalidCommandArgument {
if (GriefDefenderPlugin.getGlobalConfig().getConfig().economy.economyMode) {
TextAdapter.sendComponent(src, TextComponent.of("This command is not available while server is in economy mode.", TextColor.RED));
return;
}
if (args.length < 2) {
throw new InvalidCommandArgument();
}
GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(args[0]);
int newAmount = Integer.parseInt(args[1]);
World world = null;
if (user == null) {
TextAdapter.sendComponent(src, TextComponent.of("User ' " + args[0] + "' could not be found.", TextColor.RED));
throw new InvalidCommandArgument();
}
if (args.length > 2) {
world = Bukkit.getServer().getWorld(args[2]);
if (world == null) {
TextAdapter.sendComponent(src, TextComponent.of("World ' " + args[1] + "' could not be found.", TextColor.RED));
throw new InvalidCommandArgument();
}
}
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(world.getUID())) {
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
// set player's blocks
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(world.getUID(), user.getUniqueId());
if (!playerData.setAccruedClaimBlocks(newAmount)) {
TextAdapter.sendComponent(src, TextComponent.of("User " + user.getName() + " has a total of " + playerData.getAccruedClaimBlocks() + " and will exceed the maximum allowed accrued claim blocks if granted an additional " + newAmount + " blocks. " +
"Either lower the amount or have an admin grant the user with an override.", TextColor.RED));
return;
}
playerData.getStorageData().save();
GriefDefenderPlugin.sendMessage(src, GriefDefenderPlugin.getInstance().messageData.commandAcbSuccess.toText());
}
}

View File

@ -0,0 +1,62 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TOWN_CHAT)
public class CommandTownChat extends BaseCommand {
@CommandAlias("townchat")
@Description("Toggles town chat.")
@Subcommand("town chat")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAt(player.getLocation());
if (!claim.isInTown()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.townNotIn.toText());
return;
}
playerData.townChat = !playerData.townChat;
// toggle ignore claims mode on or off
if (!playerData.townChat) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.townChatDisabled.toText());
} else {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.townChatEnabled.toText());
}
}
}

View File

@ -0,0 +1,83 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TOWN_TAG)
public class CommandTownTag extends BaseCommand {
@CommandAlias("towntag")
@Description("Sets the tag of your town.")
@Subcommand("town tag")
public void execute(Player player, String tag) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (claim == null || !claim.isInTown()) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.townNotIn.toText());
return;
}
final GDClaim town = claim.getTownClaim();
final Component result = town.allowEdit(player);
if (result != null) {
GriefDefenderPlugin.sendMessage(player, result);
return;
}
TextComponent name = LegacyComponentSerializer.legacy().deserialize(tag, '&');
if (name == TextComponent.empty() || name.content().equals("clear")) {
town.getTownData().setTownTag(null);
} else {
town.getTownData().setTownTag(name);
}
town.getInternalClaimData().setRequiresSave(true);
Component resultMessage = null;
if (!claim.getTownData().getTownTag().isPresent()) {
resultMessage = GriefDefenderPlugin.getInstance().messageData.townTagClear.toText();
} else {
resultMessage = GriefDefenderPlugin.getInstance().messageData.townTag
.apply(ImmutableMap.of(
"tag", name)).build();
}
TextAdapter.sendComponent(player, resultMessage);
}
}

View File

@ -0,0 +1,138 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.api.permission.Context;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDGroupTrustClaimEvent;
import com.griefdefender.permission.GDPermissionHolder;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import me.lucko.luckperms.api.Group;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TRUST_GROUP)
public class CommandTrustGroup extends BaseCommand {
@CommandAlias("trustgroup")
@Description("Grants a group access to your claim."
+ "\nAccessor: access to interact with all blocks except inventory."
+ "\nContainer: access to interact with all blocks including inventory."
+ "\nBuilder: access to everything above including ability to place and break blocks."
+ "\nManager: access to everything above including ability to manage claim settings.")
@Syntax("<group> <accessor|builder|container|manager>")
@Subcommand("trust group")
public void execute(Player player, String groupName, String type) {
final TrustType trustType = CommandHelper.getTrustType(type);
if (trustType == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustInvalid.toText());
return;
}
final Group group = PermissionUtil.getInstance().getGroupSubject(groupName);
if (group == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandGroupInvalid
.apply(ImmutableMap.of(
"group", groupName)).build());
return;
}
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(player.getWorld().getUID())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
// determine which claim the player is standing in
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (!playerData.canIgnoreClaim(claim) && claim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionCommandTrust.toText());
return;
}
//check permission here
if(claim.allowGrantPermission(player) != null) {
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionTrust
.apply(ImmutableMap.of(
"owner", claim.getOwnerName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDGroupTrustClaimEvent.Remove event =
new GDGroupTrustClaimEvent.Remove(claim, ImmutableList.of(group.getName()), TrustTypes.NONE);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not trust group '" + group + "'. A plugin has denied it.").color(TextColor.RED)));
return;
}
final String permission = CommandHelper.getTrustPermission(trustType);
Set<Context> contexts = new HashSet<>();
contexts.add(claim.getContext());
final List<String> groupTrustList = claim.getGroupTrustList(trustType);
if (!groupTrustList.contains(group.getName())) {
groupTrustList.add(group.getName());
}
final GDPermissionHolder holder = PermissionHolderCache.getInstance().getOrCreateGroup(group);
PermissionUtil.getInstance().setPermissionValue(claim, holder, permission, Tristate.TRUE, contexts);
claim.getInternalClaimData().setRequiresSave(true);
final Component message = GriefDefenderPlugin.getInstance().messageData.trustGrant
.apply(ImmutableMap.of(
"target", group.getName(),
"type", trustType.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,129 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDGroupTrustClaimEvent;
import com.griefdefender.permission.GDPermissionGroup;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TRUSTALL_GROUP)
public class CommandTrustGroupAll extends BaseCommand {
@CommandAlias("trustallgroup")
@Description("Grants a group access to all your claims."
+ "\nAccessor: access to interact with all blocks except inventory."
+ "\nContainer: access to interact with all blocks including inventory."
+ "\nBuilder: access to everything above including ability to place and break blocks."
+ "\nManager: access to everything above including ability to manage claim settings.")
@Syntax("<group> <accessor|builder|container|manager>")
@Subcommand("trustall group")
public void execute(Player player, String target, String type) {
final TrustType trustType = CommandHelper.getTrustType(type);
if (trustType == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustInvalid.toText());
return;
}
final GDPermissionGroup group = PermissionHolderCache.getInstance().getOrCreateGroup(target);
// validate player argument
if (group == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandGroupInvalid
.apply(ImmutableMap.of(
"group", target)).build());
return;
}
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
Set<Claim> claimList = null;
if (playerData != null) {
claimList = playerData.getInternalClaims();
}
if (playerData == null || claimList == null || claimList.size() == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustNoClaims.toText());
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDGroupTrustClaimEvent.Add
event = new GDGroupTrustClaimEvent.Add(new ArrayList<>(claimList), ImmutableList.of(group.getName()), trustType);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not add trust for group '" + group + "'. A plugin has denied it.", TextColor.RED)));
return;
}
for (Claim claim : claimList) {
this.addAllGroupTrust(claim, group, trustType);
}
final Component message = GriefDefenderPlugin.getInstance().messageData.trustIndividualAllClaims
.apply(ImmutableMap.of(
"player", group.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
private void addAllGroupTrust(Claim claim, GDPermissionGroup holder, TrustType trustType) {
GDClaim gpClaim = (GDClaim) claim;
List<String> trustList = gpClaim.getGroupTrustList(trustType);
if (!trustList.contains(holder.getFriendlyName())) {
trustList.add(holder.getFriendlyName());
}
gpClaim.getInternalClaimData().setRequiresSave(true);
for (Claim child : gpClaim.children) {
this.addAllGroupTrust(child, holder, trustType);
}
}
}

View File

@ -0,0 +1,259 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.internal.pagination.PaginationList;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.text.action.GDCallbackHolder;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.event.ClickEvent;
import net.kyori.text.event.HoverEvent;
import net.kyori.text.format.TextColor;
import net.kyori.text.format.TextDecoration;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_LIST_TRUST)
public class CommandTrustList extends BaseCommand {
@CommandAlias("trustlist")
@Description("Lists permissions for the claim you're standing in.")
@Subcommand("trust list")
public void execute(Player player) {
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
showTrustList((CommandSender) player, claim, player, TrustTypes.NONE);
}
public static void showTrustList(CommandSender src, GDClaim claim, Player player, TrustType type) {
final Component whiteOpenBracket = TextComponent.of("[", TextColor.AQUA);
final Component whiteCloseBracket = TextComponent.of("]", TextColor.AQUA);
final Component showAllText = TextComponent.of("Click here to show all trusted users for claim.");
final Component showAccessorText = TextComponent.builder("")
.append("Click here to filter by ")
.append("ACCESSOR ", TextColor.YELLOW)
.append("permissions.")
.build();
final Component showContainerText = TextComponent.builder("")
.append("Click here to filter by ")
.append("CONTAINER ", TextColor.LIGHT_PURPLE)
.append("permissions.")
.build();
final Component showBuilderText = TextComponent.builder("")
.append("Click here to filter by ")
.append("BUILDER ", TextColor.GREEN)
.append("permissions.")
.build();
final Component showManagerText = TextComponent.builder("")
.append("Click here to filter by ")
.append("MANAGER ", TextColor.GOLD)
.append("permissions.")
.build();
final Component allTypeText = TextComponent.builder("")
.append(type == TrustTypes.NONE ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("ALL")
.append(whiteCloseBracket)
.build() : TextComponent.builder("")
.append("ALL",TextColor.GRAY)
.build())
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createTrustConsumer(src, claim, player, TrustTypes.NONE))))
.hoverEvent(HoverEvent.showText(showAllText)).build();
final Component accessorTrustText = TextComponent.builder("")
.append(type == TrustTypes.ACCESSOR ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("ACCESSOR", TextColor.YELLOW)
.append(whiteCloseBracket)
.build() : TextComponent.of("ACCESSOR", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createTrustConsumer(src, claim, player, TrustTypes.ACCESSOR))))
.hoverEvent(HoverEvent.showText(showAccessorText)).build();
final Component builderTrustText = TextComponent.builder("")
.append(type == TrustTypes.BUILDER ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("BUILDER", TextColor.GREEN)
.append(whiteCloseBracket)
.build() : TextComponent.of("BUILDER", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createTrustConsumer(src, claim, player, TrustTypes.BUILDER))))
.hoverEvent(HoverEvent.showText(showBuilderText)).build();
final Component containerTrustText = TextComponent.builder("")
.append(type == TrustTypes.CONTAINER ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("CONTAINER", TextColor.LIGHT_PURPLE)
.append(whiteCloseBracket)
.build() : TextComponent.of("CONTAINER", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createTrustConsumer(src, claim, player, TrustTypes.CONTAINER))))
.hoverEvent(HoverEvent.showText(showContainerText)).build();
final Component managerTrustText = TextComponent.builder("")
.append(type == TrustTypes.MANAGER ? TextComponent.builder("")
.append(whiteOpenBracket)
.append("MANAGER", TextColor.GOLD)
.append(whiteCloseBracket)
.build() : TextComponent.of("MANAGER", TextColor.GRAY))
.clickEvent(ClickEvent.runCommand(GDCallbackHolder.getInstance().createCallbackRunCommand(createTrustConsumer(src, claim, player, TrustTypes.MANAGER))))
.hoverEvent(HoverEvent.showText(showManagerText)).build();
final Component claimTrustHead = TextComponent.builder("")
.append(" Displaying : ", TextColor.AQUA)
.append(allTypeText)
.append(" ")
.append(accessorTrustText)
.append(" ")
.append(builderTrustText)
.append(" ")
.append(containerTrustText)
.append(" ")
.append(managerTrustText)
.build();
List<UUID> userIdList = new ArrayList<>(claim.getUserTrusts());
List<Component> trustList = new ArrayList<>();
trustList.add(TextComponent.empty());
if (type == TrustTypes.NONE) {
// check highest trust first
for (UUID uuid : claim.getInternalClaimData().getManagers()) {
final GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(uuid);
trustList.add(TextComponent.of(user.getName(), TextColor.GOLD));
userIdList.remove(user.getUniqueId());
}
for (UUID uuid : claim.getInternalClaimData().getBuilders()) {
if (!userIdList.contains(uuid)) {
continue;
}
final GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(uuid);
trustList.add(TextComponent.of(user.getName(), TextColor.GREEN));
userIdList.remove(uuid);
}
/*for (String group : claim.getInternalClaimData().getManagerGroups()) {
permissions.append(SPACE_TEXT, Text.of(group));
}*/
for (UUID uuid : claim.getInternalClaimData().getContainers()) {
if (!userIdList.contains(uuid)) {
continue;
}
final GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(uuid);
trustList.add(TextComponent.of(user.getName(), TextColor.LIGHT_PURPLE));
userIdList.remove(uuid);
}
/* for (String group : claim.getInternalClaimData().getBuilderGroups()) {
permissions.append(SPACE_TEXT, Text.of(group));
}*/
for (UUID uuid : claim.getInternalClaimData().getAccessors()) {
if (!userIdList.contains(uuid)) {
continue;
}
final GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(uuid);
trustList.add(TextComponent.of(user.getName(), TextColor.YELLOW));
userIdList.remove(uuid);
}
/*for (String group : claim.getInternalClaimData().getContainerGroups()) {
permissions.append(SPACE_TEXT, Text.of(group));
}
player.sendMessage(permissions.build());
permissions = Text.builder(">").color(TextColors.BLUE);
for (UUID uuid : claim.getInternalClaimData().getAccessors()) {
User user = GriefDefenderPlugin.getOrCreateUser(uuid);
permissions.append(SPACE_TEXT, Text.of(user.getName()));
}
for (String group : claim.getInternalClaimData().getAccessorGroups()) {
permissions.append(SPACE_TEXT, Text.of(group));
}*/
} else {
for (UUID uuid : claim.getUserTrusts(type)) {
if (!userIdList.contains(uuid)) {
continue;
}
final GDPermissionUser user = PermissionHolderCache.getInstance().getOrCreateUser(uuid);
trustList.add(TextComponent.of(user.getName(), getTrustColor(type)));
userIdList.remove(uuid);
}
}
int fillSize = 20 - (trustList.size() + 2);
for (int i = 0; i < fillSize; i++) {
trustList.add(TextComponent.of(" "));
}
PaginationList.Builder paginationBuilder = PaginationList.builder()
.title(claimTrustHead).padding(TextComponent.of(" ").decoration(TextDecoration.STRIKETHROUGH, true)).contents(trustList);
paginationBuilder.sendTo(src);
paginationBuilder.sendTo(src);
}
private static TextColor getTrustColor(TrustType type) {
if (type == TrustTypes.NONE) {
return TextColor.WHITE;
}
if (type == TrustTypes.ACCESSOR) {
return TextColor.YELLOW;
}
if (type == TrustTypes.BUILDER) {
return TextColor.GREEN;
}
if (type == TrustTypes.CONTAINER) {
return TextColor.LIGHT_PURPLE;
}
return TextColor.GOLD;
}
private static Consumer<CommandSender> createTrustConsumer(CommandSender src, GDClaim claim, Player player, TrustType type) {
return consumer -> {
showTrustList(src, claim, player, type);
};
}
}

View File

@ -0,0 +1,166 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDUserTrustClaimEvent;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import java.util.List;
import java.util.UUID;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TRUST_PLAYER)
public class CommandTrustPlayer extends BaseCommand {
@CommandAlias("trust")
@Description("Grants a player access to your claim."
+ "\nAccessor: access to interact with all blocks except inventory."
+ "\nContainer: access to interact with all blocks including inventory."
+ "\nBuilder: access to everything above including ability to place and break blocks."
+ "\nManager: access to everything above including ability to manage claim settings.")
@Syntax("<player> <accessor|builder|container|manager>")
@Subcommand("trust player")
public void execute(Player player, String target, @Optional String type) {
TrustType trustType = null;
if (type == null) {
trustType = TrustTypes.BUILDER;
} else {
trustType = CommandHelper.getTrustType(type);
if (trustType == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustInvalid.toText());
return;
}
}
GDPermissionUser user = null;
if (target.equalsIgnoreCase("public")) {
user = GriefDefenderPlugin.PUBLIC_USER;
} else {
user = PermissionHolderCache.getInstance().getOrCreateUser(target);
}
if (user == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandPlayerInvalid
.apply(ImmutableMap.of(
"player", target)).build());
return;
}
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(player.getWorld().getUID())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
// determine which claim the player is standing in
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (!claim.getOwnerUniqueId().equals(player.getUniqueId()) && !playerData.canIgnoreClaim(claim) && claim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionCommandTrust.toText());
return;
}
if (user.getUniqueId().equals(player.getUniqueId()) && !playerData.canIgnoreClaim(claim)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustSelf.toText());
return;
}
if (user != null && claim.getOwnerUniqueId().equals(user.getUniqueId())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimOwnerAlready.toText());
return;
} else {
//check permission here
if(claim.allowGrantPermission(player) != null) {
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionTrust
.apply(ImmutableMap.of(
"owner", claim.getOwnerName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
if(trustType == TrustTypes.MANAGER) {
Component denyReason = claim.allowEdit(player);
if(denyReason != null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionGrant.toText());
return;
}
}
}
GDCauseStackManager.getInstance().pushCause(player);
GDUserTrustClaimEvent.Add
event =
new GDUserTrustClaimEvent.Add(claim, ImmutableList.of(user.getUniqueId()), trustType);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not trust user '" + user.getName() + "'. A plugin has denied it.").color(TextColor.RED)));
return;
}
final List<UUID> trustList = claim.getUserTrustList(trustType);
if (trustList.contains(user.getUniqueId())) {
final Component message = GriefDefenderPlugin.getInstance().messageData.trustAlreadyHas
.apply(ImmutableMap.of(
"target", user.getName(),
"type", trustType.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
trustList.add(user.getUniqueId());
claim.getInternalClaimData().setRequiresSave(true);
claim.getInternalClaimData().save();
final Component message = GriefDefenderPlugin.getInstance().messageData.trustGrant
.apply(ImmutableMap.of(
"target", user.getName(),
"type", trustType.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,147 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Optional;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.TrustType;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDUserTrustClaimEvent;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_TRUSTALL_PLAYER)
public class CommandTrustPlayerAll extends BaseCommand {
@CommandAlias("trustall")
@Description("Grants a player access to all your claims."
+ "\nAccessor: access to interact with all blocks except inventory."
+ "\nContainer: access to interact with all blocks including inventory."
+ "\nBuilder: access to everything above including ability to place and break blocks."
+ "\nManager: access to everything above including ability to manage claim settings.")
@Syntax("<player> <accessor|builder|container|manager>")
@Subcommand("trustall player")
public void execute(Player player, String target, @Optional String type) {
TrustType trustType = null;
if (type == null) {
trustType = TrustTypes.BUILDER;
} else {
trustType = CommandHelper.getTrustType(type);
if (trustType == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustInvalid.toText());
return;
}
}
GDPermissionUser user;
if (target.equalsIgnoreCase("public")) {
user = GriefDefenderPlugin.PUBLIC_USER;
} else {
user = PermissionHolderCache.getInstance().getOrCreateUser(target);
}
// validate player argument
if (user == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandPlayerInvalid
.apply(ImmutableMap.of(
"player", target)).build());
return;
}
if (user.getUniqueId().equals(player.getUniqueId())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustSelf.toText());
return;
}
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
Set<Claim> claimList = null;
if (playerData != null) {
claimList = playerData.getInternalClaims();
}
if (playerData == null || claimList == null || claimList.size() == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustNoClaims.toText());
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDUserTrustClaimEvent.Add
event = new GDUserTrustClaimEvent.Add(new ArrayList<>(claimList), ImmutableList.of(user.getUniqueId()), trustType);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not add trust for user '" + user.getName() + "'. A plugin has denied it.").color(TextColor.RED)));
return;
}
for (Claim claim : claimList) {
this.addAllUserTrust(claim, user, trustType);
}
final Component message = GriefDefenderPlugin.getInstance().messageData.trustIndividualAllClaims
.apply(ImmutableMap.of(
"player", user.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
private void addAllUserTrust(Claim claim, GDPermissionUser user, TrustType trustType) {
GDClaim gpClaim = (GDClaim) claim;
List<UUID> trustList = gpClaim.getUserTrustList(trustType);
if (!trustList.contains(user.getUniqueId())) {
trustList.add(user.getUniqueId());
}
gpClaim.getInternalClaimData().setRequiresSave(true);
for (Claim child : gpClaim.children) {
this.addAllUserTrust(child, user, trustType);
}
}
}

View File

@ -0,0 +1,108 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDGroupTrustClaimEvent;
import com.griefdefender.permission.GDPermissions;
import com.griefdefender.util.PermissionUtil;
import me.lucko.luckperms.api.Group;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_UNTRUST_GROUP)
public class CommandUntrustGroup extends BaseCommand {
@CommandAlias("untrustgroup")
@Description("Revokes group access to your claim.")
@Subcommand("untrust group")
public void execute(Player player, String target) {
final Group group = PermissionUtil.getInstance().getGroupSubject(target);
if (group == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandGroupInvalid
.apply(ImmutableMap.of(
"group", target)).build());
return;
}
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(player.getWorld().getUID())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
// determine which claim the player is standing in
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (!playerData.canIgnoreClaim(claim) && claim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionCommandTrust.toText());
return;
}
//check permission here
if(claim.allowGrantPermission(player) != null) {
final Component message = GriefDefenderPlugin.getInstance().messageData.permissionTrust
.apply(ImmutableMap.of(
"owner", claim.getOwnerName())).build();
GriefDefenderPlugin.sendMessage(player, message);
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDGroupTrustClaimEvent.Remove event =
new GDGroupTrustClaimEvent.Remove(claim, ImmutableList.of(group.getName()), TrustTypes.NONE);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not untrust group '" + group + "'. A plugin has denied it.").color(TextColor.RED)));
return;
}
claim.removeAllTrustsFromGroup(group.getName());
claim.getInternalClaimData().setRequiresSave(true);
final Component message = GriefDefenderPlugin.getInstance().messageData.untrustIndividualSingleClaim
.apply(ImmutableMap.of(
"target", group)).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,114 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDGroupTrustClaimEvent;
import com.griefdefender.permission.GDPermissionGroup;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_UNTRUSTALL_GROUP)
public class CommandUntrustGroupAll extends BaseCommand {
@CommandAlias("untrustallgroup")
@Description("Revokes group access to all your claims")
@Syntax("<group>")
@Subcommand("untrustall group")
public void execute(Player player, String target, String type) {
final GDPermissionGroup group = PermissionHolderCache.getInstance().getOrCreateGroup(target);
// validate player argument
if (group == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandGroupInvalid
.apply(ImmutableMap.of(
"group", target)).build());
return;
}
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
Set<Claim> claimList = null;
if (playerData != null) {
claimList = playerData.getInternalClaims();
}
if (playerData == null || claimList == null || claimList.size() == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustNoClaims.toText());
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDGroupTrustClaimEvent.Remove
event = new GDGroupTrustClaimEvent.Remove(new ArrayList<>(claimList), ImmutableList.of(group.getName()), TrustTypes.NONE);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not untrust group '" + group + "'. A plugin has denied it.", TextColor.RED)));
return;
}
for (Claim claim : claimList) {
this.removeAllGroupTrust(claim, group);
}
final Component message = GriefDefenderPlugin.getInstance().messageData.untrustIndividualAllClaims
.apply(ImmutableMap.of(
"player", group.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
private void removeAllGroupTrust(Claim claim, GDPermissionGroup holder) {
GDClaim gdClaim = (GDClaim) claim;
gdClaim.removeAllTrustsFromGroup(holder.getName());
gdClaim.getInternalClaimData().setRequiresSave(true);
for (Claim child : gdClaim.children) {
this.removeAllGroupTrust(child, holder);
}
}
}

View File

@ -0,0 +1,119 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDUserTrustClaimEvent;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import org.bukkit.entity.Player;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_UNTRUST_PLAYER)
public class CommandUntrustPlayer extends BaseCommand {
@CommandAlias("untrust")
@Description("Revokes player access to your claim.")
@Syntax("<player>")
@Subcommand("untrust player")
public void execute(Player player, String target) {
GDPermissionUser user;
if (target.equalsIgnoreCase("public")) {
user = GriefDefenderPlugin.PUBLIC_USER;
} else {
user = PermissionHolderCache.getInstance().getOrCreateUser(target);
}
System.out.println("user = " + user);
if (user == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandPlayerInvalid
.apply(ImmutableMap.of(
"player", target)).build());
return;
}
if (!GriefDefenderPlugin.getInstance().claimsEnabledForWorld(player.getWorld().getUID())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimDisabledWorld.toText());
return;
}
// determine which claim the player is standing in
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
GDClaim claim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(playerData, player.getLocation());
if (!claim.getOwnerUniqueId().equals(player.getUniqueId()) && !playerData.canIgnoreClaim(claim) && claim.allowEdit(player) != null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.permissionCommandTrust.toText());
return;
}
if (user.getUniqueId().equals(player.getUniqueId()) && !playerData.canIgnoreClaim(claim)) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.untrustSelf.toText());
return;
}
if (user != null && claim.getOwnerUniqueId().equals(user.getUniqueId())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.claimOwnerAlready.toText());
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDUserTrustClaimEvent.Remove
event =
new GDUserTrustClaimEvent.Remove(claim, ImmutableList.of(user.getUniqueId()), TrustTypes.NONE);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not untrust user '" + user.getName() + "'. A plugin has denied it.").color(TextColor.RED)));
return;
}
claim.removeAllTrustsFromUser(user.getUniqueId());
claim.getInternalClaimData().setRequiresSave(true);
claim.getInternalClaimData().save();
final Component message = GriefDefenderPlugin.getInstance().messageData.untrustIndividualSingleClaim
.apply(ImmutableMap.of(
"target", user.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
}

View File

@ -0,0 +1,124 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import co.aikar.commands.BaseCommand;
import co.aikar.commands.annotation.CommandAlias;
import co.aikar.commands.annotation.CommandPermission;
import co.aikar.commands.annotation.Description;
import co.aikar.commands.annotation.Subcommand;
import co.aikar.commands.annotation.Syntax;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.event.GDCauseStackManager;
import com.griefdefender.event.GDUserTrustClaimEvent;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.GDPermissions;
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.adapter.bukkit.TextAdapter;
import net.kyori.text.format.TextColor;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Set;
@CommandAlias("%griefdefender")
@CommandPermission(GDPermissions.COMMAND_UNTRUSTALL_PLAYER)
public class CommandUntrustPlayerAll extends BaseCommand {
@CommandAlias("untrustall")
@Description("Revokes player access to all your claims.")
@Syntax("<player>")
@Subcommand("untrustall player")
public void execute(Player player, String target) {
GDPermissionUser user;
if (target.equalsIgnoreCase("public")) {
user = GriefDefenderPlugin.PUBLIC_USER;
} else {
user = PermissionHolderCache.getInstance().getOrCreateUser(target);
}
// validate player argument
if (user == null) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.commandPlayerInvalid
.apply(ImmutableMap.of(
"player", target)).build());
return;
}
if (user.getUniqueId().equals(player.getUniqueId())) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.untrustSelf.toText());
return;
}
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
Set<Claim> claimList = null;
if (playerData != null) {
claimList = playerData.getInternalClaims();
}
if (playerData == null || claimList == null || claimList.size() == 0) {
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.trustNoClaims.toText());
return;
}
GDCauseStackManager.getInstance().pushCause(player);
GDUserTrustClaimEvent.Remove
event = new GDUserTrustClaimEvent.Remove(new ArrayList<>(claimList), ImmutableList.of(user.getUniqueId()), TrustTypes.NONE);
GriefDefender.getEventManager().post(event);
GDCauseStackManager.getInstance().popCause();
if (event.cancelled()) {
TextAdapter.sendComponent(player, event.getMessage().orElse(TextComponent.of("Could not remove trust for user '" + user.getName() + "'. A plugin has denied it.").color(TextColor.RED)));
return;
}
for (Claim claim : claimList) {
this.removeAllUserTrust(claim, user);
}
final Component message = GriefDefenderPlugin.getInstance().messageData.untrustIndividualAllClaims
.apply(ImmutableMap.of(
"player", user.getName())).build();
GriefDefenderPlugin.sendMessage(player, message);
}
private void removeAllUserTrust(Claim claim, GDPermissionUser user) {
final GDClaim gdClaim = ((GDClaim) claim);
gdClaim.removeAllTrustsFromUser(user.getUniqueId());
gdClaim.getInternalClaimData().setRequiresSave(true);
for (Claim child : gdClaim.children) {
this.removeAllUserTrust(child, user);
}
}
}

View File

@ -0,0 +1,104 @@
/*
* This file is part of SpongeAPI, licensed under the MIT License (MIT).
*
* Copyright (c) SpongePowered <https://www.spongepowered.org>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.command;
import net.kyori.text.Component;
import net.kyori.text.serializer.plain.PlainComponentSerializer;
import javax.annotation.Nullable;
/**
* A subclass of Exception that contains a rich message that is an instance of
* {@link Text} rather than a String. This allows formatted and localized
* exception messages.
*/
public class ComponentMessageException extends Exception {
private static final long serialVersionUID = -5281221645176698853L;
@Nullable private final Component message;
/**
* Constructs a new {@link ComponentMessageException}.
*/
public ComponentMessageException() {
this.message = null;
}
/**
* Constructs a new {@link ComponentMessageException} with the given message.
*
* @param message The detail message
*/
public ComponentMessageException(Component message) {
this.message = message;
}
/**
* Constructs a new {@link ComponentMessageException} with the given message and
* cause.
*
* @param message The detail message
* @param throwable The cause
*/
public ComponentMessageException(Component message, Throwable throwable) {
super(throwable);
this.message = message;
}
/**
* Constructs a new {@link ComponentMessageException} with the given cause.
*
* @param throwable The cause
*/
public ComponentMessageException(Throwable throwable) {
super(throwable);
this.message = null;
}
@Override
@Nullable
public String getMessage() {
Component message = getText();
return message == null ? null : PlainComponentSerializer.INSTANCE.serialize(message);
}
/**
* Returns the text message for this exception, or null if nothing is
* present.
*
* @return The text for this message
*/
@Nullable
public Component getText() {
return this.message;
}
@Override
@Nullable
public String getLocalizedMessage() {
return getMessage();
}
}

View File

@ -0,0 +1,478 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.flowpowered.math.vector.Vector3i;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.data.EconomyData;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.configuration.category.ConfigCategory;
import com.griefdefender.internal.util.BlockUtil;
import com.griefdefender.registry.ClaimTypeRegistryModule;
import net.kyori.text.Component;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@ConfigSerializable
public class ClaimDataConfig extends ConfigCategory implements IClaimData {
private boolean requiresSave = false;
private Vector3i lesserPos;
private Vector3i greaterPos;
private Vector3i spawnPos;
private ClaimStorageData claimStorage;
@Setting
private UUID parent;
@Setting(value = ClaimStorageData.MAIN_INHERIT_PARENT)
public boolean inheritParent = true;
@Setting(value = ClaimStorageData.MAIN_WORLD_UUID)
private UUID worldUniqueId;
@Setting(value = ClaimStorageData.MAIN_OWNER_UUID)
private UUID ownerUniqueId;
@Setting(value = ClaimStorageData.MAIN_CLAIM_TYPE)
private ClaimType claimType = ClaimTypes.BASIC;
@Setting(value = ClaimStorageData.MAIN_CLAIM_CUBOID)
private boolean isCuboid = false;
@Setting(value = ClaimStorageData.MAIN_CLAIM_RESIZABLE)
private boolean isResizable = true;
@Setting
private boolean isExpired = false;
@Setting
private boolean sizeRestrictions = true;
@Setting(value = ClaimStorageData.MAIN_ALLOW_DENY_MESSAGES)
private boolean allowDenyMessages = true;
@Setting(value = ClaimStorageData.MAIN_ALLOW_CLAIM_EXPIRATION)
private boolean allowClaimExpiration = true;
@Setting(value = ClaimStorageData.MAIN_ALLOW_FLAG_OVERRIDES)
private boolean allowFlagOverrides = true;
@Setting(value = ClaimStorageData.MAIN_REQUIRES_CLAIM_BLOCKS)
private boolean requiresClaimBlocks = true;
@Setting(value = ClaimStorageData.MAIN_CLAIM_PVP)
private Tristate pvpOverride = Tristate.UNDEFINED;
@Setting(value = ClaimStorageData.MAIN_CLAIM_DATE_CREATED)
private String dateCreated = Instant.now().toString();
@Setting(value = ClaimStorageData.MAIN_CLAIM_DATE_LAST_ACTIVE)
private String dateLastActive = Instant.now().toString();
@Setting(value = ClaimStorageData.MAIN_CLAIM_NAME)
private Component claimName;
@Setting(value = ClaimStorageData.MAIN_CLAIM_GREETING)
private Component claimGreetingMessage;
@Setting(value = ClaimStorageData.MAIN_CLAIM_FAREWELL)
private Component claimFarewellMessage;
@Setting(value = ClaimStorageData.MAIN_CLAIM_SPAWN)
private String claimSpawn;
@Setting(value = ClaimStorageData.MAIN_LESSER_BOUNDARY_CORNER)
private String lesserBoundaryCornerPos;
@Setting(value = ClaimStorageData.MAIN_GREATER_BOUNDARY_CORNER)
private String greaterBoundaryCornerPos;
@Setting(value = ClaimStorageData.MAIN_ACCESSORS)
private List<UUID> accessors = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_BUILDERS)
private List<UUID> builders = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_CONTAINERS)
private List<UUID> containers = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_MANAGERS)
private List<UUID> managers = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_ACCESSOR_GROUPS)
private List<String> accessorGroups = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_BUILDER_GROUPS)
private List<String> builderGroups = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_CONTAINER_GROUPS)
private List<String> containerGroups = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_MANAGER_GROUPS)
private List<String> managerGroups = new ArrayList<>();
@Setting
private EconomyDataConfig economyData = new EconomyDataConfig();
public ClaimDataConfig() {
}
public ClaimDataConfig(GDClaim claim) {
this.lesserBoundaryCornerPos = BlockUtil.getInstance().posToString(claim.lesserBoundaryCorner);
this.greaterBoundaryCornerPos = BlockUtil.getInstance().posToString(claim.greaterBoundaryCorner);
this.isCuboid = claim.cuboid;
this.claimType = claim.getType();
this.ownerUniqueId = claim.getOwnerUniqueId();
}
@Override
public UUID getWorldUniqueId() {
return this.worldUniqueId;
}
@Override
public UUID getOwnerUniqueId() {
return this.ownerUniqueId;
}
@Override
public boolean allowExpiration() {
return this.allowClaimExpiration;
}
@Override
public boolean allowFlagOverrides() {
return this.allowFlagOverrides;
}
@Override
public boolean isCuboid() {
return this.isCuboid;
}
@Override
public boolean allowDenyMessages() {
return this.allowDenyMessages;
}
@Override
public Tristate getPvpOverride() {
return this.pvpOverride;
}
@Override
public boolean isResizable() {
return this.isResizable;
}
@Override
public boolean hasSizeRestrictions() {
if (this.claimType == ClaimTypes.ADMIN || this.claimType == ClaimTypes.WILDERNESS) {
this.sizeRestrictions = false;
return false;
}
return this.sizeRestrictions;
}
@Override
public ClaimType getType() {
return this.claimType;
}
@Override
public Instant getDateCreated() {
return Instant.parse(this.dateCreated);
}
@Override
public Instant getDateLastActive() {
return Instant.parse(this.dateLastActive);
}
@Override
public Optional<Component> getName() {
return Optional.ofNullable(this.claimName);
}
@Override
public Optional<Component> getGreeting() {
return Optional.ofNullable(this.claimGreetingMessage);
}
@Override
public Optional<Component> getFarewell() {
return Optional.ofNullable(this.claimFarewellMessage);
}
@Override
public Optional<Vector3i> getSpawnPos() {
if (this.spawnPos == null && this.claimSpawn != null) {
try {
this.spawnPos = BlockUtil.getInstance().posFromString(this.claimSpawn);
this.requiresSave = true;
} catch (Exception e) {
e.printStackTrace();
}
}
return Optional.ofNullable(this.spawnPos);
}
@Override
public Vector3i getLesserBoundaryCornerPos() {
if (this.lesserPos == null) {
try {
this.lesserPos = BlockUtil.getInstance().posFromString(this.lesserBoundaryCornerPos);
} catch (Exception e) {
e.printStackTrace();
}
}
return this.lesserPos;
}
@Override
public Vector3i getGreaterBoundaryCornerPos() {
if (this.greaterPos == null) {
try {
this.greaterPos = BlockUtil.getInstance().posFromString(this.greaterBoundaryCornerPos);
} catch (Exception e) {
e.printStackTrace();
}
}
return this.greaterPos;
}
public List<UUID> getAccessors() {
return this.accessors;
}
public List<UUID> getBuilders() {
return this.builders;
}
public List<UUID> getContainers() {
return this.containers;
}
public List<UUID> getManagers() {
return this.managers;
}
public List<String> getAccessorGroups() {
return this.accessorGroups;
}
public List<String> getBuilderGroups() {
return this.builderGroups;
}
public List<String> getContainerGroups() {
return this.containerGroups;
}
public List<String> getManagerGroups() {
return this.managerGroups;
}
@Override
public void setDenyMessages(boolean flag) {
this.requiresSave = true;
this.allowDenyMessages = flag;
}
@Override
public void setExpiration(boolean flag) {
this.requiresSave = true;
this.allowClaimExpiration = flag;
}
@Override
public void setFlagOverrides(boolean flag) {
this.allowFlagOverrides = flag;
}
@Override
public void setCuboid(boolean cuboid) {
this.isCuboid = cuboid;
}
@Override
public void setPvpOverride(Tristate pvp) {
this.requiresSave = true;
this.pvpOverride = pvp;
}
@Override
public void setResizable(boolean resizable) {
this.requiresSave = true;
this.isResizable = resizable;
}
@Override
public void setType(ClaimType type) {
this.requiresSave = true;
this.claimType = type;
}
@Override
public void setDateLastActive(Instant date) {
this.requiresSave = true;
this.dateLastActive = date.toString();
}
@Override
public void setName(Component name) {
this.requiresSave = true;
this.claimName = name;
}
@Override
public void setGreeting(Component message) {
this.requiresSave = true;
this.claimGreetingMessage = message;
}
@Override
public void setFarewell(Component message) {
this.requiresSave = true;
this.claimFarewellMessage = message;
}
@Override
public void setLesserBoundaryCorner(String location) {
this.requiresSave = true;
this.lesserBoundaryCornerPos = location;
this.lesserPos = null;
}
@Override
public void setGreaterBoundaryCorner(String location) {
this.requiresSave = true;
this.greaterBoundaryCornerPos = location;
this.greaterPos = null;
}
@Override
public void setAccessors(List<UUID> accessors) {
this.requiresSave = true;
this.accessors = accessors;
}
@Override
public void setBuilders(List<UUID> builders) {
this.requiresSave = true;
this.builders = builders;
}
@Override
public void setContainers(List<UUID> containers) {
this.requiresSave = true;
this.containers = containers;
}
@Override
public void setManagers(List<UUID> coowners) {
this.requiresSave = true;
this.managers = coowners;
}
public boolean requiresSave() {
return this.requiresSave;
}
@Override
public void setRequiresSave(boolean flag) {
this.requiresSave = flag;
}
@Override
public void setSizeRestrictions(boolean sizeRestrictions) {
this.sizeRestrictions = sizeRestrictions;
}
@Override
public boolean doesInheritParent() {
// NOTE: admin claims ONLY inherit from other parent admin claims
return this.inheritParent;
}
@Override
public void setInheritParent(boolean flag) {
this.requiresSave = true;
this.inheritParent = flag;
}
@Override
public void setOwnerUniqueId(UUID newClaimOwner) {
this.requiresSave = true;
this.ownerUniqueId = newClaimOwner;
}
@Override
public void setWorldUniqueId(UUID uuid) {
this.requiresSave = true;
this.worldUniqueId = uuid;
}
public void setClaimStorageData(ClaimStorageData claimStorage) {
this.claimStorage = claimStorage;
}
@Override
public void save() {
this.claimStorage.save();
}
@Override
public void setSpawnPos(Vector3i spawnPos) {
if (spawnPos == null) {
return;
}
this.requiresSave = true;
this.spawnPos = spawnPos;
this.claimSpawn = BlockUtil.getInstance().posToString(spawnPos);
}
@Override
public boolean requiresClaimBlocks() {
return this.requiresClaimBlocks;
}
@Override
public void setRequiresClaimBlocks(boolean requiresClaimBlocks) {
this.requiresSave = true;
this.requiresClaimBlocks = requiresClaimBlocks;
}
@Override
public void setParent(UUID uuid) {
this.requiresSave = true;
this.parent = uuid;
}
@Override
public Optional<UUID> getParent() {
return Optional.ofNullable(this.parent);
}
public boolean isExpired() {
return this.isExpired;
}
public void setExpired(boolean expire) {
this.isExpired = expire;
}
@Override
public EconomyData getEconomyData() {
return this.economyData;
}
}

View File

@ -0,0 +1,193 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.google.common.reflect.TypeToken;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ClaimTypes;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.objectmapping.ObjectMapper;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.objectmapping.serialize.TypeSerializers;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.UUID;
import java.util.logging.Level;
public class ClaimStorageData {
protected HoconConfigurationLoader loader;
private CommentedConfigurationNode root = SimpleCommentedConfigurationNode.root(ConfigurationOptions.defaults());
protected ObjectMapper<ClaimDataConfig>.BoundInstance configMapper;
protected ClaimDataConfig configBase;
public Path filePath;
public Path folderPath;
// MAIN
public static final String MAIN_WORLD_UUID = "world-uuid";
public static final String MAIN_OWNER_UUID = "owner-uuid";
public static final String MAIN_CLAIM_NAME = "claim-name";
public static final String MAIN_CLAIM_GREETING = "claim-greeting";
public static final String MAIN_CLAIM_FAREWELL = "claim-farewell";
public static final String MAIN_CLAIM_SPAWN = "claim-spawn";
public static final String MAIN_CLAIM_TYPE = "claim-type";
public static final String MAIN_CLAIM_CUBOID = "cuboid";
public static final String MAIN_CLAIM_RESIZABLE = "resizable";
public static final String MAIN_CLAIM_PVP = "pvp";
public static final String MAIN_CLAIM_DATE_CREATED = "date-created";
public static final String MAIN_CLAIM_DATE_LAST_ACTIVE = "date-last-active";
public static final String MAIN_CLAIM_MAX_WIDTH = "max-width";
public static final String MAIN_CLAIM_FOR_SALE = "for-sale";
public static final String MAIN_CLAIM_SALE_PRICE = "sale-price";
public static final String MAIN_REQUIRES_CLAIM_BLOCKS = "requires-claim-blocks";
public static final String MAIN_SUBDIVISION_UUID = "uuid";
public static final String MAIN_PARENT_CLAIM_UUID = "parent-claim-uuid";
public static final String MAIN_LESSER_BOUNDARY_CORNER = "lesser-boundary-corner";
public static final String MAIN_GREATER_BOUNDARY_CORNER = "greater-boundary-corner";
public static final String MAIN_ACCESSORS = "accessors";
public static final String MAIN_BUILDERS = "builders";
public static final String MAIN_CONTAINERS = "containers";
public static final String MAIN_MANAGERS = "managers";
public static final String MAIN_ACCESSOR_GROUPS = "accessor-groups";
public static final String MAIN_BUILDER_GROUPS = "builder-groups";
public static final String MAIN_CONTAINER_GROUPS = "container-groups";
public static final String MAIN_MANAGER_GROUPS = "manager-groups";
public static final String MAIN_ALLOW_DENY_MESSAGES = "deny-messages";
public static final String MAIN_ALLOW_FLAG_OVERRIDES = "flag-overrides";
public static final String MAIN_ALLOW_CLAIM_EXPIRATION = "claim-expiration";
public static final String MAIN_TAX_PAST_DUE_DATE = "tax-past-due-date";
public static final String MAIN_TAX_BALANCE = "tax-balance";
// SUB
public static final String MAIN_INHERIT_PARENT = "inherit-parent";
// Used for new claims after server startup
@SuppressWarnings({"unchecked", "rawtypes"})
public ClaimStorageData(Path path, UUID worldUniqueId, UUID ownerUniqueId, ClaimType type, boolean cuboid) {
this.filePath = path;
this.folderPath = path.getParent();
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
if (type == ClaimTypes.TOWN) {
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(TownDataConfig.class).bindToNew();
} else {
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(ClaimDataConfig.class).bindToNew();
}
this.configMapper.getInstance().setWorldUniqueId(worldUniqueId);
this.configMapper.getInstance().setOwnerUniqueId(ownerUniqueId);
this.configMapper.getInstance().setType(type);
this.configMapper.getInstance().setCuboid(cuboid);
this.configMapper.getInstance().setClaimStorageData(this);
reload();
((EconomyDataConfig) this.configMapper.getInstance().getEconomyData()).activeConfig = GriefDefenderPlugin.getActiveConfig(worldUniqueId);
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize configuration", e);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public ClaimStorageData(Path path, UUID worldUniqueId, ClaimDataConfig claimData) {
this.filePath = path;
this.folderPath = path.getParent();
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(ClaimDataConfig.class).bind(claimData);
this.configMapper.getInstance().setClaimStorageData(this);
reload();
((EconomyDataConfig) this.configMapper.getInstance().getEconomyData()).activeConfig = GriefDefenderPlugin.getActiveConfig(worldUniqueId);
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize configuration", e);
}
}
// Used during server load
@SuppressWarnings({"unchecked", "rawtypes"})
public ClaimStorageData(Path path, UUID worldUniqueId) {
this.filePath = path;
this.folderPath = path.getParent();
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
if (path.getParent().endsWith("town")) {
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(TownDataConfig.class).bindToNew();
} else {
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(ClaimDataConfig.class).bindToNew();
}
this.configMapper.getInstance().setClaimStorageData(this);
reload();
((EconomyDataConfig) this.configMapper.getInstance().getEconomyData()).activeConfig = GriefDefenderPlugin.getActiveConfig(worldUniqueId);
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize configuration", e);
}
}
public ClaimDataConfig getConfig() {
return this.configBase;
}
public void save() {
try {
this.configMapper.serialize(this.root.getNode(GriefDefenderPlugin.MOD_ID));
this.loader.save(this.root);
this.configBase.setRequiresSave(false);
} catch (IOException | ObjectMappingException e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to save configuration", e);
}
}
public void reload() {
try {
this.root = this.loader.load(ConfigurationOptions.defaults());
this.configBase = this.configMapper.populate(this.root.getNode(GriefDefenderPlugin.MOD_ID));
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to load configuration", e);
}
}
}

View File

@ -0,0 +1,130 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.google.common.collect.Maps;
import com.griefdefender.api.permission.Context;
import com.griefdefender.configuration.category.ConfigCategory;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@ConfigSerializable
public class ClaimTemplateConfig extends ConfigCategory {
@Setting(value = "name", comment = "The template name.")
public String templateName;
@Setting(value = "description", comment = "A description to help describe the template.")
public String templateDescription = "";
@Setting(value = ClaimStorageData.MAIN_OWNER_UUID, comment = "The owner uuid that created this template.")
public UUID ownerUniqueId;
@Setting(value = ClaimStorageData.MAIN_CLAIM_DATE_CREATED, comment = "The date and time this template was created.")
public String dateCreated = Instant.now().toString();
@Setting(value = ClaimStorageData.MAIN_ACCESSORS, comment = "The accessors associated with subdivision.")
public ArrayList<UUID> accessors = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_BUILDERS, comment = "The builders associated with subdivision.")
public ArrayList<UUID> builders = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_CONTAINERS, comment = "The containers associated with subdivision.")
public ArrayList<UUID> containers = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_MANAGERS, comment = "The coowners associated with subdivision.")
public ArrayList<UUID> coowners = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_ACCESSOR_GROUPS)
private List<String> accessorGroups = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_BUILDER_GROUPS)
private List<String> builderGroups = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_CONTAINER_GROUPS)
private List<String> containerGroups = new ArrayList<>();
@Setting(value = ClaimStorageData.MAIN_MANAGER_GROUPS)
private List<String> managerGroups = new ArrayList<>();
@Setting(value = "permissions")
private Map<Context, String> permissions = Maps.newHashMap();
public ClaimTemplateConfig() {
}
public UUID getOwnerUniqueId() {
return this.ownerUniqueId;
}
public String getDateCreated() {
return this.dateCreated;
}
public List<UUID> getAccessors() {
return this.accessors;
}
public List<UUID> getBuilders() {
return this.builders;
}
public List<UUID> getContainers() {
return this.containers;
}
public List<UUID> getCoowners() {
return this.coowners;
}
public List<String> getAccessorGroups() {
return this.accessorGroups;
}
public List<String> getBuilderGroups() {
return this.builderGroups;
}
public List<String> getContainerGroups() {
return this.containerGroups;
}
public List<String> getManagerGroups() {
return this.managerGroups;
}
public String getTemplateName() {
return this.templateName;
}
public void setTemplateName(String template) {
this.templateName = template;
}
public String getTemplateDescription() {
return this.templateDescription;
}
public void setTemplateDescription(String description) {
this.templateDescription = description;
}
}

View File

@ -0,0 +1,131 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.storage.FileStorage;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.objectmapping.ObjectMapper;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Optional;
import java.util.UUID;
import java.util.logging.Level;
public class ClaimTemplateStorage {
private HoconConfigurationLoader loader;
private CommentedConfigurationNode root = SimpleCommentedConfigurationNode.root(ConfigurationOptions.defaults()
.setHeader(GriefDefenderPlugin.CONFIG_HEADER));
private ObjectMapper<ClaimTemplateConfig>.BoundInstance configMapper;
private ClaimTemplateConfig configBase;
public Path filePath;
@SuppressWarnings({"unchecked", "rawtypes"})
public ClaimTemplateStorage(Path path) {
this.filePath = path;
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(ClaimTemplateConfig.class).bindToNew();
reload();
save();
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize claim template data", e);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public ClaimTemplateStorage(String templateName, Optional<String> description, IClaimData claimData, UUID creator) {
this.filePath = FileStorage.rootWorldSavePath.resolve(FileStorage.claimTemplatePath.resolve(UUID.randomUUID().toString()));
try {
if (Files.notExists(this.filePath.getParent())) {
Files.createDirectories(this.filePath.getParent());
}
if (Files.notExists(this.filePath)) {
Files.createFile(this.filePath);
}
this.loader = HoconConfigurationLoader.builder().setPath(this.filePath).build();
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(ClaimTemplateConfig.class).bindToNew();
reload();
this.configBase.templateName = templateName;
if (description.isPresent()) {
this.configBase.templateDescription = description.get();
}
this.configBase.ownerUniqueId = creator;
this.configBase.accessors = new ArrayList<UUID>(claimData.getAccessors());
this.configBase.builders = new ArrayList<UUID>(claimData.getBuilders());
this.configBase.containers = new ArrayList<UUID>(claimData.getContainers());
this.configBase.coowners = new ArrayList<UUID>(claimData.getManagers());
//this.configBase.flags = new HashMap<String, Tristate>(claimData.getFlags());
save();
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize claim template data", e);
}
}
public ClaimTemplateConfig getConfig() {
return this.configBase;
}
public void save() {
try {
this.configMapper.serialize(this.root.getNode(GriefDefenderPlugin.MOD_ID));
this.loader.save(this.root);
} catch (IOException | ObjectMappingException e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to save configuration", e);
}
}
public void reload() {
try {
this.root = this.loader.load(ConfigurationOptions.defaults()
.setHeader(GriefDefenderPlugin.CONFIG_HEADER));
this.configBase = this.configMapper.populate(this.root.getNode(GriefDefenderPlugin.MOD_ID));
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to load configuration", e);
}
}
public CommentedConfigurationNode getRootNode() {
return this.root.getNode(GriefDefenderPlugin.MOD_ID);
}
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.google.common.reflect.TypeToken;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.registry.ClaimTypeRegistryModule;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.objectmapping.serialize.TypeSerializer;
public class ClaimTypeSerializer implements TypeSerializer<ClaimType> {
@Override
public ClaimType deserialize(TypeToken<?> type, ConfigurationNode node) throws ObjectMappingException {
ClaimType ret = ClaimTypeRegistryModule.getInstance().getById(node.getString().toLowerCase()).orElse(null);
if (ret == null) {
throw new ObjectMappingException("Input '" + node.getValue() + "' was not a valid value for type " + type);
}
return ret;
}
@Override
public void serialize(TypeToken<?> type, ClaimType obj, ConfigurationNode node) throws ObjectMappingException {
node.setValue(obj.getName());
}
}

View File

@ -0,0 +1,120 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.google.gson.Gson;
import com.griefdefender.api.data.EconomyData;
import com.griefdefender.api.economy.BankTransaction;
import com.griefdefender.configuration.category.ConfigCategory;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.time.Instant;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@ConfigSerializable
public class EconomyDataConfig extends ConfigCategory implements EconomyData {
public GriefDefenderConfig<?> activeConfig;
@Setting(value = ClaimStorageData.MAIN_CLAIM_FOR_SALE)
private boolean forSale = false;
@Setting(value = ClaimStorageData.MAIN_CLAIM_SALE_PRICE)
private double salePrice = 0.0;
@Setting(value = ClaimStorageData.MAIN_TAX_BALANCE)
private double taxBalance = 0.0;
@Setting(value = ClaimStorageData.MAIN_TAX_PAST_DUE_DATE)
private String taxPastDueDate;
@Setting
private List<String> bankTransactionLog = new ArrayList<>();
@Override
public boolean isForSale() {
return this.forSale;
}
@Override
public double getSalePrice() {
return this.salePrice;
}
@Override
public void setForSale(boolean forSale) {
this.forSale = forSale;
}
@Override
public double getTaxBalance() {
return this.taxBalance;
}
@Override
public void setTaxBalance(double balance) {
this.taxBalance = balance;
}
@Override
public Optional<Instant> getTaxPastDueDate() {
if (this.taxPastDueDate == null) {
return Optional.empty();
}
try {
return Optional.of(Instant.parse(this.taxPastDueDate));
} catch (DateTimeParseException e) {
return Optional.empty();
}
}
@Override
public void setTaxPastDueDate(Instant date) {
this.taxPastDueDate = date == null ? null : date.toString();
}
@Override
public void setSalePrice(double price) {
this.salePrice = price;
}
@Override
public List<String> getBankTransactionLog() {
return this.bankTransactionLog;
}
@Override
public void addBankTransaction(BankTransaction transaction) {
if (this.getBankTransactionLog().size() == this.activeConfig.getConfig().claim.bankTransactionLogLimit) {
this.getBankTransactionLog().remove(0);
}
this.getBankTransactionLog().add(new Gson().toJson(transaction));
}
@Override
public void clearBankTransactionLog() {
this.bankTransactionLog.clear();
}
}

View File

@ -0,0 +1,230 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.configuration.type.ConfigBase;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.Types;
import ninja.leaping.configurate.ValueType;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.objectmapping.ObjectMapper;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.util.ConfigurationNodeWalker;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
public class GriefDefenderConfig<T extends ConfigBase> {
private static final ConfigurationOptions LOADER_OPTIONS = ConfigurationOptions.defaults()
.setHeader(GriefDefenderPlugin.CONFIG_HEADER);
private final Path path;
/**
* The parent configuration - values are inherited from this
*/
private final GriefDefenderConfig<?> parent;
/**
* The loader (mapped to a file) used to read/write the config to disk
*/
private HoconConfigurationLoader loader;
/**
* A node representation of "whats actually in the file".
*/
private CommentedConfigurationNode fileData = SimpleCommentedConfigurationNode.root(LOADER_OPTIONS);
/**
* A node representation of {@link #fileData}, merged with the data of {@link #parent}.
*/
private CommentedConfigurationNode data = SimpleCommentedConfigurationNode.root(LOADER_OPTIONS);
/**
* The mapper instance used to populate the config instance
*/
private ObjectMapper<T>.BoundInstance configMapper;
public GriefDefenderConfig(Class<T> clazz, Path path, GriefDefenderConfig<?> parent) {
this.parent = parent;
this.path = path;
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
this.configMapper = ObjectMapper.forClass(clazz).bindToNew();
load();
// In order for the removeDuplicates method to function properly, it is extremely
// important to avoid running save on parent BEFORE children save. Doing so will
// cause duplicate nodes to not be removed properly as parent would have cleaned up
// all duplicates prior.
// To handle the above issue, we only call save for world configs during init.
if (parent != null && parent.parent != null) {
save();
}
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().severe("Failed to load configuration at path " + path.toAbsolutePath());
e.printStackTrace();
}
}
public T getConfig() {
return this.configMapper.getInstance();
}
public boolean save() {
try {
// save from the mapped object --> node
CommentedConfigurationNode saveNode = SimpleCommentedConfigurationNode.root(LOADER_OPTIONS);
this.configMapper.serialize(saveNode.getNode(GriefDefenderPlugin.MOD_ID));
// before saving this config, remove any values already declared with the same value on the parent
if (this.parent != null) {
removeDuplicates(saveNode);
}
// save the data to disk
this.loader.save(saveNode);
// In order for the removeDuplicates method to function properly, it is extremely
// important to avoid running save on parent BEFORE children save. Doing so will
// cause duplicate nodes to not be removed as parent would have cleaned up
// all duplicates prior.
// To handle the above issue, we save AFTER saving child config.
if (this.parent != null) {
this.parent.save();
}
return true;
} catch (IOException | ObjectMappingException e) {
GriefDefenderPlugin.getInstance().getLogger().severe("Failed to save configuration");
e.printStackTrace();
return false;
}
}
public void load() throws IOException, ObjectMappingException {
// load settings from file
CommentedConfigurationNode loadedNode = this.loader.load();
// store "what's in the file" separately in memory
this.fileData = loadedNode;
// make a copy of the file data
this.data = this.fileData.copy();
// merge with settings from parent
if (this.parent != null) {
this.parent.load();
this.data.mergeValuesFrom(this.parent.data);
}
// populate the config object
populateInstance();
}
private void populateInstance() throws ObjectMappingException {
this.configMapper.populate(this.data.getNode(GriefDefenderPlugin.MOD_ID));
}
/**
* Traverses the given {@code root} config node, removing any values which
* are also present and set to the same value on this configs "parent".
*
* @param root The node to process
*/
private void removeDuplicates(CommentedConfigurationNode root) {
if (this.parent == null) {
throw new IllegalStateException("parent is null");
}
Iterator<ConfigurationNodeWalker.VisitedNode<CommentedConfigurationNode>> it = ConfigurationNodeWalker.DEPTH_FIRST_POST_ORDER.walkWithPath(root);
while (it.hasNext()) {
ConfigurationNodeWalker.VisitedNode<CommentedConfigurationNode> next = it.next();
CommentedConfigurationNode node = next.getNode();
// remove empty maps
if (node.hasMapChildren()) {
if (node.getChildrenMap().isEmpty()) {
node.setValue(null);
}
continue;
}
// ignore list values
if (node.getParent() != null && node.getParent().getValueType() == ValueType.LIST) {
continue;
}
// if the node already exists in the parent config, remove it
CommentedConfigurationNode parentValue = this.parent.data.getNode(next.getPath().getArray());
if (Objects.equals(node.getValue(), parentValue.getValue())) {
node.setValue(null);
} else {
// Fix list bug
if (parentValue.getValue() == null) {
if (node.getValueType() == ValueType.LIST) {
final List<?> nodeList = (List<?>) node.getValue();
if (nodeList.isEmpty()) {
node.setValue(null);
}
continue;
}
}
// Fix double bug
final Double nodeVal = node.getValue(Types::asDouble);
if (nodeVal != null) {
Double parentVal = parentValue.getValue(Types::asDouble);
if (parentVal == null && nodeVal.doubleValue() == 0 || (parentVal != null && nodeVal.doubleValue() == parentVal.doubleValue())) {
node.setValue(null);
continue;
}
}
}
}
}
public CommentedConfigurationNode getRootNode() {
return this.data.getNode(GriefDefenderPlugin.MOD_ID);
}
public Path getPath() {
return this.path;
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.data.ClaimData;
import java.util.List;
import java.util.UUID;
public interface IClaimData extends ClaimData {
boolean requiresSave();
boolean isExpired();
List<UUID> getAccessors();
List<UUID> getBuilders();
List<UUID> getContainers();
List<UUID> getManagers();
List<String> getAccessorGroups();
List<String> getBuilderGroups();
List<String> getContainerGroups();
List<String> getManagerGroups();
void setOwnerUniqueId(UUID newClaimOwner);
void setWorldUniqueId(UUID uuid);
void setType(ClaimType type);
void setCuboid(boolean cuboid);
void setLesserBoundaryCorner(String location);
void setGreaterBoundaryCorner(String location);
void setAccessors(List<UUID> accessors);
void setBuilders(List<UUID> builders);
void setContainers(List<UUID> containers);
void setManagers(List<UUID> coowners);
void setRequiresSave(boolean flag);
void setExpired(boolean expire);
}

View File

@ -0,0 +1,657 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.configuration.category.ConfigCategory;
import com.griefdefender.text.TextTemplate;
import net.kyori.text.format.TextColor;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ConfigSerializable
public class MessageDataConfig extends ConfigCategory {
@Setting(MessageStorage.ABANDON_OTHER_SUCCESS)
public TextTemplate abandonOtherSuccess = TextTemplate.of(TextColor.GREEN, TextTemplate.arg("player"), "'s claim has been abandoned.", TextTemplate.arg("player"), " now has ", TextTemplate.arg("total"), " available claim blocks.");
@Setting(MessageStorage.ADJUST_BLOCKS_SUCCESS)
public TextTemplate adjustBlocksSuccess = TextTemplate.of(TextColor.GREEN, "Adjusted ", TextTemplate.arg("player"), "'s bonus claim blocks by ", TextTemplate.arg("adjustment"), ". New total bonus blocks: ", TextTemplate.arg("total"), ".");
@Setting(MessageStorage.BLOCK_CLAIMED)
public TextTemplate blockClaimed = TextTemplate.of(TextColor.GREEN, "That block has been claimed by ", TextTemplate.arg("owner").color(TextColor.GOLD), ".");
@Setting("block-not-claimed")
public TextTemplate blockNotClaimed = TextTemplate.of(TextColor.RED, "No one has claimed this block.");
@Setting(MessageStorage.BLOCK_SALE_VALUE)
public TextTemplate blockSaleValue = TextTemplate.of(TextColor.GREEN, "Each claim block is worth ", TextTemplate.arg("block-value"), ". You have ", TextTemplate.arg("available-blocks"), " available for sale.");
@Setting(MessageStorage.CLAIM_ABANDON_SUCCESS)
public TextTemplate claimAbandonSuccess = TextTemplate.of(TextColor.GREEN, "Claim abandoned. You now have ", TextTemplate.arg("remaining-blocks"), " available claim blocks.");
@Setting("claim-automatic-notification")
public TextTemplate claimAutomaticNotification = TextTemplate.of(TextColor.RED, "This chest and nearby blocks are protected from breakage and theft.");
@Setting("claim-bank-tax-system-not-enabled")
public TextTemplate claimBankTaxSystemNotEnabled = TextTemplate.of(TextColor.RED, "The bank/tax system is not enabled. If you want it enabled, set 'bank-tax-system' to true in config.");
@Setting("claim-bank-info")
public TextTemplate claimBankInfo = TextTemplate.of(TextColor.GREEN, "Balance: ", TextTemplate.arg("balance").color(TextColor.GOLD),
TextColor.GREEN, "\nTax: ", TextTemplate.arg("amount").color(TextColor.GOLD), TextColor.WHITE, " due in ", TextTemplate.arg("time_remaining").color(TextColor.GRAY),
TextColor.GREEN, "\nTax Owed: ", TextTemplate.arg("tax_balance").color(TextColor.GOLD));
@Setting("claim-bank-deposit")
public TextTemplate claimBankDeposit = TextTemplate.of(TextColor.GREEN, "Successful deposit of ", TextTemplate.arg("amount").color(TextColor.GOLD), " into bank.");
@Setting("claim-bank-deposit-no-funds")
public TextTemplate claimBankDepositNoFunds = TextTemplate.of(TextColor.RED, "You do not have enough funds to deposit into the bank.");
@Setting("claim-bank-no-permission")
public TextTemplate claimBankNoPermission = TextTemplate.of(TextColor.RED, "You don't have permission to manage", TextTemplate.arg("owner"), "'s claim bank.");
@Setting("claim-bank-withdraw")
public TextTemplate claimBankWithdraw = TextTemplate.of(TextColor.GREEN, "Successful withdraw of ", TextTemplate.arg("amount").color(TextColor.GOLD), " from bank.");
@Setting("claim-bank-withdraw-no-funds")
public TextTemplate claimBankWithdrawNoFunds = TextTemplate.of(TextColor.RED, "The claim bank has a remaining balance of ", TextTemplate.arg("balance").color(TextColor.GOLD), " and does not have enough funds to withdraw ", TextTemplate.arg("amount").color(TextColor.GOLD), ".");
@Setting("claim-block-purchase-limit")
public TextTemplate claimBlockPurchaseLimit = TextTemplate.of(TextColor.RED, "The new claim block total of ", TextTemplate.arg("new_total").color(TextColor.GOLD), " will exceed your claim block limit of ", TextTemplate.arg("block_limit").color(TextColor.GREEN), ". The transaction has been cancelled.");
@Setting("claim-chest-confirmation")
public TextTemplate claimChestConfirmation = TextTemplate.of(TextColor.RED, "This chest is protected.");
@Setting("claim-chest-outside-level")
public TextTemplate claimChestOutsideLevel = TextTemplate.of(TextColor.RED, "This chest can't be protected as the position is outside your claim level limits of ", TextTemplate.arg("min-claim-level").color(TextColor.GREEN), " and ", TextTemplate.arg("max-claim-level").color(TextColor.GREEN), ". (/playerinfo)");
@Setting("claim-children-warning")
public TextTemplate claimChildrenWarning = TextTemplate.of(TextColor.AQUA, "This claim includes child claims. If you're sure you want to delete it, use /DeleteClaim again.");
@Setting("claim-create-only-subdivision")
public TextTemplate claimCreateOnlySubdivision = TextTemplate.of(TextColor.RED, "Unable to create claim. Only subdivisions can be created at a single block location.");
@Setting("claim-create-cuboid-disabled")
public TextTemplate claimCreateCuboidDisabled = TextTemplate.of(TextColor.RED, "The creation of 3D cuboid claims has been disabled by an administrator.\nYou can only create 3D claims as an Admin or on a 2D claim that you own.");
@Setting("claim-create-overlap")
public TextTemplate claimCreateOverlap = TextTemplate.of(TextColor.RED, "You can't create a claim here because it would overlap your other claim. Use /abandonclaim to delete it, or use your shovel at a corner to resize it.");
@Setting("claim-create-overlap-player")
public TextTemplate claimCreateOverlapPlayer = TextTemplate.of(TextColor.RED, "You can't create a claim here because it would overlap ", TextTemplate.arg("owner"), "'s claim.");
@Setting("claim-create-overlap-short")
public TextTemplate claimCreateOverlapShort = TextTemplate.of(TextColor.RED, "Your selected area overlaps an existing claim.");
@Setting("claim-create-success")
public TextTemplate claimCreateSuccess = TextTemplate.of(TextColor.GREEN, TextTemplate.arg("type"), " created! Use /trust to share it with friends.");
@Setting("claim-create-error-result")
public TextTemplate claimCreateErrorResult = TextTemplate.of(TextColor.RED, "Unable to create claim due to error result ", TextTemplate.arg("result"), ".");
@Setting("claim-cleanup-warning")
public TextTemplate claimCleanupWarning = TextTemplate.of(TextColor.RED, "The land you've unclaimed may be changed by other players or cleaned up by administrators. If you've built something there you want to keep, you should reclaim it.");
@Setting("claim-context-not-found")
public TextTemplate claimContextNotFound = TextTemplate.of(TextColor.RED, "Context '", TextTemplate.arg("context"), "' was not found.");
@Setting(MessageStorage.CLAIM_SIZE_MAX_X)
public TextTemplate claimSizeMaxX = TextTemplate.of(TextColor.RED, "The claim x size of ", TextTemplate.arg("size").color(TextColor.GREEN), " exceeds the max size of ", TextTemplate.arg("max-size").color(TextColor.GREEN), ".\nThe area needs to be a mininum of ", TextTemplate.arg("min-area").color(TextColor.GREEN), " and a max of ", TextTemplate.arg("max-area").color(TextColor.GREEN));
@Setting(MessageStorage.CLAIM_SIZE_MAX_Y)
public TextTemplate claimSizeMaxY = TextTemplate.of(TextColor.RED, "The claim y size of ", TextTemplate.arg("size").color(TextColor.GREEN), " exceeds the max size of ", TextTemplate.arg("max-size").color(TextColor.GREEN), ".\nThe area needs to be a minimum of ", TextTemplate.arg("min-area").color(TextColor.GREEN), " and a max of ", TextTemplate.arg("max-area").color(TextColor.GREEN));
@Setting(MessageStorage.CLAIM_SIZE_MAX_Z)
public TextTemplate claimSizeMaxZ = TextTemplate.of(TextColor.RED, "The claim z size of ", TextTemplate.arg("size").color(TextColor.GREEN), " exceeds the max size of ", TextTemplate.arg("max-size").color(TextColor.GREEN), ".\nThe area needs to be a minimum of ", TextTemplate.arg("min-area").color(TextColor.GREEN), " and a max of ", TextTemplate.arg("max-area").color(TextColor.GREEN));
@Setting(MessageStorage.CLAIM_SIZE_MIN_X)
public TextTemplate claimSizeMinX = TextTemplate.of(TextColor.RED, "The claim x size of ", TextTemplate.arg("size").color(TextColor.GREEN), " is below the minimum size of ", TextTemplate.arg("min-size").color(TextColor.GREEN), ".\nThe area needs to be a minimum of ", TextTemplate.arg("min-area").color(TextColor.GREEN), " and a max of ", TextTemplate.arg("max-area").color(TextColor.GREEN));
@Setting(MessageStorage.CLAIM_SIZE_MIN_Y)
public TextTemplate claimSizeMinY = TextTemplate.of(TextColor.RED, "The claim y size of ", TextTemplate.arg("size").color(TextColor.GREEN), " is below the minimum size of ", TextTemplate.arg("min-size").color(TextColor.GREEN), ".\nThe area needs to be a minimum of ", TextTemplate.arg("min-area").color(TextColor.GREEN), " and a max of ", TextTemplate.arg("max-area").color(TextColor.GREEN));
@Setting(MessageStorage.CLAIM_SIZE_MIN_Z)
public TextTemplate claimSizeMinZ = TextTemplate.of(TextColor.RED, "The claim z size of ", TextTemplate.arg("size").color(TextColor.GREEN), " is below the minimum size of ", TextTemplate.arg("min-size").color(TextColor.GREEN), ".\nThe area needs to be a minimum of ", TextTemplate.arg("min-area").color(TextColor.GREEN), " and a max of ", TextTemplate.arg("max-area").color(TextColor.GREEN));
@Setting(MessageStorage.CLAIM_SIZE_TOO_SMALL)
public TextTemplate claimSizeTooSmall = TextTemplate.of(TextColor.RED, "The selected claim size of ", TextTemplate.arg("width"), "x", TextTemplate.arg("length"), " would be too small. A claim must be at least ", TextTemplate.arg("minimum-width"), "x", TextTemplate.arg("minimum-length"), " in size.");
@Setting("claim-create-cancel")
public TextTemplate claimCreateCancel = TextTemplate.of(TextColor.RED, "A plugin has denied the creation of this claim.");
@Setting("claim-create-failed-claim-limit")
public TextTemplate claimCreateFailedLimit = TextTemplate.of(TextColor.RED, "You've reached your limit on land claims. Use /AbandonClaim to remove one before creating another.");
@Setting(MessageStorage.CLAIM_CREATE_INSUFFICIENT_BLOCKS_2D)
public TextTemplate claimCreateInsufficientBlocks2d = TextTemplate.of(TextColor.RED, "You don't have enough blocks to claim this area.\nYou need ", TextTemplate.arg("remaining-blocks").color(TextColor.GOLD), " more blocks.");
@Setting(MessageStorage.CLAIM_CREATE_INSUFFICIENT_BLOCKS_3D)
public TextTemplate claimCreateInsufficientBlocks3d = TextTemplate.of(TextColor.RED, "You don't have enough blocks to claim this area.\nYou need ", TextTemplate.arg("remaining-chunks").color(TextColor.GOLD), " more chunks. (", TextTemplate.arg("remaining-blocks").color(TextColor.WHITE), " blocks)");
@Setting("claim-create-subdivision-fail")
public TextTemplate claimCreateSubdivisionFail = TextTemplate.of(TextColor.RED, "No claim exists at selected corner. Please click a valid block location within parent claim in order to create your subdivision.");
@Setting("claim-delete-all-admin-success")
public TextTemplate claimDeleteAllAdminSuccess = TextTemplate.of("Deleted all administrative claims.");
@Setting("claim-delete-all-success")
public TextTemplate claimDeleteAllSuccess = TextTemplate.of("Deleted all of ", TextTemplate.arg("owner"), "'s claims.");
@Setting("claim-protected-entity")
public TextTemplate claimProtectedEntity = TextTemplate.of(TextColor.RED, "That belongs to ", TextTemplate.arg("owner"), ".");
@Setting("claim-farewell")
public TextTemplate claimFarewell = TextTemplate.of(TextColor.GREEN, "Set claim farewell to ", TextTemplate.arg("farewell").optional(), ".");
@Setting("claim-greeting")
public TextTemplate claimGreeting = TextTemplate.of(TextColor.GREEN, "Set claim greeting to ", TextTemplate.arg("greeting").optional(), ".");
@Setting("claim-farewell-clear")
public TextTemplate claimFarewellClear = TextTemplate.of(TextColor.GREEN, "The claim farewell message has been cleared.");
@Setting("claim-greeting-clear")
public TextTemplate claimGreetingClear = TextTemplate.of(TextColor.GREEN, "The claim greeting message has been cleared.");
@Setting("claim-ignore")
public TextTemplate claimIgnore = TextTemplate.of(TextColor.GREEN, "Now ignoring claims.");
@Setting("claim-last-active")
public TextTemplate claimLastActive = TextTemplate.of(TextColor.GREEN, "Claim last active ", TextTemplate.arg("date"), ".");
@Setting("claim-mode-admin")
public TextTemplate claimModeAdmin = TextTemplate.of(TextColor.GREEN, "Administrative claims mode active. Any claims created will be free and editable by other administrators.");
@Setting("claim-mode-basic")
public TextTemplate claimModeBasic = TextTemplate.of(TextColor.GREEN, "Basic claim creation mode enabled.");
@Setting("claim-mode-subdivision")
public TextTemplate claimModeSubdivision = TextTemplate.of(TextColor.GREEN, "Subdivision mode. Use your shovel to create subdivisions in your existing claims. Use /modebasic to exit.");
@Setting("claim-mode-town")
public TextTemplate claimModeTown = TextTemplate.of(TextColor.GREEN, "Town creation mode enabled.");
@Setting("claim-type-not-found")
public TextTemplate claimTypeNotFound = TextTemplate.of(TextColor.RED, "No ", TextTemplate.arg("type"), " claims found.");
@Setting("claim-not-found")
public TextTemplate claimNotFound = TextTemplate.of(TextColor.RED, "There's no claim here.");
@Setting("claim-not-yours")
public TextTemplate claimNotYours = TextTemplate.of(TextColor.RED, "This isn't your claim.");
@Setting("claim-no-claims")
public TextTemplate claimNoClaims = TextTemplate.of(TextColor.RED, "You don't have any land claims.");
@Setting("claim-owner-already")
public TextTemplate claimOwnerAlready = TextTemplate.of(TextColor.RED, "You are already the claim owner.");
@Setting("claim-owner-only")
public TextTemplate claimOwnerOnly = TextTemplate.of(TextColor.RED, "Only ", TextTemplate.arg("owner"), " can modify this claim.");
@Setting(MessageStorage.CLAIM_SIZE_NEED_BLOCKS_2D)
public TextTemplate claimSizeNeedBlocks2d = TextTemplate.of(TextColor.RED, "You don't have enough blocks for this claim size.\nYou need ", TextTemplate.arg("blocks").color(TextColor.GREEN), " more blocks.");
@Setting(MessageStorage.CLAIM_SIZE_NEED_BLOCKS_3D)
public TextTemplate claimSizeNeedBlocks3d = TextTemplate.of(TextColor.RED, "You don't have enough blocks for this claim size.\nYou need ", TextTemplate.arg("chunks").color(TextColor.GREEN), " more chunks. (", TextTemplate.arg("blocks").color(TextColor.WHITE), " blocks)");
@Setting("claim-resize-same-location")
public TextTemplate claimResizeSameLocation = TextTemplate.of(TextColor.RED, "You must select a different block location to resize claim.");
@Setting("claim-resize-overlap-subdivision")
public TextTemplate claimResizeOverlapSubdivision = TextTemplate.of(TextColor.RED, "You can't create a subdivision here because it would overlap another subdivision. Consider /abandonclaim to delete it, or use " + "your shovel at a corner to resize it.");
@Setting("claim-resize-overlap")
public TextTemplate claimResizeOverlap = TextTemplate.of(TextColor.RED, "Can't resize here because it would overlap another nearby claim.");
@Setting("claim-resize-start")
public TextTemplate claimResizeStart = TextTemplate.of(TextColor.GREEN, "Resizing claim. Use your shovel again at the new location for this corner.");
@Setting("claim-resize-success-2d")
public TextTemplate claimResizeSuccess = TextTemplate.of(TextColor.GREEN, "Claim resized. You have ", TextTemplate.arg("remaining-blocks").color(TextColor.GOLD), " more blocks remaining.");
@Setting(MessageStorage.CLAIM_RESIZE_SUCCESS_3D)
public TextTemplate claimResizeSuccess3d = TextTemplate.of(TextColor.GREEN, "Claim resized. You have ", TextTemplate.arg("remaining-chunks").color(TextColor.GOLD), " more chunks remaining.\n(", TextTemplate.arg("remaining-blocks").color(TextColor.WHITE), " blocks)");
@Setting("claim-respecting")
public TextTemplate claimRespecting = TextTemplate.of(TextColor.GREEN, "Now respecting claims.");
@Setting("claim-restore-success")
public TextTemplate claimRestoreSuccess = TextTemplate.of(TextColor.GREEN, "Successfully restored claim.");
@Setting("claim-show-nearby")
public TextTemplate claimShowNearby = TextTemplate.of(TextColor.GREEN, "Found ", TextTemplate.arg("claim-count"), " land claims.");
@Setting("claim-start")
public TextTemplate claimStart = TextTemplate.of(TextColor.GREEN, TextTemplate.arg("type"), " corner set! Use the shovel again at the opposite corner to claim a rectangle of land. To cancel, put your shovel away.");
@Setting(MessageStorage.CLAIM_ABOVE_LEVEL)
public TextTemplate claimAboveLevel = TextTemplate.of(TextColor.RED, "Unable to claim block as it is above your maximum claim level limit of ", TextTemplate.arg("claim-level").color(TextColor.GREEN), ". (/playerinfo)");
@Setting(MessageStorage.CLAIM_BELOW_LEVEL)
public TextTemplate claimBelowLevel = TextTemplate.of(TextColor.RED, "Unable to claim block as it is below your minimum claim level limit of ", TextTemplate.arg("claim-level").color(TextColor.GREEN), ". (/playerinfo)");
@Setting("claim-too-far")
public TextTemplate claimTooFar = TextTemplate.of(TextColor.RED, "That's too far away.");
@Setting("claim-transfer-success")
public TextTemplate claimTransferSuccess = TextTemplate.of(TextColor.GREEN, "Claim transferred.");
@Setting("claim-transfer-exceeds-limit")
public TextTemplate claimTransferExceedsLimit = TextTemplate.of(TextColor.RED, "Claim could not be transferred as it would exceed the new owner's creation limit.");
@Setting("claim-deleted")
public TextTemplate claimDeleted = TextTemplate.of(TextColor.GREEN, "Claim deleted.");
@Setting("claim-disabled-world")
public TextTemplate claimDisabledWorld = TextTemplate.of(TextColor.RED, "Claims are disabled in this world.");
@Setting("command-abandon-claim-missing")
public TextTemplate commandAbandonClaimMissing = TextTemplate.of("Stand in the claim you want to delete, or consider /abandonall.");
@Setting("command-abandon-top-level")
public TextTemplate commandAbandonTopLevel = TextTemplate.of(TextColor.RED, "This claim cannot be abandoned as it contains one or more child claims. In order to abandon a claim with child claims, you must use /abandontop instead.");
@Setting("command-abandon-town-children")
public TextTemplate commandAbandonTownChildren = TextTemplate.of(TextColor.RED, "You do not have permission to abandon a town with child claims you do not own. Use /ignoreclaims or have the child claim owner abandon their claim first. If you just want to abandon the town without affecting children then use /abandonclaim instead.");
@Setting("command-blocked")
public TextTemplate commandBlocked = TextTemplate.of(TextColor.RED, "The command ", TextTemplate.arg("command"), " has been blocked by claim owner ", TextTemplate.arg("owner"), ".");
@Setting("command-create-worldedit")
public TextTemplate commandCreateWorldEdit = TextTemplate.of(TextColor.RED, "This command requires WorldEdit to be installed on server.");
@Setting("command-farewell")
public TextTemplate commandFarewell = TextTemplate.of(TextColor.GREEN, "Claim flag ", TextTemplate.arg("flag").optional(), " is invalid.");
@Setting("command-greeting")
public TextTemplate commandGreeting = TextTemplate.of(TextColor.GREEN, "Set claim greeting to ", TextTemplate.arg("greeting").optional(), ".");
@Setting("command-group-invalid")
public TextTemplate commandGroupInvalid = TextTemplate.of(TextColor.RED, "Group ", TextTemplate.arg("group"), " is not valid.");
@Setting("command-inherit")
public TextTemplate commandInherit = TextTemplate.of(TextColor.RED, "This command can only be used in child claims.");
@Setting("command-claim-name")
public TextTemplate commandClaimName = TextTemplate.of(TextColor.GREEN, "Set claim name to ", TextTemplate.arg("name"), ".");
@Setting("command-option-exceeds-admin")
public TextTemplate commandOptionExceedsAdmin = TextTemplate.of(TextColor.RED, "Option value of ", TextTemplate.arg("original_value").color(TextColor.GREEN), " exceeds admin set value of '", TextTemplate.arg("admin_value").color(TextColor.GREEN),"'. Adjusting to admin value...");
@Setting("command-option-invalid-claim")
public TextTemplate commandOptionInvalidClaim = TextTemplate.of(TextColor.RED, "This command cannot be used in subdivisions.");
@Setting("command-player-invalid")
public TextTemplate commandPlayerInvalid = TextTemplate.of(TextColor.RED, "Player ", TextTemplate.arg("player"), " is not valid.");
@Setting("command-acb-success")
public TextTemplate commandAcbSuccess = TextTemplate.of(TextColor.GREEN, "Updated accrued claim blocks.");
@Setting("command-spawn-not-set")
public TextTemplate commandSpawnNotSet = TextTemplate.of(TextColor.RED, "No claim spawn has been set.");
@Setting("command-spawn-set-success")
public TextTemplate commandSpawnSet = TextTemplate.of(TextColor.GREEN, "Successfully set claim spawn to ", TextTemplate.arg("location"), ".");
@Setting("command-spawn-teleport")
public TextTemplate commandSpawnTeleport = TextTemplate.of(TextColor.GREEN, "Teleported to claim spawn at ", TextTemplate.arg("location"), ".");
@Setting("cuboid-claim-disabled")
public TextTemplate claimCuboidDisabled = TextTemplate.of(TextColor.GREEN, "Now claiming in 2D mode.");
@Setting("cuboid-claim-enabled")
public TextTemplate claimCuboidEnabled = TextTemplate.of(TextColor.GREEN, "Now claiming in 3D mode.");
@Setting("economy-not-enough-funds")
public TextTemplate economyNotEnoughFunds = TextTemplate.of(TextColor.RED, "You do not have enough funds to purchase this land. Your current economy balance is '", TextTemplate.arg("balance").color(TextColor.GOLD), "' but you require '", TextTemplate.arg("cost").color(TextColor.GREEN), "' to complete the purchase.");
@Setting("economy-blocks-purchase-cost")
public TextTemplate economyBlockPurchaseCost = TextTemplate.of("Each claim block costs ", TextTemplate.arg("cost"), ". Your balance is ", TextTemplate.arg("balance"), ".");
@Setting("economy-blocks-not-available")
public TextTemplate economyBlocksNotAvailable = TextTemplate.of(TextColor.RED, "You don't have that many claim blocks available for sale.");
@Setting("economy-blocks-buy-sell-not-configured")
public TextTemplate economyBuySellNotConfigured = TextTemplate.of(TextColor.RED, "Sorry, buying and selling claim blocks is disabled.");
@Setting("economy-blocks-buy-invalid-count")
public TextTemplate economyBuyInvalidBlockCount = TextTemplate.of(TextColor.RED, "Block count must be greater than 0.");
@Setting("economy-not-installed")
public TextTemplate economyNotInstalled = TextTemplate.of(TextColor.RED, "Economy plugin not installed!.");
@Setting("economy-blocks-only-buy")
public TextTemplate economyOnlyBuyBlocks = TextTemplate.of(TextColor.RED, "Claim blocks may only be purchased, not sold.");
@Setting("economy-blocks-only-sell")
public TextTemplate economyOnlySellBlocks = TextTemplate.of(TextColor.RED, "Claim blocks may only be sold, not purchased.");
@Setting("economy-blocks-purchase-confirmation")
public TextTemplate economyBlocksPurchaseConfirmation = TextTemplate.of(TextColor.GREEN, "Withdrew ", TextTemplate.arg("cost"), " from your account. You now have ", TextTemplate.arg("remaining-blocks"), " available claim blocks.");
@Setting("economy-blocks-sale-confirmation")
public TextTemplate economyBlockSaleConfirmation = TextTemplate.of(TextColor.GREEN, "Deposited ", TextTemplate.arg("deposit"), " in your account. You now have ", TextTemplate.arg("remaining-blocks"), " available claim blocks.");
@Setting("economy-blocks-sell-error")
public TextTemplate economyBlockSellError = TextTemplate.of(TextColor.RED, "Could not sell blocks. Reason: ", TextTemplate.arg("reason"), ".");
@Setting("economy-claim-abandon-success")
public TextTemplate economyClaimAbandonSuccess = TextTemplate.of(TextColor.GREEN, "Claim(s) abandoned. You have been refunded a total of '", TextTemplate.arg("refund").color(TextColor.GOLD), "'.");
@Setting("economy-claim-not-for-sale")
public TextTemplate economyClaimNotForSale = TextTemplate.of(TextColor.RED, "This claim is not for sale.");
@Setting("economy-claim-buy-not-enough-funds")
public TextTemplate economyClaimBuyNotEnoughFunds = TextTemplate.of(TextColor.RED, "You do not have enough funds to purchase this claim for ", TextTemplate.arg("sale_price").color(TextColor.GOLD), ". You currently have a balance of ", TextTemplate.arg("balance").color(TextColor.GOLD), " and need ", TextTemplate.arg("amount_needed").color(TextColor.GOLD), " more for purchase.");
@Setting("economy-claim-buy-confirmation")
public TextTemplate economyClaimBuyConfirmation = TextTemplate.of(TextColor.GREEN, "Are you sure you want to buy this claim for ", TextTemplate.arg("sale_price").color(TextColor.GOLD), " ? Click confirm to proceed.");
@Setting("economy-claim-buy-confirmed")
public TextTemplate economyClaimBuyConfirmed = TextTemplate.of(TextColor.GREEN, "You have successfully bought the claim for ", TextTemplate.arg("sale_price").color(TextColor.GOLD), ".");
@Setting("economy-claim-sale-cancelled")
public TextTemplate economyClaimSaleCancelled = TextTemplate.of(TextColor.GREEN, "You have cancelled your claim sale.");
@Setting("economy-claim-sale-confirmation")
public TextTemplate economyClaimSaleConfirmation = TextTemplate.of(TextColor.GREEN, "Are you sure you want to sell your claim for ", TextTemplate.arg("sale_price").color(TextColor.GOLD), " ? If your claim is sold, all items and blocks will be transferred to the buyer. Click confirm if this is OK.");
@Setting(MessageStorage.ECONOMY_CLAIM_SALE_CONFIRMED)
public TextTemplate economyClaimSaleConfirmed = TextTemplate.of(TextColor.GREEN, "You have successfully put your claim up for sale for the amount of ", TextTemplate.arg("sale_price").color(TextColor.GOLD), ".");
@Setting("economy-claim-sale-invalid-price")
public TextTemplate economyClaimSaleInvalidPrice = TextTemplate.of(TextColor.RED, "The sale price of, ", TextTemplate.arg("sale_price").color(TextColor.GOLD), " must be greater than or equal to 0.");
@Setting("economy-claim-sold")
public TextTemplate economyClaimSold = TextTemplate.of(TextColor.GREEN, "Your claim sold! The amount of ", TextTemplate.arg("amount").color(TextColor.GOLD), " has been deposited into your account. Your total available balance is now ", TextTemplate.arg("balance").color(TextColor.GOLD));
@Setting(MessageStorage.ECONOMY_USER_NOT_FOUND)
public TextTemplate economyUserNotFound = TextTemplate.of(TextColor.RED, "No economy account found for user ", TextTemplate.arg("user"), ".");
@Setting("economy-withdraw-error")
public TextTemplate economyWithdrawError = TextTemplate.of(TextColor.RED, "Could not withdraw funds. Reason: ", TextTemplate.arg("reason"), ".");
@Setting("economy-virtual-not-supported")
public TextTemplate economyVirtualNotSupported = TextTemplate.of(TextColor.RED, "Economy plugin does not support virtual accounts which is required. Use another economy plugin or contact plugin dev for virtual account support.");
@Setting("flag-invalid-context")
public TextTemplate flagInvalidContext = TextTemplate.of(TextColor.RED, "Invalid context '", TextTemplate.arg("context") + "' entered for base flag ", TextTemplate.arg("flag"), ".");
@Setting("flag-invalid-meta")
public TextTemplate flagInvalidMeta = TextTemplate.of(TextColor.RED, "Invalid target meta '", TextTemplate.arg("meta") + "' entered for base flag ", TextTemplate.arg("flag"), ".");
@Setting("flag-invalid-target")
public TextTemplate flagInvalidTarget = TextTemplate.of(TextColor.RED, "Invalid target '", TextTemplate.arg("target"), "' entered for base flag ", TextTemplate.arg("flag"), ".");
@Setting("flag-overridden")
public TextTemplate flagOverridden = TextTemplate.of(TextColor.RED, "Failed to set claim flag. The flag ", TextTemplate.arg("flag"), " has been overridden by an admin.");
@Setting("flag-overrides-not-supported")
public TextTemplate flagOverridesNotSupported = TextTemplate.of("Claim type ", TextTemplate.arg("type"), " does not support flag overrides.");
@Setting("flag-reset-success")
public TextTemplate flagResetSuccess = TextTemplate.of(TextColor.GREEN, "Claim flags reset to defaults successfully.");
@Setting("nucleus-no-sethome")
public TextTemplate nucleusNoSetHome = TextTemplate.of(TextColor.RED, "You must be trusted in order to use /sethome here.");
@Setting("owner-admin")
public TextTemplate ownerAdmin = TextTemplate.of("an administrator");
@Setting("permission-access")
public TextTemplate permissionAccess = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("player").color(TextColor.GOLD), "'s permission to access that.");
@Setting("permission-build")
public TextTemplate permissionBuild = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("player").color(TextColor.GOLD), "'s permission to build.");
@Setting("permission-build-near-claim")
public TextTemplate permissionBuildNearClaim = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner").color(TextColor.GOLD), "'s permission to build near claim.");
@Setting("permission-claim-create")
public TextTemplate permissionClaimCreate = TextTemplate.of(TextColor.RED, "You don't have permission to claim land.");
@Setting("permission-claim-delete")
public TextTemplate permissionClaimDelete = TextTemplate.of(TextColor.RED, "You don't have permission to delete ", TextTemplate.arg("type"), " claims.");
@Setting("permission-claim-enter")
public TextTemplate permissionClaimEnter = TextTemplate.of(TextColor.RED, "You don't have permission to enter this claim.");
@Setting("permission-claim-exit")
public TextTemplate permissionClaimExit = TextTemplate.of(TextColor.RED, "You don't have permission to exit this claim.");
@Setting("permission-claim-ignore")
public TextTemplate permissionClaimIgnore = TextTemplate.of(TextColor.RED, "You do not have permission to ignore ", TextTemplate.arg("type"), " claims.");
@Setting("permission-claim-list")
public TextTemplate permissionClaimList = TextTemplate.of(TextColor.RED, "You don't have permission to get information about another player's land claims.");
@Setting("permission-claim-manage")
public TextTemplate permissionClaimManage = TextTemplate.of(TextColor.RED, "You don't have permission to manage ", TextTemplate.arg("type"), " claims.");
@Setting("permission-claim-reset-flags")
public TextTemplate permissionClaimResetFlags = TextTemplate.of(TextColor.RED, "You don't have permission to reset ", TextTemplate.arg("type"), " claims to flag defaults.");
@Setting("permission-claim-reset-flags-self")
public TextTemplate permissionClaimResetFlagsSelf = TextTemplate.of(TextColor.RED, "You don't have permission to reset your claim flags to defaults.");
@Setting("permission-claim-resize")
public TextTemplate permissionClaimResize = TextTemplate.of(TextColor.RED, "You don't have permission to resize this claim.");
@Setting("permission-claim-sale")
public TextTemplate permissionClaimSale = TextTemplate.of(TextColor.RED, "You don't have permission to sell this claim.");
@Setting("permission-claim-transfer-admin")
public TextTemplate permissionClaimTransferAdmin = TextTemplate.of(TextColor.RED, "You don't have permission to transfer admin claims.");
@Setting("permission-clear-all")
public TextTemplate permissionClearAll = TextTemplate.of(TextColor.RED, "Only the claim owner can clear all permissions.");
@Setting("permission-clear")
public TextTemplate permissionClear = TextTemplate.of(TextColor.RED, "Cleared permissions in this claim. To set permission for ALL your claims, stand outside them.");
@Setting("permission-command-trust")
public TextTemplate permissionCommandTrust = TextTemplate.of(TextColor.RED, "You don't have permission to use this type of trust.");
@Setting("permission-cuboid")
public TextTemplate permissionCuboid = TextTemplate.of(TextColor.RED, "You don't have permission to create/resize basic claims in 3D mode.");
@Setting("permission-edit-claim")
public TextTemplate permissionEditClaim = TextTemplate.of(TextColor.RED, "You don't have permission to edit this claim.");
@Setting("permission-fire-spread")
public TextTemplate permissionFireSpread = TextTemplate.of(TextColor.RED, "You don't have permission to spread fire in this claim.");
@Setting("permission-flag-defaults")
public TextTemplate permissionFlagDefaults = TextTemplate.of(TextColor.RED, "You don't have permission to manage flag defaults.");
@Setting("permission-flag-overrides")
public TextTemplate permissionFlagOverrides = TextTemplate.of(TextColor.RED, "You don't have permission to manage flag overrides.");
@Setting("permission-flag-use")
public TextTemplate permissionFlagUse = TextTemplate.of(TextColor.RED, "You don't have permission to use this flag.");
@Setting("permission-flow-liquid")
public TextTemplate permissionFlowLiquid = TextTemplate.of(TextColor.RED, "You don't have permission to flow liquid in this claim.");
@Setting("permission-interact-block")
public TextTemplate permissionInteractBlock = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner").color(TextColor.GOLD), "'s", TextColor.RED, " permission to interact with the block ", TextTemplate.arg("block").color(TextColor.LIGHT_PURPLE), ".");
@Setting("permission-interact-entity")
public TextTemplate permissionInteractEntity = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner").color(TextColor.GOLD), "'s", TextColor.RED, " permission to interact with the entity ", TextTemplate.arg("entity").color(TextColor.LIGHT_PURPLE), ".");
@Setting("permission-interact-item-block")
public TextTemplate permissionInteractItemBlock = TextTemplate.of(TextColor.RED, "You don't have permission to use ", TextTemplate.arg("item").color(TextColor.LIGHT_PURPLE), TextColor.RED, " on a ", TextTemplate.arg("block").color(TextColor.AQUA), ".");
@Setting("permission-interact-item-entity")
public TextTemplate permissionInteractItemEntity = TextTemplate.of(TextColor.RED, "You don't have permission to use ", TextTemplate.arg("item").color(TextColor.LIGHT_PURPLE), TextColor.RED, " on a ", TextTemplate.arg("entity").color(TextColor.AQUA), ".");
@Setting("permission-interact-item")
public TextTemplate permissionInteractItem = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner").color(TextColor.GOLD), "'s", TextColor.RED, " permission to interact with the item ", TextTemplate.arg("item").color(TextColor.LIGHT_PURPLE), ".");
@Setting("permission-inventory-open")
public TextTemplate permissionInventoryOpen = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner").color(TextColor.GOLD), "'s", TextColor.RED, " permission to open ", TextTemplate.arg("block").color(TextColor.LIGHT_PURPLE), ".");
@Setting("permission-item-drop")
public TextTemplate permissionItemDrop = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner").color(TextColor.GOLD), "'s", TextColor.RED, " permission to drop the item ", TextTemplate.arg("item").color(TextColor.LIGHT_PURPLE), " in this claim.");
@Setting("permission-item-use")
public TextTemplate permissionItemUse = TextTemplate.of(TextColor.RED, "You can't use the item ", TextTemplate.arg("item"), " in this claim.");
@Setting("permission-grant")
public TextTemplate permissionGrant = TextTemplate.of(TextColor.RED, "You can't grant a permission you don't have yourself.");
@Setting("permission-global-option")
public TextTemplate permissionGlobalOption = TextTemplate.of(TextColor.RED, "You don't have permission to manage global options.");
@Setting("permission-group-option")
public TextTemplate permissionGroupOption = TextTemplate.of(TextColor.RED, "You don't have permission to assign an option to a group.");
@Setting("permission-assign-without-having")
public TextTemplate permissionAssignWithoutHaving = TextTemplate.of(TextColor.RED, "You are not allowed to assign a permission that you do not have.");
@Setting("permission-override-deny")
public TextTemplate permissionOverrideDeny = TextTemplate.of(TextColor.RED, "The action you are attempting to perform has been denied by an administrator's override flag.");
@Setting("permission-player-option")
public TextTemplate permissionPlayerOption = TextTemplate.of(TextColor.RED, "You don't have permission to assign an option to a player.");
@Setting("permission-player-admin-flags")
public TextTemplate permissionSetAdminFlags = TextTemplate.of(TextColor.RED, "You don't have permission to change flags on an admin player.");
@Setting("permission-player-not-ignorable")
public TextTemplate permissionPlayerNotIgnorable = TextTemplate.of(TextColor.RED, "You can't ignore that player.");
@Setting("permission-portal-enter")
public TextTemplate permissionPortalEnter = TextTemplate.of(TextColor.RED, "You can't use this portal because you don't have ", TextTemplate.arg("owner"), "'s permission to enter the destination land claim.");
@Setting("permission-portal-exit")
public TextTemplate permissionPortalExit = TextTemplate.of(TextColor.RED, "You can't use this portal because you don't have ", TextTemplate.arg("owner"), "'s permission to build an exit portal in the destination land claim.");
@Setting("permission-protected-portal")
public TextTemplate permissionProtectedPortal = TextTemplate.of(TextColor.RED, "You don't have permission to use portals in this claim owned by ", TextTemplate.arg("owner"), ".");
@Setting("permission-trust")
public TextTemplate permissionTrust = TextTemplate.of(TextColor.RED, "You don't have ", TextTemplate.arg("owner"), "'s permission to manage permissions here.");
@Setting("permission-visual-claims-nearby")
public TextTemplate permissionVisualClaimsNearby = TextTemplate.of(TextColor.RED, "You don't have permission to visualize nearby claims.");
@Setting("player-remaining-blocks-2d")
public TextTemplate playerRemainingBlocks2d = TextTemplate.of(TextColor.YELLOW, "You may claim up to ", TextTemplate.arg("remaining-blocks").color(TextColor.GREEN), " more blocks.");
@Setting("player-remaining-blocks-3d")
public TextTemplate playerRemainingBlocks3d = TextTemplate.of(TextColor.YELLOW, "You may claim up to ", TextTemplate.arg("remaining-chunks").color(TextColor.GREEN), " more chunks. (", TextTemplate.arg("remaining-blocks").color(TextColor.WHITE), " blocks)");
@Setting("plugin-reload")
public TextTemplate pluginReload = TextTemplate.of("GriefDefender has been reloaded.");
@Setting("restore-nature-activate")
public TextTemplate restoreNatureActivate = TextTemplate.of(TextColor.GREEN, "Ready to restore claim! Right click on a block to restore. Use /modebasic to stop.");
@Setting(MessageStorage.SCHEMATIC_RESTORE_CONFIRMED)
public TextTemplate schematicRestoreConfirmed = TextTemplate.of(TextColor.GREEN, "You have successfully restored your claim from schematic backup ", TextTemplate.arg("schematic_name").color(TextColor.GOLD), ".");
@Setting("tax-claim-expired")
public TextTemplate taxClaimExpired = TextTemplate.of(TextColor.RED, "This claim has been frozen due to unpaid taxes. The current amount owed is '", TextTemplate.arg("tax_owed").color(TextColor.GOLD), "'."
+ "\nThere are '", TextTemplate.arg("remaining_days").color(TextColor.GREEN), "' days left to deposit payment to claim bank in order to unfreeze this claim.\nFailure to pay this debt will result in deletion of claim.\nNote: To deposit funds to claimbank, use /claimbank deposit <amount>.");
@Setting("tax-claim-paid-balance")
public TextTemplate taxClaimPaidBalance = TextTemplate.of(TextColor.GREEN, "The tax debt of '", TextTemplate.arg("amount").color(TextColor.GOLD), "' has been paid. Your claim has been unfrozen and is now available for use.");
@Setting("tax-claim-paid-partial")
public TextTemplate taxClaimPaidPartial = TextTemplate.of(TextColor.GREEN, "The tax debt of '", TextTemplate.arg("amount").color(TextColor.GOLD), "' has been partially paid. In order to unfreeze your claim, the remaining tax owed balance of '", TextTemplate.arg("balance").color(TextColor.GOLD), "' must be paid.");
@Setting("tax-info")
public TextTemplate taxInfo = TextTemplate.of(TextColor.GREEN, "Your next scheduled tax payment of ", TextTemplate.arg("amount").color(TextColor.GOLD), " will be withdrawn from your account on ", TextColor.AQUA, TextTemplate.arg("withdraw_date"), ".");
@Setting("tax-past-due")
public TextTemplate taxPastDue = TextTemplate.of(TextColor.RED, "You currently have a past due tax balance of ", TextTemplate.arg("balance_due").color(TextColor.GOLD), TextColor.RED, " that must be paid by ", TextTemplate.arg("due_date").color(TextColor.AQUA), TextColor.RED, ". Failure to pay off your tax balance will result in losing your property.");
@Setting("town-create-not-enough-funds")
public TextTemplate townCreateNotEnoughFunds = TextTemplate.of(TextColor.RED, "You do not have enough funds to create this town for ", TextTemplate.arg("create_cost").color(TextColor.GOLD), ". You currently have a balance of ", TextTemplate.arg("balance").color(TextColor.GOLD), " and need ", TextTemplate.arg("amount_needed").color(TextColor.GOLD), " more for creation.");
@Setting("town-chat-disabled")
public TextTemplate townChatDisabled = TextTemplate.of("Town chat disabled.");
@Setting("town-chat-enabled")
public TextTemplate townChatEnabled = TextTemplate.of("Town chat enabled.");
@Setting("town-name")
public TextTemplate townName = TextTemplate.of("Set town name to ", TextTemplate.arg("name"), ".");
@Setting("town-not-found")
public TextTemplate townNotFound = TextTemplate.of(TextColor.RED, "Town not found.");
@Setting("town-not-in")
public TextTemplate townNotIn = TextTemplate.of(TextColor.RED, "You are not in a town.");
@Setting("town-tag")
public TextTemplate townTag = TextTemplate.of("Set town tag to ", TextTemplate.arg("tag"), ".");
@Setting("town-tag-clear")
public TextTemplate townTagClear = TextTemplate.of(TextColor.GREEN, "The town tag has been cleared.");
@Setting("town-tax-no-claims")
public TextTemplate townTaxNoClaims = TextTemplate.of(TextColor.RED, "You must own property in this town in order to be taxed.");
@Setting("town-owner")
public TextTemplate townTrust = TextTemplate.of(TextColor.RED, "That belongs to the town.");
@Setting("trust-already-has")
public TextTemplate trustAlreadyHas = TextTemplate.of(TextColor.RED, TextTemplate.arg("target").color(TextColor.AQUA), " already has ", TextTemplate.arg("type"), " permission.");
@Setting("trust-current-claim")
public TextTemplate trustGrant = TextTemplate.of(TextColor.GREEN, "Granted ", TextTemplate.arg("target").color(TextColor.AQUA), " permission to ", TextTemplate.arg("type").color(TextColor.LIGHT_PURPLE), " in current claim.");
@Setting("trust-invalid")
public TextTemplate trustInvalid = TextTemplate.of(TextColor.RED, "Invalid trust type entered.\nThe allowed types are : accessor, builder, container, and manager.");
@Setting("trust-individual-all-claims")
public TextTemplate trustIndividualAllClaims = TextTemplate.of(TextColor.GREEN, "Granted ", TextTemplate.arg("player").color(TextColor.AQUA), "'s full trust to all your claims. To unset permissions for ALL your claims, use /untrustall.");
@Setting("trust-no-claims")
public TextTemplate trustNoClaims = TextTemplate.of(TextColor.RED, "You have no claims to trust.");
@Setting("trust-self")
public TextTemplate trustSelf = TextTemplate.of(TextColor.RED, "You cannot trust yourself.");
@Setting("untrust-individual-all-claims")
public TextTemplate untrustIndividualAllClaims = TextTemplate.of(TextColor.GREEN, "Revoked ", TextTemplate.arg("target").color(TextColor.AQUA), "'s access to ALL your claims. To set permissions for a single claim, stand inside it and use /untrust.");
@Setting("untrust-individual-single-claim")
public TextTemplate untrustIndividualSingleClaim = TextTemplate.of(TextColor.GREEN, "Revoked ", TextTemplate.arg("target").color(TextColor.AQUA), "'s access to this claim. To unset permissions for ALL your claims, use /untrustall.");
@Setting("untrust-owner")
public TextTemplate untrustOwner = TextTemplate.of(TextColor.RED, TextTemplate.arg("owner").color(TextColor.AQUA), " is owner of claim and cannot be untrusted.");
@Setting("untrust-no-claims")
public TextTemplate untrustNoClaims = TextTemplate.of(TextColor.RED, "You have no claims to untrust.");
@Setting("untrust-self")
public TextTemplate untrustSelf = TextTemplate.of(TextColor.RED, "You cannot untrust yourself.");
@Setting("tutorial-claim-basic")
public TextTemplate tutorialClaimBasic = TextTemplate.of(TextColor.YELLOW, "Click for Land Claim Help: ", TextColor.GREEN, "https://bit.ly/2J1IKIC");
}

View File

@ -0,0 +1,149 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.GriefDefenderPlugin;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.objectmapping.ObjectMapper;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.logging.Level;
public class MessageStorage {
private HoconConfigurationLoader loader;
private CommentedConfigurationNode root = SimpleCommentedConfigurationNode.root(ConfigurationOptions.defaults()
.setHeader(GriefDefenderPlugin.CONFIG_HEADER));
private ObjectMapper<MessageDataConfig>.BoundInstance configMapper;
private MessageDataConfig configBase;
public static final String ABANDON_CLAIM_ADVERTISEMENT = "abandon-claim-advertisement";
public static final String ABANDON_OTHER_SUCCESS = "abandon-other-success";
public static final String ADJUST_BLOCKS_SUCCESS = "adjust-blocks-success";
public static final String ADJUST_GROUP_BLOCKS_SUCCESS = "adjust-group-blocks-success";
public static final String BLOCK_CLAIMED = "block-claimed";
public static final String BLOCK_SALE_VALUE = "block-sale-value";
public static final String BOOK_TOOLS = "book-tools";
public static final String CLAIM_ABANDON_SUCCESS = "claim-abandon-success";
public static final String CLAIM_ABOVE_LEVEL = "claim-above-level";
public static final String CLAIM_BANK_INFO = "claim-bank-info";
public static final String CLAIM_BELOW_LEVEL = "claim-below-level";
public static final String CLAIM_SIZE_NEED_BLOCKS_2D = "claim-size-need-blocks-2d";
public static final String CLAIM_SIZE_NEED_BLOCKS_3D = "claim-size-need-blocks-3d";
public static final String CLAIM_RESIZE_SUCCESS_2D = "claim-resize-success-2d";
public static final String CLAIM_RESIZE_SUCCESS_3D = "claim-resize-success-3d";
public static final String CLAIM_SIZE_MAX_X = "claim-size-max-x";
public static final String CLAIM_SIZE_MAX_Y = "claim-size-max-y";
public static final String CLAIM_SIZE_MAX_Z = "claim-size-max-z";
public static final String CLAIM_SIZE_MIN_X = "claim-size-min-x";
public static final String CLAIM_SIZE_MIN_Y = "claim-size-min-y";
public static final String CLAIM_SIZE_MIN_Z = "claim-size-min-z";
public static final String CLAIM_SIZE_TOO_SMALL = "claim-size-too-small";
public static final String CLAIM_CREATE_INSUFFICIENT_BLOCKS_2D = "claim-create-insufficient-blocks-2d";
public static final String CLAIM_CREATE_INSUFFICIENT_BLOCKS_3D = "claim-create-insufficient-blocks-3d";
public static final String ECONOMY_CLAIM_SALE_CONFIRMED = "economy-claim-sale-confirmed";
public static final String ECONOMY_USER_NOT_FOUND = "economy-user-not-found";
public static final String SCHEMATIC_RESTORE_CONFIRMED = "schematic-restore-confirmed";
@SuppressWarnings({"unchecked", "rawtypes"})
public MessageStorage(Path path) {
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(MessageDataConfig.class).bindToNew();
reload();
save();
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize configuration", e);
}
}
public MessageDataConfig getConfig() {
return this.configBase;
}
public void save() {
try {
this.configMapper.serialize(this.root.getNode(GriefDefenderPlugin.MOD_ID));
this.loader.save(this.root);
} catch (IOException | ObjectMappingException e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to save configuration", e);
}
}
public void reload() {
try {
this.root = this.loader.load(ConfigurationOptions.defaults()
.setHeader(GriefDefenderPlugin.CONFIG_HEADER));
this.configBase = this.configMapper.populate(this.root.getNode(GriefDefenderPlugin.MOD_ID));
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to load configuration", e);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
public void resetMessageData(String message) {
for (Map.Entry<Object, ? extends CommentedConfigurationNode> mapEntry : this.root.getNode(GriefDefenderPlugin.MOD_ID).getChildrenMap().entrySet()) {
CommentedConfigurationNode node = (CommentedConfigurationNode) mapEntry.getValue();
String key = "";
String comment = node.getComment().orElse(null);
if (comment == null && node.getKey() instanceof String) {
key = (String) node.getKey();
if (key.equalsIgnoreCase(message)) {
this.root.getNode(GriefDefenderPlugin.MOD_ID).removeChild(mapEntry.getKey());
}
}
}
try {
this.loader.save(this.root);
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(MessageDataConfig.class).bindToNew();
this.configBase = this.configMapper.populate(this.root.getNode(GriefDefenderPlugin.MOD_ID));
} catch (IOException | ObjectMappingException e) {
e.printStackTrace();
}
GriefDefenderPlugin.getInstance().messageData = this.configBase;
}
public CommentedConfigurationNode getRootNode() {
return this.root.getNode(GriefDefenderPlugin.MOD_ID);
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.configuration.category.ConfigCategory;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ConfigSerializable
public class PlayerDataConfig extends ConfigCategory {
private boolean requiresSave = true;
@Setting(value = "accrued-claim-blocks", comment = "How many claim blocks the player has earned in world via play time.")
private int accruedClaimBlocks;
@Setting(value = "bonus-claim-blocks",
comment = "How many claim blocks the player has been gifted in world by admins, or purchased via economy integration.")
private int bonusClaimBlocks = 0;
@Setting(value = "migrated-blocks")
private boolean migrated = false;
public int getAccruedClaimBlocks() {
return this.accruedClaimBlocks;
}
public int getBonusClaimBlocks() {
return this.bonusClaimBlocks;
}
public void setAccruedClaimBlocks(int blocks) {
this.requiresSave = true;
this.accruedClaimBlocks = blocks;
}
public void setBonusClaimBlocks(int blocks) {
this.requiresSave = true;
this.bonusClaimBlocks = blocks;
}
public boolean requiresSave() {
return this.requiresSave;
}
public void setRequiresSave(boolean flag) {
this.requiresSave = flag;
}
// Remove after 4.0
public boolean hasMigratedBlocks() {
return this.migrated;
}
public void setMigratedBlocks(boolean flag) {
this.migrated = flag;
}
}

View File

@ -0,0 +1,98 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.GriefDefenderPlugin;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.objectmapping.ObjectMapper;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.logging.Level;
public class PlayerStorageData {
private HoconConfigurationLoader loader;
private CommentedConfigurationNode root = SimpleCommentedConfigurationNode.root(ConfigurationOptions.defaults());
private ObjectMapper<PlayerDataConfig>.BoundInstance configMapper;
private PlayerDataConfig configBase;
@SuppressWarnings({"unchecked", "rawtypes"})
public PlayerStorageData(Path path) {
try {
if (Files.notExists(path.getParent())) {
Files.createDirectories(path.getParent());
}
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
this.configMapper = (ObjectMapper.BoundInstance) ObjectMapper.forClass(PlayerDataConfig.class).bindToNew();
reload();
save();
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to initialize configuration", e);
}
}
public PlayerDataConfig getConfig() {
return this.configBase;
}
public void save() {
try {
if (this.configBase != null) {
if (this.configBase.requiresSave()) {
this.configMapper.serialize(this.root.getNode(GriefDefenderPlugin.MOD_ID));
this.loader.save(this.root);
this.configBase.setRequiresSave(false);
}
}
} catch (IOException | ObjectMappingException e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to save configuration", e);
}
}
public void reload() {
try {
this.root = this.loader.load(ConfigurationOptions.defaults());
this.configBase = this.configMapper.populate(this.root.getNode(GriefDefenderPlugin.MOD_ID));
} catch (Exception e) {
GriefDefenderPlugin.getInstance().getLogger().log(Level.SEVERE, "Failed to load configuration", e);
}
}
public CommentedConfigurationNode getRootNode() {
return this.root.getNode(GriefDefenderPlugin.MOD_ID);
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.api.data.TownData;
import net.kyori.text.Component;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
@ConfigSerializable
public class TownDataConfig extends ClaimDataConfig implements TownData {
@Setting
private Component townTag;
@Setting
private Map<UUID, Integer> accruedBlocks = new HashMap<>();
@Setting
private Map<UUID, Integer> bonusBlocks = new HashMap<>();
@Setting
private Map<UUID, Integer> createMode = new HashMap<>();
@Setting
private Map<UUID, String> residentPastDueTaxTimestamps = new HashMap<>();
@Setting
private Map<UUID, Double> residentTaxBalances = new HashMap<>();
@Override
public Optional<Component> getTownTag() {
return Optional.ofNullable(this.townTag);
}
public void setTownTag(Component tag) {
this.townTag = tag;
}
public Map<UUID, Integer> getAccruedClaimBlocks() {
return this.accruedBlocks;
}
public Map<UUID, Integer> getBonusClaimBlocks() {
return this.bonusBlocks;
}
public Map<UUID, Integer> getCreateModes() {
return this.createMode;
}
public Map<UUID, String> getResidentPastDueTaxTimestamps() {
return this.residentPastDueTaxTimestamps;
}
public Map<UUID, Double> getResidentTaxBalances() {
return this.residentTaxBalances;
}
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration;
import com.griefdefender.api.claim.ClaimTypes;
import java.nio.file.Path;
import java.util.UUID;
public class TownStorageData extends ClaimStorageData {
public TownStorageData(Path path, UUID worldUniqueId, UUID ownerUniqueId, boolean cuboid) {
super(path, worldUniqueId, ownerUniqueId, ClaimTypes.TOWN, cuboid);
}
public TownStorageData(Path path, UUID worldUniqueId) {
super(path, worldUniqueId);
}
public TownDataConfig getConfig() {
return (TownDataConfig) this.configBase;
}
}

View File

@ -0,0 +1,59 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.griefdefender.configuration.category;
import com.google.common.collect.Maps;
import net.kyori.text.Component;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
import java.util.Map;
@ConfigSerializable
public class BanCategory extends ConfigCategory {
@Setting
private Map<String, Component> banReasons = Maps.newHashMap();
public void addBanReason(String permission, Component reason) {
permission = permission.replace("griefdefender.flag.", "").toLowerCase();
this.banReasons.put(permission, reason);
}
public void removeBanReason(String permission) {
permission = permission.replace("griefdefender.flag.", "").toLowerCase();
this.banReasons.remove(permission);
}
public Component getReason(String permission) {
permission = permission.replace("griefdefender.flag.", "").toLowerCase();
for (Map.Entry<String, Component> banEntry : this.banReasons.entrySet()) {
if (permission.contains(banEntry.getKey())) {
return banEntry.getValue();
}
}
return null;
}
}

Some files were not shown because too many files have changed in this diff Show More