diff --git a/src/com/massivecraft/factions/Conf.java b/src/com/massivecraft/factions/Conf.java index bf57274f..3c29fd7e 100644 --- a/src/com/massivecraft/factions/Conf.java +++ b/src/com/massivecraft/factions/Conf.java @@ -76,6 +76,10 @@ public class Conf { public static boolean disablePVPBetweenNeutralFactions = false; public static boolean disablePVPForFactionlessPlayers = false; public static int noPVPDamageToOthersForXSecondsAfterLogin = 3; + + public static boolean peacefulTerritoryDisablePVP = true; + public static boolean peacefulTerritoryDisableMonsters = false; + public static boolean peacefulMembersDisablePowerLoss = true; public static boolean claimsMustBeConnected = false; public static boolean claimsCanBeUnconnectedIfOwnedByOtherFaction = true; @@ -173,6 +177,7 @@ public class Conf { public static double econCostAlly = 0.0; public static double econCostEnemy = 0.0; public static double econCostNeutral = 0.0; + public static double econCostNoBoom = 0.0; public static Set worldsNoClaiming = new HashSet(); public static Set worldsNoPowerLoss = new HashSet(); @@ -196,7 +201,7 @@ public class Conf { territoryDenyUseageMaterials.add(Material.BUCKET); territoryDenyUseageMaterials.add(Material.WATER_BUCKET); territoryDenyUseageMaterials.add(Material.LAVA_BUCKET); - + territoryProtectedMaterialsWhenOffline.add(Material.WOODEN_DOOR); territoryProtectedMaterialsWhenOffline.add(Material.TRAP_DOOR); territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER); diff --git a/src/com/massivecraft/factions/FPlayer.java b/src/com/massivecraft/factions/FPlayer.java index 91d106b8..9f134333 100644 --- a/src/com/massivecraft/factions/FPlayer.java +++ b/src/com/massivecraft/factions/FPlayer.java @@ -561,6 +561,15 @@ public class FPlayer { } if (otherFaction.isNormal()) { + if (myFaction.isPeaceful()) { + sendMessage(this.getRelationColor(otherFaction)+otherFaction.getTag()+Conf.colorSystem+" owns this land. Your faction is peaceful, so you cannot claim land from other factions."); + return false; + } + if (otherFaction.isPeaceful()) { + sendMessage(this.getRelationColor(otherFaction)+otherFaction.getTag()+Conf.colorSystem+" owns this land, and is a peaceful faction. You cannot claim land from them."); + return false; + } + if ( ! otherFaction.hasLandInflation()) { // TODO more messages WARN current faction most importantly sendMessage(this.getRelationColor(otherFaction)+otherFaction.getTag()+Conf.colorSystem+" owns this land and is strong enough to keep it."); diff --git a/src/com/massivecraft/factions/Faction.java b/src/com/massivecraft/factions/Faction.java index b36ead78..7cce2504 100644 --- a/src/com/massivecraft/factions/Faction.java +++ b/src/com/massivecraft/factions/Faction.java @@ -31,6 +31,8 @@ public class Faction { private Map> claimOwnership = new HashMap>(); private Set invites; // Where string is a lowercase player name private boolean open; + private boolean peaceful; + private boolean peacefulExplosionsEnabled; private String tag; private String description; private Location home; @@ -120,7 +122,34 @@ public class Faction { sendMessage("Your faction home has been un-set since it is no longer in your territory."); this.home = null; } - + + // "peaceful" status can only be set by server admins/moderators/ops, and prevents PvP and land capture to/from the faction + public boolean isPeaceful() { + return peaceful; + } + public void setPeaceful(boolean isPeaceful) { + peaceful = isPeaceful; + } + + public void setPeacefulExplosions(boolean disable) { + peacefulExplosionsEnabled = disable; + } + public void setPeacefulExplosions() { + setPeacefulExplosions(!peacefulExplosionsEnabled); + } + + public boolean noPvPInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisablePVP); + } + + public boolean noMonstersInTerritory() { + return isSafeZone() || (peaceful && Conf.peacefulTerritoryDisableMonsters); + } + + public boolean noExplosionsInTerritory() { + return peaceful && !peacefulExplosionsEnabled; + } + // ------------------------------- // Understand the types // ------------------------------- @@ -177,12 +206,19 @@ public class Faction { } public Relation getRelation(Faction otherFaction) { + return getRelation(otherFaction, false); + } + + public Relation getRelation(Faction otherFaction, boolean ignorePeaceful) { if (!otherFaction.isNormal() || !this.isNormal()) { return Relation.NEUTRAL; } if (otherFaction.equals(this)) { return Relation.MEMBER; } + if (!ignorePeaceful && (this.peaceful || otherFaction.isPeaceful())) { + return Relation.NEUTRAL; + } if(this.getRelationWish(otherFaction).value >= otherFaction.getRelationWish(this).value) { return otherFaction.getRelationWish(this); } diff --git a/src/com/massivecraft/factions/Factions.java b/src/com/massivecraft/factions/Factions.java index b986ee0e..e31d331c 100644 --- a/src/com/massivecraft/factions/Factions.java +++ b/src/com/massivecraft/factions/Factions.java @@ -113,10 +113,12 @@ public class Factions extends JavaPlugin { commands.add(new FCommandLock()); commands.add(new FCommandMap()); commands.add(new FCommandMod()); + commands.add(new FCommandNoBoom()); commands.add(new FCommandOpen()); commands.add(new FCommandOwner()); commands.add(new FCommandOwnerList()); commands.add(new FCommandPower()); + commands.add(new FCommandPeaceful()); commands.add(new FCommandRelationAlly()); commands.add(new FCommandRelationEnemy()); commands.add(new FCommandRelationNeutral()); @@ -400,6 +402,14 @@ public class Factions extends JavaPlugin { return hasPerm(sender, "factions.ownershipBypass"); } + public static boolean hasPermSetPeaceful(CommandSender sender) { + return hasPerm(sender, "factions.setPeaceful"); + } + + public static boolean hasPermPeacefulExplosionToggle(CommandSender sender) { + return hasPerm(sender, "factions.peacefulExplosionToggle"); + } + public static boolean isCommandDisabled(CommandSender sender, String command) { return (hasPerm(sender, "factions.commandDisable."+command) && !hasPerm(sender, "factions.commandDisable.none")); } diff --git a/src/com/massivecraft/factions/commands/FCommandHelp.java b/src/com/massivecraft/factions/commands/FCommandHelp.java index bdc05158..ae263906 100644 --- a/src/com/massivecraft/factions/commands/FCommandHelp.java +++ b/src/com/massivecraft/factions/commands/FCommandHelp.java @@ -92,7 +92,7 @@ public class FCommandHelp extends FBaseCommand { pageLines = new ArrayList(); pageLines.add( new FCommandMap().getUseageTemplate() ); - pageLines.add(""); + pageLines.add( new FCommandNoBoom().getUseageTemplate() ); pageLines.add(""); pageLines.add( new FCommandOwner().getUseageTemplate() ); pageLines.add( new FCommandOwnerList().getUseageTemplate() ); @@ -153,6 +153,8 @@ public class FCommandHelp extends FBaseCommand { pageLines = new ArrayList(); pageLines.add("More commands for server admins:"); pageLines.add( new FCommandBypass().getUseageTemplate() ); + pageLines.add( new FCommandPeaceful().getUseageTemplate() ); + pageLines.add("Peaceful factions are protected from PvP and land capture."); pageLines.add( new FCommandLock().getUseageTemplate() ); pageLines.add( new FCommandReload().getUseageTemplate() ); pageLines.add( new FCommandSaveAll().getUseageTemplate() ); diff --git a/src/com/massivecraft/factions/commands/FCommandNoBoom.java b/src/com/massivecraft/factions/commands/FCommandNoBoom.java new file mode 100644 index 00000000..38a7fc41 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandNoBoom.java @@ -0,0 +1,58 @@ +package com.massivecraft.factions.commands; + +import org.bukkit.command.CommandSender; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.struct.Role; + +public class FCommandNoBoom extends FBaseCommand { + + public FCommandNoBoom() { + aliases.add("noboom"); + + helpDescription = "Peaceful factions only: toggle explosions"; + } + + @Override + public boolean hasPermission(CommandSender sender) { + return Factions.hasPermPeacefulExplosionToggle(sender); + } + + @Override + public void perform() { + if ( ! assertHasFaction()) { + return; + } + + if( isLocked() ) { + sendLockMessage(); + return; + } + + if ( ! assertMinRole(Role.MODERATOR)) { + return; + } + + Faction myFaction = me.getFaction(); + + if (!myFaction.isPeaceful()) { + me.sendMessage("This command is only usable by factions which are specially designated as peaceful."); + return; + } + + // if economy is enabled, they're not on the bypass list, and this command has a cost set, make 'em pay + if (!payForCommand(Conf.econCostNoBoom)) { + return; + } + + myFaction.setPeacefulExplosions(); + + String enabled = myFaction.noExplosionsInTerritory() ? "disabled" : "enabled"; + + // Inform + myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" has "+enabled+" explosions in your faction's territory."); + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandPeaceful.java b/src/com/massivecraft/factions/commands/FCommandPeaceful.java new file mode 100644 index 00000000..6c392cca --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandPeaceful.java @@ -0,0 +1,45 @@ +package com.massivecraft.factions.commands; + +import org.bukkit.command.CommandSender; + +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; + +public class FCommandPeaceful extends FBaseCommand { + + public FCommandPeaceful() { + aliases.add("peaceful"); + + senderMustBePlayer = false; + + requiredParameters.add("faction tag"); + + helpDescription = "Designate a faction as peaceful"; + } + + @Override + public boolean hasPermission(CommandSender sender) { + return Factions.hasPermSetPeaceful(sender); + } + + @Override + public void perform() { + if( parameters.size() > 0) { + Faction faction = Faction.findByTag(parameters.get(0)); + + if (faction == null) { + sendMessage("No faction found with the tag \"" + parameters.get(0) + "\""); + return; + } + + if( faction != null && faction.isPeaceful() ) { + sendMessage("Faction \"" + parameters.get(0) + "\" peaceful designation removed"); + faction.setPeaceful(false); + } else { + sendMessage("Faction \"" + faction.getTag() + "\" has been designated as peaceful"); + faction.setPeaceful(true); + } + } + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandShow.java b/src/com/massivecraft/factions/commands/FCommandShow.java index 251db260..4b1b6aa0 100644 --- a/src/com/massivecraft/factions/commands/FCommandShow.java +++ b/src/com/massivecraft/factions/commands/FCommandShow.java @@ -62,11 +62,12 @@ public class FCommandShow extends FBaseCommand { return; } - if(faction.getOpen()) { - sendMessage(Conf.colorChrome+"Joining: "+Conf.colorSystem+"no invitation is needed"); - } else { - sendMessage(Conf.colorChrome+"Joining: "+Conf.colorSystem+"invitation is required"); + String peaceStatus = ""; + if (faction.isPeaceful()) { + peaceStatus = " "+Conf.colorNeutral+"This faction is Peaceful"; } + + sendMessage(Conf.colorChrome+"Joining: "+Conf.colorSystem+(faction.getOpen() ? "no invitation is needed" : "invitation is required")+peaceStatus); sendMessage(Conf.colorChrome+"Land / Power / Maxpower: "+Conf.colorSystem+ faction.getLandRounded()+" / "+faction.getPowerRounded()+" / "+faction.getPowerMaxRounded()); // show the land value diff --git a/src/com/massivecraft/factions/commands/FRelationCommand.java b/src/com/massivecraft/factions/commands/FRelationCommand.java index 4001d361..f5c6f073 100644 --- a/src/com/massivecraft/factions/commands/FRelationCommand.java +++ b/src/com/massivecraft/factions/commands/FRelationCommand.java @@ -54,9 +54,9 @@ public class FRelationCommand extends FBaseCommand { } myFaction.setRelationWish(otherFaction, whishedRelation); - Relation currentRelation = myFaction.getRelation(otherFaction); + Relation currentRelation = myFaction.getRelation(otherFaction, true); ChatColor currentRelationColor = currentRelation.getColor(); - if (whishedRelation == currentRelation) { + if (whishedRelation.value == currentRelation.value) { otherFaction.sendMessage(Conf.colorSystem+"Your faction is now "+currentRelationColor+whishedRelation.toString()+Conf.colorSystem+" to "+currentRelationColor+myFaction.getTag()); myFaction.sendMessage(Conf.colorSystem+"Your faction is now "+currentRelationColor+whishedRelation.toString()+Conf.colorSystem+" to "+currentRelationColor+otherFaction.getTag()); } else { @@ -64,5 +64,13 @@ public class FRelationCommand extends FBaseCommand { otherFaction.sendMessage(Conf.colorSystem+"Type "+Conf.colorCommand+Factions.instance.getBaseCommand()+" "+whishedRelation+" "+myFaction.getTag()+Conf.colorSystem+" to accept."); myFaction.sendMessage(currentRelationColor+otherFaction.getTag()+Conf.colorSystem+ " were informed that you wish to be "+whishedRelation.getColor()+whishedRelation); } + if (!whishedRelation.isNeutral() && otherFaction.isPeaceful()) { + otherFaction.sendMessage(Conf.colorSystem+"This will have no effect while your faction is peaceful."); + myFaction.sendMessage(Conf.colorSystem+"This will have no effect while their faction is peaceful."); + } + if (!whishedRelation.isNeutral() && myFaction.isPeaceful()) { + otherFaction.sendMessage(Conf.colorSystem+"This will have no effect while their faction is peaceful."); + myFaction.sendMessage(Conf.colorSystem+"This will have no effect while your faction is peaceful."); + } } } diff --git a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java index 0fabadb3..8ee6bd51 100644 --- a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -56,6 +56,9 @@ public class FactionsEntityListener extends EntityListener { } else if (Conf.worldsNoPowerLoss.contains(player.getWorld().getName())) { fplayer.sendMessage("You didn't lose any power due to the world you died in."); return; + } else if (Conf.peacefulMembersDisablePowerLoss && fplayer.hasFaction() && fplayer.getFaction().isPeaceful()) { + fplayer.sendMessage("You didn't lose any power since you are in a peaceful faction."); + return; } fplayer.onDeath(); fplayer.sendMessage("Your power is now "+fplayer.getPowerRounded()+" / "+fplayer.getPowerMaxRounded()); @@ -99,10 +102,13 @@ public class FactionsEntityListener extends EntityListener { Faction faction = Board.getFactionAt(new FLocation(event.getLocation())); boolean online = faction.hasPlayersOnline(); - if (event.getEntity() instanceof Creeper && ( + if (faction.noExplosionsInTerritory()) { + // faction is peaceful and has explosions set to disabled + event.setCancelled(true); + } + else if (event.getEntity() instanceof Creeper && ( (faction.isNone() && Conf.wildernessBlockCreepers) || - (faction.isNormal() && online && Conf.territoryBlockCreepers) || - (faction.isNormal() && !online && Conf.territoryBlockCreepersWhenOffline) || + (faction.isNormal() && (online ? Conf.territoryBlockCreepers : Conf.territoryBlockCreepersWhenOffline)) || (faction.isWarZone() && Conf.warZoneBlockCreepers) || faction.isSafeZone() )) { @@ -110,8 +116,7 @@ public class FactionsEntityListener extends EntityListener { event.setCancelled(true); } else if (event.getEntity() instanceof Fireball && ( (faction.isNone() && Conf.wildernessBlockFireballs) || - (faction.isNormal() && online && Conf.territoryBlockFireballs) || - (faction.isNormal() && !online && Conf.territoryBlockFireballsWhenOffline) || + (faction.isNormal() && (online ? Conf.territoryBlockFireballs : Conf.territoryBlockFireballsWhenOffline)) || (faction.isWarZone() && Conf.warZoneBlockFireballs) || faction.isSafeZone() )) { @@ -119,8 +124,7 @@ public class FactionsEntityListener extends EntityListener { event.setCancelled(true); } else if ( (faction.isNone() && Conf.wildernessBlockTNT) || - (faction.isNormal() && online && Conf.territoryBlockTNT) || - (faction.isNormal() && !online && Conf.territoryBlockTNTWhenOffline) || + (faction.isNormal() && (online ? Conf.territoryBlockTNT : Conf.territoryBlockTNTWhenOffline)) || (faction.isWarZone() && Conf.warZoneBlockTNT) || (faction.isSafeZone() && Conf.safeZoneBlockTNT) ) { @@ -160,13 +164,16 @@ public class FactionsEntityListener extends EntityListener { return true; } - // Players can not take attack damage in a SafeZone - if (Board.getFactionAt(new FLocation(defenderLoc)).isSafeZone()) { + Faction defLocFaction = Board.getFactionAt(new FLocation(defenderLoc)); + + // Players can not take attack damage in a SafeZone, or possibly peaceful territory + if (defLocFaction.noPvPInTerritory()) { if (damager instanceof Player) { FPlayer attacker = FPlayer.get((Player)damager); - attacker.sendMessage("You can't hurt other players in a SafeZone."); + attacker.sendMessage("You can't hurt other players in "+(defLocFaction.isSafeZone() ? "a SafeZone." : "peaceful territory.")); + return false; } - return false; + return !defLocFaction.noMonstersInTerritory(); } if ( ! (damager instanceof Player)) { @@ -187,8 +194,8 @@ public class FactionsEntityListener extends EntityListener { Faction locFaction = Board.getFactionAt(new FLocation(attacker)); // so we know from above that the defender isn't in a safezone... what about the attacker, sneaky dog that he might be? - if (locFaction.isSafeZone()) { - attacker.sendMessage("You can't hurt other players while you are in a SafeZone."); + if (locFaction.noPvPInTerritory()) { + attacker.sendMessage("You can't hurt other players while you are in "+(locFaction.isSafeZone() ? "a SafeZone." : "peaceful territory.")); return false; } else if (locFaction.isWarZone() && Conf.warZoneFriendlyFire) { @@ -204,7 +211,19 @@ public class FactionsEntityListener extends EntityListener { return false; } - Relation relation = defender.getRelation(attacker); + Faction defendFaction = defender.getFaction(); + Faction attackFaction = attacker.getFaction(); + + if (defendFaction.isPeaceful()) { + attacker.sendMessage("You can't hurt players who are in a peaceful faction."); + return false; + } + else if (attackFaction.isPeaceful()) { + attacker.sendMessage("You can't hurt players while you are in a peaceful faction."); + return false; + } + + Relation relation = defendFaction.getRelation(attackFaction); // You can not hurt neutral factions if (Conf.disablePVPBetweenNeutralFactions && relation.isNeutral()) { @@ -223,15 +242,17 @@ public class FactionsEntityListener extends EntityListener { return false; } + boolean ownTerritory = defender.isInOwnTerritory(); + // You can not hurt neutrals in their own territory. - if (relation.isNeutral() && defender.isInOwnTerritory()) { + if (ownTerritory && relation.isNeutral()) { attacker.sendMessage(Conf.colorSystem+"You can't hurt "+relation.getColor()+defender.getNameAndRelevant(attacker)+Conf.colorSystem+" in their own territory."); defender.sendMessage(attacker.getNameAndRelevant(defender)+Conf.colorSystem+" tried to hurt you."); return false; } // Damage will be dealt. However check if the damage should be reduced. - if (defender.isInOwnTerritory() && Conf.territoryShieldFactor > 0) { + if (ownTerritory && Conf.territoryShieldFactor > 0) { int newDamage = (int)Math.ceil(damage * (1D - Conf.territoryShieldFactor)); sub.setDamage(newDamage); @@ -245,11 +266,11 @@ public class FactionsEntityListener extends EntityListener { @Override public void onCreatureSpawn(CreatureSpawnEvent event) { - if (event.isCancelled()) { + if (event.isCancelled() || event.getLocation() == null) { return; } - if (Conf.safeZoneNerfedCreatureTypes.contains(event.getCreatureType()) && Board.getFactionAt(new FLocation(event.getLocation())).isSafeZone()) { + if (Conf.safeZoneNerfedCreatureTypes.contains(event.getCreatureType()) && Board.getFactionAt(new FLocation(event.getLocation())).noMonstersInTerritory()) { event.setCancelled(true); } } @@ -272,7 +293,7 @@ public class FactionsEntityListener extends EntityListener { } // in case the target is in a safe zone. - if (Board.getFactionAt(new FLocation(target.getLocation())).isSafeZone()) { + if (Board.getFactionAt(new FLocation(target.getLocation())).noMonstersInTerritory()) { event.setCancelled(true); } } diff --git a/src/plugin.yml b/src/plugin.yml index 7f1aba45..c32e52ac 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -20,6 +20,7 @@ permissions: factions.participate: true factions.create: true factions.viewAnyPower: true + factions.peacefulExplosionToggle: true factions.adminBypass: true factions.config: true factions.disband: true @@ -29,6 +30,7 @@ permissions: factions.ownershipBypass: true factions.reload: true factions.saveall: true + factions.setPeaceful: true factions.commandDisable.none: true factions.participate: description: Allows the player to participate in a faction @@ -39,6 +41,9 @@ permissions: factions.viewAnyPower: description: Allows the player to view the power level of anyone else default: true + factions.peacefulExplosionToggle: + description: Allows peaceful faction admins and moderators to disable explosions in their territory + default: true factions.adminBypass: description: Allows the player to bypass many normal restrictions, and use the bypass command default: op @@ -66,6 +71,9 @@ permissions: factions.saveall: description: Can use the /f saveall command to save all data to disk default: op + factions.setPeaceful: + description: Can designate specific factions as "peaceful" (no PvP, no land stealing, etc.) + default: op factions.commandDisable.none: description: no commands disabled (ignore all other commandDisable permissions) default: op @@ -150,6 +158,9 @@ permissions: factions.commandDisable.mod: description: mod command disabled default: false + factions.commandDisable.noboom: + description: noboom command disabled + default: false factions.commandDisable.open: description: open command disabled default: false @@ -162,6 +173,9 @@ permissions: factions.commandDisable.ownerlist: description: ownerlist command disabled default: false + factions.commandDisable.peaceful: + description: peaceful command disabled + default: false factions.commandDisable.power: description: power command disabled default: false