6.3
This commit is contained in:
parent
bd215673c0
commit
008f313d09
|
|
@ -2,7 +2,7 @@ name: GriefPrevention
|
|||
main: me.ryanhamshire.GriefPrevention.GriefPrevention
|
||||
softdepend: [Vault, Multiverse-Core, My Worlds]
|
||||
dev-url: http://dev.bukkit.org/server-mods/grief-prevention
|
||||
version: 6.1
|
||||
version: 6.3
|
||||
commands:
|
||||
abandonclaim:
|
||||
description: Deletes a claim.
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ public class BlockEventHandler implements Listener
|
|||
}
|
||||
|
||||
//FEATURE: warn players when they're placing non-trash blocks outside of their claimed areas
|
||||
else if(GriefPrevention.instance.config_claims_warnOnBuildOutside && !this.trashBlocks.contains(block.getType()) && GriefPrevention.instance.claimsEnabledForWorld(block.getWorld()))
|
||||
else if(GriefPrevention.instance.config_claims_warnOnBuildOutside && !this.trashBlocks.contains(block.getType()) && GriefPrevention.instance.claimsEnabledForWorld(block.getWorld()) && playerData.claims.size() > 0)
|
||||
{
|
||||
if(--playerData.unclaimedBlockPlacementsUntilWarning <= 0)
|
||||
{
|
||||
|
|
@ -601,7 +601,8 @@ public class BlockEventHandler implements Listener
|
|||
Claim toClaim = this.dataStore.getClaimAt(toBlock.getLocation(), false, fromClaim);
|
||||
|
||||
//into wilderness is NOT OK when surface buckets are limited
|
||||
if(GriefPrevention.instance.config_blockWildernessWaterBuckets && toClaim == null)
|
||||
Material materialDispensed = dispenseEvent.getItem().getType();
|
||||
if((materialDispensed == Material.WATER_BUCKET || materialDispensed == Material.LAVA_BUCKET) && GriefPrevention.instance.config_blockWildernessWaterBuckets && toClaim == null)
|
||||
{
|
||||
dispenseEvent.setCancelled(true);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,9 @@ public class Claim
|
|||
//don't do it for very large claims
|
||||
if(this.getArea() > 10000) return;
|
||||
|
||||
//don't do it when surface fluids are allowed to be dumped
|
||||
if(!GriefPrevention.instance.config_blockWildernessWaterBuckets) return;
|
||||
|
||||
Location lesser = this.getLesserBoundaryCorner();
|
||||
Location greater = this.getGreaterBoundaryCorner();
|
||||
|
||||
|
|
@ -430,9 +433,6 @@ public class Claim
|
|||
//access permission check
|
||||
public String allowAccess(Player player)
|
||||
{
|
||||
//everyone always has access to admin claims
|
||||
if(this.isAdminClaim()) return null;
|
||||
|
||||
//following a siege where the defender lost, the claim will allow everyone access for a time
|
||||
if(this.doorsOpen) return null;
|
||||
|
||||
|
|
@ -471,9 +471,6 @@ public class Claim
|
|||
return GriefPrevention.instance.dataStore.getMessage(Messages.NoContainersSiege, siegeData.attacker.getName());
|
||||
}
|
||||
|
||||
//containers are always accessible in admin claims
|
||||
if(this.isAdminClaim()) return null;
|
||||
|
||||
//owner and administrators in ignoreclaims mode have access
|
||||
if(this.ownerName.equals(player.getName()) || GriefPrevention.instance.dataStore.getPlayerData(player.getName()).ignoreClaims) return null;
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,13 @@ public abstract class DataStore
|
|||
{
|
||||
claim.removeSurfaceFluids(null);
|
||||
this.deleteClaim(claim);
|
||||
|
||||
//if in a creative mode world, delete the claim
|
||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||
{
|
||||
GriefPrevention.instance.restoreClaim(claim, 0);
|
||||
}
|
||||
|
||||
GriefPrevention.AddLogEntry(" " + playerName + "'s new player claim expired.");
|
||||
}
|
||||
}
|
||||
|
|
@ -776,8 +783,16 @@ public abstract class DataStore
|
|||
//delete them one by one
|
||||
for(int i = 0; i < claimsToDelete.size(); i++)
|
||||
{
|
||||
claimsToDelete.get(i).removeSurfaceFluids(null);
|
||||
this.deleteClaim(claimsToDelete.get(i));
|
||||
Claim claim = claimsToDelete.get(i);
|
||||
claim.removeSurfaceFluids(null);
|
||||
|
||||
this.deleteClaim(claim);
|
||||
|
||||
//if in a creative mode world, delete the claim
|
||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||
{
|
||||
GriefPrevention.instance.restoreClaim(claim, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -996,7 +1011,8 @@ public abstract class DataStore
|
|||
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.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.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);
|
||||
|
||||
//load the config file
|
||||
FileConfiguration config = YamlConfiguration.loadConfiguration(new File(messagesFilePath));
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import org.bukkit.event.EventPriority;
|
|||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||
import org.bukkit.event.entity.EntityBreakDoorEvent;
|
||||
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
|
|
@ -75,6 +76,13 @@ class EntityEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
|
||||
//don't allow zombies to break down doors
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onZombieBreakDoor(EntityBreakDoorEvent event)
|
||||
{
|
||||
if(!GriefPrevention.instance.config_zombiesBreakDoors) event.setCancelled(true);
|
||||
}
|
||||
|
||||
//don't allow entities to trample crops
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
|
||||
public void onEntityInteract(EntityInteractEvent event)
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
public boolean config_claims_creationRequiresPermission; //whether creating claims with the shovel requires a permission
|
||||
public int config_claims_claimsExtendIntoGroundDistance; //how far below the shoveled block a new claim will reach
|
||||
public int config_claims_minSize; //minimum width and height for non-admin claims
|
||||
public boolean config_claims_allowUnclaimInCreative; //whether players may unclaim land (resize or abandon) in creative mode
|
||||
|
||||
public boolean config_claims_noBuildOutsideClaims; //whether players can build in survival worlds outside their claimed areas
|
||||
|
||||
|
|
@ -127,6 +128,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
public boolean config_endermenMoveBlocks; //whether or not endermen may move blocks around
|
||||
public boolean config_creaturesTrampleCrops; //whether or not non-player entities may trample crops
|
||||
public boolean config_zombiesBreakDoors; //whether or not hard-mode zombies may break down wooden doors
|
||||
|
||||
public List<Integer> config_mods_accessTrustIds; //list of block IDs which should require /accesstrust for player interaction
|
||||
public List<Integer> config_mods_containerTrustIds; //list of block IDs which should require /containertrust for player interaction
|
||||
|
|
@ -245,7 +247,8 @@ public class GriefPrevention extends JavaPlugin
|
|||
this.config_claims_expirationDays = config.getInt("GriefPrevention.Claims.IdleLimitDays", 0);
|
||||
this.config_claims_trappedCooldownHours = config.getInt("GriefPrevention.Claims.TrappedCommandCooldownHours", 8);
|
||||
this.config_claims_noBuildOutsideClaims = config.getBoolean("GriefPrevention.Claims.NoSurvivalBuildingOutsideClaims", false);
|
||||
this.config_claims_warnOnBuildOutside = config.getBoolean("GriefPrevention.Claims.WarnWhenBuildingOutsideClaims");
|
||||
this.config_claims_warnOnBuildOutside = config.getBoolean("GriefPrevention.Claims.WarnWhenBuildingOutsideClaims", true);
|
||||
this.config_claims_allowUnclaimInCreative = config.getBoolean("GriefPrevention.Claims.AllowUnclaimingCreativeModeLand", true);
|
||||
|
||||
this.config_spam_enabled = config.getBoolean("GriefPrevention.Spam.Enabled", true);
|
||||
this.config_spam_loginCooldownMinutes = config.getInt("GriefPrevention.Spam.LoginCooldownMinutes", 2);
|
||||
|
|
@ -283,6 +286,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
this.config_endermenMoveBlocks = config.getBoolean("GriefPrevention.EndermenMoveBlocks", false);
|
||||
this.config_creaturesTrampleCrops = config.getBoolean("GriefPrevention.CreaturesTrampleCrops", false);
|
||||
this.config_zombiesBreakDoors = config.getBoolean("GriefPrevention.HardModeZombiesBreakDoors", false);
|
||||
|
||||
this.config_mods_accessTrustIds = config.getIntegerList("GriefPrevention.Mods.BlockIdsRequiringAccessTrust");
|
||||
if(this.config_mods_accessTrustIds == null) this.config_mods_accessTrustIds = new ArrayList<Integer>();
|
||||
|
|
@ -423,6 +427,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
config.set("GriefPrevention.Claims.ModificationTool", this.config_claims_modificationTool.name());
|
||||
config.set("GriefPrevention.Claims.NoSurvivalBuildingOutsideClaims", this.config_claims_noBuildOutsideClaims);
|
||||
config.set("GriefPrevention.Claims.WarnWhenBuildingOutsideClaims", this.config_claims_warnOnBuildOutside);
|
||||
config.set("GriefPrevention.Claims.AllowUnclaimingCreativeModeLand", this.config_claims_allowUnclaimInCreative);
|
||||
|
||||
config.set("GriefPrevention.Spam.Enabled", this.config_spam_enabled);
|
||||
config.set("GriefPrevention.Spam.LoginCooldownMinutes", this.config_spam_loginCooldownMinutes);
|
||||
|
|
@ -463,6 +468,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
|
||||
config.set("GriefPrevention.EndermenMoveBlocks", this.config_endermenMoveBlocks);
|
||||
config.set("GriefPrevention.CreaturesTrampleCrops", this.config_creaturesTrampleCrops);
|
||||
config.set("GriefPrevention.HardModeZombiesBreakDoors", this.config_zombiesBreakDoors);
|
||||
|
||||
config.set("GriefPrevention.Database.URL", databaseUrl);
|
||||
config.set("GriefPrevention.Database.UserName", databaseUserName);
|
||||
|
|
@ -657,7 +663,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
{
|
||||
if(args.length != 0) return false;
|
||||
|
||||
if(creativeRulesApply(player.getLocation()))
|
||||
if(!GriefPrevention.instance.config_claims_allowUnclaimInCreative && creativeRulesApply(player.getLocation()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoCreativeUnClaim);
|
||||
return true;
|
||||
|
|
@ -1235,6 +1241,13 @@ public class GriefPrevention extends JavaPlugin
|
|||
{
|
||||
claim.removeSurfaceFluids(null);
|
||||
this.dataStore.deleteClaim(claim);
|
||||
|
||||
//if in a creative mode world, delete the claim
|
||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||
{
|
||||
GriefPrevention.instance.restoreClaim(claim, 0);
|
||||
}
|
||||
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.DeleteSuccess);
|
||||
GriefPrevention.AddLogEntry(player.getName() + " deleted " + claim.getOwnerName() + "'s claim at " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()));
|
||||
|
||||
|
|
@ -1633,7 +1646,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
}
|
||||
|
||||
//don't allow abandon of creative mode claims
|
||||
else if(this.creativeRulesApply(player.getLocation()))
|
||||
else if(!GriefPrevention.instance.config_claims_allowUnclaimInCreative && this.creativeRulesApply(player.getLocation()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoCreativeUnClaim);
|
||||
}
|
||||
|
|
@ -1658,6 +1671,14 @@ public class GriefPrevention extends JavaPlugin
|
|||
claim.removeSurfaceFluids(null);
|
||||
this.dataStore.deleteClaim(claim);
|
||||
|
||||
//if in a creative mode world, restore the claim area
|
||||
if(GriefPrevention.instance.creativeRulesApply(claim.getLesserBoundaryCorner()))
|
||||
{
|
||||
GriefPrevention.AddLogEntry(player.getName() + " abandoned a claim @ " + GriefPrevention.getfriendlyLocationString(claim.getLesserBoundaryCorner()));
|
||||
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.UnclaimCleanupWarning);
|
||||
GriefPrevention.instance.restoreClaim(claim, 20L * 60 * 2);
|
||||
}
|
||||
|
||||
//tell the player how many claim blocks he has left
|
||||
int remainingBlocks = playerData.getRemainingClaimBlocks();
|
||||
GriefPrevention.sendMessage(player, TextMode.Success, Messages.AbandonSuccess, String.valueOf(remainingBlocks));
|
||||
|
|
@ -1694,7 +1715,7 @@ public class GriefPrevention extends JavaPlugin
|
|||
else
|
||||
{
|
||||
otherPlayer = this.resolvePlayer(recipientName);
|
||||
if(otherPlayer == null && !recipientName.equals("public"))
|
||||
if(otherPlayer == null && !recipientName.equals("public") && !recipientName.equals("all"))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.PlayerNotFound);
|
||||
return;
|
||||
|
|
@ -2268,4 +2289,55 @@ public class GriefPrevention extends JavaPlugin
|
|||
return claim.allowBreak(player, location.getBlock().getType());
|
||||
}
|
||||
}
|
||||
|
||||
//restores nature in multiple chunks, as described by a claim instance
|
||||
//this restores all chunks which have ANY number of claim blocks from this claim in them
|
||||
//if the claim is still active (in the data store), then the claimed blocks will not be changed (only the area bordering the claim)
|
||||
public void restoreClaim(Claim claim, long delayInTicks)
|
||||
{
|
||||
//admin claims aren't automatically cleaned up when deleted or abandoned
|
||||
if(claim.isAdminClaim()) return;
|
||||
|
||||
//it's too expensive to do this for huge claims
|
||||
if(claim.getArea() > 10000) return;
|
||||
|
||||
Chunk lesserChunk = claim.getLesserBoundaryCorner().getChunk();
|
||||
Chunk greaterChunk = claim.getGreaterBoundaryCorner().getChunk();
|
||||
|
||||
for(int x = lesserChunk.getX(); x <= greaterChunk.getX(); x++)
|
||||
for(int z = lesserChunk.getZ(); z <= greaterChunk.getZ(); z++)
|
||||
{
|
||||
Chunk chunk = lesserChunk.getWorld().getChunkAt(x, z);
|
||||
this.restoreChunk(chunk, chunk.getWorld().getSeaLevel() - 15, false, delayInTicks, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void restoreChunk(Chunk chunk, int miny, boolean aggressiveMode, long delayInTicks, Player playerReceivingVisualization)
|
||||
{
|
||||
//build a snapshot of this chunk, including 1 block boundary outside of the chunk all the way around
|
||||
int maxHeight = chunk.getWorld().getMaxHeight();
|
||||
BlockSnapshot[][][] snapshots = new BlockSnapshot[18][maxHeight][18];
|
||||
Block startBlock = chunk.getBlock(0, 0, 0);
|
||||
Location startLocation = new Location(chunk.getWorld(), startBlock.getX() - 1, 0, startBlock.getZ() - 1);
|
||||
for(int x = 0; x < snapshots.length; x++)
|
||||
{
|
||||
for(int z = 0; z < snapshots[0][0].length; z++)
|
||||
{
|
||||
for(int y = 0; y < snapshots[0].length; y++)
|
||||
{
|
||||
Block block = chunk.getWorld().getBlockAt(startLocation.getBlockX() + x, startLocation.getBlockY() + y, startLocation.getBlockZ() + z);
|
||||
snapshots[x][y][z] = new BlockSnapshot(block.getLocation(), block.getTypeId(), block.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create task to process those data in another thread
|
||||
Location lesserBoundaryCorner = chunk.getBlock(0, 0, 0).getLocation();
|
||||
Location greaterBoundaryCorner = chunk.getBlock(15, 0, 15).getLocation();
|
||||
|
||||
//create task
|
||||
//when done processing, this task will create a main thread task to actually update the world with processing results
|
||||
RestoreNatureProcessingTask task = new RestoreNatureProcessingTask(snapshots, miny, chunk.getWorld().getEnvironment(), chunk.getWorld().getBiome(lesserBoundaryCorner.getBlockX(), lesserBoundaryCorner.getBlockZ()), lesserBoundaryCorner, greaterBoundaryCorner, chunk.getWorld().getSeaLevel() + 1, aggressiveMode, GriefPrevention.instance.creativeRulesApply(lesserBoundaryCorner), playerReceivingVisualization);
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleAsyncDelayedTask(GriefPrevention.instance, task, delayInTicks);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,5 +2,5 @@ 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
|
||||
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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -807,10 +807,11 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//if the bucket is being used in a claim, allow for dumping lava closer to other players
|
||||
Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, null);
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
Claim claim = this.dataStore.getClaimAt(block.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
minLavaDistance = 3;
|
||||
minLavaDistance = 3;
|
||||
}
|
||||
|
||||
//otherwise no wilderness dumping (unless underground) in worlds where claims are enabled
|
||||
|
|
@ -900,6 +901,25 @@ class PlayerEventHandler implements Listener
|
|||
|
||||
Material clickedBlockType = clickedBlock.getType();
|
||||
|
||||
//apply rules for putting out fires (requires build permission)
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
if(event.getClickedBlock() != null && event.getClickedBlock().getRelative(event.getBlockFace()).getType() == Material.FIRE)
|
||||
{
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
playerData.lastClaim = claim;
|
||||
|
||||
String noBuildReason = claim.allowBuild(player);
|
||||
if(noBuildReason != null)
|
||||
{
|
||||
event.setCancelled(true);
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, noBuildReason);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//apply rules for containers and crafting blocks
|
||||
if( GriefPrevention.instance.config_claims_preventTheft && (
|
||||
event.getAction() == Action.RIGHT_CLICK_BLOCK && (
|
||||
|
|
@ -913,7 +933,6 @@ class PlayerEventHandler implements Listener
|
|||
GriefPrevention.instance.config_mods_containerTrustIds.contains(clickedBlock.getTypeId()))))
|
||||
{
|
||||
//block container use while under siege, so players can't hide items from attackers
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
if(playerData.siegeData != null)
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.SiegeNoContainers);
|
||||
|
|
@ -930,9 +949,11 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//otherwise check permissions for the claim the player is in
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, null);
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
playerData.lastClaim = claim;
|
||||
|
||||
String noContainersReason = claim.allowContainers(player);
|
||||
if(noContainersReason != null)
|
||||
{
|
||||
|
|
@ -956,9 +977,11 @@ class PlayerEventHandler implements Listener
|
|||
(GriefPrevention.instance.config_claims_lockTrapDoors && clickedBlockType == Material.TRAP_DOOR) ||
|
||||
(GriefPrevention.instance.config_claims_lockFenceGates && clickedBlockType == Material.FENCE_GATE))
|
||||
{
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, null);
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
playerData.lastClaim = claim;
|
||||
|
||||
String noAccessReason = claim.allowAccess(player);
|
||||
if(noAccessReason != null)
|
||||
{
|
||||
|
|
@ -972,9 +995,11 @@ class PlayerEventHandler implements Listener
|
|||
//otherwise apply rules for buttons and switches
|
||||
else if(GriefPrevention.instance.config_claims_preventButtonsSwitches && (clickedBlockType == null || clickedBlockType == Material.STONE_BUTTON || clickedBlockType == Material.LEVER || GriefPrevention.instance.config_mods_accessTrustIds.contains(clickedBlock.getTypeId())))
|
||||
{
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, null);
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
playerData.lastClaim = claim;
|
||||
|
||||
String noAccessReason = claim.allowAccess(player);
|
||||
if(noAccessReason != null)
|
||||
{
|
||||
|
|
@ -996,7 +1021,7 @@ class PlayerEventHandler implements Listener
|
|||
//apply rule for note blocks and repeaters
|
||||
else if(clickedBlockType == Material.NOTE_BLOCK || clickedBlockType == Material.DIODE_BLOCK_ON || clickedBlockType == Material.DIODE_BLOCK_OFF)
|
||||
{
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, null);
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||
if(claim != null)
|
||||
{
|
||||
String noBuildReason = claim.allowBuild(player);
|
||||
|
|
@ -1045,7 +1070,6 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
|
||||
//enforce limit on total number of entities in this claim
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false, playerData.lastClaim);
|
||||
if(claim == null) return;
|
||||
|
||||
|
|
@ -1070,7 +1094,7 @@ class PlayerEventHandler implements Listener
|
|||
return;
|
||||
}
|
||||
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false /*ignore height*/, null);
|
||||
Claim claim = this.dataStore.getClaimAt(clickedBlock.getLocation(), false /*ignore height*/, playerData.lastClaim);
|
||||
|
||||
//no claim case
|
||||
if(claim == null)
|
||||
|
|
@ -1082,6 +1106,7 @@ class PlayerEventHandler implements Listener
|
|||
//claim case
|
||||
else
|
||||
{
|
||||
playerData.lastClaim = claim;
|
||||
GriefPrevention.sendMessage(player, TextMode.Info, Messages.BlockClaimed, claim.getOwnerName());
|
||||
|
||||
//visualize boundary
|
||||
|
|
@ -1116,8 +1141,6 @@ class PlayerEventHandler implements Listener
|
|||
//if it's a golden shovel
|
||||
else if(materialInHand != GriefPrevention.instance.config_claims_modificationTool) return;
|
||||
|
||||
PlayerData playerData = this.dataStore.getPlayerData(player.getName());
|
||||
|
||||
//disable golden shovel while under siege
|
||||
if(playerData.siegeData != null)
|
||||
{
|
||||
|
|
@ -1152,24 +1175,7 @@ class PlayerEventHandler implements Listener
|
|||
//figure out which chunk to repair
|
||||
Chunk chunk = player.getWorld().getChunkAt(clickedBlock.getLocation());
|
||||
|
||||
//build a snapshot of this chunk, including 1 block boundary outside of the chunk all the way around
|
||||
int maxHeight = chunk.getWorld().getMaxHeight();
|
||||
BlockSnapshot[][][] snapshots = new BlockSnapshot[18][maxHeight][18];
|
||||
Block startBlock = chunk.getBlock(0, 0, 0);
|
||||
Location startLocation = new Location(chunk.getWorld(), startBlock.getX() - 1, 0, startBlock.getZ() - 1);
|
||||
for(int x = 0; x < snapshots.length; x++)
|
||||
{
|
||||
for(int z = 0; z < snapshots[0][0].length; z++)
|
||||
{
|
||||
for(int y = 0; y < snapshots[0].length; y++)
|
||||
{
|
||||
Block block = chunk.getWorld().getBlockAt(startLocation.getBlockX() + x, startLocation.getBlockY() + y, startLocation.getBlockZ() + z);
|
||||
snapshots[x][y][z] = new BlockSnapshot(block.getLocation(), block.getTypeId(), block.getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//create task to process those data in another thread
|
||||
//start the repair process
|
||||
|
||||
//set boundaries for processing
|
||||
int miny = clickedBlock.getY();
|
||||
|
|
@ -1183,13 +1189,7 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
}
|
||||
|
||||
Location lesserBoundaryCorner = chunk.getBlock(0, 0, 0).getLocation();
|
||||
Location greaterBoundaryCorner = chunk.getBlock(15, 0, 15).getLocation();
|
||||
|
||||
//create task
|
||||
//when done processing, this task will create a main thread task to actually update the world with processing results
|
||||
RestoreNatureProcessingTask task = new RestoreNatureProcessingTask(snapshots, miny, chunk.getWorld().getEnvironment(), chunk.getWorld().getBiome(lesserBoundaryCorner.getBlockX(), lesserBoundaryCorner.getBlockZ()), lesserBoundaryCorner, greaterBoundaryCorner, chunk.getWorld().getSeaLevel(), playerData.shovelMode == ShovelMode.RestoreNatureAggressive, player);
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleAsyncDelayedTask(GriefPrevention.instance, task);
|
||||
GriefPrevention.instance.restoreChunk(chunk, miny, playerData.shovelMode == ShovelMode.RestoreNatureAggressive, 0, player);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -1209,11 +1209,11 @@ class PlayerEventHandler implements Listener
|
|||
}
|
||||
else
|
||||
{
|
||||
allowedFillBlocks.add(Material.GRASS);
|
||||
allowedFillBlocks.add(Material.DIRT);
|
||||
allowedFillBlocks.add(Material.STONE);
|
||||
allowedFillBlocks.add(Material.SAND);
|
||||
allowedFillBlocks.add(Material.SANDSTONE);
|
||||
allowedFillBlocks.add(Material.DIRT);
|
||||
allowedFillBlocks.add(Material.GRASS);
|
||||
allowedFillBlocks.add(Material.ICE);
|
||||
}
|
||||
|
||||
|
|
@ -1236,6 +1236,29 @@ class PlayerEventHandler implements Listener
|
|||
Location location = new Location(centerBlock.getWorld(), x, centerBlock.getY(), z);
|
||||
if(location.distance(centerBlock.getLocation()) > playerData.fillRadius) continue;
|
||||
|
||||
//default fill block is initially the first from the allowed fill blocks list above
|
||||
Material defaultFiller = allowedFillBlocks.get(0);
|
||||
|
||||
//prefer to use the block the player clicked on, if it's an acceptable fill block
|
||||
if(allowedFillBlocks.contains(centerBlock.getType()))
|
||||
{
|
||||
defaultFiller = centerBlock.getType();
|
||||
}
|
||||
|
||||
//if the player clicks on water, try to sink through the water to find something underneath that's useful for a filler
|
||||
else if(centerBlock.getType() == Material.WATER || centerBlock.getType() == Material.STATIONARY_WATER)
|
||||
{
|
||||
Block block = centerBlock.getWorld().getBlockAt(centerBlock.getLocation());
|
||||
while(!allowedFillBlocks.contains(block.getType()) && block.getY() > centerBlock.getY() - 10)
|
||||
{
|
||||
block = block.getRelative(BlockFace.DOWN);
|
||||
}
|
||||
if(allowedFillBlocks.contains(block.getType()))
|
||||
{
|
||||
defaultFiller = block.getType();
|
||||
}
|
||||
}
|
||||
|
||||
//fill bottom to top
|
||||
for(int y = minHeight; y <= maxHeight; y++)
|
||||
{
|
||||
|
|
@ -1252,41 +1275,43 @@ class PlayerEventHandler implements Listener
|
|||
//only replace air, spilling water, snow, long grass
|
||||
if(block.getType() == Material.AIR || block.getType() == Material.SNOW || (block.getType() == Material.STATIONARY_WATER && block.getData() != 0) || block.getType() == Material.LONG_GRASS)
|
||||
{
|
||||
//look to neighbors for an appropriate fill block
|
||||
Block eastBlock = block.getRelative(BlockFace.EAST);
|
||||
Block westBlock = block.getRelative(BlockFace.WEST);
|
||||
Block northBlock = block.getRelative(BlockFace.NORTH);
|
||||
Block southBlock = block.getRelative(BlockFace.SOUTH);
|
||||
Block underBlock = block.getRelative(BlockFace.DOWN);
|
||||
|
||||
//first, check lateral neighbors (ideally, want to keep natural layers)
|
||||
if(allowedFillBlocks.contains(eastBlock.getType()))
|
||||
//if the top level, always use the default filler picked above
|
||||
if(y == maxHeight)
|
||||
{
|
||||
block.setType(eastBlock.getType());
|
||||
}
|
||||
else if(allowedFillBlocks.contains(westBlock.getType()))
|
||||
{
|
||||
block.setType(westBlock.getType());
|
||||
}
|
||||
else if(allowedFillBlocks.contains(northBlock.getType()))
|
||||
{
|
||||
block.setType(northBlock.getType());
|
||||
}
|
||||
else if(allowedFillBlocks.contains(southBlock.getType()))
|
||||
{
|
||||
block.setType(southBlock.getType());
|
||||
block.setType(defaultFiller);
|
||||
}
|
||||
|
||||
//then check underneath
|
||||
else if(allowedFillBlocks.contains(underBlock.getType()))
|
||||
{
|
||||
block.setType(underBlock.getType());
|
||||
}
|
||||
|
||||
//if all else fails, use the first material listed in the acceptable fill blocks above
|
||||
//otherwise look to neighbors for an appropriate fill block
|
||||
else
|
||||
{
|
||||
block.setType(allowedFillBlocks.get(0));
|
||||
Block eastBlock = block.getRelative(BlockFace.EAST);
|
||||
Block westBlock = block.getRelative(BlockFace.WEST);
|
||||
Block northBlock = block.getRelative(BlockFace.NORTH);
|
||||
Block southBlock = block.getRelative(BlockFace.SOUTH);
|
||||
|
||||
//first, check lateral neighbors (ideally, want to keep natural layers)
|
||||
if(allowedFillBlocks.contains(eastBlock.getType()))
|
||||
{
|
||||
block.setType(eastBlock.getType());
|
||||
}
|
||||
else if(allowedFillBlocks.contains(westBlock.getType()))
|
||||
{
|
||||
block.setType(westBlock.getType());
|
||||
}
|
||||
else if(allowedFillBlocks.contains(northBlock.getType()))
|
||||
{
|
||||
block.setType(northBlock.getType());
|
||||
}
|
||||
else if(allowedFillBlocks.contains(southBlock.getType()))
|
||||
{
|
||||
block.setType(southBlock.getType());
|
||||
}
|
||||
|
||||
//if all else fails, use the default filler selected above
|
||||
else
|
||||
{
|
||||
block.setType(defaultFiller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1380,6 +1405,7 @@ class PlayerEventHandler implements Listener
|
|||
//rule1: in creative mode, top-level claims can't be moved or resized smaller.
|
||||
//rule2: in any mode, shrinking a claim removes any surface fluids
|
||||
Claim oldClaim = playerData.claimResizing;
|
||||
boolean smaller = false;
|
||||
if(oldClaim.parent == null)
|
||||
{
|
||||
//temporary claim instance, just for checking contains()
|
||||
|
|
@ -1391,8 +1417,10 @@ class PlayerEventHandler implements Listener
|
|||
//if the new claim is smaller
|
||||
if(!newClaim.contains(oldClaim.getLesserBoundaryCorner(), true, false) || !newClaim.contains(oldClaim.getGreaterBoundaryCorner(), true, false))
|
||||
{
|
||||
smaller = true;
|
||||
|
||||
//enforce creative mode rule
|
||||
if(!player.hasPermission("griefprevention.deleteclaims") && GriefPrevention.instance.creativeRulesApply(player.getLocation()))
|
||||
if(!GriefPrevention.instance.config_claims_allowUnclaimInCreative && !player.hasPermission("griefprevention.deleteclaims") && GriefPrevention.instance.creativeRulesApply(player.getLocation()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Err, Messages.NoCreativeUnClaim);
|
||||
return;
|
||||
|
|
@ -1419,6 +1447,14 @@ class PlayerEventHandler implements Listener
|
|||
GriefPrevention.AddLogEntry(playerName + " resized " + playerData.claimResizing.getOwnerName() + "'s claim at " + GriefPrevention.getfriendlyLocationString(playerData.claimResizing.lesserBoundaryCorner) + ".");
|
||||
}
|
||||
|
||||
//if in a creative mode world and shrinking an existing claim, restore any unclaimed area
|
||||
if(smaller && GriefPrevention.instance.creativeRulesApply(oldClaim.getLesserBoundaryCorner()))
|
||||
{
|
||||
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.UnclaimCleanupWarning);
|
||||
GriefPrevention.instance.restoreClaim(oldClaim, 20L * 60 * 2); //2 minutes
|
||||
GriefPrevention.AddLogEntry(player.getName() + " shrank a claim @ " + GriefPrevention.getfriendlyLocationString(playerData.claimResizing.getLesserBoundaryCorner()));
|
||||
}
|
||||
|
||||
//clean up
|
||||
playerData.claimResizing = null;
|
||||
playerData.lastShovelLocation = null;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.bukkit.Location;
|
|||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.Animals;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
|
|
@ -88,7 +89,7 @@ class RestoreNatureExecutionTask implements Runnable
|
|||
for(int i = 0; i < entities.length; i++)
|
||||
{
|
||||
Entity entity = entities[i];
|
||||
if(!(entity instanceof Player))
|
||||
if(!(entity instanceof Player || entity instanceof Animals))
|
||||
{
|
||||
entity.remove();
|
||||
}
|
||||
|
|
@ -101,8 +102,11 @@ class RestoreNatureExecutionTask implements Runnable
|
|||
}
|
||||
|
||||
//show visualization to player
|
||||
Claim claim = new Claim(lesserCorner, greaterCorner, "", new String[] {}, new String[] {}, new String[] {}, new String[] {}, null);
|
||||
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation());
|
||||
Visualization.Apply(player, visualization);
|
||||
if(player != null)
|
||||
{
|
||||
Claim claim = new Claim(lesserCorner, greaterCorner, "", new String[] {}, new String[] {}, new String[] {}, new String[] {}, null);
|
||||
Visualization visualization = Visualization.FromClaim(claim, player.getLocation().getBlockY(), VisualizationType.RestoreNature, player.getLocation());
|
||||
Visualization.Apply(player, visualization);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
private Location greaterBoundaryCorner;
|
||||
private Player player; //absolutely must not be accessed. not thread safe.
|
||||
private Biome biome;
|
||||
private boolean creativeMode;
|
||||
private int seaLevel;
|
||||
private boolean aggressiveMode;
|
||||
|
||||
|
|
@ -49,7 +50,7 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
private ArrayList<Integer> notAllowedToHang; //natural blocks which don't naturally hang in their air
|
||||
private ArrayList<Integer> playerBlocks; //a "complete" list of player-placed blocks. MUST BE MAINTAINED as patches introduce more
|
||||
|
||||
public RestoreNatureProcessingTask(BlockSnapshot[][][] snapshots, int miny, Environment environment, Biome biome, Location lesserBoundaryCorner, Location greaterBoundaryCorner, int seaLevel, boolean aggressiveMode, Player player)
|
||||
public RestoreNatureProcessingTask(BlockSnapshot[][][] snapshots, int miny, Environment environment, Biome biome, Location lesserBoundaryCorner, Location greaterBoundaryCorner, int seaLevel, boolean aggressiveMode, boolean creativeMode, Player player)
|
||||
{
|
||||
this.snapshots = snapshots;
|
||||
this.miny = miny;
|
||||
|
|
@ -60,6 +61,7 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
this.seaLevel = seaLevel;
|
||||
this.aggressiveMode = aggressiveMode;
|
||||
this.player = player;
|
||||
this.creativeMode = creativeMode;
|
||||
|
||||
this.notAllowedToHang = new ArrayList<Integer>();
|
||||
this.notAllowedToHang.add(Material.DIRT.getId());
|
||||
|
|
@ -150,6 +152,9 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
this.playerBlocks.add(Material.DIODE_BLOCK_ON.getId());
|
||||
this.playerBlocks.add(Material.WEB.getId());
|
||||
this.playerBlocks.add(Material.SPONGE.getId());
|
||||
this.playerBlocks.add(Material.GRAVEL.getId());
|
||||
this.playerBlocks.add(Material.EMERALD_BLOCK.getId());
|
||||
this.playerBlocks.add(Material.SANDSTONE.getId());
|
||||
|
||||
//these are unnatural in the standard world, but not in the nether
|
||||
if(this.environment != Environment.NETHER)
|
||||
|
|
@ -169,25 +174,33 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
}
|
||||
|
||||
//these are unnatural in sandy biomes, but not elsewhere
|
||||
if(this.biome == Biome.DESERT || this.biome == Biome.DESERT_HILLS || this.biome == Biome.BEACH || this.aggressiveMode)
|
||||
if(this.biome == Biome.DESERT || this.biome == Biome.DESERT_HILLS || this.biome == Biome.BEACH || this.environment != Environment.NORMAL || this.aggressiveMode)
|
||||
{
|
||||
this.playerBlocks.add(Material.LEAVES.getId());
|
||||
this.playerBlocks.add(Material.LOG.getId());
|
||||
}
|
||||
|
||||
//in aggressive mode, also treat these blocks as user placed, to be removed
|
||||
//in aggressive or creative world mode, also treat these blocks as user placed, to be removed
|
||||
//this is helpful in the few cases where griefers intentionally use natural blocks to grief,
|
||||
//like a single-block tower of iron ore or a giant penis constructed with logs
|
||||
if(this.aggressiveMode)
|
||||
//like a single-block tower of iron ore or a giant penis constructed with melons
|
||||
if(this.aggressiveMode || this.creativeMode)
|
||||
{
|
||||
this.playerBlocks.add(Material.IRON_ORE.getId());
|
||||
this.playerBlocks.add(Material.PUMPKIN.getId());
|
||||
this.playerBlocks.add(Material.PUMPKIN_STEM.getId());
|
||||
this.playerBlocks.add(Material.IRON_ORE.getId());
|
||||
this.playerBlocks.add(Material.GOLD_ORE.getId());
|
||||
this.playerBlocks.add(Material.DIAMOND_ORE.getId());
|
||||
this.playerBlocks.add(Material.MELON_BLOCK.getId());
|
||||
this.playerBlocks.add(Material.MELON_STEM.getId());
|
||||
this.playerBlocks.add(Material.BEDROCK.getId());
|
||||
this.playerBlocks.add(Material.GRAVEL.getId());
|
||||
this.playerBlocks.add(Material.SANDSTONE.getId());
|
||||
this.playerBlocks.add(Material.COAL_ORE.getId());
|
||||
this.playerBlocks.add(Material.PUMPKIN.getId());
|
||||
this.playerBlocks.add(Material.PUMPKIN_STEM.getId());
|
||||
this.playerBlocks.add(Material.MELON.getId());
|
||||
}
|
||||
|
||||
if(this.aggressiveMode)
|
||||
{
|
||||
this.playerBlocks.add(Material.LEAVES.getId());
|
||||
this.playerBlocks.add(Material.VINE.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -196,18 +209,24 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
{
|
||||
//order is important!
|
||||
|
||||
//remove sandstone which appears to be unnatural
|
||||
this.removeSandstone();
|
||||
|
||||
//remove any blocks which are definitely player placed
|
||||
this.removePlayerBlocks();
|
||||
|
||||
//remove natural blocks which are unnaturally hanging in the air
|
||||
this.removeHanging();
|
||||
|
||||
//reduce large outcroppings of stone, sandstone
|
||||
this.reduceStone();
|
||||
|
||||
//reduce logs, except in jungle biomes
|
||||
this.reduceLogs();
|
||||
|
||||
//remove natural blocks which are unnaturally stacked high
|
||||
this.removeWallsAndTowers();
|
||||
|
||||
//cover surface stone and gravel with sand or grass, as the biome requires
|
||||
this.coverSurfaceStone();
|
||||
|
||||
//fill unnatural thin trenches and single-block potholes
|
||||
this.fillHolesAndTrenches();
|
||||
|
||||
|
|
@ -217,11 +236,161 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
//remove water/lava above sea level
|
||||
this.removeDumpedFluids();
|
||||
|
||||
//cover over any gaping holes in creative mode worlds
|
||||
if(this.creativeMode && this.environment == Environment.NORMAL)
|
||||
{
|
||||
this.fillBigHoles();
|
||||
}
|
||||
|
||||
//cover surface stone and gravel with sand or grass, as the biome requires
|
||||
this.coverSurfaceStone();
|
||||
|
||||
//schedule main thread task to apply the result to the world
|
||||
RestoreNatureExecutionTask task = new RestoreNatureExecutionTask(this.snapshots, this.miny, this.lesserBoundaryCorner, this.greaterBoundaryCorner, this.player);
|
||||
GriefPrevention.instance.getServer().getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, task);
|
||||
}
|
||||
|
||||
private void fillBigHoles()
|
||||
{
|
||||
for(int x = 1; x < snapshots.length - 1; x++)
|
||||
{
|
||||
for(int z = 1; z < snapshots[0][0].length - 1; z++)
|
||||
{
|
||||
//replace air, lava, or running water at sea level with stone
|
||||
if(this.snapshots[x][this.seaLevel - 3][z].typeId == Material.AIR.getId() || this.snapshots[x][this.seaLevel][z].typeId == Material.LAVA.getId() || (this.snapshots[x][this.seaLevel][z].typeId == Material.WATER.getId() || this.snapshots[x][this.seaLevel][z].data != 0))
|
||||
{
|
||||
this.snapshots[x][this.seaLevel - 3][z].typeId = Material.STONE.getId();
|
||||
}
|
||||
|
||||
//do the same for one layer beneath that (because a future restoration step may convert surface stone to sand, which falls down)
|
||||
if(this.snapshots[x][this.seaLevel - 4][z].typeId == Material.AIR.getId() || this.snapshots[x][this.seaLevel][z].typeId == Material.LAVA.getId() || (this.snapshots[x][this.seaLevel][z].typeId == Material.WATER.getId() || this.snapshots[x][this.seaLevel][z].data != 0))
|
||||
{
|
||||
this.snapshots[x][this.seaLevel - 4][z].typeId = Material.STONE.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//converts sandstone adjacent to sand to sand, and any other sandstone to air
|
||||
private void removeSandstone()
|
||||
{
|
||||
for(int x = 1; x < snapshots.length - 1; x++)
|
||||
{
|
||||
for(int z = 1; z < snapshots[0][0].length - 1; z++)
|
||||
{
|
||||
for(int y = snapshots[0].length - 2; y > miny; y--)
|
||||
{
|
||||
if(snapshots[x][y][z].typeId != Material.SANDSTONE.getId()) continue;
|
||||
|
||||
BlockSnapshot leftBlock = this.snapshots[x + 1][y][z];
|
||||
BlockSnapshot rightBlock = this.snapshots[x - 1][y][z];
|
||||
BlockSnapshot upBlock = this.snapshots[x][y][z + 1];
|
||||
BlockSnapshot downBlock = this.snapshots[x][y][z - 1];
|
||||
BlockSnapshot underBlock = this.snapshots[x][y - 1][z];
|
||||
BlockSnapshot aboveBlock = this.snapshots[x][y + 1][z];
|
||||
|
||||
//skip blocks which may cause a cave-in
|
||||
if(aboveBlock.typeId == Material.SAND.getId() && underBlock.typeId == Material.AIR.getId()) continue;
|
||||
|
||||
//count adjacent non-air/non-leaf blocks
|
||||
if( leftBlock.typeId == Material.SAND.getId() ||
|
||||
rightBlock.typeId == Material.SAND.getId() ||
|
||||
upBlock.typeId == Material.SAND.getId() ||
|
||||
downBlock.typeId == Material.SAND.getId() ||
|
||||
aboveBlock.typeId == Material.SAND.getId() ||
|
||||
underBlock.typeId == Material.SAND.getId())
|
||||
{
|
||||
snapshots[x][y][z].typeId = Material.SAND.getId();
|
||||
}
|
||||
else
|
||||
{
|
||||
snapshots[x][y][z].typeId = Material.AIR.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reduceStone()
|
||||
{
|
||||
for(int x = 1; x < snapshots.length - 1; x++)
|
||||
{
|
||||
for(int z = 1; z < snapshots[0][0].length - 1; z++)
|
||||
{
|
||||
int thisy = this.highestY(x, z, true);
|
||||
|
||||
while(thisy > this.seaLevel - 2 && (this.snapshots[x][thisy][z].typeId == Material.STONE.getId() || this.snapshots[x][thisy][z].typeId == Material.SANDSTONE.getId()))
|
||||
{
|
||||
BlockSnapshot leftBlock = this.snapshots[x + 1][thisy][z];
|
||||
BlockSnapshot rightBlock = this.snapshots[x - 1][thisy][z];
|
||||
BlockSnapshot upBlock = this.snapshots[x][thisy][z + 1];
|
||||
BlockSnapshot downBlock = this.snapshots[x][thisy][z - 1];
|
||||
|
||||
//count adjacent non-air/non-leaf blocks
|
||||
byte adjacentBlockCount = 0;
|
||||
if(leftBlock.typeId != Material.AIR.getId() && leftBlock.typeId != Material.LEAVES.getId() && leftBlock.typeId != Material.VINE.getId())
|
||||
{
|
||||
adjacentBlockCount++;
|
||||
}
|
||||
if(rightBlock.typeId != Material.AIR.getId() && rightBlock.typeId != Material.LEAVES.getId() && rightBlock.typeId != Material.VINE.getId())
|
||||
{
|
||||
adjacentBlockCount++;
|
||||
}
|
||||
if(downBlock.typeId != Material.AIR.getId() && downBlock.typeId != Material.LEAVES.getId() && downBlock.typeId != Material.VINE.getId())
|
||||
{
|
||||
adjacentBlockCount++;
|
||||
}
|
||||
if(upBlock.typeId != Material.AIR.getId() && upBlock.typeId != Material.LEAVES.getId() && upBlock.typeId != Material.VINE.getId())
|
||||
{
|
||||
adjacentBlockCount++;
|
||||
}
|
||||
|
||||
if(adjacentBlockCount < 3)
|
||||
{
|
||||
this.snapshots[x][thisy][z].typeId = Material.AIR.getId();
|
||||
}
|
||||
|
||||
thisy--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void reduceLogs()
|
||||
{
|
||||
boolean jungleBiome = this.biome == Biome.JUNGLE || this.biome == Biome.JUNGLE_HILLS;
|
||||
|
||||
//scan all blocks above sea level
|
||||
for(int x = 1; x < snapshots.length - 1; x++)
|
||||
{
|
||||
for(int z = 1; z < snapshots[0][0].length - 1; z++)
|
||||
{
|
||||
for(int y = this.seaLevel - 2; y < snapshots[0].length; y++)
|
||||
{
|
||||
BlockSnapshot block = snapshots[x][y][z];
|
||||
|
||||
//skip non-logs
|
||||
if(block.typeId != Material.LOG.getId()) continue;
|
||||
|
||||
//if in jungle biome, skip jungle logs
|
||||
if(jungleBiome && block.data == 3) continue;
|
||||
|
||||
//examine adjacent blocks for logs
|
||||
BlockSnapshot leftBlock = this.snapshots[x + 1][y][z];
|
||||
BlockSnapshot rightBlock = this.snapshots[x - 1][y][z];
|
||||
BlockSnapshot upBlock = this.snapshots[x][y][z + 1];
|
||||
BlockSnapshot downBlock = this.snapshots[x][y][z - 1];
|
||||
|
||||
//if any, remove the log
|
||||
if(leftBlock.typeId == Material.LOG.getId() || rightBlock.typeId == Material.LOG.getId() || upBlock.typeId == Material.LOG.getId() || downBlock.typeId == Material.LOG.getId())
|
||||
{
|
||||
this.snapshots[x][y][z].typeId = Material.AIR.getId();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removePlayerBlocks()
|
||||
{
|
||||
int miny = this.miny;
|
||||
|
|
@ -332,7 +501,7 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
int y = this.highestY(x, z, true);
|
||||
BlockSnapshot block = snapshots[x][y][z];
|
||||
|
||||
if(block.typeId == Material.STONE.getId() || block.typeId == Material.GRAVEL.getId() || block.typeId == Material.DIRT.getId())
|
||||
if(block.typeId == Material.STONE.getId() || block.typeId == Material.GRAVEL.getId() || block.typeId == Material.DIRT.getId() || block.typeId == Material.SANDSTONE.getId())
|
||||
{
|
||||
if(this.biome == Biome.DESERT || this.biome == Biome.DESERT_HILLS || this.biome == Biome.BEACH)
|
||||
{
|
||||
|
|
@ -516,6 +685,7 @@ class RestoreNatureProcessingTask implements Runnable
|
|||
{
|
||||
BlockSnapshot block = this.snapshots[x][y][z];
|
||||
if(block.typeId != Material.AIR.getId() &&
|
||||
!(ignoreLeaves && block.typeId == Material.SNOW.getId()) &&
|
||||
!(ignoreLeaves && block.typeId == Material.LEAVES.getId()) &&
|
||||
!(block.typeId == Material.STATIONARY_WATER.getId() && block.data != 0) &&
|
||||
!(block.typeId == Material.STATIONARY_LAVA.getId() && block.data != 0))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user