3.4.1
This commit is contained in:
parent
5037847814
commit
0bed62739c
10
plugin.yml
10
plugin.yml
|
|
@ -1,7 +1,7 @@
|
|||
name: GriefPrevention
|
||||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||
softdepend: [Vault]
|
||||
version: 3.3.2
|
||||
softdepend: [Vault, Multiverse-Core]
|
||||
version: 3.4.1
|
||||
commands:
|
||||
abandonclaim:
|
||||
description: Deletes a claim.
|
||||
|
|
@ -89,7 +89,11 @@ commands:
|
|||
deletealladminclaims:
|
||||
description: Deletes all administrative claims.
|
||||
usage: /DeleteAllAdminClaims
|
||||
permission: adminclaims
|
||||
permission: griefprevention.adminclaims
|
||||
transferclaim:
|
||||
description: Converts an administrative claim to a private claim.
|
||||
usage: /TransferClaim <player>
|
||||
permission: griefprevention.adjustclaimblocks
|
||||
permissions:
|
||||
griefprevention.createclaims:
|
||||
description: Grants permission to create claims.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import org.bukkit.entity.Player;
|
|||
//represents a player claim
|
||||
//creating an instance doesn't make an effective claim
|
||||
//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
|
||||
//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;
|
||||
}
|
||||
|
||||
//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.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
//singleton class which manages all GriefPrevention data (except for config options)
|
||||
public class DataStore
|
||||
|
|
@ -125,8 +126,13 @@ public class DataStore
|
|||
else
|
||||
{
|
||||
topLevelClaim.modifiedDate = new Date(files[i].lastModified());
|
||||
this.claims.add(topLevelClaim);
|
||||
topLevelClaim.inDataStore = true;
|
||||
int j = 0;
|
||||
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
|
||||
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;
|
||||
|
||||
//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
|
||||
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
|
||||
for(int i = 0; i < this.claims.size(); 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
|
||||
if(claim.contains(location, ignoreHeight, false))
|
||||
{
|
||||
|
|
@ -848,7 +868,7 @@ public class DataStore
|
|||
|
||||
//ends a siege
|
||||
//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;
|
||||
|
||||
|
|
@ -930,6 +950,36 @@ public class DataStore
|
|||
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
|
||||
|
|
|
|||
|
|
@ -112,8 +112,11 @@ class EntityEventHandler implements Listener
|
|||
//if involved in a siege
|
||||
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
|
||||
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;
|
||||
}
|
||||
|
||||
//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
|
||||
else if(cmd.getName().equalsIgnoreCase("trustlist") && player != null)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,6 +73,12 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
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());
|
||||
|
||||
boolean spam = false;
|
||||
|
|
@ -166,7 +172,8 @@ class PlayerEventHandler implements Listener
|
|||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Warn, GriefPrevention.instance.config_spam_warningMessage);
|
||||
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);
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
//if player was involved in a siege, he forfeits
|
||||
if(playerData.siegeData != null)
|
||||
{
|
||||
player.setHealth(0);
|
||||
this.dataStore.endSiege(playerData.siegeData, null, player.getName());
|
||||
if(player.getHealth() > 0) player.setHealth(0); //might already be zero from above, this avoids a double death message
|
||||
}
|
||||
|
||||
//disable ignore claims mode
|
||||
|
|
@ -773,7 +775,7 @@ class PlayerEventHandler implements Listener
|
|||
if(playerData.shovelMode == ShovelMode.RestoreNature)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
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.add(Material.DIRT.getId());
|
||||
this.notAllowedToHang.add(Material.GRASS.getId());
|
||||
this.notAllowedToHang.add(Material.LONG_GRASS.getId());
|
||||
this.notAllowedToHang.add(Material.SNOW.getId());
|
||||
this.notAllowedToHang.add(Material.LOG.getId());
|
||||
|
||||
|
|
@ -454,7 +455,7 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
private int highestY(int x, int z)
|
||||
{
|
||||
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];
|
||||
if(block.typeId != Material.AIR.getId() &&
|
||||
|
|
|
|||
|
|
@ -65,13 +65,13 @@ class SiegeCheckupTask implements Runnable
|
|||
//otherwise attacker wins if the defender runs away
|
||||
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
|
||||
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)
|
||||
|
|
@ -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)
|
||||
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