7.0
This commit is contained in:
parent
e09a6732ba
commit
7f600e7098
12
plugin.yml
12
plugin.yml
|
|
@ -2,7 +2,7 @@ name: GriefPrevention
|
|||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||
softdepend: [Vault, Multiverse-Core, My Worlds, MystCraft, Transporter]
|
||||
dev-url: http://dev.bukkit.org/server-mods/grief-prevention
|
||||
version: 6.9
|
||||
version: 7.0
|
||||
commands:
|
||||
abandonclaim:
|
||||
description: Deletes a claim.
|
||||
|
|
@ -89,12 +89,12 @@ commands:
|
|||
description: Purchases additional claim blocks with server money. Doesn't work on servers without a Vault-compatible economy plugin.
|
||||
usage: /BuyClaimBlocks <numberOfBlocks>
|
||||
aliases: buyclaim
|
||||
permission: griefprevention.claims
|
||||
permission: griefprevention.buysellclaimblocks
|
||||
sellclaimblocks:
|
||||
description: Sells your claim blocks for server money. Doesn't work on servers without a Vault-compatible economy plugin.
|
||||
usage: /SellClaimBlocks <numberOfBlocks>
|
||||
aliases: sellclaim
|
||||
permission: griefprevention.claims
|
||||
permission: griefprevention.buysellclaimblocks
|
||||
trapped:
|
||||
description: Ejects you to nearby unclaimed land. Has a substantial cooldown period.
|
||||
usage: /Trapped
|
||||
|
|
@ -124,8 +124,7 @@ commands:
|
|||
permission: griefprevention.deathblow
|
||||
claimslist:
|
||||
description: Lists information about a player's claim blocks and claims.
|
||||
usage: /ClaimsList <player>
|
||||
permission: griefprevention.adjustclaimblocks
|
||||
usage: /ClaimsList or /ClaimsList <player>
|
||||
permissions:
|
||||
griefprevention.createclaims:
|
||||
description: Grants permission to create claims.
|
||||
|
|
@ -175,4 +174,7 @@ permissions:
|
|||
default: op
|
||||
griefprevention.claims:
|
||||
description: Grants access to claim-related slash commands.
|
||||
default: true
|
||||
griefprevention.buysellclaimblocks:
|
||||
description: Grants access to claim block buy/sell commands.
|
||||
default: true
|
||||
|
|
@ -150,6 +150,9 @@ public class BlockEventHandler implements Listener
|
|||
return;
|
||||
}
|
||||
|
||||
//if a player is in pvp combat, he can't give away items
|
||||
if(playerData.inPvpCombat()) return;
|
||||
|
||||
//NOTE: to eliminate accidental give-aways, first hit on a chest displays a confirmation message
|
||||
//subsequent hits donate item to the chest
|
||||
|
||||
|
|
@ -266,7 +269,7 @@ public class BlockEventHandler implements Listener
|
|||
//FEATURE: limit fire placement, to prevent PvP-by-fire
|
||||
|
||||
//if placed block is fire and pvp is off, apply rules for proximity to other players
|
||||
if(block.getType() == Material.FIRE && !block.getWorld().getPVP() && !player.hasPermission("griefprevention.lava"))
|
||||
if(block.getType() == Material.FIRE && !GriefPrevention.instance.config_pvp_enabledWorlds.contains(block.getWorld()) && !player.hasPermission("griefprevention.lava"))
|
||||
{
|
||||
List<Player> players = block.getWorld().getPlayers();
|
||||
for(int i = 0; i < players.size(); i++)
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public class Claim
|
|||
//administrative claims are created and maintained by players with the griefprevention.adminclaims permission.
|
||||
public boolean isAdminClaim()
|
||||
{
|
||||
return this.ownerName.isEmpty();
|
||||
return (this.ownerName == null || this.ownerName.isEmpty());
|
||||
}
|
||||
|
||||
//accessor for ID
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,15 +1,33 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
public class CustomizableMessage
|
||||
{
|
||||
public Messages id;
|
||||
public String text;
|
||||
public String notes;
|
||||
|
||||
public CustomizableMessage(Messages id, String text, String notes)
|
||||
{
|
||||
this.id = id;
|
||||
this.text = text;
|
||||
this.notes = notes;
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
public class CustomizableMessage
|
||||
{
|
||||
public Messages id;
|
||||
public String text;
|
||||
public String notes;
|
||||
|
||||
public CustomizableMessage(Messages id, String text, String notes)
|
||||
{
|
||||
this.id = id;
|
||||
this.text = text;
|
||||
this.notes = notes;
|
||||
}
|
||||
}
|
||||
|
|
@ -884,7 +884,7 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.AutomaticClaimNotification, "This chest and nearby blocks are protected from breakage and theft. The temporary gold and glowstone blocks mark the protected area. To toggle them on and off, right-click with a stick.", null);
|
||||
this.addDefault(defaults, Messages.TrustCommandAdvertisement, "Use the /trust command to grant other players access.", null);
|
||||
this.addDefault(defaults, Messages.GoldenShovelAdvertisement, "To claim more land, you need a golden shovel. When you equip one, you'll get more information.", null);
|
||||
this.addDefault(defaults, Messages.UnprotectedChestWarning, "This chest is NOT protected. Consider expanding an existing claim or creating a new one.", null);
|
||||
this.addDefault(defaults, Messages.UnprotectedChestWarning, "This chest is NOT protected. Consider using a golden shovel to expand an existing claim or to create a new one.", null);
|
||||
this.addDefault(defaults, Messages.ThatPlayerPvPImmune, "You can't injure defenseless players.", null);
|
||||
this.addDefault(defaults, Messages.CantFightWhileImmune, "You can't fight someone while you're protected from PvP.", null);
|
||||
this.addDefault(defaults, Messages.NoDamageClaimedEntity, "That belongs to {0}.", "0: owner name");
|
||||
|
|
@ -893,7 +893,7 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.CreativeBasicsDemoAdvertisement, "Land Claim Help: http://tinyurl.com/c7bajb8", null);
|
||||
this.addDefault(defaults, Messages.SurvivalBasicsDemoAdvertisement, "Land Claim Help: http://tinyurl.com/6nkwegj", null);
|
||||
this.addDefault(defaults, Messages.TrappedChatKeyword, "trapped", "When mentioned in chat, players get information about the /trapped command.");
|
||||
this.addDefault(defaults, Messages.TrappedInstructions, "Are you trapped in someone's claim? Consider the /trapped command.", null);
|
||||
this.addDefault(defaults, Messages.TrappedInstructions, "Are you trapped in someone's land claim? Try the /trapped command.", null);
|
||||
this.addDefault(defaults, Messages.PvPNoDrop, "You can't drop items while in PvP combat.", null);
|
||||
this.addDefault(defaults, Messages.SiegeNoTeleport, "You can't teleport out of a besieged area.", null);
|
||||
this.addDefault(defaults, Messages.BesiegedNoTeleport, "You can't teleport into a besieged area.", null);
|
||||
|
|
@ -952,7 +952,7 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.HowToClaimRegex, "(^|.*\\W)how\\W.*\\W(claim|protect|lock)(\\W.*|$)", "This is a Java Regular Expression. Look it up before editing! It's used to tell players about the demo video when they ask how to claim land.");
|
||||
this.addDefault(defaults, Messages.NoBuildOutsideClaims, "You can't build here unless you claim some land first.", null);
|
||||
this.addDefault(defaults, Messages.PlayerOfflineTime, " Last login: {0} days ago.", "0: number of full days since last login");
|
||||
this.addDefault(defaults, Messages.BuildingOutsideClaims, "Other players can undo your work here! Consider claiming this area to protect your work.", null);
|
||||
this.addDefault(defaults, Messages.BuildingOutsideClaims, "Other players can undo your work here! Consider using a golden shovel to claim this area so that your work will be protected.", null);
|
||||
this.addDefault(defaults, Messages.TrappedWontWorkHere, "Sorry, unable to find a safe location to teleport you to. Contact an admin, or consider /kill if you don't want to wait.", null);
|
||||
this.addDefault(defaults, Messages.CommandBannedInPvP, "You can't use that command while in PvP combat.", null);
|
||||
this.addDefault(defaults, Messages.UnclaimCleanupWarning, "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.", null);
|
||||
|
|
@ -961,6 +961,8 @@ public abstract class DataStore
|
|||
this.addDefault(defaults, Messages.NoTNTDamageAboveSeaLevel, "Warning: TNT will not destroy blocks above sea level.", null);
|
||||
this.addDefault(defaults, Messages.NoTNTDamageClaims, "Warning: TNT will not destroy claimed blocks.", null);
|
||||
this.addDefault(defaults, Messages.IgnoreClaimsAdvertisement, "To override, use /IgnoreClaims.", null);
|
||||
this.addDefault(defaults, Messages.NoPermissionForCommand, "You don't have permission to do that.", null);
|
||||
this.addDefault(defaults, Messages.ClaimsListNoPermission, "You don't have permission to get information about another player's land claims.", null);
|
||||
|
||||
//load the config file
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
|
||||
|
|
|
|||
|
|
@ -1,75 +1,75 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//FEATURE: give players claim blocks for playing, as long as they're not away from their computer
|
||||
|
||||
//runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing
|
||||
class DeliverClaimBlocksTask implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Player [] players = GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
|
||||
//ensure players get at least 1 block (if accrual is totally disabled, this task won't even be scheduled)
|
||||
int accruedBlocks = GriefPrevention.instance.config_claims_blocksAccruedPerHour / 12;
|
||||
if(accruedBlocks < 0) accruedBlocks = 1;
|
||||
|
||||
//for each online player
|
||||
for(int i = 0; i < players.length; i++)
|
||||
{
|
||||
Player player = players[i];
|
||||
DataStore dataStore = GriefPrevention.instance.dataStore;
|
||||
PlayerData playerData = dataStore.getPlayerData(player.getName());
|
||||
|
||||
Location lastLocation = playerData.lastAfkCheckLocation;
|
||||
try //distance squared will throw an exception if the player has changed worlds
|
||||
{
|
||||
//if he's not in a vehicle and has moved at least three blocks since the last check
|
||||
if(!player.isInsideVehicle() && (lastLocation == null || lastLocation.distanceSquared(player.getLocation()) >= 9))
|
||||
{
|
||||
//if player is over accrued limit, accrued limit was probably reduced in config file AFTER he accrued
|
||||
//in that case, leave his blocks where they are
|
||||
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks) continue;
|
||||
|
||||
//add blocks
|
||||
playerData.accruedClaimBlocks += accruedBlocks;
|
||||
|
||||
//respect limits
|
||||
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks)
|
||||
{
|
||||
playerData.accruedClaimBlocks = GriefPrevention.instance.config_claims_maxAccruedBlocks;
|
||||
}
|
||||
|
||||
//intentionally NOT saving data here to reduce overall secondary storage access frequency
|
||||
//many other operations will cause this players data to save, including his eventual logout
|
||||
//dataStore.savePlayerData(player.getName(), playerData);
|
||||
}
|
||||
}
|
||||
catch(Exception e) { }
|
||||
|
||||
//remember current location for next time
|
||||
playerData.lastAfkCheckLocation = player.getLocation();
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//FEATURE: give players claim blocks for playing, as long as they're not away from their computer
|
||||
|
||||
//runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing
|
||||
class DeliverClaimBlocksTask implements Runnable
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Player [] players = GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
|
||||
//ensure players get at least 1 block (if accrual is totally disabled, this task won't even be scheduled)
|
||||
int accruedBlocks = GriefPrevention.instance.config_claims_blocksAccruedPerHour / 12;
|
||||
if(accruedBlocks < 0) accruedBlocks = 1;
|
||||
|
||||
//for each online player
|
||||
for(int i = 0; i < players.length; i++)
|
||||
{
|
||||
Player player = players[i];
|
||||
DataStore dataStore = GriefPrevention.instance.dataStore;
|
||||
PlayerData playerData = dataStore.getPlayerData(player.getName());
|
||||
|
||||
Location lastLocation = playerData.lastAfkCheckLocation;
|
||||
try //distance squared will throw an exception if the player has changed worlds
|
||||
{
|
||||
//if he's not in a vehicle and has moved at least three blocks since the last check
|
||||
if(!player.isInsideVehicle() && (lastLocation == null || lastLocation.distanceSquared(player.getLocation()) >= 9))
|
||||
{
|
||||
//if player is over accrued limit, accrued limit was probably reduced in config file AFTER he accrued
|
||||
//in that case, leave his blocks where they are
|
||||
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks) continue;
|
||||
|
||||
//add blocks
|
||||
playerData.accruedClaimBlocks += accruedBlocks;
|
||||
|
||||
//respect limits
|
||||
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks)
|
||||
{
|
||||
playerData.accruedClaimBlocks = GriefPrevention.instance.config_claims_maxAccruedBlocks;
|
||||
}
|
||||
|
||||
//intentionally NOT saving data here to reduce overall secondary storage access frequency
|
||||
//many other operations will cause this players data to save, including his eventual logout
|
||||
//dataStore.savePlayerData(player.getName(), playerData);
|
||||
}
|
||||
}
|
||||
catch(Exception e) { }
|
||||
|
||||
//remember current location for next time
|
||||
playerData.lastAfkCheckLocation = player.getLocation();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,143 +1,143 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Boat;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
|
||||
//FEATURE: creative mode worlds get a regular entity cleanup
|
||||
|
||||
//this main thread task revisits the location of a partially chopped tree from several minutes ago
|
||||
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
|
||||
class EntityCleanupTask implements Runnable
|
||||
{
|
||||
//where to start cleaning in the list of entities
|
||||
private double percentageStart;
|
||||
|
||||
public EntityCleanupTask(double percentageStart)
|
||||
{
|
||||
this.percentageStart = percentageStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ArrayList<World> worlds = GriefPrevention.instance.config_claims_enabledCreativeWorlds;
|
||||
|
||||
for(int i = 0; i < worlds.size(); i++)
|
||||
{
|
||||
World world = worlds.get(i);
|
||||
|
||||
List<Entity> entities = world.getEntities();
|
||||
|
||||
//starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities
|
||||
int j = (int)(entities.size() * this.percentageStart);
|
||||
int k = (int)(entities.size() * (this.percentageStart + .1));
|
||||
Claim cachedClaim = null;
|
||||
for(; j < entities.size() && j < k; j++)
|
||||
{
|
||||
Entity entity = entities.get(j);
|
||||
|
||||
boolean remove = false;
|
||||
if(entity instanceof Boat) //boats must be occupied
|
||||
{
|
||||
Boat boat = (Boat)entity;
|
||||
if(boat.isEmpty()) remove = true;
|
||||
}
|
||||
|
||||
else if(entity instanceof Vehicle)
|
||||
{
|
||||
Vehicle vehicle = (Vehicle)entity;
|
||||
|
||||
//minecarts in motion must be occupied by a player
|
||||
if(vehicle.getVelocity().lengthSquared() != 0)
|
||||
{
|
||||
if(vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
//stationary carts must be on rails
|
||||
else
|
||||
{
|
||||
Material material = world.getBlockAt(vehicle.getLocation()).getType();
|
||||
if(material != Material.RAILS && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//all non-player entities must be in claims
|
||||
else if(!(entity instanceof Player))
|
||||
{
|
||||
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
cachedClaim = claim;
|
||||
}
|
||||
else
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(remove)
|
||||
{
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//starting and stopping point. each execution of the task scans 5% of the server's claims
|
||||
List<Claim> claims = GriefPrevention.instance.dataStore.claims;
|
||||
int j = (int)(claims.size() * this.percentageStart);
|
||||
int k = (int)(claims.size() * (this.percentageStart + .05));
|
||||
for(; j < claims.size() && j < k; j++)
|
||||
{
|
||||
Claim claim = claims.get(j);
|
||||
|
||||
//if it's a creative mode claim
|
||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||
{
|
||||
//check its entity count and remove any extras
|
||||
claim.allowMoreEntities();
|
||||
}
|
||||
}
|
||||
|
||||
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
|
||||
double nextRunPercentageStart = this.percentageStart + .05;
|
||||
if(nextRunPercentageStart > .99)
|
||||
{
|
||||
nextRunPercentageStart = 0;
|
||||
System.gc(); //clean up every hour
|
||||
}
|
||||
|
||||
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Boat;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Vehicle;
|
||||
|
||||
//FEATURE: creative mode worlds get a regular entity cleanup
|
||||
|
||||
//this main thread task revisits the location of a partially chopped tree from several minutes ago
|
||||
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
|
||||
class EntityCleanupTask implements Runnable
|
||||
{
|
||||
//where to start cleaning in the list of entities
|
||||
private double percentageStart;
|
||||
|
||||
public EntityCleanupTask(double percentageStart)
|
||||
{
|
||||
this.percentageStart = percentageStart;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ArrayList<World> worlds = GriefPrevention.instance.config_claims_enabledCreativeWorlds;
|
||||
|
||||
for(int i = 0; i < worlds.size(); i++)
|
||||
{
|
||||
World world = worlds.get(i);
|
||||
|
||||
List<Entity> entities = world.getEntities();
|
||||
|
||||
//starting and stopping point. each execution of the task scans 10% of the server's (loaded) entities
|
||||
int j = (int)(entities.size() * this.percentageStart);
|
||||
int k = (int)(entities.size() * (this.percentageStart + .1));
|
||||
Claim cachedClaim = null;
|
||||
for(; j < entities.size() && j < k; j++)
|
||||
{
|
||||
Entity entity = entities.get(j);
|
||||
|
||||
boolean remove = false;
|
||||
if(entity instanceof Boat) //boats must be occupied
|
||||
{
|
||||
Boat boat = (Boat)entity;
|
||||
if(boat.isEmpty()) remove = true;
|
||||
}
|
||||
|
||||
else if(entity instanceof Vehicle)
|
||||
{
|
||||
Vehicle vehicle = (Vehicle)entity;
|
||||
|
||||
//minecarts in motion must be occupied by a player
|
||||
if(vehicle.getVelocity().lengthSquared() != 0)
|
||||
{
|
||||
if(vehicle.isEmpty() || !(vehicle.getPassenger() instanceof Player))
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
//stationary carts must be on rails
|
||||
else
|
||||
{
|
||||
Material material = world.getBlockAt(vehicle.getLocation()).getType();
|
||||
if(material != Material.RAILS && material != Material.POWERED_RAIL && material != Material.DETECTOR_RAIL)
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//all non-player entities must be in claims
|
||||
else if(!(entity instanceof Player))
|
||||
{
|
||||
Claim claim = GriefPrevention.instance.dataStore.getClaimAt(entity.getLocation(), false, cachedClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
cachedClaim = claim;
|
||||
}
|
||||
else
|
||||
{
|
||||
remove = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(remove)
|
||||
{
|
||||
entity.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//starting and stopping point. each execution of the task scans 5% of the server's claims
|
||||
List<Claim> claims = GriefPrevention.instance.dataStore.claims;
|
||||
int j = (int)(claims.size() * this.percentageStart);
|
||||
int k = (int)(claims.size() * (this.percentageStart + .05));
|
||||
for(; j < claims.size() && j < k; j++)
|
||||
{
|
||||
Claim claim = claims.get(j);
|
||||
|
||||
//if it's a creative mode claim
|
||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||
{
|
||||
//check its entity count and remove any extras
|
||||
claim.allowMoreEntities();
|
||||
}
|
||||
}
|
||||
|
||||
//schedule the next run of this task, in 3 minutes (20L is approximately 1 second)
|
||||
double nextRunPercentageStart = this.percentageStart + .05;
|
||||
if(nextRunPercentageStart > .99)
|
||||
{
|
||||
nextRunPercentageStart = 0;
|
||||
System.gc(); //clean up every hour
|
||||
}
|
||||
|
||||
EntityCleanupTask task = new EntityCleanupTask(nextRunPercentageStart);
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task, 20L * 60 * 1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import org.bukkit.entity.LivingEntity;
|
|||
import org.bukkit.entity.Monster;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.ThrownPotion;
|
||||
import org.bukkit.entity.Villager;
|
||||
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
|
@ -361,7 +362,7 @@ class EntityEventHandler implements Listener
|
|||
}
|
||||
|
||||
//if the attacker is a player and defender is a player (pvp combat)
|
||||
if(attacker != null && event.getEntity() instanceof Player)
|
||||
if(attacker != null && event.getEntity() instanceof Player && GriefPrevention.instance.config_pvp_enabledWorlds.contains(attacker.getWorld()))
|
||||
{
|
||||
//FEATURE: prevent pvp in the first minute after spawn, and prevent pvp when one or both players have no inventory
|
||||
|
||||
|
|
@ -425,10 +426,21 @@ class EntityEventHandler implements Listener
|
|||
//if it's claimed
|
||||
if(claim != null)
|
||||
{
|
||||
//if damaged by anything other than a player, cancel the event
|
||||
//if damaged by anything other than a player (exception villagers injured by zombies in admin claims), cancel the event
|
||||
//why exception? so admins can set up a village which can't be CHANGED by players, but must be "protected" by players.
|
||||
if(attacker == null)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
//exception case
|
||||
if(event.getEntity() instanceof Villager && damageSource instanceof Monster && claim.isAdminClaim())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//all other cases
|
||||
else
|
||||
{
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
//otherwise the player damaging the entity must have permission
|
||||
|
|
|
|||
|
|
@ -1,66 +1,66 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//tells a player about how many claim blocks he has, etc
|
||||
//implemented as a task so that it can be delayed
|
||||
//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars
|
||||
class EquipShovelProcessingTask implements Runnable
|
||||
{
|
||||
//player data
|
||||
private Player player;
|
||||
|
||||
public EquipShovelProcessingTask(Player player)
|
||||
{
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//if he logged out, don't do anything
|
||||
if(!player.isOnline()) return;
|
||||
|
||||
//if he's not holding the golden shovel anymore, do nothing
|
||||
if(player.getItemInHand().getType() != GriefPrevention.instance.config_claims_modificationTool) return;
|
||||
|
||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
|
||||
|
||||
int remainingBlocks = playerData.getRemainingClaimBlocks();
|
||||
|
||||
//if in basic claims mode...
|
||||
if(playerData.shovelMode == ShovelMode.Basic)
|
||||
{
|
||||
//tell him how many claim blocks he has available
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks));
|
||||
|
||||
//link to a video demo of land claiming, based on world type
|
||||
if(GriefPrevention.instance.creativeRulesApply(player.getLocation()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsDemoAdvertisement);
|
||||
}
|
||||
else
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsDemoAdvertisement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//tells a player about how many claim blocks he has, etc
|
||||
//implemented as a task so that it can be delayed
|
||||
//otherwise, it's spammy when players mouse-wheel past the shovel in their hot bars
|
||||
class EquipShovelProcessingTask implements Runnable
|
||||
{
|
||||
//player data
|
||||
private Player player;
|
||||
|
||||
public EquipShovelProcessingTask(Player player)
|
||||
{
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//if he logged out, don't do anything
|
||||
if(!player.isOnline()) return;
|
||||
|
||||
//if he's not holding the golden shovel anymore, do nothing
|
||||
if(player.getItemInHand().getType() != GriefPrevention.instance.config_claims_modificationTool) return;
|
||||
|
||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
|
||||
|
||||
int remainingBlocks = playerData.getRemainingClaimBlocks();
|
||||
|
||||
//if in basic claims mode...
|
||||
if(playerData.shovelMode == ShovelMode.Basic)
|
||||
{
|
||||
//tell him how many claim blocks he has available
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.RemainingBlocks, String.valueOf(remainingBlocks));
|
||||
|
||||
//link to a video demo of land claiming, based on world type
|
||||
if(GriefPrevention.instance.creativeRulesApply(player.getLocation()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.CreativeBasicsDemoAdvertisement);
|
||||
}
|
||||
else
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsDemoAdvertisement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
public String config_spam_warningMessage; //message to show a player who is close to spam level
|
||||
public String config_spam_allowedIpAddresses; //IP addresses which will not be censored
|
||||
|
||||
public ArrayList<World> config_pvp_enabledWorlds; //list of worlds where pvp anti-grief rules apply
|
||||
public boolean config_pvp_protectFreshSpawns; //whether to make newly spawned players immune until they pick up an item
|
||||
public boolean config_pvp_punishLogout; //whether to kill players who log out during PvP combat
|
||||
public int config_pvp_combatTimeoutSeconds; //how long combat is considered to continue after the most recent damage
|
||||
|
|
@ -238,6 +239,40 @@ public class GriefPrevention extends JavaPlugin
|
|||
}
|
||||
}
|
||||
|
||||
//default for pvp worlds list
|
||||
ArrayList<String> defaultPvpWorldNames = new ArrayList<String>();
|
||||
for(int i = 0; i < worlds.size(); i++)
|
||||
{
|
||||
World world = worlds.get(i);
|
||||
if(world.getPVP())
|
||||
{
|
||||
defaultPvpWorldNames.add(world.getName());
|
||||
}
|
||||
}
|
||||
|
||||
//get pvp world names from the config file
|
||||
List<String> pvpEnabledWorldNames = config.getStringList("GriefPrevention.PvP.Worlds");
|
||||
if(pvpEnabledWorldNames == null || pvpEnabledWorldNames.size() == 0)
|
||||
{
|
||||
pvpEnabledWorldNames = defaultPvpWorldNames;
|
||||
}
|
||||
|
||||
//validate that list
|
||||
this.config_pvp_enabledWorlds = new ArrayList<World>();
|
||||
for(int i = 0; i < pvpEnabledWorldNames.size(); i++)
|
||||
{
|
||||
String worldName = pvpEnabledWorldNames.get(i);
|
||||
World world = this.getServer().getWorld(worldName);
|
||||
if(world == null)
|
||||
{
|
||||
AddLogEntry("Error: PvP Configuration: There's no world named \"" + worldName + "\". Please update your config.yml.");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.config_pvp_enabledWorlds.add(world);
|
||||
}
|
||||
}
|
||||
|
||||
//sea level
|
||||
this.config_seaLevelOverride = new HashMap<String, Integer>();
|
||||
for(int i = 0; i < worlds.size(); i++)
|
||||
|
|
@ -525,6 +560,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
config.set("GriefPrevention.Spam.BanMessage", this.config_spam_banMessage);
|
||||
config.set("GriefPrevention.Spam.AllowedIpAddresses", this.config_spam_allowedIpAddresses);
|
||||
|
||||
config.set("GriefPrevention.PvP.Worlds", pvpEnabledWorldNames);
|
||||
config.set("GriefPrevention.PvP.ProtectFreshSpawns", this.config_pvp_protectFreshSpawns);
|
||||
config.set("GriefPrevention.PvP.PunishLogout", this.config_pvp_punishLogout);
|
||||
config.set("GriefPrevention.PvP.CombatTimeoutSeconds", this.config_pvp_combatTimeoutSeconds);
|
||||
|
|
@ -1148,6 +1184,12 @@ public class GriefPrevention extends JavaPlugin
|
|||
return true;
|
||||
}
|
||||
|
||||
if(!player.hasPermission("griefprevention.buysellclaimblocks"))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoPermissionForCommand);
|
||||
return true;
|
||||
}
|
||||
|
||||
//if purchase disabled, send error message
|
||||
if(GriefPrevention.instance.config_economy_claimBlocksPurchaseCost == 0)
|
||||
{
|
||||
|
|
@ -1233,6 +1275,12 @@ public class GriefPrevention extends JavaPlugin
|
|||
return true;
|
||||
}
|
||||
|
||||
if(!player.hasPermission("griefprevention.buysellclaimblocks"))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoPermissionForCommand);
|
||||
return true;
|
||||
}
|
||||
|
||||
//if disabled, error message
|
||||
if(GriefPrevention.instance.config_economy_claimBlocksSellValue == 0)
|
||||
{
|
||||
|
|
@ -1404,21 +1452,40 @@ public class GriefPrevention extends JavaPlugin
|
|||
return true;
|
||||
}
|
||||
|
||||
//claimslist <player>
|
||||
//claimslist or claimslist <player>
|
||||
else if(cmd.getName().equalsIgnoreCase("claimslist"))
|
||||
{
|
||||
//requires exactly one parameter, the other player's name
|
||||
if(args.length != 1) return false;
|
||||
//at most one parameter
|
||||
if(args.length > 1) return false;
|
||||
|
||||
//try to find that player
|
||||
OfflinePlayer otherPlayer = this.resolvePlayer(args[0]);
|
||||
if(otherPlayer == null)
|
||||
//player whose claims will be listed
|
||||
OfflinePlayer otherPlayer;
|
||||
|
||||
//if another player isn't specified, assume current player
|
||||
if(args.length < 1)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound);
|
||||
return true;
|
||||
otherPlayer = player;
|
||||
}
|
||||
|
||||
//load the player's data
|
||||
//otherwise if no permission to delve into another player's claims data
|
||||
else if(!player.hasPermission("griefprevention.deleteclaims"))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.ClaimsListNoPermission);
|
||||
return true;
|
||||
}
|
||||
|
||||
//otherwise try to find the specified player
|
||||
else
|
||||
{
|
||||
otherPlayer = this.resolvePlayer(args[0]);
|
||||
if(otherPlayer == null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//load the target player's data
|
||||
PlayerData playerData = this.dataStore.getPlayerData(otherPlayer.getName());
|
||||
GriefPrevention.sendMessage(player, TextMode.Instr, " " + playerData.accruedClaimBlocks + "(+" + playerData.bonusClaimBlocks + ")=" + (playerData.accruedClaimBlocks + playerData.bonusClaimBlocks));
|
||||
for(int i = 0; i < playerData.claims.size(); i++)
|
||||
|
|
@ -1597,6 +1664,13 @@ public class GriefPrevention extends JavaPlugin
|
|||
return true;
|
||||
}
|
||||
|
||||
//if the player is in an administrative claim, he should contact an admin
|
||||
if(claim.isAdminClaim())
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.TrappedWontWorkHere);
|
||||
return true;
|
||||
}
|
||||
|
||||
//check cooldown
|
||||
long lastTrappedUsage = playerData.lastTrappedUsage.getTime();
|
||||
long nextTrappedUsage = lastTrappedUsage + 1000 * 60 * 60 * this.config_claims_trappedCooldownHours;
|
||||
|
|
@ -2003,7 +2077,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
public void checkPvpProtectionNeeded(Player player)
|
||||
{
|
||||
//if pvp is disabled, do nothing
|
||||
if(!player.getWorld().getPVP()) return;
|
||||
if(!this.config_pvp_enabledWorlds.contains(player.getWorld())) return;
|
||||
|
||||
//if player is in creative mode, do nothing
|
||||
if(player.getGameMode() == GameMode.CREATIVE) return;
|
||||
|
|
|
|||
|
|
@ -1,17 +1,35 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class IpBanInfo
|
||||
{
|
||||
InetAddress address;
|
||||
long expirationTimestamp;
|
||||
String bannedAccountName;
|
||||
|
||||
IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName)
|
||||
{
|
||||
this.address = address;
|
||||
this.expirationTimestamp = expirationTimestamp;
|
||||
this.bannedAccountName = bannedAccountName;
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class IpBanInfo
|
||||
{
|
||||
InetAddress address;
|
||||
long expirationTimestamp;
|
||||
String bannedAccountName;
|
||||
|
||||
IpBanInfo(InetAddress address, long expirationTimestamp, String bannedAccountName)
|
||||
{
|
||||
this.address = address;
|
||||
this.expirationTimestamp = expirationTimestamp;
|
||||
this.bannedAccountName = bannedAccountName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +1,74 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
//ordered list of material info objects, for fast searching
|
||||
public class MaterialCollection
|
||||
{
|
||||
ArrayList<MaterialInfo> materials = new ArrayList<MaterialInfo>();
|
||||
|
||||
void Add(MaterialInfo material)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < this.materials.size() && this.materials.get(i).typeID <= material.typeID; i++);
|
||||
this.materials.add(i, material);
|
||||
}
|
||||
|
||||
boolean Contains(MaterialInfo material)
|
||||
{
|
||||
for(int i = 0; i < this.materials.size() ; i++)
|
||||
{
|
||||
MaterialInfo thisMaterial = this.materials.get(i);
|
||||
if(material.typeID == thisMaterial.typeID && (thisMaterial.allDataValues || material.data == thisMaterial.data))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(thisMaterial.typeID > material.typeID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for(int i = 0; i < this.materials.size(); i++)
|
||||
{
|
||||
stringBuilder.append(this.materials.get(i).toString() + " ");
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return this.materials.size();
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
this.materials.clear();
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
//ordered list of material info objects, for fast searching
|
||||
public class MaterialCollection
|
||||
{
|
||||
ArrayList<MaterialInfo> materials = new ArrayList<MaterialInfo>();
|
||||
|
||||
void Add(MaterialInfo material)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < this.materials.size() && this.materials.get(i).typeID <= material.typeID; i++);
|
||||
this.materials.add(i, material);
|
||||
}
|
||||
|
||||
boolean Contains(MaterialInfo material)
|
||||
{
|
||||
for(int i = 0; i < this.materials.size() ; i++)
|
||||
{
|
||||
MaterialInfo thisMaterial = this.materials.get(i);
|
||||
if(material.typeID == thisMaterial.typeID && (thisMaterial.allDataValues || material.data == thisMaterial.data))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if(thisMaterial.typeID > material.typeID)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for(int i = 0; i < this.materials.size(); i++)
|
||||
{
|
||||
stringBuilder.append(this.materials.get(i).toString() + " ");
|
||||
}
|
||||
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public int size()
|
||||
{
|
||||
return this.materials.size();
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
this.materials.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,75 +1,93 @@
|
|||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
//represents a material or collection of materials
|
||||
public class MaterialInfo
|
||||
{
|
||||
int typeID;
|
||||
byte data;
|
||||
boolean allDataValues;
|
||||
String description;
|
||||
|
||||
public MaterialInfo(int typeID, byte data, String description)
|
||||
{
|
||||
this.typeID = typeID;
|
||||
this.data = data;
|
||||
this.allDataValues = false;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public MaterialInfo(int typeID, String description)
|
||||
{
|
||||
this.typeID = typeID;
|
||||
this.data = 0;
|
||||
this.allDataValues = true;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
private MaterialInfo(int typeID, byte data, boolean allDataValues, String description)
|
||||
{
|
||||
this.typeID = typeID;
|
||||
this.data = data;
|
||||
this.allDataValues = allDataValues;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues?"*":String.valueOf(this.data));
|
||||
if(this.description != null) returnValue += ":" + this.description;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static MaterialInfo fromString(String string)
|
||||
{
|
||||
if(string == null || string.isEmpty()) return null;
|
||||
|
||||
String [] parts = string.split(":");
|
||||
if(parts.length < 3) return null;
|
||||
|
||||
try
|
||||
{
|
||||
int typeID = Integer.parseInt(parts[0]);
|
||||
|
||||
byte data;
|
||||
boolean allDataValues;
|
||||
if(parts[1].equals("*"))
|
||||
{
|
||||
allDataValues = true;
|
||||
data = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
allDataValues = false;
|
||||
data = Byte.parseByte(parts[1]);
|
||||
}
|
||||
|
||||
return new MaterialInfo(typeID, data, allDataValues, parts[2]);
|
||||
}
|
||||
catch(NumberFormatException exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
//represents a material or collection of materials
|
||||
public class MaterialInfo
|
||||
{
|
||||
int typeID;
|
||||
byte data;
|
||||
boolean allDataValues;
|
||||
String description;
|
||||
|
||||
public MaterialInfo(int typeID, byte data, String description)
|
||||
{
|
||||
this.typeID = typeID;
|
||||
this.data = data;
|
||||
this.allDataValues = false;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public MaterialInfo(int typeID, String description)
|
||||
{
|
||||
this.typeID = typeID;
|
||||
this.data = 0;
|
||||
this.allDataValues = true;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
private MaterialInfo(int typeID, byte data, boolean allDataValues, String description)
|
||||
{
|
||||
this.typeID = typeID;
|
||||
this.data = data;
|
||||
this.allDataValues = allDataValues;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String returnValue = String.valueOf(this.typeID) + ":" + (this.allDataValues?"*":String.valueOf(this.data));
|
||||
if(this.description != null) returnValue += ":" + this.description;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public static MaterialInfo fromString(String string)
|
||||
{
|
||||
if(string == null || string.isEmpty()) return null;
|
||||
|
||||
String [] parts = string.split(":");
|
||||
if(parts.length < 3) return null;
|
||||
|
||||
try
|
||||
{
|
||||
int typeID = Integer.parseInt(parts[0]);
|
||||
|
||||
byte data;
|
||||
boolean allDataValues;
|
||||
if(parts[1].equals("*"))
|
||||
{
|
||||
allDataValues = true;
|
||||
data = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
allDataValues = false;
|
||||
data = Byte.parseByte(parts[1]);
|
||||
}
|
||||
|
||||
return new MaterialInfo(typeID, data, allDataValues, parts[2]);
|
||||
}
|
||||
catch(NumberFormatException exception)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,24 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
public enum Messages
|
||||
{
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionDemo, DeleteClaimMissing, DeletionSubdivisionWarning, DeleteSuccess, CantDeleteAdminClaim, DeleteAllSuccess, NoDeletePermission, AllAdminDeleted, AdjustBlocksSuccess, NotTrappedHere, TrappedOnCooldown, RescuePending, NonSiegeWorld, AlreadySieging, NotSiegableThere, SiegeTooFarAway, NoSiegeDefenseless, AlreadyUnderSiegePlayer, AlreadyUnderSiegeArea, NoSiegeAdminClaim, SiegeOnCooldown, SiegeAlert, SiegeConfirmed, AbandonClaimMissing, NotYourClaim, DeleteTopLevelClaim, AbandonSuccess, CantGrantThatPermission, GrantPermissionNoClaim, GrantPermissionConfirmation, ManageUniversalPermissionsInstruction, ManageOneClaimPermissionsInstruction, CollectivePublic, BuildPermission, ContainersPermission, AccessPermission, PermissionsPermission, LocationCurrentClaim, LocationAllClaims, PvPImmunityStart, SiegeNoDrop, DonateItemsInstruction, ChestFull, DonationSuccess, PlayerTooCloseForFire, TooDeepToClaim, ChestClaimConfirmation, AutomaticClaimNotification, TrustCommandAdvertisement, GoldenShovelAdvertisement, UnprotectedChestWarning, ThatPlayerPvPImmune, CantFightWhileImmune, NoDamageClaimedEntity, ShovelBasicClaimMode, RemainingBlocks, CreativeBasicsDemoAdvertisement, SurvivalBasicsDemoAdvertisement, TrappedChatKeyword, TrappedInstructions, PvPNoDrop, SiegeNoTeleport, BesiegedNoTeleport, SiegeNoContainers, PvPNoContainers, PvPImmunityEnd, NoBedPermission, NoWildernessBuckets, NoLavaNearOtherPlayer, TooFarAway, BlockNotClaimed, BlockClaimed, SiegeNoShovel, RestoreNaturePlayerInChunk, NoCreateClaimPermission, ResizeClaimTooSmall, ResizeNeedMoreBlocks, NoCreativeUnClaim, ClaimResizeSuccess, ResizeFailOverlap, ResizeStart, ResizeFailOverlapSubdivision, SubdivisionStart, CreateSubdivisionOverlap, SubdivisionSuccess, CreateClaimFailOverlap, CreateClaimFailOverlapOtherPlayer, ClaimsDisabledWorld, ClaimStart, NewClaimTooSmall, CreateClaimInsufficientBlocks, AbandonClaimAdvertisement, CreateClaimFailOverlapShort, CreateClaimSuccess, SiegeWinDoorsOpen, RescueAbortedMoved, SiegeDoorsLockedEjection, NoModifyDuringSiege, OnlyOwnersModifyClaims, NoBuildUnderSiege, NoBuildPvP, NoBuildPermission, NonSiegeMaterial, NoOwnerBuildUnderSiege, NoAccessPermission, NoContainersSiege, NoContainersPermission, OwnerNameForAdminClaims, ClaimTooSmallForEntities, TooManyEntitiesInClaim, YouHaveNoClaims, ConfirmFluidRemoval, AutoBanNotify, AdjustGroupBlocksSuccess, InvalidPermissionID, UntrustOwnerOnly, HowToClaimRegex, NoBuildOutsideClaims, PlayerOfflineTime, BuildingOutsideClaims, TrappedWontWorkHere, CommandBannedInPvP, UnclaimCleanupWarning, BuySellNotConfigured, NoTeleportPvPCombat, NoTNTDamageAboveSeaLevel, NoTNTDamageClaims, IgnoreClaimsAdvertisement
|
||||
RespectingClaims, IgnoringClaims, SuccessfulAbandon, RestoreNatureActivate, RestoreNatureAggressiveActivate, FillModeActive, TransferClaimPermission, TransferClaimMissing, TransferClaimAdminOnly, PlayerNotFound, TransferTopLevel, TransferSuccess, TrustListNoClaim, ClearPermsOwnerOnly, UntrustIndividualAllClaims, UntrustEveryoneAllClaims, NoPermissionTrust, ClearPermissionsOneClaim, UntrustIndividualSingleClaim, OnlySellBlocks, BlockPurchaseCost, ClaimBlockLimit, InsufficientFunds, PurchaseConfirmation, OnlyPurchaseBlocks, BlockSaleValue, NotEnoughBlocksForSale, BlockSaleConfirmation, AdminClaimsMode, BasicClaimsMode, SubdivisionMode, SubdivisionDemo, DeleteClaimMissing, DeletionSubdivisionWarning, DeleteSuccess, CantDeleteAdminClaim, DeleteAllSuccess, NoDeletePermission, AllAdminDeleted, AdjustBlocksSuccess, NotTrappedHere, TrappedOnCooldown, RescuePending, NonSiegeWorld, AlreadySieging, NotSiegableThere, SiegeTooFarAway, NoSiegeDefenseless, AlreadyUnderSiegePlayer, AlreadyUnderSiegeArea, NoSiegeAdminClaim, SiegeOnCooldown, SiegeAlert, SiegeConfirmed, AbandonClaimMissing, NotYourClaim, DeleteTopLevelClaim, AbandonSuccess, CantGrantThatPermission, GrantPermissionNoClaim, GrantPermissionConfirmation, ManageUniversalPermissionsInstruction, ManageOneClaimPermissionsInstruction, CollectivePublic, BuildPermission, ContainersPermission, AccessPermission, PermissionsPermission, LocationCurrentClaim, LocationAllClaims, PvPImmunityStart, SiegeNoDrop, DonateItemsInstruction, ChestFull, DonationSuccess, PlayerTooCloseForFire, TooDeepToClaim, ChestClaimConfirmation, AutomaticClaimNotification, TrustCommandAdvertisement, GoldenShovelAdvertisement, UnprotectedChestWarning, ThatPlayerPvPImmune, CantFightWhileImmune, NoDamageClaimedEntity, ShovelBasicClaimMode, RemainingBlocks, CreativeBasicsDemoAdvertisement, SurvivalBasicsDemoAdvertisement, TrappedChatKeyword, TrappedInstructions, PvPNoDrop, SiegeNoTeleport, BesiegedNoTeleport, SiegeNoContainers, PvPNoContainers, PvPImmunityEnd, NoBedPermission, NoWildernessBuckets, NoLavaNearOtherPlayer, TooFarAway, BlockNotClaimed, BlockClaimed, SiegeNoShovel, RestoreNaturePlayerInChunk, NoCreateClaimPermission, ResizeClaimTooSmall, ResizeNeedMoreBlocks, NoCreativeUnClaim, ClaimResizeSuccess, ResizeFailOverlap, ResizeStart, ResizeFailOverlapSubdivision, SubdivisionStart, CreateSubdivisionOverlap, SubdivisionSuccess, CreateClaimFailOverlap, CreateClaimFailOverlapOtherPlayer, ClaimsDisabledWorld, ClaimStart, NewClaimTooSmall, CreateClaimInsufficientBlocks, AbandonClaimAdvertisement, CreateClaimFailOverlapShort, CreateClaimSuccess, SiegeWinDoorsOpen, RescueAbortedMoved, SiegeDoorsLockedEjection, NoModifyDuringSiege, OnlyOwnersModifyClaims, NoBuildUnderSiege, NoBuildPvP, NoBuildPermission, NonSiegeMaterial, NoOwnerBuildUnderSiege, NoAccessPermission, NoContainersSiege, NoContainersPermission, OwnerNameForAdminClaims, ClaimTooSmallForEntities, TooManyEntitiesInClaim, YouHaveNoClaims, ConfirmFluidRemoval, AutoBanNotify, AdjustGroupBlocksSuccess, InvalidPermissionID, UntrustOwnerOnly, HowToClaimRegex, NoBuildOutsideClaims, PlayerOfflineTime, BuildingOutsideClaims, TrappedWontWorkHere, CommandBannedInPvP, UnclaimCleanupWarning, BuySellNotConfigured, NoTeleportPvPCombat, NoTNTDamageAboveSeaLevel, NoTNTDamageClaims, IgnoreClaimsAdvertisement, NoPermissionForCommand, ClaimsListNoPermission
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,23 +125,26 @@ class PlayerEventHandler implements Listener
|
|||
//if the player has permission to spam, don't bother even examining the message
|
||||
if(player.hasPermission("griefprevention.spam")) return false;
|
||||
|
||||
//remedy any CAPS SPAM without bothering to fault the player for it
|
||||
boolean spam = false;
|
||||
boolean muted = false;
|
||||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
|
||||
//remedy any CAPS SPAM, exception for very short messages which could be emoticons like =D or XD
|
||||
if(message.length() > 4 && this.stringsAreSimilar(message.toUpperCase(), message))
|
||||
{
|
||||
if(event instanceof AsyncPlayerChatEvent)
|
||||
//exception for strings containing forward slash to avoid changing a case-sensitive URL
|
||||
if(event instanceof AsyncPlayerChatEvent && !message.contains("/"))
|
||||
{
|
||||
((AsyncPlayerChatEvent)event).setMessage(message.toLowerCase());
|
||||
playerData.spamCount++;
|
||||
spam = true;
|
||||
}
|
||||
}
|
||||
|
||||
//where other types of spam are concerned, casing isn't significant
|
||||
message = message.toLowerCase();
|
||||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
|
||||
boolean spam = false;
|
||||
boolean muted = false;
|
||||
|
||||
//check message content and timing
|
||||
long millisecondsSinceLastMessage = (new Date()).getTime() - playerData.lastMessageTimestamp.getTime();
|
||||
|
||||
|
|
@ -363,7 +366,7 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
//if in pvp, block any pvp-banned slash commands
|
||||
PlayerData playerData = this.dataStore.getPlayerData(event.getPlayer().getName());
|
||||
if(playerData.inPvpCombat() && GriefPrevention.instance.config_pvp_blockedCommands.contains(command))
|
||||
if((playerData.inPvpCombat() || playerData.siegeData != null) && GriefPrevention.instance.config_pvp_blockedCommands.contains(command))
|
||||
{
|
||||
event.setCancelled(true);
|
||||
GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, Messages.CommandBannedInPvP);
|
||||
|
|
@ -642,17 +645,10 @@ class PlayerEventHandler implements Listener
|
|||
if(event.getCause() == TeleportCause.ENDER_PEARL) return;
|
||||
|
||||
Player player = event.getPlayer();
|
||||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
if(playerData.inPvpCombat())
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoTeleportPvPCombat);
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Location source = event.getFrom();
|
||||
Claim sourceClaim = this.dataStore.getClaimAt(source, false, null);
|
||||
Claim sourceClaim = this.dataStore.getClaimAt(source, false, playerData.lastClaim);
|
||||
if(sourceClaim != null && sourceClaim.siegeData != null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeNoTeleport);
|
||||
|
|
@ -875,7 +871,7 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//lava buckets can't be dumped near other players unless pvp is on
|
||||
if(!block.getWorld().getPVP() && !player.hasPermission("griefprevention.lava"))
|
||||
if(!GriefPrevention.instance.config_pvp_enabledWorlds.contains(block.getWorld()) && !player.hasPermission("griefprevention.lava"))
|
||||
{
|
||||
if(bucketEvent.getBucket() == Material.LAVA_BUCKET)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,69 +1,69 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//tries to rescue a trapped player from a claim where he doesn't have permission to save himself
|
||||
//related to the /trapped slash command
|
||||
//this does run in the main thread, so it's okay to make non-thread-safe calls
|
||||
class PlayerRescueTask implements Runnable
|
||||
{
|
||||
//original location where /trapped was used
|
||||
private Location location;
|
||||
|
||||
//player data
|
||||
private Player player;
|
||||
|
||||
public PlayerRescueTask(Player player, Location location)
|
||||
{
|
||||
this.player = player;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//if he logged out, don't do anything
|
||||
if(!player.isOnline()) return;
|
||||
|
||||
//he no longer has a pending /trapped slash command, so he can try to use it again now
|
||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
|
||||
playerData.pendingTrapped = false;
|
||||
|
||||
//if the player moved three or more blocks from where he used /trapped, admonish him and don't save him
|
||||
if(player.getLocation().distance(this.location) > 3)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved);
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise find a place to teleport him
|
||||
Location destination = GriefPrevention.instance.ejectPlayer(this.player);
|
||||
|
||||
//log entry, in case admins want to investigate the "trap"
|
||||
GriefPrevention.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(destination) + ".");
|
||||
|
||||
//timestamp this successful save so that he can't use /trapped again for a while
|
||||
playerData.lastTrappedUsage = Calendar.getInstance().getTime();
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.Calendar;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//tries to rescue a trapped player from a claim where he doesn't have permission to save himself
|
||||
//related to the /trapped slash command
|
||||
//this does run in the main thread, so it's okay to make non-thread-safe calls
|
||||
class PlayerRescueTask implements Runnable
|
||||
{
|
||||
//original location where /trapped was used
|
||||
private Location location;
|
||||
|
||||
//player data
|
||||
private Player player;
|
||||
|
||||
public PlayerRescueTask(Player player, Location location)
|
||||
{
|
||||
this.player = player;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//if he logged out, don't do anything
|
||||
if(!player.isOnline()) return;
|
||||
|
||||
//he no longer has a pending /trapped slash command, so he can try to use it again now
|
||||
PlayerData playerData = GriefPrevention.instance.dataStore.getPlayerData(player.getName());
|
||||
playerData.pendingTrapped = false;
|
||||
|
||||
//if the player moved three or more blocks from where he used /trapped, admonish him and don't save him
|
||||
if(player.getLocation().distance(this.location) > 3)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.RescueAbortedMoved);
|
||||
return;
|
||||
}
|
||||
|
||||
//otherwise find a place to teleport him
|
||||
Location destination = GriefPrevention.instance.ejectPlayer(this.player);
|
||||
|
||||
//log entry, in case admins want to investigate the "trap"
|
||||
GriefPrevention.AddLogEntry("Rescued trapped player " + player.getName() + " from " + GriefPrevention.getfriendlyLocationString(this.location) + " to " + GriefPrevention.getfriendlyLocationString(destination) + ".");
|
||||
|
||||
//timestamp this successful save so that he can't use /trapped again for a while
|
||||
playerData.lastTrappedUsage = Calendar.getInstance().getTime();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,56 +1,56 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//secures a claim after a siege looting window has closed
|
||||
class SecureClaimTask implements Runnable
|
||||
{
|
||||
private SiegeData siegeData;
|
||||
|
||||
public SecureClaimTask(SiegeData siegeData)
|
||||
{
|
||||
this.siegeData = siegeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//for each claim involved in this siege
|
||||
for(int i = 0; i < this.siegeData.claims.size(); i++)
|
||||
{
|
||||
//lock the doors
|
||||
Claim claim = this.siegeData.claims.get(i);
|
||||
claim.doorsOpen = false;
|
||||
|
||||
//eject bad guys
|
||||
Player [] onlinePlayers = GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
for(int j = 0; j < onlinePlayers.length; j++)
|
||||
{
|
||||
Player player = onlinePlayers[j];
|
||||
if(claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection);
|
||||
GriefPrevention.instance.ejectPlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//secures a claim after a siege looting window has closed
|
||||
class SecureClaimTask implements Runnable
|
||||
{
|
||||
private SiegeData siegeData;
|
||||
|
||||
public SecureClaimTask(SiegeData siegeData)
|
||||
{
|
||||
this.siegeData = siegeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//for each claim involved in this siege
|
||||
for(int i = 0; i < this.siegeData.claims.size(); i++)
|
||||
{
|
||||
//lock the doors
|
||||
Claim claim = this.siegeData.claims.get(i);
|
||||
claim.doorsOpen = false;
|
||||
|
||||
//eject bad guys
|
||||
Player [] onlinePlayers = GriefPrevention.instance.getServer().getOnlinePlayers();
|
||||
for(int j = 0; j < onlinePlayers.length; j++)
|
||||
{
|
||||
Player player = onlinePlayers[j];
|
||||
if(claim.contains(player.getLocation(), false, false) && claim.allowAccess(player) != null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeDoorsLockedEjection);
|
||||
GriefPrevention.instance.ejectPlayer(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,44 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//sends a message to a player
|
||||
//used to send delayed messages, for example help text triggered by a player's chat
|
||||
class SendPlayerMessageTask implements Runnable
|
||||
{
|
||||
private Player player;
|
||||
private ChatColor color;
|
||||
private String message;
|
||||
|
||||
public SendPlayerMessageTask(Player player, ChatColor color, String message)
|
||||
{
|
||||
this.player = player;
|
||||
this.color = color;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
GriefPrevention.sendMessage(this.player, this.color, this.message);
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//sends a message to a player
|
||||
//used to send delayed messages, for example help text triggered by a player's chat
|
||||
class SendPlayerMessageTask implements Runnable
|
||||
{
|
||||
private Player player;
|
||||
private ChatColor color;
|
||||
private String message;
|
||||
|
||||
public SendPlayerMessageTask(Player player, ChatColor color, String message)
|
||||
{
|
||||
this.player = player;
|
||||
this.color = color;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
GriefPrevention.sendMessage(this.player, this.color, this.message);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
//enumeration for golden shovel modes
|
||||
enum ShovelMode
|
||||
{
|
||||
Basic,
|
||||
Admin,
|
||||
Subdivide,
|
||||
RestoreNature,
|
||||
RestoreNatureAggressive,
|
||||
RestoreNatureFill
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
//enumeration for golden shovel modes
|
||||
enum ShovelMode
|
||||
{
|
||||
Basic,
|
||||
Admin,
|
||||
Subdivide,
|
||||
RestoreNature,
|
||||
RestoreNatureAggressive,
|
||||
RestoreNatureFill
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,110 +1,110 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//checks to see whether or not a siege should end based on the locations of the players
|
||||
//for example, defender escaped or attacker gave up and left
|
||||
class SiegeCheckupTask implements Runnable
|
||||
{
|
||||
private SiegeData siegeData;
|
||||
|
||||
public SiegeCheckupTask(SiegeData siegeData)
|
||||
{
|
||||
this.siegeData = siegeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
DataStore dataStore = GriefPrevention.instance.dataStore;
|
||||
Player defender = this.siegeData.defender;
|
||||
Player attacker = this.siegeData.attacker;
|
||||
|
||||
//where is the defender?
|
||||
Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null);
|
||||
|
||||
//if this is a new claim and he has some permission there, extend the siege to include it
|
||||
if(defenderClaim != null)
|
||||
{
|
||||
String noAccessReason = defenderClaim.allowAccess(defender);
|
||||
if(defenderClaim.canSiege(defender) && noAccessReason == null)
|
||||
{
|
||||
this.siegeData.claims.add(defenderClaim);
|
||||
defenderClaim.siegeData = this.siegeData;
|
||||
}
|
||||
}
|
||||
|
||||
//determine who's close enough to the siege area to be considered "still here"
|
||||
boolean attackerRemains = this.playerRemains(attacker);
|
||||
boolean defenderRemains = this.playerRemains(defender);
|
||||
|
||||
//if they're both here, just plan to come check again later
|
||||
if(attackerRemains && defenderRemains)
|
||||
{
|
||||
this.scheduleAnotherCheck();
|
||||
}
|
||||
|
||||
//otherwise attacker wins if the defender runs away
|
||||
else if(attackerRemains && !defenderRemains)
|
||||
{
|
||||
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(), false);
|
||||
}
|
||||
|
||||
//if they both left, but are still close together, the battle continues (check again later)
|
||||
else if(attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing
|
||||
{
|
||||
this.scheduleAnotherCheck();
|
||||
}
|
||||
|
||||
//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(), false);
|
||||
}
|
||||
}
|
||||
|
||||
//a player has to be within 25 blocks of the edge of a besieged claim to be considered still in the fight
|
||||
private boolean playerRemains(Player player)
|
||||
{
|
||||
for(int i = 0; i < this.siegeData.claims.size(); i++)
|
||||
{
|
||||
Claim claim = this.siegeData.claims.get(i);
|
||||
if(claim.isNear(player.getLocation(), 25))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//schedules another checkup later
|
||||
private void scheduleAnotherCheck()
|
||||
{
|
||||
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30);
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//checks to see whether or not a siege should end based on the locations of the players
|
||||
//for example, defender escaped or attacker gave up and left
|
||||
class SiegeCheckupTask implements Runnable
|
||||
{
|
||||
private SiegeData siegeData;
|
||||
|
||||
public SiegeCheckupTask(SiegeData siegeData)
|
||||
{
|
||||
this.siegeData = siegeData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
DataStore dataStore = GriefPrevention.instance.dataStore;
|
||||
Player defender = this.siegeData.defender;
|
||||
Player attacker = this.siegeData.attacker;
|
||||
|
||||
//where is the defender?
|
||||
Claim defenderClaim = dataStore.getClaimAt(defender.getLocation(), false, null);
|
||||
|
||||
//if this is a new claim and he has some permission there, extend the siege to include it
|
||||
if(defenderClaim != null)
|
||||
{
|
||||
String noAccessReason = defenderClaim.allowAccess(defender);
|
||||
if(defenderClaim.canSiege(defender) && noAccessReason == null)
|
||||
{
|
||||
this.siegeData.claims.add(defenderClaim);
|
||||
defenderClaim.siegeData = this.siegeData;
|
||||
}
|
||||
}
|
||||
|
||||
//determine who's close enough to the siege area to be considered "still here"
|
||||
boolean attackerRemains = this.playerRemains(attacker);
|
||||
boolean defenderRemains = this.playerRemains(defender);
|
||||
|
||||
//if they're both here, just plan to come check again later
|
||||
if(attackerRemains && defenderRemains)
|
||||
{
|
||||
this.scheduleAnotherCheck();
|
||||
}
|
||||
|
||||
//otherwise attacker wins if the defender runs away
|
||||
else if(attackerRemains && !defenderRemains)
|
||||
{
|
||||
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(), false);
|
||||
}
|
||||
|
||||
//if they both left, but are still close together, the battle continues (check again later)
|
||||
else if(attacker.getLocation().distanceSquared(defender.getLocation()) < 2500) //50-block radius for chasing
|
||||
{
|
||||
this.scheduleAnotherCheck();
|
||||
}
|
||||
|
||||
//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(), false);
|
||||
}
|
||||
}
|
||||
|
||||
//a player has to be within 25 blocks of the edge of a besieged claim to be considered still in the fight
|
||||
private boolean playerRemains(Player player)
|
||||
{
|
||||
for(int i = 0; i < this.siegeData.claims.size(); i++)
|
||||
{
|
||||
Claim claim = this.siegeData.claims.get(i);
|
||||
if(claim.isNear(player.getLocation(), 25))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//schedules another checkup later
|
||||
private void scheduleAnotherCheck()
|
||||
{
|
||||
this.siegeData.checkupTaskID = GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 20L * 30);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +1,40 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//information about an ongoing siege
|
||||
public class SiegeData
|
||||
{
|
||||
public Player defender;
|
||||
public Player attacker;
|
||||
public ArrayList<Claim> claims;
|
||||
public int checkupTaskID;
|
||||
|
||||
public SiegeData(Player attacker, Player defender, Claim claim)
|
||||
{
|
||||
this.defender = defender;
|
||||
this.attacker = attacker;
|
||||
this.claims = new ArrayList<Claim>();
|
||||
this.claims.add(claim);
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//information about an ongoing siege
|
||||
public class SiegeData
|
||||
{
|
||||
public Player defender;
|
||||
public Player attacker;
|
||||
public ArrayList<Claim> claims;
|
||||
public int checkupTaskID;
|
||||
|
||||
public SiegeData(Player attacker, Player defender, Claim claim)
|
||||
{
|
||||
this.defender = defender;
|
||||
this.attacker = attacker;
|
||||
this.claims = new ArrayList<Claim>();
|
||||
this.claims.add(claim);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
//just a few constants for chat color codes
|
||||
class TextMode
|
||||
{
|
||||
final static ChatColor Info = ChatColor.BLUE;
|
||||
final static ChatColor Instr = ChatColor.YELLOW;
|
||||
final static ChatColor Warn = ChatColor.GOLD;
|
||||
final static ChatColor Err = ChatColor.RED;
|
||||
final static ChatColor Success = ChatColor.GREEN;
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
//just a few constants for chat color codes
|
||||
class TextMode
|
||||
{
|
||||
final static ChatColor Info = ChatColor.BLUE;
|
||||
final static ChatColor Instr = ChatColor.YELLOW;
|
||||
final static ChatColor Warn = ChatColor.GOLD;
|
||||
final static ChatColor Err = ChatColor.RED;
|
||||
final static ChatColor Success = ChatColor.GREEN;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,100 +1,100 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
//FEATURE: treetops left unnaturally hanging will be automatically cleaned up
|
||||
|
||||
//this main thread task revisits the location of a partially chopped tree from several minutes ago
|
||||
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
|
||||
class TreeCleanupTask implements Runnable
|
||||
{
|
||||
private Block originalChoppedBlock; //first block chopped in the tree
|
||||
private Block originalRootBlock; //where the root of the tree used to be
|
||||
private ArrayList<Block> originalTreeBlocks; //a list of other log blocks determined to be part of this tree
|
||||
|
||||
public TreeCleanupTask(Block originalChoppedBlock, Block originalRootBlock, ArrayList<Block> originalTreeBlocks)
|
||||
{
|
||||
this.originalChoppedBlock = originalChoppedBlock;
|
||||
this.originalRootBlock = originalRootBlock;
|
||||
this.originalTreeBlocks = originalTreeBlocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//if this chunk is no longer loaded, load it and come back in a few seconds
|
||||
Chunk chunk = this.originalChoppedBlock.getWorld().getChunkAt(this.originalChoppedBlock);
|
||||
if(!chunk.isLoaded())
|
||||
{
|
||||
chunk.load();
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 100L);
|
||||
return;
|
||||
}
|
||||
|
||||
//if the block originally chopped has been replaced with anything but air, something has been built (or has grown here)
|
||||
//in that case, don't do any cleanup
|
||||
if(this.originalChoppedBlock.getWorld().getBlockAt(this.originalChoppedBlock.getLocation()).getType() != Material.AIR) return;
|
||||
|
||||
//scan the original tree block locations to see if any of them have been replaced
|
||||
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
|
||||
{
|
||||
Location location = this.originalTreeBlocks.get(i).getLocation();
|
||||
Block currentBlock = location.getBlock();
|
||||
|
||||
//if the block has been replaced, stop here, we won't do any cleanup
|
||||
if(currentBlock.getType() != Material.LOG && currentBlock.getType() != Material.AIR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//otherwise scan again, this time removing any remaining log blocks
|
||||
boolean logsRemaining = false;
|
||||
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
|
||||
{
|
||||
Location location = this.originalTreeBlocks.get(i).getLocation();
|
||||
Block currentBlock = location.getBlock();
|
||||
if(currentBlock.getType() == Material.LOG)
|
||||
{
|
||||
logsRemaining = true;
|
||||
currentBlock.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
//if any were actually removed and we're set to automatically replant griefed trees, place a sapling where the root block was previously
|
||||
if(logsRemaining && GriefPrevention.instance.config_trees_regrowGriefedTrees)
|
||||
{
|
||||
Block currentBlock = this.originalRootBlock.getLocation().getBlock();
|
||||
//make sure there's grass or dirt underneath
|
||||
if(currentBlock.getType() == Material.AIR && (currentBlock.getRelative(BlockFace.DOWN).getType() == Material.DIRT || currentBlock.getRelative(BlockFace.DOWN).getType() == Material.GRASS))
|
||||
{
|
||||
currentBlock.setType(Material.SAPLING);
|
||||
currentBlock.setData(this.originalRootBlock.getData()); //makes the sapling type match the original tree type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
|
||||
//FEATURE: treetops left unnaturally hanging will be automatically cleaned up
|
||||
|
||||
//this main thread task revisits the location of a partially chopped tree from several minutes ago
|
||||
//if any part of the tree is still there and nothing else has been built in its place, remove the remaining parts
|
||||
class TreeCleanupTask implements Runnable
|
||||
{
|
||||
private Block originalChoppedBlock; //first block chopped in the tree
|
||||
private Block originalRootBlock; //where the root of the tree used to be
|
||||
private ArrayList<Block> originalTreeBlocks; //a list of other log blocks determined to be part of this tree
|
||||
|
||||
public TreeCleanupTask(Block originalChoppedBlock, Block originalRootBlock, ArrayList<Block> originalTreeBlocks)
|
||||
{
|
||||
this.originalChoppedBlock = originalChoppedBlock;
|
||||
this.originalRootBlock = originalRootBlock;
|
||||
this.originalTreeBlocks = originalTreeBlocks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//if this chunk is no longer loaded, load it and come back in a few seconds
|
||||
Chunk chunk = this.originalChoppedBlock.getWorld().getChunkAt(this.originalChoppedBlock);
|
||||
if(!chunk.isLoaded())
|
||||
{
|
||||
chunk.load();
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, this, 100L);
|
||||
return;
|
||||
}
|
||||
|
||||
//if the block originally chopped has been replaced with anything but air, something has been built (or has grown here)
|
||||
//in that case, don't do any cleanup
|
||||
if(this.originalChoppedBlock.getWorld().getBlockAt(this.originalChoppedBlock.getLocation()).getType() != Material.AIR) return;
|
||||
|
||||
//scan the original tree block locations to see if any of them have been replaced
|
||||
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
|
||||
{
|
||||
Location location = this.originalTreeBlocks.get(i).getLocation();
|
||||
Block currentBlock = location.getBlock();
|
||||
|
||||
//if the block has been replaced, stop here, we won't do any cleanup
|
||||
if(currentBlock.getType() != Material.LOG && currentBlock.getType() != Material.AIR)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//otherwise scan again, this time removing any remaining log blocks
|
||||
boolean logsRemaining = false;
|
||||
for(int i = 0; i < this.originalTreeBlocks.size(); i++)
|
||||
{
|
||||
Location location = this.originalTreeBlocks.get(i).getLocation();
|
||||
Block currentBlock = location.getBlock();
|
||||
if(currentBlock.getType() == Material.LOG)
|
||||
{
|
||||
logsRemaining = true;
|
||||
currentBlock.setType(Material.AIR);
|
||||
}
|
||||
}
|
||||
|
||||
//if any were actually removed and we're set to automatically replant griefed trees, place a sapling where the root block was previously
|
||||
if(logsRemaining && GriefPrevention.instance.config_trees_regrowGriefedTrees)
|
||||
{
|
||||
Block currentBlock = this.originalRootBlock.getLocation().getBlock();
|
||||
//make sure there's grass or dirt underneath
|
||||
if(currentBlock.getType() == Material.AIR && (currentBlock.getRelative(BlockFace.DOWN).getType() == Material.DIRT || currentBlock.getRelative(BlockFace.DOWN).getType() == Material.GRASS))
|
||||
{
|
||||
currentBlock.setType(Material.SAPLING);
|
||||
currentBlock.setData(this.originalRootBlock.getData()); //makes the sapling type match the original tree type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
|
|
|||
|
|
@ -1,52 +1,52 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//applies a visualization for a player by sending him block change packets
|
||||
class VisualizationApplicationTask implements Runnable
|
||||
{
|
||||
private Visualization visualization;
|
||||
private Player player;
|
||||
private PlayerData playerData;
|
||||
|
||||
public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization)
|
||||
{
|
||||
this.visualization = visualization;
|
||||
this.playerData = playerData;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//for each element (=block) of the visualization
|
||||
for(int i = 0; i < visualization.elements.size(); i++)
|
||||
{
|
||||
VisualizationElement element = visualization.elements.get(i);
|
||||
|
||||
//send the player a fake block change event
|
||||
player.sendBlockChange(element.location, element.visualizedMaterial, element.visualizedData);
|
||||
}
|
||||
|
||||
//remember the visualization applied to this player for later (so it can be inexpensively reverted)
|
||||
playerData.currentVisualization = visualization;
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
//applies a visualization for a player by sending him block change packets
|
||||
class VisualizationApplicationTask implements Runnable
|
||||
{
|
||||
private Visualization visualization;
|
||||
private Player player;
|
||||
private PlayerData playerData;
|
||||
|
||||
public VisualizationApplicationTask(Player player, PlayerData playerData, Visualization visualization)
|
||||
{
|
||||
this.visualization = visualization;
|
||||
this.playerData = playerData;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
//for each element (=block) of the visualization
|
||||
for(int i = 0; i < visualization.elements.size(); i++)
|
||||
{
|
||||
VisualizationElement element = visualization.elements.get(i);
|
||||
|
||||
//send the player a fake block change event
|
||||
player.sendBlockChange(element.location, element.visualizedMaterial, element.visualizedData);
|
||||
}
|
||||
|
||||
//remember the visualization applied to this player for later (so it can be inexpensively reverted)
|
||||
playerData.currentVisualization = visualization;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +1,36 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
//represents a "fake" block sent to a player as part of a visualization
|
||||
public class VisualizationElement
|
||||
{
|
||||
public Location location;
|
||||
public Material visualizedMaterial;
|
||||
public byte visualizedData;
|
||||
|
||||
public VisualizationElement(Location location, Material visualizedMaterial, byte visualizedData)
|
||||
{
|
||||
this.location = location;
|
||||
this.visualizedMaterial= visualizedMaterial;
|
||||
this.visualizedData = visualizedData;
|
||||
}
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
|
||||
//represents a "fake" block sent to a player as part of a visualization
|
||||
public class VisualizationElement
|
||||
{
|
||||
public Location location;
|
||||
public Material visualizedMaterial;
|
||||
public byte visualizedData;
|
||||
|
||||
public VisualizationElement(Location location, Material visualizedMaterial, byte visualizedData)
|
||||
{
|
||||
this.location = location;
|
||||
this.visualizedMaterial= visualizedMaterial;
|
||||
this.visualizedData = visualizedData;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2011 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
//just an enumeration of the visualization types, which determine what materials will be for the fake blocks
|
||||
public enum VisualizationType
|
||||
{
|
||||
Claim,
|
||||
Subdivision,
|
||||
ErrorClaim,
|
||||
RestoreNature
|
||||
}
|
||||
/*
|
||||
GriefPrevention Server Plugin for Minecraft
|
||||
Copyright (C) 2012 Ryan Hamshire
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package me.ryanhamshire.GriefPrevention;
|
||||
|
||||
//just an enumeration of the visualization types, which determine what materials will be for the fake blocks
|
||||
public enum VisualizationType
|
||||
{
|
||||
Claim,
|
||||
Subdivision,
|
||||
ErrorClaim,
|
||||
RestoreNature
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user