More improvements and bug fixes.

* Add PlaceholderAPI support. See https://github.com/bloodmc/GriefDefender/wiki/PlaceholderAPI
* Add Dynmap support. See https://github.com/bloodmc/GriefDefender/wiki/Dynmap
* Fix /claimexpand and /claimcontract up and down directions.
* Fix create claim location cache not clearing properly on delete.
* Fix being unable to interact with doors with access trust if holding an item.
* Fix getAllPlayerClaims not accounting for global playerdata.
* Avoid migrating empty claim files during GP migration.

Fixes #71, Fixes #73, Fixes #75
This commit is contained in:
bloodshot 2019-12-07 16:50:56 -05:00
parent dea4476ee4
commit f3ac02782c
20 changed files with 876 additions and 3 deletions

View File

@ -44,6 +44,10 @@ repositories {
name = 'bstats'
url = 'https://repo.codemc.org/repository/maven-public'
}
maven {
name = 'dynmap-repo'
url = 'http://repo.mikeprimm.com'
}
maven {
name = 'essentials'
url = 'https://ci.ender.zone/plugin/repository/everything/'
@ -60,6 +64,10 @@ repositories {
name = 'permissionsex'
url = 'https://repo.glaremasters.me/repository/permissionsex'
}
maven {
name = 'placeholderapi'
url = 'http://repo.extendedclip.com/content/repositories/placeholderapi'
}
maven {
name = 'sk89q'
url = 'https://maven.sk89q.com/repo'
@ -102,9 +110,11 @@ dependencies {
compileOnly "org.bukkit:bukkit:$spigotVersion"
compileOnly "org.spigotmc:spigot:$spigotVersion"
// Plugins
compileOnly "ca.stellardrift.permissionsex:permissionsex-bukkit:2.0-SNAPSHOT"
compileOnly "me.clip:placeholderapi:2.10.4"
compileOnly "net.ess3:EssentialsX:2.17.1"
compileOnly "net.milkbowl.vault:VaultAPI:1.7"
compileOnly "ca.stellardrift.permissionsex:permissionsex-bukkit:2.0-SNAPSHOT"
compileOnly "us.dynmap:dynmap-api:3.0-SNAPSHOT"
// Libs
compileOnly "aopalliance:aopalliance:1.0"
compileOnly "co.aikar:acf-core:0.5.0-SNAPSHOT"

View File

@ -27,6 +27,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
@ -44,6 +45,8 @@
import com.griefdefender.api.data.PlayerData;
import com.griefdefender.api.permission.flag.Flag;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.storage.BaseStorage;
@Singleton
public class GDCore implements Core {
@ -81,6 +84,13 @@ public Optional<PlayerData> getPlayerData(UUID worldUniqueId, UUID playerUniqueI
@Override
public List<Claim> getAllPlayerClaims(UUID playerUniqueId) {
List<Claim> claimList = new ArrayList<>();
if (BaseStorage.USE_GLOBAL_PLAYER_STORAGE) {
final World world = Bukkit.getWorlds().get(0);
final ClaimManager claimManager = this.getClaimManager(world.getUID());
claimList.addAll(claimManager.getPlayerClaims(playerUniqueId));
return ImmutableList.copyOf(claimList);
}
for (World world : Bukkit.getServer().getWorlds()) {
claimList.addAll(this.getClaimManager(world.getUID()).getPlayerClaims(playerUniqueId));
}

View File

@ -684,6 +684,13 @@ public boolean inPvpCombat(World world) {
return true;
}
public void onClaimDelete() {
this.lastShovelLocation = null;
this.eventResultCache = null;
this.claimResizing = null;
this.claimSubdividing = null;
}
public void onDisconnect() {
this.visualBlocks.clear();
this.claimMode = false;

View File

@ -185,9 +185,11 @@
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.permission.flag.GDCustomFlagDefinition;
import com.griefdefender.permission.flag.GDFlags;
import com.griefdefender.provider.DynmapProvider;
import com.griefdefender.provider.EssentialsProvider;
import com.griefdefender.provider.LuckPermsProvider;
import com.griefdefender.provider.PermissionProvider;
import com.griefdefender.provider.PlaceholderProvider;
import com.griefdefender.provider.VaultProvider;
import com.griefdefender.registry.ChatTypeRegistryModule;
import com.griefdefender.registry.ClaimTypeRegistryModule;
@ -255,6 +257,7 @@ public class GriefDefenderPlugin {
public BaseStorage dataStore;
private DynmapProvider dynmapProvider;
private EssentialsProvider essentialsProvider;
private WorldEditProvider worldEditProvider;
private WorldGuardProvider worldGuardProvider;
@ -453,6 +456,17 @@ public void onEnable() {
if (Bukkit.getPluginManager().getPlugin("Essentials") != null) {
this.essentialsProvider = new EssentialsProvider();
}
if (Bukkit.getPluginManager().getPlugin("dynmap") != null) {
this.dynmapProvider = new DynmapProvider();
}
if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null){
this.getLogger().info("Detected PlaceholderAPI. Enabling GD PlaceholderAPI expansion...");
new PlaceholderProvider();
this.getLogger().info("GriefDefender PlaceholderAPI expansion enabled!");
}
if (this.dataStore == null) {
try {
this.dataStore = new FileStorage();
@ -1069,6 +1083,9 @@ public boolean isEconomyModeEnabled() {
return false;
}
public DynmapProvider getDynmapProvider() {
return this.dynmapProvider;
}
public EssentialsProvider getEssentialsProvider() {
return this.essentialsProvider;

View File

@ -84,6 +84,7 @@
import net.kyori.text.Component;
import net.kyori.text.TextComponent;
import net.kyori.text.format.TextColor;
import net.kyori.text.serializer.plain.PlainComponentSerializer;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
@ -365,6 +366,14 @@ public Optional<Component> getName() {
return this.claimData.getName();
}
public String getFriendlyName() {
final Component claimName = this.claimData.getName().orElse(null);
if (claimName == null) {
return "none";
}
return PlainComponentSerializer.INSTANCE.serialize(claimName);
}
public Component getFriendlyNameType() {
return this.getFriendlyNameType(false);
}
@ -518,6 +527,20 @@ public Component getOwnerName() {
return TextComponent.of(this.getOwnerPlayerData().getPlayerName());
}
public String getOwnerFriendlyName() {
if (this.isAdminClaim()) {
return "administrator";
}
if (this.isWilderness()) {
return "wilderness";
}
final GDPlayerData playerData = this.ownerPlayerData;
if (playerData == null) {
return "[unknown]";
}
return playerData.getPlayerName();
}
@Override
public boolean contains(Vector3i pos, boolean excludeChildren) {
return this.contains(pos.getX(), pos.getY(), pos.getZ(), excludeChildren, null, false);

View File

@ -175,6 +175,7 @@ private static Consumer<CommandSender> createConfirmationConsumer(Player player,
return;
}
playerData.onClaimDelete();
// remove all context permissions
PermissionUtil.getInstance().clearPermissions(claim);
playerData.revertActiveVisual(player);

View File

@ -151,6 +151,7 @@ private static Consumer<CommandSender> createConfirmationConsumer(GDPermissionUs
playerData.useRestoreSchematic = event.isRestoring();
GriefDefenderPlugin.getInstance().dataStore.abandonClaimsForPlayer(user, allowedClaims);
playerData.useRestoreSchematic = false;
playerData.onClaimDelete();
if (GriefDefenderPlugin.getInstance().isEconomyModeEnabled()) {
final Economy economy = GriefDefenderPlugin.getInstance().getVaultProvider().getApi();

View File

@ -111,6 +111,12 @@ public void execute(Player player, int amount, @Optional String direction) {
} else if (face == BlockFace.SOUTH) {
point1 = new Vector3i(lesser.getX(), lesser.getY(), lesser.getZ());
point2 = new Vector3i(greater.getX(), greater.getY(), greater.getZ() - amount);
} else if (face == BlockFace.UP) {
point1 = new Vector3i(lesser.getX(), lesser.getY() - amount, lesser.getZ());
point2 = new Vector3i(greater.getX(), greater.getY(), greater.getZ() + amount);
} else if (face == BlockFace.DOWN) {
point1 = new Vector3i(lesser.getX(), lesser.getY(), lesser.getZ());
point2 = new Vector3i(greater.getX(), greater.getY() - amount, greater.getZ() + amount);
}
} else {
point1 = new Vector3i(

View File

@ -106,6 +106,7 @@ private static Consumer<CommandSender> createConfirmationConsumer(Player player,
return;
}
playerData.onClaimDelete();
PermissionUtil.getInstance().clearPermissions((GDClaim) claim);
playerData.revertActiveVisual(player);

View File

@ -102,6 +102,7 @@ private static Consumer<CommandSender> createConfirmationConsumer(Player src, Of
}
GriefDefenderPlugin.getInstance().dataStore.deleteClaimsForPlayer(otherPlayer.getUniqueId());
playerData.onClaimDelete();
if (src != null) {
final Component message = GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.DELETE_ALL_PLAYER_SUCCESS, ImmutableMap.of(
"player", TextComponent.of(otherPlayer.getName()).color(TextColor.AQUA)));

View File

@ -86,7 +86,8 @@ private static Consumer<CommandSender> createConfirmationConsumer(Player player)
GriefDefenderPlugin.sendMessage(player, GriefDefenderPlugin.getInstance().messageData.getMessage(MessageStorage.DELETE_ALL_TYPE_SUCCESS,
ImmutableMap.of("type", TextComponent.of("ADMIN").color(TextColor.RED))));
GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
final GDPlayerData playerData = GriefDefenderPlugin.getInstance().dataStore.getOrCreatePlayerData(player.getWorld(), player.getUniqueId());
playerData.onClaimDelete();
playerData.revertActiveVisual(player);
};
}

View File

@ -111,6 +111,12 @@ public void execute(Player player, int amount, @Optional String direction) {
} else if (face == BlockFace.SOUTH) {
point1 = new Vector3i(lesser.getX(), lesser.getY(), lesser.getZ());
point2 = new Vector3i(greater.getX(), greater.getY(), greater.getZ() + amount);
} else if (face == BlockFace.UP) {
point1 = new Vector3i(lesser.getX(), lesser.getY(), lesser.getZ());
point2 = new Vector3i(greater.getX(), greater.getY() + amount, greater.getZ() + amount);
} else if (face == BlockFace.DOWN) {
point1 = new Vector3i(lesser.getX(), lesser.getY() - amount, lesser.getZ());
point2 = new Vector3i(greater.getX(), greater.getY(), greater.getZ() + amount);
}
} else {
point1 = new Vector3i(

View File

@ -0,0 +1,77 @@
/*
* 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 java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ConfigSerializable
public class DynmapCategory {
@Setting("owner-styles")
public Map<String, DynmapOwnerStyleCategory> ownerStyles = new HashMap<>();
@Setting
public int minzoom = 0;
@Setting("layer-priority")
public int layerPriority = 10;
@Setting("layer-hide-by-default")
public boolean layerHideByDefault = false;
@Setting("use-3d-regions")
public boolean use3dRegions = false;
@Setting("hidden-regions")
public List<String> hiddenRegions = new ArrayList<>();
@Setting("visible-regions")
public List<String> visibleRegions = new ArrayList<>();
@Setting("info-window-basic")
public String infoWindowBasic = "<div class=\"infowindow\">"
+ "Name: <span style=\"font-weight:bold;\">%claimname%</span><br/>"
+ "Owner: <span style=\"font-weight:bold;\">%owner%</span><br/>"
+ "Type: <span style=\"font-weight:bold;\">%gdtype%</span><br/>"
+ "Last Seen: <span style=\"font-weight:bold;\">%lastseen%</span><br/>"
+ "Permission Trust: <span style=\"font-weight:bold;\">%managers%</span><br/>"
+ "Trust: <span style=\"font-weight:bold;\">%builders%</span><br/>"
+ "Container Trust: <span style=\"font-weight:bold;\">%containers%</span><br/>"
+ "Access Trust: <span style=\"font-weight:bold;\">%accessors%</span></div>";
@Setting("info-window-admin")
public String infoWindowAdmin = "<div class=\"infowindow\">"
+ "<span style=\"font-weight:bold;\">Administrator Claim</span><br/>"
+ "Permission Trust: <span style=\"font-weight:bold;\">%managers%</span><br/>"
+ "Trust: <span style=\"font-weight:bold;\">%builders%</span><br/>"
+ "Container Trust: <span style=\"font-weight:bold;\">%containers%</span><br/>"
+ "Access Trust: <span style=\"font-weight:bold;\">%accessors%</span></div>";
}

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.category;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ConfigSerializable
public class DynmapOwnerStyleCategory {
@Setting("stroke-color")
public String strokeColor = "#FF0000";
@Setting("stroke-opacity")
public double strokeOpacity = 0.8d;
@Setting("stroke-weight")
public int strokeWeight = 3;
@Setting("fill-color")
public String fillColor = "#FF0000";
@Setting("fill-opacity")
public double fillOpacity = 0.35d;
@Setting("label")
public String label = "none";
}

View File

@ -26,6 +26,7 @@
import com.griefdefender.configuration.category.CustomFlagGroupDefinitionCategory;
import com.griefdefender.configuration.category.DefaultPermissionCategory;
import com.griefdefender.configuration.category.DynmapCategory;
import com.griefdefender.configuration.category.EconomyCategory;
import com.griefdefender.configuration.category.MessageCategory;
import com.griefdefender.configuration.category.MigratorCategory;
@ -64,6 +65,8 @@ public class GlobalConfig extends ConfigBase {
+ "\nThese contexts may change, See https://github.com/bloodmc/GriefDefender/wiki for latest information.")
public CustomFlagGroupDefinitionCategory customFlags = new CustomFlagGroupDefinitionCategory();
@Setting
public DynmapCategory dynmap = new DynmapCategory();
@Setting
public EconomyCategory economy = new EconomyCategory();
@Setting
public PlayerDataCategory playerdata = new PlayerDataCategory();

View File

@ -716,7 +716,10 @@ public void onPlayerInteractBlockSecondary(PlayerInteractEvent event) {
return;
}
final GDClaim claim = this.dataStore.getClaimAt(location);
final TrustType trustType = event.isBlockInHand() && event.getAction() != Action.PHYSICAL ? TrustTypes.BUILDER : TrustTypes.ACCESSOR;
TrustType trustType = event.isBlockInHand() && event.getAction() != Action.PHYSICAL ? TrustTypes.BUILDER : TrustTypes.ACCESSOR;
if (clickedBlock != null && clickedBlock.getType().toString().contains("DOOR")) {
trustType = TrustTypes.ACCESSOR;
}
if (GDFlags.INTERACT_BLOCK_SECONDARY && playerData != null) {
String permission = GDPermissions.INTERACT_BLOCK_SECONDARY;
if (event.getAction() == Action.PHYSICAL) {

View File

@ -528,6 +528,10 @@ private static void createClaim(World world, File file, boolean parentsOnly) {
e1.printStackTrace();
return;
}
if (region.getChildrenMap().isEmpty()) {
GriefDefenderPlugin.getInstance().getLogger().info("Detected corrupted claim file '" + file + "'. Skipping...");
return;
}
if (parentsOnly && region.getChildrenMap().get("Parent Claim ID").getInt() != -1) {
return;
}

View File

@ -0,0 +1,362 @@
/*
* This file is part of GriefDefender, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) Dockter
* 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.provider;
import com.flowpowered.math.vector.Vector3i;
import com.griefdefender.GDBootstrap;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.claim.Claim;
import com.griefdefender.api.claim.ClaimManager;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.claim.TrustTypes;
import com.griefdefender.api.event.ChangeClaimEvent;
import com.griefdefender.api.event.CreateClaimEvent;
import com.griefdefender.api.event.RemoveClaimEvent;
import com.griefdefender.claim.GDClaim;
import com.griefdefender.configuration.category.DynmapOwnerStyleCategory;
import com.griefdefender.configuration.category.DynmapCategory;
import com.griefdefender.util.PlayerUtil;
import net.kyori.event.method.annotation.Subscribe;
import net.kyori.text.serializer.plain.PlainComponentSerializer;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.scheduler.BukkitRunnable;
import org.dynmap.DynmapCommonAPI;
import org.dynmap.DynmapCommonAPIListener;
import org.dynmap.markers.AreaMarker;
import org.dynmap.markers.MarkerAPI;
import org.dynmap.markers.MarkerSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Logger;
public class DynmapProvider {
private final Logger logger;
private DynmapCommonAPI dynmap;
private MarkerAPI markerapi;
private DynmapCategory cfg;
private DynmapOwnerStyleCategory defaultStyle = new DynmapOwnerStyleCategory();
private MarkerSet set;
private boolean disabled = false;
private boolean reload = false;
public DynmapProvider() {
this.logger = GriefDefenderPlugin.getInstance().getLogger();
logger.info("Initializing GriefDefender Dynmap provider...");
DynmapCommonAPIListener.register(new DynmapCommonAPIListener() {
@Override
public void apiEnabled(DynmapCommonAPI api) {
dynmap = api;
cfg = GriefDefenderPlugin.getGlobalConfig().getConfig().dynmap;
activate();
}
});
if (this.markerapi == null) {
this.logger.severe("Error loading Dynmap Provider! Could not locate Marker API.");
return;
}
GriefDefender.getEventManager().register(this);
}
private Map<String, AreaMarker> areaMarkers = new HashMap<String, AreaMarker>();
private String getWindowInfo(Claim claim, AreaMarker marker) {
String info;
if (claim.isAdminClaim()) {
info = "<div class=\"regioninfo\">" + this.cfg.infoWindowAdmin + "</div>";
} else {
info = "<div class=\"regioninfo\">" + this.cfg.infoWindowBasic + "</div>";
}
info = info.replace("%owner%", ((GDClaim) claim).getOwnerFriendlyName());
info = info.replace("%area%", Integer.toString(claim.getArea()));
info = info.replace("%claimname%",
claim.getData().getName().isPresent()
? PlainComponentSerializer.INSTANCE.serialize(claim.getName().get())
: "none");
info = info.replace("%lastseen%", claim.getData().getDateLastActive().toString());
info = info.replace("%gdtype%", claim.getType().toString());
final List<UUID> builderList = claim.getUserTrusts(TrustTypes.BUILDER);
final List<UUID> containerList = claim.getUserTrusts(TrustTypes.CONTAINER);
final List<UUID> accessorList = claim.getUserTrusts(TrustTypes.ACCESSOR);
final List<UUID> managerList = claim.getUserTrusts(TrustTypes.MANAGER);
String trusted = "";
for (int i = 0; i < builderList.size(); i++) {
if (i > 0) {
trusted += ", ";
}
final UUID uuid = builderList.get(i);
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName.equalsIgnoreCase("unknown")) {
trusted += uuid.toString();
} else {
trusted += userName;
}
}
info = info.replace("%builders%", trusted);
trusted = "";
for (int i = 0; i < containerList.size(); i++) {
if (i > 0) {
trusted += ", ";
}
final UUID uuid = containerList.get(i);
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName.equalsIgnoreCase("unknown")) {
trusted += uuid.toString();
} else {
trusted += userName;
}
}
info = info.replace("%containers%", trusted);
trusted = "";
for (int i = 0; i < accessorList.size(); i++) {
if (i > 0) {
trusted += ", ";
}
final UUID uuid = accessorList.get(i);
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName.equalsIgnoreCase("unknown")) {
trusted += uuid.toString();
} else {
trusted += userName;
}
}
info = info.replace("%accessors%", trusted);
trusted = "";
for (int i = 0; i < managerList.size(); i++) {
if (i > 0) {
trusted += ", ";
}
final UUID uuid = managerList.get(i);
final String userName = PlayerUtil.getInstance().getUserName(uuid);
if (userName.equalsIgnoreCase("unknown")) {
trusted += uuid.toString();
} else {
trusted += userName;
}
}
info = info.replace("%managers%", trusted);
return info;
}
private boolean isVisible(String owner, String worldname) {
if (!this.cfg.visibleRegions.isEmpty()) {
if (!this.cfg.visibleRegions.contains(owner) && !this.cfg.visibleRegions.contains("world:" + worldname)
&& !this.cfg.visibleRegions.contains(worldname + "/" + owner)) {
return false;
}
}
if (!this.cfg.hiddenRegions.isEmpty()) {
if (this.cfg.hiddenRegions.contains(owner) || this.cfg.hiddenRegions.contains("world:" + worldname)
|| this.cfg.hiddenRegions.contains(worldname + "/" + owner))
return false;
}
return true;
}
private void addOwnerStyle(String owner, String worldid, AreaMarker marker, Claim claim) {
DynmapOwnerStyleCategory ownerStyle = null;
if (!this.cfg.ownerStyles.isEmpty()) {
ownerStyle = this.cfg.ownerStyles.get(owner.toLowerCase());
}
if (ownerStyle == null) {
ownerStyle = this.defaultStyle;
}
int sc = 0xFF0000;
int fc = 0xFF0000;
if (claim.getType().equals(ClaimTypes.ADMIN)) {
sc = 0xFF0000;
fc = 0xFF0000;
} else if (claim.getType().equals(ClaimTypes.BASIC)) {
sc = 0xFFFF00;
fc = 0xFFFF00;
} else if (claim.getType().equals(ClaimTypes.TOWN)) {
sc = 0x00FF00;
fc = 0x00FF00;
} else if (claim.getType().equals(ClaimTypes.SUBDIVISION)) {
sc = 0xFF9C00;
fc = 0xFF9C00;
}
marker.setLineStyle(ownerStyle.strokeWeight, ownerStyle.strokeOpacity, sc);
marker.setFillStyle(ownerStyle.fillOpacity, fc);
if (ownerStyle.label != null) {
marker.setLabel(ownerStyle.label);
}
}
private void updateClaimMarker(Claim claim, Map<String, AreaMarker> markerMap) {
final World world = Bukkit.getWorld(claim.getWorldUniqueId());
if (world == null) {
return;
}
final String worldName = world.getName();
final String owner = ((GDClaim) claim).getOwnerFriendlyName();
if (isVisible(owner, worldName)) {
final Vector3i lesserPos = claim.getLesserBoundaryCorner();
final Vector3i greaterPos = claim.getGreaterBoundaryCorner();
final double[] x = new double[4];
final double[] z = new double[4];
x[0] = lesserPos.getX();
z[0] = lesserPos.getZ();
x[1] = lesserPos.getX();
z[1] = greaterPos.getZ() + 1.0;
x[2] = greaterPos.getX() + 1.0;
z[2] = greaterPos.getZ() + 1.0;
x[3] = greaterPos.getX() + 1.0;
z[3] = lesserPos.getZ();
final UUID id = claim.getUniqueId();
final String markerid = "GD_" + id;
AreaMarker marker = this.areaMarkers.remove(markerid);
if (marker == null) {
marker = this.set.createAreaMarker(markerid, owner, false, worldName, x, z, false);
if (marker == null) {
return;
}
} else {
marker.setCornerLocations(x, z);
marker.setLabel(owner);
}
if (this.cfg.use3dRegions) {
marker.setRangeY(greaterPos.getY() + 1.0, lesserPos.getY());
}
addOwnerStyle(owner, worldName, marker, claim);
String desc = getWindowInfo(claim, marker);
marker.setDescription(desc);
markerMap.put(markerid, marker);
}
}
private void updateClaims() {
Map<String, AreaMarker> newmap = new HashMap<String, AreaMarker>();
Bukkit.getServer().getWorlds().stream().map(w -> GriefDefender.getCore().getClaimManager(w.getUID()))
.map(ClaimManager::getWorldClaims).forEach(claims -> {
claims.forEach(claim -> updateClaimMarker(claim, newmap));
});
for (AreaMarker oldm : this.areaMarkers.values()) {
oldm.deleteMarker();
}
this.areaMarkers = newmap;
}
private void activate() {
this.markerapi = this.dynmap.getMarkerAPI();
if (this.markerapi == null) {
return;
}
if (this.reload) {
GriefDefenderPlugin.getInstance().loadConfig();
if (this.set != null) {
this.set.deleteMarkerSet();
this.set = null;
}
this.areaMarkers.clear();
} else {
this.reload = true;
}
this.set = this.markerapi.getMarkerSet("griefdefender.markerset");
if (this.set == null) {
this.set = this.markerapi.createMarkerSet("griefdefender.markerset", GriefDefenderPlugin.MOD_ID, null, false);
} else {
this.set.setMarkerSetLabel(GriefDefenderPlugin.MOD_ID);
}
if (this.set == null) {
this.logger.severe("Error creating marker set");
return;
}
int minzoom = this.cfg.minzoom;
if (minzoom > 0) {
this.set.setMinZoom(minzoom);
}
this.set.setLayerPriority(this.cfg.layerPriority);
this.set.setHideByDefault(this.cfg.layerHideByDefault);
new GriefDefenderUpdate(40L);
this.logger.info("Dynmap provider is activated");
}
public void onDisable() {
if (this.set != null) {
this.set.deleteMarkerSet();
this.set = null;
}
this.areaMarkers.clear();
this.disabled = true;
}
private class GriefDefenderUpdate extends BukkitRunnable {
public GriefDefenderUpdate(long delay) {
this.runTaskLater(GDBootstrap.getInstance(), delay);
}
@Override
public void run() {
if (!disabled) {
updateClaims();
} else {
this.cancel();
}
}
}
@Subscribe
public void onClaimCreate(CreateClaimEvent event) {
new GriefDefenderUpdate(20L);
}
@Subscribe
public void onClaimDelete(RemoveClaimEvent event) {
new GriefDefenderUpdate(20L);
}
@Subscribe
public void onClaimChange(ChangeClaimEvent event) {
new GriefDefenderUpdate(20L);
}
}

View File

@ -0,0 +1,260 @@
/*
* 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.provider;
import java.util.List;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.entity.Player;
import com.griefdefender.GDBootstrap;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.GriefDefender;
import com.griefdefender.api.Subject;
import com.griefdefender.api.claim.Claim;
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.internal.util.VecHelper;
import com.griefdefender.permission.GDPermissionUser;
import com.griefdefender.util.PlayerUtil;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
public class PlaceholderProvider {
public PlaceholderProvider() {
if(Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null){
new GDPlaceholderExpansion().register();
}
}
private class GDPlaceholderExpansion extends PlaceholderExpansion {
public GDPlaceholderExpansion() {
}
@Override
public String onPlaceholderRequest(Player player, String identifier){
return onRequest(player, identifier);
}
@Override
public String onRequest(OfflinePlayer user, String identifier) {
final Player player = user instanceof Player ? (Player) user : null;
final Subject subject = GriefDefender.getCore().getSubject(user.getUniqueId().toString());
GDPlayerData playerData = null;
Claim claim = null;
if (player != null) {
final World world = player.getWorld();
claim = GriefDefender.getCore().getClaimManager(world.getUID()).getClaimAt(VecHelper.toVector3i(player.getLocation()));
playerData = (GDPlayerData) GriefDefender.getCore().getPlayerData(world.getUID(), player.getUniqueId()).get();
} else {
playerData = (GDPlayerData) GriefDefender.getCore().getPlayerData(Bukkit.getWorlds().get(0).getUID(), user.getUniqueId()).get();
}
switch (identifier) {
case "claim_admin" :
return this.getAdminClaimsInside(player, claim);
case "claim_basic" :
return this.getPlayerClaimsInside(player, claim, ClaimTypes.BASIC);
case "claim_subdivision" :
return this.getPlayerClaimsInside(player, claim, ClaimTypes.SUBDIVISION);
case "claim_town" :
return this.getPlayerClaimsInside(player, claim, ClaimTypes.TOWN);
case "claims_admin" :
return this.getAllAdminClaims(player);
case "claims_basic" :
return this.getAllPlayerClaims(playerData, ClaimTypes.BASIC);
case "claims_subdivision" :
return this.getAllPlayerClaims(playerData, ClaimTypes.SUBDIVISION);
case "claims_town" :
return this.getAllPlayerClaims(playerData, ClaimTypes.TOWN);
case "claims_town_basic" :
return this.getAllTownChildrenClaims(playerData, ClaimTypes.BASIC);
case "claims_town_subdivision" :
return this.getAllTownChildrenClaims(playerData, ClaimTypes.SUBDIVISION);
case "claim_for_sale" :
if (claim == null) {
return "false";
}
return String.valueOf(claim.getEconomyData().isForSale());
case "claim_name" :
if (claim == null) {
return "none";
}
return ((GDClaim) claim).getFriendlyName();
case "claim_owner" :
if (claim == null) {
return "none";
}
if (claim.isWilderness()) {
return "wilderness";
}
return ((GDClaim) claim).getOwnerFriendlyName();
case "claim_trust" :
if (claim == null) {
return "[unknown]";
}
return String.valueOf(claim.isUserTrusted(player.getUniqueId(), TrustTypes.ACCESSOR));
case "claim_type" :
if (claim == null) {
return "none";
}
return claim.getType().getName();
case "pvp" :
if (claim == null) {
return "[unknown]";
}
return String.valueOf(PlayerUtil.getInstance().canPlayerPvP((GDClaim) claim, ((GDPermissionUser) subject)));
case "blocks_total" :
final int initial = playerData.getInitialClaimBlocks();
final int accrued = playerData.getAccruedClaimBlocks();
final int bonus = playerData.getBonusClaimBlocks();
return String.valueOf(initial + accrued + bonus);
case "blocks_left" :
return String.valueOf(playerData.getRemainingClaimBlocks());
case "blocks_accrued_rate" :
return String.valueOf(playerData.getBlocksAccruedPerHour());
case "blocks_accrued_max" :
return String.valueOf(playerData.getMaxAccruedClaimBlocks());
default :
return null;
}
}
@Override
public boolean canRegister(){
return true;
}
@Override
public String getIdentifier() {
return GriefDefenderPlugin.MOD_ID.toLowerCase();
}
@Override
public String getVersion() {
return "0.1";
}
@Override
public String getAuthor(){
return GDBootstrap.getInstance().getDescription().getAuthors().toString();
}
/**
* Because this is an internal class,
* you must override this method to let PlaceholderAPI know to not unregister your expansion class when
* PlaceholderAPI is reloaded
*
* @return true to persist through reloads
*/
@Override
public boolean persist(){
return true;
}
private String getAdminClaimsInside(Player player, Claim currentClaim) {
if (player == null) {
return "0";
}
int count = 0;
if (currentClaim.isWilderness()) {
return this.getAllAdminClaims(player);
}
for (Claim claim : currentClaim.getChildren(true)) {
if (claim.isAdminClaim()) {
count++;
}
}
return String.valueOf(count);
}
private String getAllAdminClaims(Player player) {
if (player == null) {
return "0";
}
final World world = player == null ? Bukkit.getWorlds().get(0) : player.getWorld();
int count = 0;
final Set<Claim> claimList = GriefDefender.getCore().getClaimManager(world.getUID()).getWorldClaims();
for (Claim claim : claimList) {
if (claim.isAdminClaim()) {
count++;
}
}
return String.valueOf(count);
}
private String getPlayerClaimsInside(Player player, Claim currentClaim, ClaimType type) {
if (player == null || currentClaim == null) {
return "0";
}
int count = 0;
if (currentClaim.isWilderness()) {
return String.valueOf(GriefDefender.getCore().getAllPlayerClaims(player.getUniqueId()).size());
}
for (Claim claim : currentClaim.getChildren(true)) {
if (claim.getType() == type) {
count++;
}
}
return String.valueOf(count);
}
private String getAllPlayerClaims(GDPlayerData playerData, ClaimType type) {
if (playerData == null) {
return "0";
}
int count = 0;
final List<Claim> claimList = GriefDefender.getCore().getAllPlayerClaims(playerData.playerID);
for (Claim claim : claimList) {
if (claim.getType() == type) {
count++;
}
}
return String.valueOf(count);
}
private String getAllTownChildrenClaims(GDPlayerData playerData, ClaimType subType) {
if (playerData == null) {
return "0";
}
int count = 0;
final List<Claim> claimList = GriefDefender.getCore().getAllPlayerClaims(playerData.playerID);
for (Claim claim : claimList) {
if (!claim.isTown() && claim.isInTown() && claim.getType() == subType) {
count++;
}
}
return String.valueOf(count);
}
}
}

View File

@ -25,12 +25,16 @@
package com.griefdefender.util;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
import com.griefdefender.GDPlayerData;
import com.griefdefender.GriefDefenderPlugin;
import com.griefdefender.api.Tristate;
import com.griefdefender.api.claim.ClaimType;
import com.griefdefender.api.claim.ClaimTypes;
import com.griefdefender.api.claim.ShovelType;
import com.griefdefender.api.claim.ShovelTypes;
import com.griefdefender.api.permission.flag.Flags;
import com.griefdefender.api.permission.option.Options;
import com.griefdefender.api.permission.option.type.CreateModeTypes;
import com.griefdefender.cache.PermissionHolderCache;
import com.griefdefender.claim.GDClaim;
@ -38,6 +42,7 @@
import com.griefdefender.internal.util.NMSUtil;
import com.griefdefender.internal.visual.ClaimVisual;
import com.griefdefender.internal.visual.GDClaimVisualType;
import com.griefdefender.permission.GDPermissionManager;
import com.griefdefender.permission.GDPermissionUser;
import net.kyori.text.Component;
@ -54,6 +59,7 @@
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet;
import java.util.UUID;
import org.checkerframework.checker.nullness.qual.Nullable;
@ -217,4 +223,28 @@ public boolean isSafeLocation(Location location) {
}
return true;
}
public boolean canPlayerPvP(GDClaim claim, GDPermissionUser source) {
final Player sourcePlayer = source.getOnlinePlayer();
Tristate sourceResult = GDPermissionManager.getInstance().getInternalOptionValue(TypeToken.of(Tristate.class), source, Options.PVP, claim);
if (sourceResult == Tristate.UNDEFINED) {
sourceResult = Tristate.fromBoolean(claim.getWorld().getPVP());
}
if (sourceResult == Tristate.FALSE) {
return false;
}
final GDClaim sourceClaim = GriefDefenderPlugin.getInstance().dataStore.getClaimAtPlayer(source.getInternalPlayerData(), sourcePlayer.getLocation());
if (!sourceClaim.isPvpEnabled()) {
return false;
}
if (!claim.isPvpEnabled()) {
return false;
}
final Tristate flagResult = GDPermissionManager.getInstance().getActiveFlagPermissionValue(claim, source, Flags.ENTITY_DAMAGE, source, "minecraft:player", new HashSet<>());
return flagResult.asBoolean();
}
}