// when a painting is placed... @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onPaintingPlace(PaintingPlaceEvent event) { // FEATURE: similar to above, placing a painting requires build permission in the claim // if the player doesn't have permission, don't allow the placement String noBuildReason = GriefPrevention.instance.allowBuild(event.getPlayer(), event.getPainting().getLocation()); if (noBuildReason != null) { event.setCancelled(true); GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, noBuildReason); return; } // otherwise, apply entity-count limitations for creative worlds else if (GriefPrevention.instance.creativeRulesApply(event.getPainting().getLocation())) { PlayerData playerData = this.dataStore.getPlayerData(event.getPlayer().getName()); Claim claim = this.dataStore.getClaimAt(event.getBlock().getLocation(), false, playerData.lastClaim); if (claim == null) return; String noEntitiesReason = claim.allowMoreEntities(); if (noEntitiesReason != null) { GriefPrevention.sendMessage(event.getPlayer(), TextMode.Err, noEntitiesReason); event.setCancelled(true); return; } } }
// when a painting is broken @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onPaintingBreak(PaintingBreakEvent event) { // FEATURE: claimed paintings are protected from breakage // only allow players to break paintings, not anything else (like water and explosions) if (!(event instanceof PaintingBreakByEntityEvent)) { event.setCancelled(true); return; } PaintingBreakByEntityEvent entityEvent = (PaintingBreakByEntityEvent) event; // who is removing it? Entity remover = entityEvent.getRemover(); // again, making sure the breaker is a player if (!(remover instanceof Player)) { event.setCancelled(true); return; } // if the player doesn't have build permission, don't allow the breakage Player playerRemover = (Player) entityEvent.getRemover(); String noBuildReason = GriefPrevention.instance.allowBuild(playerRemover, event.getPainting().getLocation()); if (noBuildReason != null) { event.setCancelled(true); GriefPrevention.sendMessage(playerRemover, TextMode.Err, noBuildReason); } }
// when a vehicle is damaged @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onVehicleDamage(VehicleDamageEvent event) { // all of this is anti theft code if (!GriefPrevention.instance.config_claims_preventTheft) return; // determine which player is attacking, if any Player attacker = null; Entity damageSource = event.getAttacker(); if (damageSource instanceof Player) { attacker = (Player) damageSource; } else if (damageSource instanceof Arrow) { Arrow arrow = (Arrow) damageSource; if (arrow.getShooter() instanceof Player) { attacker = (Player) arrow.getShooter(); } } else if (damageSource instanceof ThrownPotion) { ThrownPotion potion = (ThrownPotion) damageSource; if (potion.getShooter() instanceof Player) { attacker = (Player) potion.getShooter(); } } // NOTE: vehicles can be pushed around. // so unless precautions are taken by the owner, a resourceful thief might find ways to steal // anyway Claim cachedClaim = null; PlayerData playerData = null; if (attacker != null) { playerData = this.dataStore.getPlayerData(attacker.getName()); cachedClaim = playerData.lastClaim; } Claim claim = this.dataStore.getClaimAt(event.getVehicle().getLocation(), false, cachedClaim); // if it's claimed if (claim != null) { // if damaged by anything other than a player, cancel the event if (attacker == null) { event.setCancelled(true); } // otherwise the player damaging the entity must have permission else { String noContainersReason = claim.allowContainers(attacker); if (noContainersReason != null) { event.setCancelled(true); GriefPrevention.sendMessage( attacker, TextMode.Err, Messages.NoDamageClaimedEntity, claim.getOwnerName()); } // cache claim for later if (playerData != null) { playerData.lastClaim = claim; } } } }
@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, "Looting time is up! Ejected from the claim."); GriefPrevention.instance.ejectPlayer(player); } } } }
// called when a player spawns, applies protection for that player if necessary public void checkPvpProtectionNeeded(Player player) { WorldConfig wc = GriefPrevention.instance.getWorldCfg(player.getWorld()); // if pvp is disabled, do nothing if (!player.getWorld().getPVP()) return; // if player is in creative mode, do nothing if (player.getGameMode() == GameMode.CREATIVE) return; // if anti spawn camping feature is not enabled, do nothing if (!wc.getProtectFreshSpawns()) return; // if the player has the damage any player permission enabled, do nothing if (player.hasPermission("griefprevention.nopvpimmunity")) return; // check inventory for well, anything PlayerInventory inventory = player.getInventory(); ItemStack[] armorStacks = inventory.getArmorContents(); // check armor slots, stop if any items are found for (int i = 0; i < armorStacks.length; i++) { if (!(armorStacks[i] == null || armorStacks[i].getType() == Material.AIR)) return; } // check other slots, stop if any items are found ItemStack[] generalStacks = inventory.getContents(); for (int i = 0; i < generalStacks.length; i++) { if (!(generalStacks[i] == null || generalStacks[i].getType() == Material.AIR)) return; } // otherwise, apply immunity PlayerData playerData = this.dataStore.getPlayerData(player.getName()); playerData.pvpImmune = true; // inform the player GriefPrevention.sendMessage(player, TextMode.Success, Messages.PvPImmunityStart); }
// when an entity is damaged @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) public void onEntityDamage(EntityDamageEvent event) { // only actually interested in entities damaging entities (ignoring environmental damage) if (!(event instanceof EntityDamageByEntityEvent)) return; // monsters are never protected if (event.getEntity() instanceof Monster) return; EntityDamageByEntityEvent subEvent = (EntityDamageByEntityEvent) event; // determine which player is attacking, if any Player attacker = null; Entity damageSource = subEvent.getDamager(); if (damageSource instanceof Player) { attacker = (Player) damageSource; } else if (damageSource instanceof Arrow) { Arrow arrow = (Arrow) damageSource; if (arrow.getShooter() instanceof Player) { attacker = (Player) arrow.getShooter(); } } else if (damageSource instanceof ThrownPotion) { ThrownPotion potion = (ThrownPotion) damageSource; if (potion.getShooter() instanceof Player) { attacker = (Player) potion.getShooter(); } } // if the attacker is a player and defender is a player (pvp combat) if (attacker != null && event.getEntity() instanceof Player) { // FEATURE: prevent pvp in the first minute after spawn, and prevent pvp when one or both // players have no inventory // doesn't apply when the attacker has the no pvp immunity permission // this rule is here to allow server owners to have a world with no spawn camp protection by // assigning permissions based on the player's world if (attacker.hasPermission("griefprevention.nopvpimmunity")) return; Player defender = (Player) (event.getEntity()); PlayerData defenderData = this.dataStore.getPlayerData(((Player) event.getEntity()).getName()); PlayerData attackerData = this.dataStore.getPlayerData(attacker.getName()); // otherwise if protecting spawning players if (GriefPrevention.instance.config_pvp_protectFreshSpawns) { if (defenderData.pvpImmune) { event.setCancelled(true); GriefPrevention.sendMessage(attacker, TextMode.Err, Messages.ThatPlayerPvPImmune); return; } if (attackerData.pvpImmune) { event.setCancelled(true); GriefPrevention.sendMessage(attacker, TextMode.Err, Messages.CantFightWhileImmune); return; } } // FEATURE: prevent players who very recently participated in pvp combat from hiding inventory // to protect it from looting // FEATURE: prevent players who are in pvp combat from logging out to avoid being defeated long now = Calendar.getInstance().getTimeInMillis(); defenderData.lastPvpTimestamp = now; defenderData.lastPvpPlayer = attacker.getName(); attackerData.lastPvpTimestamp = now; attackerData.lastPvpPlayer = defender.getName(); } // FEATURE: protect claimed animals, boats, minecarts // NOTE: animals can be lead with wheat, vehicles can be pushed around. // so unless precautions are taken by the owner, a resourceful thief might find ways to steal // anyway // if theft protection is enabled if (event instanceof EntityDamageByEntityEvent) { // if the entity is an non-monster creature (remember monsters disqualified above), or a // vehicle if ((subEvent.getEntity() instanceof Creature && GriefPrevention.instance.config_claims_protectCreatures)) { Claim cachedClaim = null; PlayerData playerData = null; if (attacker != null) { playerData = this.dataStore.getPlayerData(attacker.getName()); cachedClaim = playerData.lastClaim; } Claim claim = this.dataStore.getClaimAt(event.getEntity().getLocation(), false, cachedClaim); // if it's claimed if (claim != null) { // if damaged by anything other than a player, cancel the event if (attacker == null) { event.setCancelled(true); } // otherwise the player damaging the entity must have permission else { String noContainersReason = claim.allowContainers(attacker); if (noContainersReason != null) { event.setCancelled(true); GriefPrevention.sendMessage( attacker, TextMode.Err, Messages.NoDamageClaimedEntity, claim.getOwnerName()); } // cache claim for later if (playerData != null) { playerData.lastClaim = claim; } } } } } }