3.4.1
This commit is contained in:
parent
5037847814
commit
0bed62739c
10
plugin.yml
10
plugin.yml
|
|
@ -1,7 +1,7 @@
|
||||||
name: GriefPrevention
|
name: GriefPrevention
|
||||||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||||
softdepend: [Vault]
|
softdepend: [Vault, Multiverse-Core]
|
||||||
version: 3.3.2
|
version: 3.4.1
|
||||||
commands:
|
commands:
|
||||||
abandonclaim:
|
abandonclaim:
|
||||||
description: Deletes a claim.
|
description: Deletes a claim.
|
||||||
|
|
@ -89,7 +89,11 @@ commands:
|
||||||
deletealladminclaims:
|
deletealladminclaims:
|
||||||
description: Deletes all administrative claims.
|
description: Deletes all administrative claims.
|
||||||
usage: /DeleteAllAdminClaims
|
usage: /DeleteAllAdminClaims
|
||||||
permission: adminclaims
|
permission: griefprevention.adminclaims
|
||||||
|
transferclaim:
|
||||||
|
description: Converts an administrative claim to a private claim.
|
||||||
|
usage: /TransferClaim <player>
|
||||||
|
permission: griefprevention.adjustclaimblocks
|
||||||
permissions:
|
permissions:
|
||||||
griefprevention.createclaims:
|
griefprevention.createclaims:
|
||||||
description: Grants permission to create claims.
|
description: Grants permission to create claims.
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import org.bukkit.entity.Player;
|
||||||
//represents a player claim
|
//represents a player claim
|
||||||
//creating an instance doesn't make an effective claim
|
//creating an instance doesn't make an effective claim
|
||||||
//only claims which have been added to the datastore have any effect
|
//only claims which have been added to the datastore have any effect
|
||||||
public class Claim
|
public class Claim
|
||||||
{
|
{
|
||||||
//two locations, which together define the boundaries of the claim
|
//two locations, which together define the boundaries of the claim
|
||||||
//note that the upper Y value is always ignored, because claims ALWAYS extend up to the sky
|
//note that the upper Y value is always ignored, because claims ALWAYS extend up to the sky
|
||||||
|
|
@ -553,4 +553,21 @@ public class Claim
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//implements a strict ordering of claims, used to keep the claims collection sorted for faster searching
|
||||||
|
boolean greaterThan(Claim otherClaim)
|
||||||
|
{
|
||||||
|
Location thisCorner = this.getLesserBoundaryCorner();
|
||||||
|
Location otherCorner = otherClaim.getLesserBoundaryCorner();
|
||||||
|
|
||||||
|
if(thisCorner.getBlockX() > otherCorner.getBlockX()) return true;
|
||||||
|
|
||||||
|
if(thisCorner.getBlockX() < otherCorner.getBlockX()) return false;
|
||||||
|
|
||||||
|
if(thisCorner.getBlockZ() > otherCorner.getBlockZ()) return true;
|
||||||
|
|
||||||
|
if(thisCorner.getBlockZ() < otherCorner.getBlockZ()) return false;
|
||||||
|
|
||||||
|
return thisCorner.getWorld().getName().compareTo(otherCorner.getWorld().getName()) < 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import java.util.*;
|
||||||
|
|
||||||
import org.bukkit.*;
|
import org.bukkit.*;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
//singleton class which manages all GriefPrevention data (except for config options)
|
//singleton class which manages all GriefPrevention data (except for config options)
|
||||||
public class DataStore
|
public class DataStore
|
||||||
|
|
@ -125,8 +126,13 @@ public class DataStore
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
topLevelClaim.modifiedDate = new Date(files[i].lastModified());
|
topLevelClaim.modifiedDate = new Date(files[i].lastModified());
|
||||||
this.claims.add(topLevelClaim);
|
int j = 0;
|
||||||
topLevelClaim.inDataStore = true;
|
while(j < this.claims.size() && !this.claims.get(j).greaterThan(topLevelClaim)) j++;
|
||||||
|
if(j < this.claims.size())
|
||||||
|
this.claims.add(j, topLevelClaim);
|
||||||
|
else
|
||||||
|
this.claims.add(this.claims.size(), topLevelClaim);
|
||||||
|
topLevelClaim.inDataStore = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -277,7 +283,12 @@ public class DataStore
|
||||||
}
|
}
|
||||||
|
|
||||||
//add it and mark it as added
|
//add it and mark it as added
|
||||||
this.claims.add(newClaim);
|
int j = 0;
|
||||||
|
while(j < this.claims.size() && !this.claims.get(j).greaterThan(newClaim)) j++;
|
||||||
|
if(j < this.claims.size())
|
||||||
|
this.claims.add(j, newClaim);
|
||||||
|
else
|
||||||
|
this.claims.add(this.claims.size(), newClaim);
|
||||||
newClaim.inDataStore = true;
|
newClaim.inDataStore = true;
|
||||||
|
|
||||||
//except for administrative claims (which have no owner), update the owner's playerData with the new claim
|
//except for administrative claims (which have no owner), update the owner's playerData with the new claim
|
||||||
|
|
@ -619,11 +630,20 @@ public class DataStore
|
||||||
//check cachedClaim guess first. if it's in the datastore and the location is inside it, we're done
|
//check cachedClaim guess first. if it's in the datastore and the location is inside it, we're done
|
||||||
if(cachedClaim != null && cachedClaim.inDataStore && cachedClaim.contains(location, ignoreHeight, true)) return cachedClaim;
|
if(cachedClaim != null && cachedClaim.inDataStore && cachedClaim.contains(location, ignoreHeight, true)) return cachedClaim;
|
||||||
|
|
||||||
|
//the claims list is ordered by greater boundary corner
|
||||||
|
//create a temporary "fake" claim in memory for comparison purposes
|
||||||
|
Claim tempClaim = new Claim();
|
||||||
|
tempClaim.lesserBoundaryCorner = location;
|
||||||
|
|
||||||
//otherwise, search all existing claims until we find the right claim
|
//otherwise, search all existing claims until we find the right claim
|
||||||
for(int i = 0; i < this.claims.size(); i++)
|
for(int i = 0; i < this.claims.size(); i++)
|
||||||
{
|
{
|
||||||
Claim claim = this.claims.get(i);
|
Claim claim = this.claims.get(i);
|
||||||
|
|
||||||
|
//if we reach a claim which is greater than the temp claim created above, there's definitely no claim
|
||||||
|
//in the collection which includes our location
|
||||||
|
if(claim.greaterThan(tempClaim)) return null;
|
||||||
|
|
||||||
//find a top level claim
|
//find a top level claim
|
||||||
if(claim.contains(location, ignoreHeight, false))
|
if(claim.contains(location, ignoreHeight, false))
|
||||||
{
|
{
|
||||||
|
|
@ -848,7 +868,7 @@ public class DataStore
|
||||||
|
|
||||||
//ends a siege
|
//ends a siege
|
||||||
//either winnerName or loserName can be null, but not both
|
//either winnerName or loserName can be null, but not both
|
||||||
public void endSiege(SiegeData siegeData, String winnerName, String loserName)
|
public void endSiege(SiegeData siegeData, String winnerName, String loserName, boolean death)
|
||||||
{
|
{
|
||||||
boolean grantAccess = false;
|
boolean grantAccess = false;
|
||||||
|
|
||||||
|
|
@ -930,6 +950,36 @@ public class DataStore
|
||||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 5);
|
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if the siege ended due to death, transfer inventory to winner
|
||||||
|
if(death)
|
||||||
|
{
|
||||||
|
Player winner = GriefPrevention.instance.getServer().getPlayer(winnerName);
|
||||||
|
Player loser = GriefPrevention.instance.getServer().getPlayer(loserName);
|
||||||
|
if(winner != null && loser != null)
|
||||||
|
{
|
||||||
|
//get loser's inventory, then clear it
|
||||||
|
ItemStack [] loserItems = loser.getInventory().getContents();
|
||||||
|
loser.getInventory().clear();
|
||||||
|
|
||||||
|
//try to add it to the winner's inventory
|
||||||
|
for(int j = 0; j < loserItems.length; j++)
|
||||||
|
{
|
||||||
|
if(loserItems[j] == null || loserItems[j].getType() == Material.AIR || loserItems[j].getAmount() == 0) continue;
|
||||||
|
|
||||||
|
HashMap<Integer, ItemStack> wontFitItems = winner.getInventory().addItem(loserItems[j]);
|
||||||
|
|
||||||
|
//drop any remainder on the ground at his feet
|
||||||
|
Object [] keys = wontFitItems.keySet().toArray();
|
||||||
|
Location winnerLocation = winner.getLocation();
|
||||||
|
for(int i = 0; i < keys.length; i++)
|
||||||
|
{
|
||||||
|
Integer key = (Integer)keys[i];
|
||||||
|
winnerLocation.getWorld().dropItemNaturally(winnerLocation, wontFitItems.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//timestamp for each siege cooldown to end
|
//timestamp for each siege cooldown to end
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,11 @@ class EntityEventHandler implements Listener
|
||||||
//if involved in a siege
|
//if involved in a siege
|
||||||
if(playerData.siegeData != null)
|
if(playerData.siegeData != null)
|
||||||
{
|
{
|
||||||
|
//don't drop items as usual, they will be sent to the siege winner
|
||||||
|
event.getDrops().clear();
|
||||||
|
|
||||||
//end it, with the dieing player being the loser
|
//end it, with the dieing player being the loser
|
||||||
this.dataStore.endSiege(playerData.siegeData, null, player.getName());
|
this.dataStore.endSiege(playerData.siegeData, null, player.getName(), true /*ended due to death*/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -469,6 +469,56 @@ public class GriefPrevention extends JavaPlugin
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//transferclaim <player>
|
||||||
|
else if(cmd.getName().equalsIgnoreCase("transferclaim") && player != null)
|
||||||
|
{
|
||||||
|
//requires exactly one parameter, the other player's name
|
||||||
|
if(args.length != 1) return false;
|
||||||
|
|
||||||
|
//check additional permission
|
||||||
|
if(!player.hasPermission("griefprevention.adminclaims"))
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, "That command requires the administrative claims permission.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//which claim is the user in?
|
||||||
|
Claim claim = this.dataStore.getClaimAt(player.getLocation(), true, null);
|
||||||
|
if(claim == null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Instr, "There's no claim here. Stand in the administrative claim you want to transfer.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if(!claim.isAdminClaim())
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, "Only administrative claims may be transferred to a player.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
OfflinePlayer targetPlayer = this.resolvePlayer(args[0]);
|
||||||
|
if(targetPlayer == null)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Err, "Player not found.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//change ownerhsip
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.dataStore.changeClaimOwner(claim, targetPlayer.getName());
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Instr, "Only top level claims (not subdivisions) may be transferred. Stand outside of the subdivision and try again.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//confirm
|
||||||
|
GriefPrevention.sendMessage(player, TextMode.Success, "Claim transferred.");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//trustlist
|
//trustlist
|
||||||
else if(cmd.getName().equalsIgnoreCase("trustlist") && player != null)
|
else if(cmd.getName().equalsIgnoreCase("trustlist") && player != null)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -73,6 +73,12 @@ class PlayerEventHandler implements Listener
|
||||||
|
|
||||||
if(!GriefPrevention.instance.config_spam_enabled) return;
|
if(!GriefPrevention.instance.config_spam_enabled) return;
|
||||||
|
|
||||||
|
//remedy any CAPS SPAM without bothering to fault the player for it
|
||||||
|
if(message.length() > 4 && !player.hasPermission("griefprevention.spam") && message.toUpperCase().equals(message))
|
||||||
|
{
|
||||||
|
event.setMessage(message.toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||||
|
|
||||||
boolean spam = false;
|
boolean spam = false;
|
||||||
|
|
@ -166,7 +172,8 @@ class PlayerEventHandler implements Listener
|
||||||
{
|
{
|
||||||
GriefPrevention.sendMessage(player, TextMode.Warn, GriefPrevention.instance.config_spam_warningMessage);
|
GriefPrevention.sendMessage(player, TextMode.Warn, GriefPrevention.instance.config_spam_warningMessage);
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
GriefPrevention.AddLogEntry("Muted spam from " + player.getName() + ".");
|
GriefPrevention.AddLogEntry("Warned " + player.getName() + " about spam penalties.");
|
||||||
|
GriefPrevention.AddLogEntry("Muted spam from " + player.getName() + ": " + message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -273,17 +280,12 @@ class PlayerEventHandler implements Listener
|
||||||
player.setHealth(0);
|
player.setHealth(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//FEATURE: on logout or kick, give player the any claim blocks he may have earned for this play session
|
|
||||||
//NOTE: not all kicks are bad, for example an AFK kick or a kick to make room for an admin to log in
|
|
||||||
//that's why even kicked players get their claim blocks
|
|
||||||
|
|
||||||
//FEATURE: during a siege, any player who logs out dies and forfeits the siege
|
//FEATURE: during a siege, any player who logs out dies and forfeits the siege
|
||||||
|
|
||||||
//if player was involved in a siege, he forfeits
|
//if player was involved in a siege, he forfeits
|
||||||
if(playerData.siegeData != null)
|
if(playerData.siegeData != null)
|
||||||
{
|
{
|
||||||
player.setHealth(0);
|
if(player.getHealth() > 0) player.setHealth(0); //might already be zero from above, this avoids a double death message
|
||||||
this.dataStore.endSiege(playerData.siegeData, null, player.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//disable ignore claims mode
|
//disable ignore claims mode
|
||||||
|
|
@ -773,7 +775,7 @@ class PlayerEventHandler implements Listener
|
||||||
if(playerData.shovelMode == ShovelMode.RestoreNature)
|
if(playerData.shovelMode == ShovelMode.RestoreNature)
|
||||||
{
|
{
|
||||||
//if the clicked block is in a claim, visualize that claim and deliver an error message
|
//if the clicked block is in a claim, visualize that claim and deliver an error message
|
||||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), true, playerData.lastClaim);
|
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||||
if(claim != null)
|
if(claim != null)
|
||||||
{
|
{
|
||||||
GriefPrevention.sendMessage(player, TextMode.Err, claim.getOwnerName() + " claimed that block.");
|
GriefPrevention.sendMessage(player, TextMode.Err, claim.getOwnerName() + " claimed that block.");
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ class RestoreNatureProcessingTask implements Runnable
|
||||||
this.notAllowedToHang = new ArrayList<Integer>();
|
this.notAllowedToHang = new ArrayList<Integer>();
|
||||||
this.notAllowedToHang.add(Material.DIRT.getId());
|
this.notAllowedToHang.add(Material.DIRT.getId());
|
||||||
this.notAllowedToHang.add(Material.GRASS.getId());
|
this.notAllowedToHang.add(Material.GRASS.getId());
|
||||||
|
this.notAllowedToHang.add(Material.LONG_GRASS.getId());
|
||||||
this.notAllowedToHang.add(Material.SNOW.getId());
|
this.notAllowedToHang.add(Material.SNOW.getId());
|
||||||
this.notAllowedToHang.add(Material.LOG.getId());
|
this.notAllowedToHang.add(Material.LOG.getId());
|
||||||
|
|
||||||
|
|
@ -454,7 +455,7 @@ class RestoreNatureProcessingTask implements Runnable
|
||||||
private int highestY(int x, int z)
|
private int highestY(int x, int z)
|
||||||
{
|
{
|
||||||
int y;
|
int y;
|
||||||
for(y = snapshots[0].length - 1; y >= 0; y--)
|
for(y = snapshots[0].length - 1; y > 0; y--)
|
||||||
{
|
{
|
||||||
BlockSnapshot block = this.snapshots[x][y][z];
|
BlockSnapshot block = this.snapshots[x][y][z];
|
||||||
if(block.typeId != Material.AIR.getId() &&
|
if(block.typeId != Material.AIR.getId() &&
|
||||||
|
|
|
||||||
|
|
@ -65,13 +65,13 @@ class SiegeCheckupTask implements Runnable
|
||||||
//otherwise attacker wins if the defender runs away
|
//otherwise attacker wins if the defender runs away
|
||||||
else if(attackerRemains && !defenderRemains)
|
else if(attackerRemains && !defenderRemains)
|
||||||
{
|
{
|
||||||
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName());
|
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//or defender wins if the attacker leaves
|
//or defender wins if the attacker leaves
|
||||||
else if(!attackerRemains && defenderRemains)
|
else if(!attackerRemains && defenderRemains)
|
||||||
{
|
{
|
||||||
dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName());
|
dataStore.endSiege(this.siegeData, defender.getName(), attacker.getName(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if they both left, but are still close together, the battle continues (check again later)
|
//if they both left, but are still close together, the battle continues (check again later)
|
||||||
|
|
@ -83,7 +83,7 @@ class SiegeCheckupTask implements Runnable
|
||||||
//otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase)
|
//otherwise they both left and aren't close to each other, so call the attacker the winner (defender escaped, possibly after a chase)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName());
|
dataStore.endSiege(this.siegeData, attacker.getName(), defender.getName(), false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user