diff --git a/lib/Register.jar b/lib/Register.jar new file mode 100644 index 00000000..0c4dd81f Binary files /dev/null and b/lib/Register.jar differ diff --git a/lib/SpoutAPI.jar b/lib/SpoutAPI.jar index 0c07893d..324ee83d 100644 Binary files a/lib/SpoutAPI.jar and b/lib/SpoutAPI.jar differ diff --git a/lib/bukkit-0.0.1-SNAPSHOT.jar b/lib/bukkit-0.0.1-SNAPSHOT.jar index 921a7c91..b348aa10 100644 Binary files a/lib/bukkit-0.0.1-SNAPSHOT.jar and b/lib/bukkit-0.0.1-SNAPSHOT.jar differ diff --git a/src/com/earth2me/essentials/chat/IEssentialsChatListener.java b/src/com/earth2me/essentials/chat/IEssentialsChatListener.java deleted file mode 100644 index 5c9c5c21..00000000 --- a/src/com/earth2me/essentials/chat/IEssentialsChatListener.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.earth2me.essentials.chat; - -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerChatEvent; - - -public interface IEssentialsChatListener -{ - boolean shouldHandleThisChat(PlayerChatEvent event); - - String modifyMessage(PlayerChatEvent event, Player target, String message); -} diff --git a/src/com/massivecraft/factions/Conf.java b/src/com/massivecraft/factions/Conf.java index dffe45cf..fbb6ddc4 100644 --- a/src/com/massivecraft/factions/Conf.java +++ b/src/com/massivecraft/factions/Conf.java @@ -28,6 +28,8 @@ public class Conf { public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power public static double powerPerDeath = 4.0; // A death makes you lose 4 power public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline? + public static double powerOfflineLossPerDay = 1.0; // players will lose this much power per day offline + public static double powerOfflineLossLimit = 0.0; // players will no longer lose power from being offline once their power drops to this amount or less public static double powerFactionMax = 0.0; // if greater than 0, the cap on how much power a faction can have (additional power from players beyond that will act as a "buffer" of sorts) public static String prefixAdmin = "**"; @@ -63,6 +65,7 @@ public class Conf { public static boolean chatTagPadAfter = true; public static String chatTagFormat = "%s"+ChatColor.WHITE; public static String factionChatFormat = "%s"+ChatColor.WHITE+" %s"; + public static String allianceChatFormat = "%s"+ChatColor.WHITE+" %s"; public static boolean allowNoSlashCommand = true; @@ -126,11 +129,14 @@ public class Conf { public static boolean territoryBlockFireballsWhenOffline = false; public static boolean territoryBlockTNT = false; public static boolean territoryBlockTNTWhenOffline = false; + public static boolean territoryDenyEndermanBlocks = true; + public static boolean territoryDenyEndermanBlocksWhenOffline = true; public static boolean safeZoneDenyBuild = true; public static boolean safeZoneDenyUseage = true; public static boolean safeZoneBlockTNT = true; public static boolean safeZonePreventAllDamageToPlayers = false; + public static boolean safeZoneDenyEndermanBlocks = true; public static boolean warZoneDenyBuild = true; public static boolean warZoneDenyUseage = true; @@ -139,6 +145,7 @@ public class Conf { public static boolean warZoneBlockTNT = true; public static boolean warZonePowerLoss = true; public static boolean warZoneFriendlyFire = false; + public static boolean warZoneDenyEndermanBlocks = true; public static boolean wildernessDenyBuild = false; public static boolean wildernessDenyUseage = false; @@ -146,6 +153,7 @@ public class Conf { public static boolean wildernessBlockFireballs = false; public static boolean wildernessBlockTNT = false; public static boolean wildernessPowerLoss = true; + public static boolean wildernessDenyEndermanBlocks = false; // for claimed areas where further faction-member ownership can be defined public static boolean ownedAreasEnabled = true; @@ -177,6 +185,7 @@ public class Conf { public static boolean spoutFactionTitlesOverNames = true; public static boolean spoutFactionAdminCapes = true; public static boolean spoutFactionModeratorCapes = true; + public static int spoutTerritoryDisplayPosition = 3; public static String capeAlly = "https://github.com/MassiveCraft/Factions/raw/master/capes/ally.png"; public static String capeEnemy = "https://github.com/MassiveCraft/Factions/raw/master/capes/enemy.png"; public static String capeMember = "https://github.com/MassiveCraft/Factions/raw/master/capes/member.png"; @@ -184,6 +193,7 @@ public class Conf { public static String capePeaceful = "https://github.com/MassiveCraft/Factions/raw/master/capes/peaceful.png"; // Economy settings + public static boolean econRegisterEnabled = false; public static boolean econIConomyEnabled = false; public static boolean econEssentialsEcoEnabled = false; public static double econCostClaimWilderness = 30.0; @@ -211,6 +221,12 @@ public class Conf { public static double econCostNeutral = 0.0; public static double econCostNoBoom = 0.0; + //Faction banks, to pay for land claiming and other costs instead of individuals paying for them + public static boolean bankEnabled = true; + public static boolean bankMembersCanWithdraw = false; //Have to be at least moderator to withdraw or pay money to another faction + public static boolean bankFactionPaysCosts = true; //The faction pays for faction command costs, such as sethome + public static boolean bankFactionPaysLandCosts = true; //The faction pays for land claiming costs. + public static Set worldsNoClaiming = new HashSet(); public static Set worldsNoPowerLoss = new HashSet(); public static Set worldsIgnorePvP = new HashSet(); @@ -253,9 +269,12 @@ public class Conf { territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET); territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET); + safeZoneNerfedCreatureTypes.add(CreatureType.CAVE_SPIDER); safeZoneNerfedCreatureTypes.add(CreatureType.CREEPER); + safeZoneNerfedCreatureTypes.add(CreatureType.ENDERMAN); safeZoneNerfedCreatureTypes.add(CreatureType.GHAST); safeZoneNerfedCreatureTypes.add(CreatureType.PIG_ZOMBIE); + safeZoneNerfedCreatureTypes.add(CreatureType.SILVERFISH); safeZoneNerfedCreatureTypes.add(CreatureType.SKELETON); safeZoneNerfedCreatureTypes.add(CreatureType.SPIDER); safeZoneNerfedCreatureTypes.add(CreatureType.SLIME); diff --git a/src/com/massivecraft/factions/FPlayer.java b/src/com/massivecraft/factions/FPlayer.java index a51f0e6c..813aed4d 100644 --- a/src/com/massivecraft/factions/FPlayer.java +++ b/src/com/massivecraft/factions/FPlayer.java @@ -11,6 +11,10 @@ import org.bukkit.Location; import org.bukkit.entity.Player; import com.google.gson.reflect.TypeToken; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.integration.SpoutFeatures; +import com.massivecraft.factions.integration.Worldguard; +import com.massivecraft.factions.struct.ChatMode; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.util.DiscUtil; @@ -49,8 +53,9 @@ public class FPlayer { private transient boolean autoClaimEnabled; private transient boolean autoSafeZoneEnabled; private transient boolean autoWarZoneEnabled; - private transient boolean loginPvpDisabled; - private boolean factionChatting; + private transient boolean loginPvpDisabled; + private transient boolean deleteMe; + private ChatMode chatMode; // -------------------------------------------- // // Construct @@ -67,6 +72,7 @@ public class FPlayer { this.autoSafeZoneEnabled = false; this.autoWarZoneEnabled = false; this.loginPvpDisabled = (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) ? true : false; + this.deleteMe = false; if (Conf.newPlayerStartingFactionID > 0 && Faction.exists(Conf.newPlayerStartingFactionID)) { this.factionId = Conf.newPlayerStartingFactionID; @@ -80,9 +86,10 @@ public class FPlayer { } this.factionId = 0; // The default neutral faction - this.factionChatting = false; + this.chatMode = ChatMode.PUBLIC; this.role = Role.NORMAL; this.title = ""; + this.autoClaimEnabled = false; if (playerName != null && !playerName.isEmpty()) { SpoutFeatures.updateAppearances(this.getPlayer()); @@ -139,15 +146,15 @@ public class FPlayer { SpoutFeatures.updateAppearances(this.getPlayer()); } - public boolean isFactionChatting() { - if (this.factionId == 0) { - return false; + public ChatMode getChatMode() { + if(this.factionId == 0 ) { + return ChatMode.PUBLIC; } - return factionChatting; + return chatMode; } - public void setFactionChatting(boolean factionChatting) { - this.factionChatting = factionChatting; + public void setChatMode(ChatMode chatMode) { + this.chatMode = chatMode; } public long getLastLoginTime() { @@ -190,6 +197,7 @@ public class FPlayer { } public void setLastLoginTime(long lastLoginTime) { + losePowerFromBeingOffline(); this.lastLoginTime = lastLoginTime; this.lastPowerUpdateTime = lastLoginTime; if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) { @@ -223,6 +231,10 @@ public class FPlayer { public void setLastStoodAt(FLocation flocation) { this.lastStoodAt = flocation; } + + public void markForDeletion(boolean delete) { + deleteMe = delete; + } //----------------------------------------------// // Title, Name, Faction Tag and Chat @@ -404,8 +416,11 @@ public class FPlayer { } protected void updatePower() { - if (this.isOffline() && !Conf.powerRegenOffline) { - return; + if (this.isOffline()) { + losePowerFromBeingOffline(); + if (!Conf.powerRegenOffline) { + return; + } } long now = System.currentTimeMillis(); long millisPassed = now - this.lastPowerUpdateTime; @@ -414,6 +429,20 @@ public class FPlayer { int millisPerMinute = 60*1000; this.alterPower(millisPassed * Conf.powerPerMinute / millisPerMinute); } + + protected void losePowerFromBeingOffline() { + if (Conf.powerOfflineLossPerDay > 0.0 && this.power > Conf.powerOfflineLossLimit) { + long now = System.currentTimeMillis(); + long millisPassed = now - this.lastPowerUpdateTime; + this.lastPowerUpdateTime = now; + + double loss = millisPassed * Conf.powerOfflineLossPerDay / (24*60*60*1000); + if (this.power - loss < Conf.powerOfflineLossLimit) { + loss = this.power; + } + this.alterPower(-loss); + } + } public void onDeath() { this.updatePower(); @@ -445,6 +474,9 @@ public class FPlayer { } public void sendFactionHereMessage() { + if (SpoutFeatures.updateTerritoryDisplay(this)) { + return; + } Faction factionHere = Board.getFactionAt(new FLocation(this)); String msg = Conf.colorSystem+" ~ "+factionHere.getTag(this); if (factionHere.getDescription().length() > 0) { @@ -605,11 +637,23 @@ public class FPlayer { if (Econ.enabled() && !Conf.adminBypassPlayers.contains(this.playerName)) { double cost = Econ.calculateClaimCost(ownedLand, otherFaction.isNormal()); String costString = Econ.moneyString(cost); - if (!Econ.deductMoney(this.playerName, cost)) { - sendMessage("Claiming this land will cost "+costString+", which you can't currently afford."); - return false; + + if(Conf.bankFactionPaysLandCosts && this.hasFaction()) { + Faction faction = this.getFaction(); + + if(!faction.removeMoney(cost)) { + sendMessage("It costs "+costString+" to claim this land, which your faction can't currently afford."); + return false; + } else { + sendMessage(faction.getTag()+" has paid "+costString+" to claim some land."); + } + } else { + if (!Econ.deductMoney(this.playerName, cost)) { + sendMessage("Claiming this land will cost "+costString+", which you can't currently afford."); + return false; + } + sendMessage("You have paid "+costString+" to claim this land."); } - sendMessage("You have paid "+costString+" to claim this land."); } // announce success @@ -688,9 +732,7 @@ public class FPlayer { // -------------------------------------------- // public boolean shouldBeSaved() { -// return this.factionId != 0; - // we now need to track all players, so they don't get stuck back into a default faction if factionless; also to keep track of lost power and such - return true; + return !deleteMe; } public static boolean save() { @@ -765,6 +807,7 @@ public class FPlayer { for (FPlayer fplayer : FPlayer.getAll()) { if (now - fplayer.getLastLoginTime() > toleranceMillis) { fplayer.leave(false); + fplayer.markForDeletion(true); } } } diff --git a/src/com/massivecraft/factions/Faction.java b/src/com/massivecraft/factions/Faction.java index 017df0e3..3e83f91a 100644 --- a/src/com/massivecraft/factions/Faction.java +++ b/src/com/massivecraft/factions/Faction.java @@ -39,6 +39,7 @@ public class Faction { private String description; private Location home; private transient long lastPlayerLoggedOffTime; + private double money; // -------------------------------------------- // // Construct @@ -54,6 +55,7 @@ public class Faction { this.peaceful = false; this.peacefulExplosionsEnabled = false; this.permanent = false; + this.money = 0.0; } // -------------------------------------------- // @@ -591,7 +593,36 @@ public class Faction { return false; } - + + + //----------------------------------------------// + // Bank functions + //----------------------------------------------// + + public double getMoney() { + return this.money; + } + + public boolean addMoney(double amount) { + if ( amount > 0.0 ) + { + this.money += amount; + return true; + } + return false; + } + + public boolean removeMoney( double amount ) { + if (amount <= 0.0 ) + return false; + + if (amount > this.money ) + return false; + + this.money -= amount; + return true; + } + //----------------------------------------------// // Persistance and entity management diff --git a/src/com/massivecraft/factions/Factions.java b/src/com/massivecraft/factions/Factions.java index 75003195..384111d4 100644 --- a/src/com/massivecraft/factions/Factions.java +++ b/src/com/massivecraft/factions/Factions.java @@ -12,7 +12,9 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; +import org.bukkit.block.Block; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; @@ -23,10 +25,14 @@ import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import com.massivecraft.factions.commands.*; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.integration.SpoutFeatures; +import com.massivecraft.factions.integration.Worldguard; import com.massivecraft.factions.listeners.FactionsBlockListener; import com.massivecraft.factions.listeners.FactionsChatEarlyListener; import com.massivecraft.factions.listeners.FactionsEntityListener; import com.massivecraft.factions.listeners.FactionsPlayerListener; +import com.massivecraft.factions.struct.ChatMode; import com.massivecraft.factions.util.JarLoader; import com.massivecraft.factions.util.MapFLocToStringSetTypeAdapter; import com.massivecraft.factions.util.MyLocationTypeAdapter; @@ -34,10 +40,10 @@ import com.massivecraft.factions.util.MyLocationTypeAdapter; import com.nijiko.permissions.PermissionHandler; import com.nijikokun.bukkit.Permissions.Permissions; import com.earth2me.essentials.chat.EssentialsChat; -import com.earth2me.essentials.chat.IEssentialsChatListener; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; +import com.massivecraft.factions.integration.EssentialsFeatures; /** * The data is saved to disk every 30min and on plugin disable. @@ -97,12 +103,14 @@ public class Factions extends JavaPlugin { commands.add(new FCommandAutoClaim()); commands.add(new FCommandAutoSafeclaim()); commands.add(new FCommandAutoWarclaim()); + commands.add(new FCommandBalance()); commands.add(new FCommandBypass()); commands.add(new FCommandChat()); commands.add(new FCommandClaim()); commands.add(new FCommandConfig()); commands.add(new FCommandCreate()); commands.add(new FCommandDeinvite()); + commands.add(new FCommandDeposit()); commands.add(new FCommandDescription()); commands.add(new FCommandDisband()); commands.add(new FCommandHome()); @@ -118,6 +126,7 @@ public class Factions extends JavaPlugin { commands.add(new FCommandOpen()); commands.add(new FCommandOwner()); commands.add(new FCommandOwnerList()); + commands.add(new FCommandPay()); commands.add(new FCommandPower()); commands.add(new FCommandPeaceful()); commands.add(new FCommandPermanent()); @@ -137,6 +146,7 @@ public class Factions extends JavaPlugin { commands.add(new FCommandVersion()); commands.add(new FCommandWarclaim()); commands.add(new FCommandWarunclaimall()); + commands.add(new FCommandWithdraw()); // Ensure base folder exists! this.getDataFolder().mkdirs(); @@ -148,7 +158,7 @@ public class Factions extends JavaPlugin { setupPermissions(); integrateEssentialsChat(); - SpoutFeatures.setup(this); + setupSpout(this); Econ.setup(this); Econ.monitorPlugins(); @@ -168,6 +178,9 @@ public class Factions extends JavaPlugin { pm.registerEvent(Event.Type.PLAYER_RESPAWN, this.playerListener, Event.Priority.High, this); pm.registerEvent(Event.Type.PLAYER_BUCKET_EMPTY, this.playerListener, Event.Priority.Normal, this); pm.registerEvent(Event.Type.PLAYER_BUCKET_FILL, this.playerListener, Event.Priority.Normal, this); + pm.registerEvent(Event.Type.PLAYER_KICK, this.playerListener, Event.Priority.Normal, this); + pm.registerEvent(Event.Type.ENDERMAN_PICKUP, this.entityListener, Event.Priority.Normal, this); + pm.registerEvent(Event.Type.ENDERMAN_PLACE, this.entityListener, Event.Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_DEATH, this.entityListener, Event.Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_DAMAGE, this.entityListener, Event.Priority.Normal, this); pm.registerEvent(Event.Type.ENTITY_EXPLODE, this.entityListener, Event.Priority.Normal, this); @@ -220,6 +233,14 @@ public class Factions extends JavaPlugin { } } + private void setupSpout(Factions factions) { + Plugin test = factions.getServer().getPluginManager().getPlugin("Spout"); + + if (test != null && test.isEnabled()) { + SpoutFeatures.setAvailable(true, test.getDescription().getFullName()); + } + } + private void integrateEssentialsChat() { if (essChat != null) { return; @@ -227,29 +248,14 @@ public class Factions extends JavaPlugin { Plugin test = this.getServer().getPluginManager().getPlugin("EssentialsChat"); - if (test != null) { - try { - essChat = (EssentialsChat)test; - essChat.addEssentialsChatListener("Factions", new IEssentialsChatListener() { - public boolean shouldHandleThisChat(PlayerChatEvent event) - { - return shouldLetFactionsHandleThisChat(event); - } - public String modifyMessage(PlayerChatEvent event, Player target, String message) - { - return message.replace("{FACTION}", getPlayerFactionTagRelation(event.getPlayer(), target)).replace("{FACTION_TITLE}", getPlayerTitle(event.getPlayer())); - } - }); - Factions.log("Found and will integrate chat with "+test.getDescription().getFullName()); - } - catch (NoSuchMethodError ex) { - essChat = null; - } + if (test != null && test.isEnabled()) { + essChat = (EssentialsChat)test; + EssentialsFeatures.integrateChat(essChat); } } private void unhookEssentialsChat() { if (essChat != null) { - essChat.removeEssentialsChatListener("Factions"); + EssentialsFeatures.unhookChat(); } } @@ -259,7 +265,7 @@ public class Factions extends JavaPlugin { // This value will be updated whenever new hooks are added public int hookSupportVersion() { - return 2; + return 3; } // If another plugin is handling insertion of chat tags, this should be used to notify Factions @@ -283,7 +289,7 @@ public class Factions extends JavaPlugin { FPlayer me = FPlayer.get(player); if (me == null) return false; - return me.isFactionChatting(); + return me.getChatMode().isAtLeast(ChatMode.ALLIANCE); } // Is this chat message actually a Factions command, and thus should be left alone by other plugins? @@ -370,6 +376,21 @@ public class Factions extends JavaPlugin { return players; } + // check if player is allowed to build/destroy in a particular location + public boolean isPlayerAllowedToBuildHere(Player player, Location location) { + return FactionsBlockListener.playerCanBuildDestroyBlock(player, location, "", true); + } + + // check if player is allowed to interact with the specified block (doors/chests/whatever) + public boolean isPlayerAllowedToInteractWith(Player player, Block block) { + return FactionsPlayerListener.canPlayerUseBlock(player, block, true); + } + + // check if player is allowed to use a specified item (flint&steel, buckets, etc) in a particular location + public boolean isPlayerAllowedToUseThisHere(Player player, Location location, Material material) { + return FactionsPlayerListener.playerCanUseItemHere(player, location, material, true); + } + // -------------------------------------------- // // Test rights // -------------------------------------------- // @@ -434,6 +455,10 @@ public class Factions extends JavaPlugin { return hasPerm(sender, "factions.peacefulExplosionToggle"); } + public static boolean hasPermViewAnyFactionBalance(CommandSender sender) { + return hasPerm(sender, "factions.viewAnyFactionBalance"); + } + 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/FBaseCommand.java b/src/com/massivecraft/factions/commands/FBaseCommand.java index 5f338f89..9bf0aabc 100644 --- a/src/com/massivecraft/factions/commands/FBaseCommand.java +++ b/src/com/massivecraft/factions/commands/FBaseCommand.java @@ -9,7 +9,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.Econ; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; @@ -27,6 +27,7 @@ public class FBaseCommand { public CommandSender sender; public boolean senderMustBePlayer; + public boolean senderIsConsole; public Player player; public FPlayer me; @@ -40,6 +41,7 @@ public class FBaseCommand { optionalParameters = new ArrayList(); senderMustBePlayer = true; + senderIsConsole = false; helpNameAndParams = "fail!"; helpDescription = "no description"; @@ -60,6 +62,10 @@ public class FBaseCommand { if (sender instanceof Player) { this.player = (Player)sender; this.me = FPlayer.get(this.player); + senderIsConsole = false; + } + else { + senderIsConsole = true; } perform(); @@ -80,7 +86,7 @@ public class FBaseCommand { } public boolean validateCall() { - if ( this.senderMustBePlayer && ! (sender instanceof Player)) { + if ( this.senderMustBePlayer && senderIsConsole ) { sendMessage("This command can only be used by ingame players."); return false; } @@ -202,7 +208,7 @@ public class FBaseCommand { return fp.getFaction(); } - if (defaultToMine && sender instanceof Player) { + if (defaultToMine && !senderIsConsole) { return me.getFaction(); } @@ -227,7 +233,11 @@ public class FBaseCommand { if (you.getRole().equals(Role.ADMIN)) { i.sendMessage(Conf.colorSystem+"Only the faction admin can do that."); } else if (i.getRole().equals(Role.MODERATOR)) { - i.sendMessage(Conf.colorSystem+"Moderators can't control each other..."); + if ( i == you ) { + return true; //Moderators can control themselves + } else { + i.sendMessage(Conf.colorSystem+"Moderators can't control each other..."); + } } else { i.sendMessage(Conf.colorSystem+"You must be a faction moderator to do that."); } @@ -243,19 +253,40 @@ public class FBaseCommand { String desc = this.helpDescription.toLowerCase(); + Faction faction = me.getFaction(); + // pay up if (cost > 0.0) { String costString = Econ.moneyString(cost); - if (!Econ.deductMoney(me.getName(), cost)) { - sendMessage("It costs "+costString+" to "+desc+", which you can't currently afford."); - return false; + if(Conf.bankFactionPaysCosts && me.hasFaction() ) { + if(!faction.removeMoney(cost)) { + sendMessage("It costs "+costString+" to "+desc+", which your faction can't currently afford."); + return false; + } else { + sendMessage(faction.getTag()+" has paid "+costString+" to "+desc+"."); + } + + } else { + if (!Econ.deductMoney(me.getName(), cost)) { + sendMessage("It costs "+costString+" to "+desc+", which you can't currently afford."); + return false; + } + sendMessage("You have paid "+costString+" to "+desc+"."); } - sendMessage("You have paid "+costString+" to "+desc+"."); } // wait... we pay you to use this command? else { + String costString = Econ.moneyString(-cost); - Econ.addMoney(me.getName(), -cost); + + if(Conf.bankFactionPaysCosts && me.hasFaction() ) { + faction.addMoney(-cost); + sendMessage(faction.getTag()+" has been paid "+costString+" to "+desc+"."); + } else { + Econ.addMoney(me.getName(), -cost); + } + + sendMessage("You have been paid "+costString+" to "+desc+"."); } return true; diff --git a/src/com/massivecraft/factions/commands/FCommandBalance.java b/src/com/massivecraft/factions/commands/FCommandBalance.java new file mode 100644 index 00000000..d511ba65 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandBalance.java @@ -0,0 +1,50 @@ +package com.massivecraft.factions.commands; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; + + +public class FCommandBalance extends FBaseCommand { + + public FCommandBalance() { + aliases.add("balance"); + aliases.add("money"); + + optionalParameters.add("faction tag"); + + helpDescription = "Show faction's current balance"; + } + + @Override + public void perform() { + if ( ! assertHasFaction()) { + return; + } + + if (!Conf.bankEnabled) { + return; + } + + Faction faction; + + if (parameters.size() > 0) { + if (!Factions.hasPermViewAnyFactionBalance(sender)) { + sendMessage("You do not have sufficient permissions to view the bank balance of other factions."); + return; + } + faction = findFaction(parameters.get(0), true); + } else { + faction = me.getFaction(); + } + + if(faction == null) { + sendMessage("Faction "+parameters.get(0)+" could not be found."); + return; + } + + sendMessage(Conf.colorChrome+faction.getTag()+" balance: "+ Econ.moneyString(faction.getMoney())); + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandBypass.java b/src/com/massivecraft/factions/commands/FCommandBypass.java index f58c2da0..b033b42f 100644 --- a/src/com/massivecraft/factions/commands/FCommandBypass.java +++ b/src/com/massivecraft/factions/commands/FCommandBypass.java @@ -24,9 +24,11 @@ public class FCommandBypass extends FBaseCommand { if ( ! Conf.adminBypassPlayers.contains(player.getName())) { Conf.adminBypassPlayers.add(player.getName()); me.sendMessage("You have enabled admin bypass mode. You will be able to build or destroy anywhere."); + Factions.log(player.getName() + " has ENABLED admin bypass mode."); } else { Conf.adminBypassPlayers.remove(player.getName()); me.sendMessage("You have disabled admin bypass mode."); + Factions.log(player.getName() + " DISABLED admin bypass mode."); } } } diff --git a/src/com/massivecraft/factions/commands/FCommandChat.java b/src/com/massivecraft/factions/commands/FCommandChat.java index ebf96a61..8f9d708c 100644 --- a/src/com/massivecraft/factions/commands/FCommandChat.java +++ b/src/com/massivecraft/factions/commands/FCommandChat.java @@ -1,6 +1,7 @@ package com.massivecraft.factions.commands; import com.massivecraft.factions.Conf; +import com.massivecraft.factions.struct.ChatMode; public class FCommandChat extends FBaseCommand { @@ -8,7 +9,9 @@ public class FCommandChat extends FBaseCommand { aliases.add("chat"); aliases.add("c"); - helpDescription = "Switch faction only chat on and off"; + optionalParameters.add("mode"); + + helpDescription = "Change chat mode"; } @Override @@ -21,15 +24,34 @@ public class FCommandChat extends FBaseCommand { return; } - if ( ! me.isFactionChatting()) { - // Turn on - me.setFactionChatting(true); - sendMessage("Faction-only chat ENABLED."); + if( this.parameters.size() >= 1 ) { + String mode = this.parameters.get(0); + + if(mode.startsWith("p")) { + me.setChatMode(ChatMode.PUBLIC); + sendMessage("Public chat mode."); + } else if(mode.startsWith("a")) { + me.setChatMode(ChatMode.ALLIANCE); + sendMessage("Alliance only chat mode."); + } else if(mode.startsWith("f")) { + me.setChatMode(ChatMode.FACTION); + sendMessage("Faction only chat mode."); + } else { + sendMessage("Unrecognised chat mode. Please enter either 'a','f' or 'p'"); + } + } else { - // Turn off - me.setFactionChatting(false); - sendMessage("Faction-only chat DISABLED."); + + if(me.getChatMode() == ChatMode.PUBLIC) { + me.setChatMode(ChatMode.ALLIANCE); + sendMessage("Alliance only chat mode."); + } else if (me.getChatMode() == ChatMode.ALLIANCE ) { + me.setChatMode(ChatMode.FACTION); + sendMessage("Faction only chat mode."); + } else { + me.setChatMode(ChatMode.PUBLIC); + sendMessage("Public chat mode."); + } } } - } diff --git a/src/com/massivecraft/factions/commands/FCommandConfig.java b/src/com/massivecraft/factions/commands/FCommandConfig.java index 61217450..5aa5fd45 100644 --- a/src/com/massivecraft/factions/commands/FCommandConfig.java +++ b/src/com/massivecraft/factions/commands/FCommandConfig.java @@ -13,7 +13,7 @@ import org.bukkit.entity.Player; import com.massivecraft.factions.Conf; import com.massivecraft.factions.Factions; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; public class FCommandConfig extends FBaseCommand { diff --git a/src/com/massivecraft/factions/commands/FCommandDeposit.java b/src/com/massivecraft/factions/commands/FCommandDeposit.java new file mode 100644 index 00000000..900124af --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandDeposit.java @@ -0,0 +1,63 @@ +package com.massivecraft.factions.commands; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; + + +public class FCommandDeposit extends FBaseCommand { + + public FCommandDeposit() { + aliases.add("deposit"); + + helpDescription = "Deposit money into your faction's bank"; + requiredParameters.add("amount"); + } + + @Override + public void perform() { + if ( ! assertHasFaction()) { + return; + } + + if (!Conf.bankEnabled) { + return; + } + + double amount = 0.0; + + Faction faction = me.getFaction(); + + if (parameters.size() == 1) { + try { + amount = Double.parseDouble(parameters.get(0)); + } catch (NumberFormatException e) { + // wasn't valid + } + } + + if( amount > 0.0 ) { + String amountString = Econ.moneyString(amount); + + if( !Econ.deductMoney(me.getName(), amount ) ) { + sendMessage("You cannot afford to deposit that much."); + } + else + { + faction.addMoney(amount); + sendMessage("You have deposited "+amountString+" into "+faction.getTag()+"'s bank."); + sendMessage(faction.getTag()+" now has "+Econ.moneyString(faction.getMoney())); + Factions.log(player.getName() + " deposited "+amountString+" into "+faction.getTag()+"'s bank."); + + for (FPlayer fplayer : FPlayer.getAllOnline()) { + if (fplayer.getFaction() == faction) { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" has deposited "+amountString); + } + } + } + } + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandDisband.java b/src/com/massivecraft/factions/commands/FCommandDisband.java index 2599b063..688decec 100644 --- a/src/com/massivecraft/factions/commands/FCommandDisband.java +++ b/src/com/massivecraft/factions/commands/FCommandDisband.java @@ -1,10 +1,11 @@ package com.massivecraft.factions.commands; import com.massivecraft.factions.Conf; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.struct.Role; @@ -62,11 +63,22 @@ public class FCommandDisband extends FBaseCommand { // Inform all players for (FPlayer fplayer : FPlayer.getAllOnline()) { if (fplayer.getFaction() == faction) { - fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" disbanded your faction."); + fplayer.sendMessage((senderIsConsole ? "A server admin" : me.getNameAndRelevant(fplayer))+Conf.colorSystem+" disbanded your faction."); } else { - fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" disbanded the faction "+faction.getTag(fplayer)+"."); + fplayer.sendMessage((senderIsConsole ? "A server admin" : me.getNameAndRelevant(fplayer))+Conf.colorSystem+" disbanded the faction "+faction.getTag(fplayer)+"."); } } + + if (Conf.bankEnabled) { + double amount = faction.getMoney(); + Econ.addMoney(me.getName(), amount ); //Give all the faction's money to the disbander + if (amount > 0.0) { + String amountString = Econ.moneyString(amount); + sendMessage("You have been given the disbanded faction's bank, totaling "+amountString+"."); + Factions.log(player.getName() + " has been given bank holdings of "+amountString+" from disbanding "+faction.getTag()+"."); + } + } + Faction.delete( faction.getId() ); SpoutFeatures.updateAppearances(); diff --git a/src/com/massivecraft/factions/commands/FCommandHelp.java b/src/com/massivecraft/factions/commands/FCommandHelp.java index 8f4a7cf0..291918b1 100644 --- a/src/com/massivecraft/factions/commands/FCommandHelp.java +++ b/src/com/massivecraft/factions/commands/FCommandHelp.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import org.bukkit.command.CommandSender; import com.massivecraft.factions.Conf; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.util.TextUtil; @@ -48,9 +49,9 @@ public class FCommandHelp extends FBaseCommand { // Build the help pages //----------------------------------------------// - public static final ArrayList> helpPages; + public static ArrayList> helpPages; - static { + public static void updateHelp() { helpPages = new ArrayList>(); ArrayList pageLines; @@ -78,6 +79,20 @@ public class FCommandHelp extends FBaseCommand { pageLines.add( new FCommandSethome().getUseageTemplate() ); helpPages.add(pageLines); + if (Econ.enabled() && Conf.bankEnabled) { + pageLines = new ArrayList(); + pageLines.add( "" ); + pageLines.add( "Your faction has a bank which is used to pay for certain" ); + pageLines.add( "things, so it will need to have money deposited into it." ); + pageLines.add( "" ); + pageLines.add( new FCommandBalance().getUseageTemplate() ); + pageLines.add( new FCommandDeposit().getUseageTemplate() ); + pageLines.add( new FCommandWithdraw().getUseageTemplate() ); + pageLines.add( new FCommandPay().getUseageTemplate() ); + pageLines.add( "" ); + helpPages.add(pageLines); + } + pageLines = new ArrayList(); pageLines.add( new FCommandClaim().getUseageTemplate() ); pageLines.add( new FCommandAutoClaim().getUseageTemplate() ); @@ -162,6 +177,9 @@ public class FCommandHelp extends FBaseCommand { pageLines.add( new FCommandConfig().getUseageTemplate() ); helpPages.add(pageLines); } - + + static { + updateHelp(); + } } diff --git a/src/com/massivecraft/factions/commands/FCommandPay.java b/src/com/massivecraft/factions/commands/FCommandPay.java new file mode 100644 index 00000000..24e4e9b0 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandPay.java @@ -0,0 +1,76 @@ +package com.massivecraft.factions.commands; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.struct.Role; + + +public class FCommandPay extends FBaseCommand { + + public FCommandPay() { + aliases.add("pay"); + + helpDescription = "Pay another faction from your bank"; + requiredParameters.add("faction"); + requiredParameters.add("amount"); + } + + @Override + public void perform() { + if ( ! assertHasFaction()) { + return; + } + + if (!Conf.bankEnabled) { + return; + } + + if ( !Conf.bankMembersCanWithdraw && !assertMinRole(Role.MODERATOR)) { + sendMessage("Only faction moderators or admins are able to pay another faction."); + return; + } + + double amount = 0.0; + + Faction us = me.getFaction(); + Faction them = null; + + if (parameters.size() == 2) { + try { + them = Faction.findByTag(parameters.get(0)); + amount = Double.parseDouble(parameters.get(1)); + } catch (NumberFormatException e) { + // wasn't valid + } + } + + if(them == null) { + sendMessage("Faction "+parameters.get(0)+" could not be found."); + return; + } + + if( amount > 0.0 ) { + String amountString = Econ.moneyString(amount); + + if( amount > us.getMoney() ) { + amount = us.getMoney(); + } + + us.removeMoney(amount); + them.addMoney(amount); + sendMessage("You have paid "+amountString+" from "+us.getTag()+"'s bank to "+them.getTag()+"'s bank."); + sendMessage(us.getTag()+" now has "+Econ.moneyString(us.getMoney())); + Factions.log(player.getName() + " paid "+amountString+" from "+us.getTag()+"'s bank to "+them.getTag()+"'s bank."); + + for (FPlayer fplayer : FPlayer.getAllOnline()) { + if (fplayer.getFaction() == us || fplayer.getFaction() == them) { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" has sent "+amountString+" from "+us.getTag()+" to "+them.getTag() ); + } + } + } + } + +} diff --git a/src/com/massivecraft/factions/commands/FCommandPeaceful.java b/src/com/massivecraft/factions/commands/FCommandPeaceful.java index 4e5eb66d..aeeac60f 100644 --- a/src/com/massivecraft/factions/commands/FCommandPeaceful.java +++ b/src/com/massivecraft/factions/commands/FCommandPeaceful.java @@ -6,7 +6,7 @@ import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; import com.massivecraft.factions.FPlayer; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; public class FCommandPeaceful extends FBaseCommand { diff --git a/src/com/massivecraft/factions/commands/FCommandShow.java b/src/com/massivecraft/factions/commands/FCommandShow.java index 363a926e..b6d99e1c 100644 --- a/src/com/massivecraft/factions/commands/FCommandShow.java +++ b/src/com/massivecraft/factions/commands/FCommandShow.java @@ -6,7 +6,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.Econ; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; import com.massivecraft.factions.struct.Role; @@ -83,6 +83,11 @@ public class FCommandShow extends FBaseCommand { String stringRefund = (refund > 0.0) ? (" ("+Econ.moneyString(refund)+" depreciated)") : ""; sendMessage(Conf.colorChrome+"Total land value: " + Conf.colorSystem + stringValue + stringRefund); } + + //Show bank contents + if(Conf.bankEnabled) { + sendMessage(Conf.colorChrome+"Bank contains: " + Conf.colorSystem + Econ.moneyString(faction.getMoney())); + } } String listpart; diff --git a/src/com/massivecraft/factions/commands/FCommandTag.java b/src/com/massivecraft/factions/commands/FCommandTag.java index dd372b22..e66a1cfa 100644 --- a/src/com/massivecraft/factions/commands/FCommandTag.java +++ b/src/com/massivecraft/factions/commands/FCommandTag.java @@ -4,7 +4,7 @@ import java.util.ArrayList; import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.util.TextUtil; diff --git a/src/com/massivecraft/factions/commands/FCommandTitle.java b/src/com/massivecraft/factions/commands/FCommandTitle.java index 7e67b38b..cdf74f02 100644 --- a/src/com/massivecraft/factions/commands/FCommandTitle.java +++ b/src/com/massivecraft/factions/commands/FCommandTitle.java @@ -3,7 +3,7 @@ package com.massivecraft.factions.commands; import com.massivecraft.factions.Conf; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.util.TextUtil; public class FCommandTitle extends FBaseCommand { diff --git a/src/com/massivecraft/factions/commands/FCommandUnclaim.java b/src/com/massivecraft/factions/commands/FCommandUnclaim.java index ae21ddcd..d7991a96 100644 --- a/src/com/massivecraft/factions/commands/FCommandUnclaim.java +++ b/src/com/massivecraft/factions/commands/FCommandUnclaim.java @@ -2,7 +2,7 @@ package com.massivecraft.factions.commands; import com.massivecraft.factions.Board; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.Econ; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.FLocation; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; @@ -76,16 +76,31 @@ public class FCommandUnclaim extends FBaseCommand { double refund = Econ.calculateClaimRefund(myFaction.getLandRounded()); // a real refund if (refund > 0.0) { - Econ.addMoney(player.getName(), refund); - moneyBack = " They received a refund of "+Econ.moneyString(refund)+"."; + if(Conf.bankFactionPaysLandCosts) { + Faction faction = me.getFaction(); + faction.addMoney(refund); + moneyBack = " "+faction.getTag()+" received a refund of "+Econ.moneyString(refund)+"."; + } else { + Econ.addMoney(player.getName(), refund); + moneyBack = " They received a refund of "+Econ.moneyString(refund)+"."; + } } // wait, you're charging people to unclaim land? outrageous else if (refund < 0.0) { - if (!Econ.deductMoney(player.getName(), -refund)) { - sendMessage("Unclaiming this land will cost "+Econ.moneyString(-refund)+", which you can't currently afford."); - return; + if(Conf.bankFactionPaysLandCosts) { + Faction faction = me.getFaction(); + if(!faction.removeMoney(-refund)) { + sendMessage("Unclaiming this land will cost "+Econ.moneyString(-refund)+", which your faction can't currently afford."); + return; + } + moneyBack = " It cost "+faction.getTag()+" "+Econ.moneyString(refund)+"."; + } else { + if (!Econ.deductMoney(player.getName(), -refund)) { + sendMessage("Unclaiming this land will cost "+Econ.moneyString(-refund)+", which you can't currently afford."); + return; + } + moneyBack = " It cost them "+Econ.moneyString(refund)+"."; } - moneyBack = " It cost them "+Econ.moneyString(refund)+"."; } // no refund else { diff --git a/src/com/massivecraft/factions/commands/FCommandUnclaimall.java b/src/com/massivecraft/factions/commands/FCommandUnclaimall.java index 8fdb103f..3420c707 100644 --- a/src/com/massivecraft/factions/commands/FCommandUnclaimall.java +++ b/src/com/massivecraft/factions/commands/FCommandUnclaimall.java @@ -2,7 +2,7 @@ package com.massivecraft.factions.commands; import com.massivecraft.factions.Board; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.Econ; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.Faction; import com.massivecraft.factions.struct.Role; @@ -37,14 +37,30 @@ public class FCommandUnclaimall extends FBaseCommand { double refund = Econ.calculateTotalLandRefund(myFaction.getLandRounded()); // a real refund if (refund > 0.0) { - Econ.addMoney(player.getName(), refund); - moneyBack = " They received a refund of "+Econ.moneyString(refund)+"."; + if(Conf.bankFactionPaysLandCosts) { + Faction faction = me.getFaction(); + faction.addMoney(refund); + moneyBack = " "+faction.getTag()+" received a refund of "+Econ.moneyString(refund)+"."; + } else { + Econ.addMoney(player.getName(), refund); + moneyBack = " They received a refund of "+Econ.moneyString(refund)+"."; + } } // wait, you're charging people to unclaim land? outrageous else if (refund < 0.0) { - if (!Econ.deductMoney(player.getName(), -refund)) { - sendMessage("Unclaiming all faction land will cost "+Econ.moneyString(-refund)+", which you can't currently afford."); - return; + if(Conf.bankFactionPaysLandCosts) { + Faction faction = me.getFaction(); + if(!faction.removeMoney(-refund)) { + sendMessage("Unclaiming all faction land will cost "+Econ.moneyString(-refund)+", which your faction can't currently afford."); + return; + } + moneyBack = " It cost "+faction.getTag()+" "+Econ.moneyString(refund)+"."; + } else { + if (!Econ.deductMoney(player.getName(), -refund)) { + sendMessage("Unclaiming all faction land will cost "+Econ.moneyString(-refund)+", which you can't currently afford."); + return; + } + moneyBack = " It cost them "+Econ.moneyString(refund)+"."; } moneyBack = " It cost them "+Econ.moneyString(refund)+"."; } @@ -55,7 +71,7 @@ public class FCommandUnclaimall extends FBaseCommand { } Board.unclaimAll(myFaction.getId()); - myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" unclaimed ALL of your factions land."+moneyBack); + myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" unclaimed ALL of your faction's land."+moneyBack); } } diff --git a/src/com/massivecraft/factions/commands/FCommandWithdraw.java b/src/com/massivecraft/factions/commands/FCommandWithdraw.java new file mode 100644 index 00000000..5272e057 --- /dev/null +++ b/src/com/massivecraft/factions/commands/FCommandWithdraw.java @@ -0,0 +1,68 @@ +package com.massivecraft.factions.commands; + +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.struct.Role; + + +public class FCommandWithdraw extends FBaseCommand { + + public FCommandWithdraw() { + aliases.add("withdraw"); + + helpDescription = "Withdraw money from your faction's bank"; + requiredParameters.add("amount"); + } + + @Override + public void perform() { + if ( ! assertHasFaction()) { + return; + } + + if (!Conf.bankEnabled) { + return; + } + + if ( !Conf.bankMembersCanWithdraw && !assertMinRole(Role.MODERATOR)) { + sendMessage("Only faction moderators or admins are able to withdraw from the bank."); + return; + } + + double amount = 0.0; + + Faction faction = me.getFaction(); + + if (parameters.size() == 1) { + try { + amount = Double.parseDouble(parameters.get(0)); + } catch (NumberFormatException e) { + // wasn't valid + } + } + + if( amount > 0.0 ) { + String amountString = Econ.moneyString(amount); + + if( amount > faction.getMoney() ) { + amount = faction.getMoney(); + } + + faction.removeMoney(amount); + Econ.addMoney(me.getName(), amount); + sendMessage("You have withdrawn "+amountString+" from "+faction.getTag()+"'s bank."); + sendMessage(faction.getTag()+" now has "+Econ.moneyString(faction.getMoney())); + Factions.log(player.getName() + " withdrew "+amountString+" from "+faction.getTag()+"'s bank."); + + for (FPlayer fplayer : FPlayer.getAllOnline()) { + if (fplayer.getFaction() == faction) { + fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" has withdrawn "+amountString); + } + } + } + } + +} diff --git a/src/com/massivecraft/factions/commands/FRelationCommand.java b/src/com/massivecraft/factions/commands/FRelationCommand.java index 5e75ac55..7993904d 100644 --- a/src/com/massivecraft/factions/commands/FRelationCommand.java +++ b/src/com/massivecraft/factions/commands/FRelationCommand.java @@ -5,7 +5,7 @@ import org.bukkit.ChatColor; import com.massivecraft.factions.Conf; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; @@ -38,8 +38,8 @@ public class FRelationCommand extends FBaseCommand { return; } - if (otherFaction.getId() == 0) { - sendMessage("Nope! You can't :) The default faction is not a real faction."); + if (!otherFaction.isNormal()) { + sendMessage("Nope! You can't :) You can only ally with player factions."); return; } diff --git a/src/com/massivecraft/factions/Econ.java b/src/com/massivecraft/factions/integration/Econ.java similarity index 68% rename from src/com/massivecraft/factions/Econ.java rename to src/com/massivecraft/factions/integration/Econ.java index 32c9918c..31f0d369 100644 --- a/src/com/massivecraft/factions/Econ.java +++ b/src/com/massivecraft/factions/integration/Econ.java @@ -1,16 +1,22 @@ -package com.massivecraft.factions; +package com.massivecraft.factions.integration; import org.bukkit.event.Event; import org.bukkit.plugin.Plugin; import com.massivecraft.factions.listeners.FactionsServerListener; +import com.massivecraft.factions.commands.FCommandHelp; import com.earth2me.essentials.api.Economy; +import com.nijikokun.register.payment.Methods; +import com.nijikokun.register.payment.Method.MethodAccount; import com.iConomy.*; import com.iConomy.system.*; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.Factions; public class Econ { + private static boolean registerUse = false; private static boolean iConomyUse = false; private static boolean essEcoUse = false; @@ -24,6 +30,12 @@ public class Econ { return; } + if (!registerHooked()) { + Plugin plug = factions.getServer().getPluginManager().getPlugin("Register"); + if (plug != null && plug.getClass().getName().equals("com.nijikokun.register.Register") && plug.isEnabled()) { + registerSet(true); + } + } if (!iConomyHooked()) { Plugin plug = factions.getServer().getPluginManager().getPlugin("iConomy"); if (plug != null && plug.getClass().getName().equals("com.iConomy.iConomy") && plug.isEnabled()) { @@ -38,24 +50,41 @@ public class Econ { } } + public static void registerSet(boolean enable) { + registerUse = enable; + if (enable) { + Factions.log("Register hook available, "+(Conf.econRegisterEnabled ? "and interface is enabled" : "but disabled (\"econRegisterEnabled\": false)")+"."); + } + else { + Factions.log("Un-hooked from Register."); + } + FCommandHelp.updateHelp(); + } + public static void iConomySet(boolean enable) { iConomyUse = enable; - if (enable) { + if (enable && !registerUse) { Factions.log("iConomy hook available, "+(Conf.econIConomyEnabled ? "and interface is enabled" : "but disabled (\"econIConomyEnabled\": false)")+"."); } else { Factions.log("Un-hooked from iConomy."); } + FCommandHelp.updateHelp(); } public static void essentialsEcoSet(boolean enable) { essEcoUse = enable; - if (enable) { + if (enable && !registerUse) { Factions.log("EssentialsEco hook available, "+(Conf.econEssentialsEcoEnabled ? "and interface is enabled" : "but disabled (\"econEssentialsEcoEnabled\": false)")+"."); } else { Factions.log("Un-hooked from EssentialsEco."); } + FCommandHelp.updateHelp(); + } + + public static boolean registerHooked() { + return registerUse; } public static boolean iConomyHooked() { @@ -66,9 +95,15 @@ public class Econ { return essEcoUse; } + public static boolean registerAvailable() { + return Conf.econRegisterEnabled && registerUse && Methods.hasMethod(); + } + // If economy is enabled in conf.json, and we're successfully hooked into an economy plugin public static boolean enabled() { - return (Conf.econIConomyEnabled && iConomyUse) || (Conf.econEssentialsEcoEnabled && essEcoUse); + return (Conf.econRegisterEnabled && registerUse && Methods.hasMethod()) + || (Conf.econIConomyEnabled && iConomyUse) + || (Conf.econEssentialsEcoEnabled && essEcoUse); } // mainly for internal use, for a little less code repetition @@ -84,11 +119,23 @@ public class Econ { Holdings holdings = account.getHoldings(); return holdings; } + public static MethodAccount getRegisterAccount(String playerName) { + if (!enabled()) { + return null; + } + if (!Methods.getMethod().hasAccount(playerName)) { + return null; + } + + MethodAccount account = Methods.getMethod().getAccount(playerName); + return account; + } // format money string based on server's set currency type, like "24 gold" or "$24.50" public static String moneyString(double amount) { - return iConomyUse ? iConomy.format(amount) : Economy.format(amount); + return registerAvailable() ? Methods.getMethod().format(amount) + : (iConomyUse ? iConomy.format(amount) : Economy.format(amount)); } // whether a player can afford specified amount @@ -98,7 +145,15 @@ public class Econ { return true; } - if (iConomyUse) { + if (registerAvailable()) { + MethodAccount holdings = getRegisterAccount(playerName); + if (holdings == null) { + return false; + } + + return holdings.hasEnough(amount); + } + else if (iConomyUse) { Holdings holdings = getIconomyHoldings(playerName); if (holdings == null) { return false; @@ -122,7 +177,15 @@ public class Econ { return true; } - if (iConomyUse) { + if (registerAvailable()) { + MethodAccount holdings = getRegisterAccount(playerName); + if (holdings == null || !holdings.hasEnough(amount)) { + return false; + } + + return holdings.subtract(amount); + } + else if (iConomyUse) { Holdings holdings = getIconomyHoldings(playerName); if (holdings == null || !holdings.hasEnough(amount)) { return false; @@ -151,7 +214,15 @@ public class Econ { return true; } - if (iConomyUse) { + if (registerAvailable()) { + MethodAccount holdings = getRegisterAccount(playerName); + if (holdings == null) { + return false; + } + + return holdings.add(amount); + } + else if (iConomyUse) { Holdings holdings = getIconomyHoldings(playerName); if (holdings == null) { return false; diff --git a/src/com/massivecraft/factions/integration/EssentialsFeatures.java b/src/com/massivecraft/factions/integration/EssentialsFeatures.java new file mode 100644 index 00000000..cbb212cc --- /dev/null +++ b/src/com/massivecraft/factions/integration/EssentialsFeatures.java @@ -0,0 +1,41 @@ +package com.massivecraft.factions.integration; + +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerChatEvent; +import org.bukkit.plugin.Plugin; + +import com.massivecraft.factions.Factions; + +import com.earth2me.essentials.chat.EssentialsChat; +import com.earth2me.essentials.chat.IEssentialsChatListener; + + +public class EssentialsFeatures { + private static EssentialsChat essChat; + + public static void integrateChat(EssentialsChat instance) { + essChat = instance; + try { + essChat.addEssentialsChatListener("Factions", new IEssentialsChatListener() { + public boolean shouldHandleThisChat(PlayerChatEvent event) + { + return Factions.instance.shouldLetFactionsHandleThisChat(event); + } + public String modifyMessage(PlayerChatEvent event, Player target, String message) + { + return message.replace("{FACTION}", Factions.instance.getPlayerFactionTagRelation(event.getPlayer(), target)).replace("{FACTION_TITLE}", Factions.instance.getPlayerTitle(event.getPlayer())); + } + }); + Factions.log("Found and will integrate chat with "+essChat.getDescription().getFullName()); + } + catch (NoSuchMethodError ex) { + essChat = null; + } + } + + public static void unhookChat() { + if (essChat != null) { + essChat.removeEssentialsChatListener("Factions"); + } + } +} diff --git a/src/com/massivecraft/factions/SpoutFeatures.java b/src/com/massivecraft/factions/integration/SpoutFeatures.java similarity index 62% rename from src/com/massivecraft/factions/SpoutFeatures.java rename to src/com/massivecraft/factions/integration/SpoutFeatures.java index 7a9335e0..d1ff0aa6 100644 --- a/src/com/massivecraft/factions/SpoutFeatures.java +++ b/src/com/massivecraft/factions/integration/SpoutFeatures.java @@ -1,32 +1,33 @@ -package com.massivecraft.factions; +package com.massivecraft.factions.integration; +import com.massivecraft.factions.Board; +import com.massivecraft.factions.Conf; +import com.massivecraft.factions.FLocation; +import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; +import com.massivecraft.factions.Factions; +import java.util.HashMap; +import java.util.Map; import java.util.Set; -import org.bukkit.plugin.Plugin; +import org.bukkit.ChatColor; import org.bukkit.entity.Player; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.struct.Role; +import org.getspout.spoutapi.gui.Color; +import org.getspout.spoutapi.gui.GenericLabel; import org.getspout.spoutapi.player.AppearanceManager; import org.getspout.spoutapi.player.SpoutPlayer; import org.getspout.spoutapi.SpoutManager; +import org.getspout.spoutapi.gui.WidgetAnchor; public class SpoutFeatures { private transient static AppearanceManager spoutApp; private transient static boolean spoutMe = false; - - public static void setup(Factions factions) { - Plugin test = factions.getServer().getPluginManager().getPlugin("Spout"); - - if (test != null && test.isEnabled()) { - setAvailable(true, test.getDescription().getFullName()); - } - else { - setAvailable(false, ""); - } - } + private transient static Map territoryLabels = new HashMap(); // set integration availability public static void setAvailable(boolean enable, String pluginName) { @@ -47,10 +48,57 @@ public class SpoutFeatures { || Conf.spoutFactionTitlesOverNames || Conf.spoutFactionAdminCapes || Conf.spoutFactionModeratorCapes + || Conf.spoutTerritoryDisplayPosition > 0 ); } + // update displayed current territory for specified player; returns false if unsuccessful + public static boolean updateTerritoryDisplay(FPlayer player) { + if (!spoutMe || Conf.spoutTerritoryDisplayPosition == 0) { + return false; + } + + SpoutPlayer sPlayer = SpoutManager.getPlayer(player.getPlayer()); + if (!sPlayer.isSpoutCraftEnabled()) { + return false; + } + + GenericLabel label; + if (territoryLabels.containsKey(player.getName())) { + label = territoryLabels.get(player.getName()); + } + else { + label = new GenericLabel(); + sPlayer.getMainScreen().attachWidget(Factions.instance, label); + switch (Conf.spoutTerritoryDisplayPosition) { + case 1: label.setAlign(WidgetAnchor.TOP_LEFT).setAnchor(WidgetAnchor.TOP_LEFT); break; + case 2: label.setAlign(WidgetAnchor.TOP_CENTER).setAnchor(WidgetAnchor.TOP_CENTER); break; + default: label.setAlign(WidgetAnchor.TOP_RIGHT).setAnchor(WidgetAnchor.TOP_RIGHT); + } + territoryLabels.put(player.getName(), label); + } + + Faction factionHere = Board.getFactionAt(new FLocation(player)); + String msg = factionHere.getTag(); + if (factionHere.getDescription().length() > 0) { + msg += " - "+factionHere.getDescription(); + } + label.setTextColor(getSpoutColor(player.getRelationColor(factionHere), 0)); + label.setText(msg); + label.setDirty(true); + + return true; + } + + public static void playerDisconnect(FPlayer player) { + if (!enabled()) { + return; + } + territoryLabels.remove(player.getName()); + } + + // update all appearances between every player public static void updateAppearances() { if (!enabled()) { @@ -186,4 +234,28 @@ public class SpoutFeatures { } } + // method to convert a Bukkit ChatColor to a Spout Color + private static Color getSpoutColor(ChatColor inColor, int alpha) { + if (inColor == null) { + return new Color(191, 191, 191, alpha); + } + switch (inColor.getCode()) { + case 0x1: return new Color(0, 0, 191, alpha); + case 0x2: return new Color(0, 191, 0, alpha); + case 0x3: return new Color(0, 191, 191, alpha); + case 0x4: return new Color(191, 0, 0, alpha); + case 0x5: return new Color(191, 0, 191, alpha); + case 0x6: return new Color(191, 191, 0, alpha); + case 0x7: return new Color(191, 191, 191, alpha); + case 0x8: return new Color(64, 64, 64, alpha); + case 0x9: return new Color(64, 64, 255, alpha); + case 0xA: return new Color(64, 255, 64, alpha); + case 0xB: return new Color(64, 255, 255, alpha); + case 0xC: return new Color(255, 64, 64, alpha); + case 0xD: return new Color(255, 64, 255, alpha); + case 0xE: return new Color(255, 255, 64, alpha); + case 0xF: return new Color(255, 255, 255, alpha); + default: return new Color(0, 0, 0, alpha); + } + } } diff --git a/src/com/massivecraft/factions/Worldguard.java b/src/com/massivecraft/factions/integration/Worldguard.java similarity index 94% rename from src/com/massivecraft/factions/Worldguard.java rename to src/com/massivecraft/factions/integration/Worldguard.java index adb79b91..0bb640bf 100644 --- a/src/com/massivecraft/factions/Worldguard.java +++ b/src/com/massivecraft/factions/integration/Worldguard.java @@ -1,5 +1,6 @@ -package com.massivecraft.factions; +package com.massivecraft.factions.integration; +import com.massivecraft.factions.Factions; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/src/com/massivecraft/factions/listeners/FactionsBlockListener.java b/src/com/massivecraft/factions/listeners/FactionsBlockListener.java index ed22ac05..9197b31e 100644 --- a/src/com/massivecraft/factions/listeners/FactionsBlockListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsBlockListener.java @@ -35,7 +35,7 @@ public class FactionsBlockListener extends BlockListener { return; } - if ( ! this.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock(), "build")) { + if ( ! this.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "build", false)) { event.setCancelled(true); } } @@ -46,7 +46,7 @@ public class FactionsBlockListener extends BlockListener { return; } - if ( ! this.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock(), "destroy")) { + if ( ! this.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { event.setCancelled(true); } } @@ -57,7 +57,7 @@ public class FactionsBlockListener extends BlockListener { return; } - if (event.getInstaBreak() && ! this.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock(), "destroy")) { + if (event.getInstaBreak() && ! this.playerCanBuildDestroyBlock(event.getPlayer(), event.getBlock().getLocation(), "destroy", false)) { event.setCancelled(true); } } @@ -148,35 +148,41 @@ public class FactionsBlockListener extends BlockListener { return true; } - public boolean playerCanBuildDestroyBlock(Player player, Block block, String action) { + public static boolean playerCanBuildDestroyBlock(Player player, Location location, String action, boolean justCheck) { if (Conf.adminBypassPlayers.contains(player.getName())) { return true; } - FLocation loc = new FLocation(block); + FLocation loc = new FLocation(location); Faction otherFaction = Board.getFactionAt(loc); FPlayer me = FPlayer.get(player); if (otherFaction.isNone()) { - if (!Conf.wildernessDenyBuild || Factions.hasPermAdminBypass(player) || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) { + if (!Conf.wildernessDenyBuild || Factions.hasPermAdminBypass(player) || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) { return true; // This is not faction territory. Use whatever you like here. } - me.sendMessage("You can't "+action+" in the wilderness."); + if (!justCheck) { + me.sendMessage("You can't "+action+" in the wilderness."); + } return false; } else if (otherFaction.isSafeZone()) { if (!Conf.safeZoneDenyBuild || Factions.hasPermManageSafeZone(player)) { return true; } - me.sendMessage("You can't "+action+" in a safe zone."); + if (!justCheck) { + me.sendMessage("You can't "+action+" in a safe zone."); + } return false; } else if (otherFaction.isWarZone()) { if (!Conf.warZoneDenyBuild || Factions.hasPermManageWarZone(player)) { return true; } - me.sendMessage("You can't "+action+" in a war zone."); + if (!justCheck) { + me.sendMessage("You can't "+action+" in a war zone."); + } return false; } @@ -187,7 +193,7 @@ public class FactionsBlockListener extends BlockListener { // Cancel and/or cause pain (depending on configuration) if we are not in our own territory if (!rel.isMember()) { boolean online = otherFaction.hasPlayersOnline(); - boolean pain = rel.confPainBuild(online); + boolean pain = (!justCheck) && rel.confPainBuild(online); boolean deny = rel.confDenyBuild(online); //hurt the player for building/destroying? @@ -201,21 +207,24 @@ public class FactionsBlockListener extends BlockListener { } } if (deny) { - me.sendMessage("You can't "+action+" in the territory of "+otherFaction.getTag(myFaction)); + if (!justCheck) { + me.sendMessage("You can't "+action+" in the territory of "+otherFaction.getTag(myFaction)); + } return false; } } // Also cancel and/or cause pain if player doesn't have ownership rights for this claim - if (ownershipFail && !Factions.hasPermOwnershipBypass(player) - ) { - if (Conf.ownedAreaPainBuild){ + else if (rel.isMember() && ownershipFail && !Factions.hasPermOwnershipBypass(player)) { + if (Conf.ownedAreaPainBuild && !justCheck){ player.damage(Conf.actionDeniedPainAmount); if (!Conf.ownedAreaDenyBuild) { me.sendMessage("You are hurt for "+action+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); } } if (Conf.ownedAreaDenyBuild){ - me.sendMessage("You can't "+action+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + if (!justCheck) { + me.sendMessage("You can't "+action+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + } return false; } } diff --git a/src/com/massivecraft/factions/listeners/FactionsChatEarlyListener.java b/src/com/massivecraft/factions/listeners/FactionsChatEarlyListener.java index 07bcd569..cc15b8a9 100644 --- a/src/com/massivecraft/factions/listeners/FactionsChatEarlyListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsChatEarlyListener.java @@ -11,7 +11,10 @@ import org.bukkit.event.player.PlayerListener; import com.massivecraft.factions.Conf; import com.massivecraft.factions.FPlayer; +import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; +import com.massivecraft.factions.struct.ChatMode; +import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.util.TextUtil; @@ -45,12 +48,31 @@ public class FactionsChatEarlyListener extends PlayerListener{ FPlayer me = FPlayer.get(talkingPlayer); // Is it a faction chat message? - if (me.isFactionChatting()) { + if (me.getChatMode() == ChatMode.FACTION) { + String message = String.format(Conf.factionChatFormat, me.getNameAndRelevant(me), msg); me.getFaction().sendMessage(message); Logger.getLogger("Minecraft").info(ChatColor.stripColor("FactionChat "+me.getFaction().getTag()+": "+message)); event.setCancelled(true); return; + + } else if (me.getChatMode() == ChatMode.ALLIANCE ) { + Faction myFaction = me.getFaction(); + + String factionAndName = ChatColor.stripColor(me.getNameAndTag()); + String message = Conf.colorAlly+factionAndName+ChatColor.WHITE+" "+msg; + + //Send message to our own faction + myFaction.sendMessage(message); + for (FPlayer fplayer : FPlayer.getAllOnline()) { + if(myFaction.getRelation(fplayer) == Relation.ALLY) { + //Send to all our allies + fplayer.sendMessage(message); + } + } + Logger.getLogger("Minecraft").info(ChatColor.stripColor("AllianceChat "+me.getFaction().getTag()+": "+message)); + event.setCancelled(true); + return; } } } diff --git a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java index 4f22ff2c..83a6a9f0 100644 --- a/src/com/massivecraft/factions/listeners/FactionsEntityListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsEntityListener.java @@ -10,6 +10,8 @@ import org.bukkit.entity.Fireball; import org.bukkit.entity.Player; import org.bukkit.entity.Projectile; import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.entity.EndermanPickupEvent; +import org.bukkit.event.entity.EndermanPlaceEvent; import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.EntityDeathEvent; @@ -204,21 +206,23 @@ public class FactionsEntityListener extends EntityListener { return true; } - if (!attacker.hasFaction() && Conf.disablePVPForFactionlessPlayers) { + Faction defendFaction = defender.getFaction(); + Faction attackFaction = attacker.getFaction(); + + if (attackFaction.isNone() && Conf.disablePVPForFactionlessPlayers) { attacker.sendMessage("You can't hurt other players until you join a faction."); return false; } - else if (defLocFaction == attacker.getFaction() && Conf.enablePVPAgainstFactionlessInAttackersLand) { - // Allow PVP vs. Factionless in attacker's faction territory - return true; + else if (defendFaction.isNone()) { + if (defLocFaction == attackFaction && Conf.enablePVPAgainstFactionlessInAttackersLand) { + // Allow PVP vs. Factionless in attacker's faction territory + return true; + } + else if (Conf.disablePVPForFactionlessPlayers) { + attacker.sendMessage("You can't hurt players who are not currently in a faction."); + return false; + } } - else if (!defender.hasFaction() && Conf.disablePVPForFactionlessPlayers) { - attacker.sendMessage("You can't hurt players who are not currently in a faction."); - return false; - } - - Faction defendFaction = defender.getFaction(); - Faction attackFaction = attacker.getFaction(); if (defendFaction.isPeaceful()) { attacker.sendMessage("You can't hurt players who are in a peaceful faction."); @@ -380,11 +384,66 @@ public class FactionsEntityListener extends EntityListener { return false; } // Also cancel if player doesn't have ownership rights for this claim - else if (ownershipFail && (!rel.isMember() || !Factions.hasPermOwnershipBypass(player))) { + else if (rel.isMember() && ownershipFail && !Factions.hasPermOwnershipBypass(player)) { me.sendMessage("You can't "+action+" paintings in this territory, it is owned by: "+otherFaction.getOwnerListString(loc)); return false; } return true; } + + @Override + public void onEndermanPickup(EndermanPickupEvent event) { + if (event.isCancelled()) { + return; + } + + if (stopEndermanBlockManipulation(event.getBlock().getLocation())) { + event.setCancelled(true); + } + } + + @Override + public void onEndermanPlace(EndermanPlaceEvent event) { + if (event.isCancelled()) { + return; + } + + if (stopEndermanBlockManipulation(event.getLocation())) { + event.setCancelled(true); + } + } + + private boolean stopEndermanBlockManipulation(Location loc) { + if (loc == null) { + return false; + } + // quick check to see if all Enderman deny options are enabled; if so, no need to check location + if ( Conf.wildernessDenyEndermanBlocks + && Conf.territoryDenyEndermanBlocks + && Conf.territoryDenyEndermanBlocksWhenOffline + && Conf.safeZoneDenyEndermanBlocks + && Conf.warZoneDenyEndermanBlocks + ) { + return true; + } + + FLocation fLoc = new FLocation(loc); + Faction claimFaction = Board.getFactionAt(fLoc); + + if (claimFaction.isNone()) { + return Conf.wildernessDenyEndermanBlocks; + } + else if (claimFaction.isNormal()) { + return claimFaction.hasPlayersOnline() ? Conf.territoryDenyEndermanBlocks : Conf.territoryDenyEndermanBlocksWhenOffline; + } + else if (claimFaction.isSafeZone()) { + return Conf.safeZoneDenyEndermanBlocks; + } + else if (claimFaction.isWarZone()) { + return Conf.warZoneDenyEndermanBlocks; + } + + return false; + } } diff --git a/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java b/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java index 9762bf2f..57d18b20 100644 --- a/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsPlayerListener.java @@ -17,6 +17,7 @@ import org.bukkit.event.player.PlayerChatEvent; import org.bukkit.event.player.PlayerCommandPreprocessEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerListener; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; @@ -24,12 +25,12 @@ import org.bukkit.event.player.PlayerRespawnEvent; import com.massivecraft.factions.Board; import com.massivecraft.factions.Conf; -import com.massivecraft.factions.Econ; +import com.massivecraft.factions.integration.Econ; import com.massivecraft.factions.FLocation; import com.massivecraft.factions.FPlayer; import com.massivecraft.factions.Faction; import com.massivecraft.factions.Factions; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.SpoutFeatures; import com.massivecraft.factions.struct.Role; import com.massivecraft.factions.struct.Relation; import com.massivecraft.factions.util.TextUtil; @@ -107,6 +108,8 @@ public class FactionsPlayerListener extends PlayerListener{ Factions.log(Level.SEVERE, "Critical error in chat message formatting! Complete format string: "+yourFormat); Factions.log(Level.SEVERE, "First half of event.getFormat() string: "+formatStart); Factions.log(Level.SEVERE, "Second half of event.getFormat() string: "+formatEnd); + Factions.log(Level.SEVERE, "NOTE: To fix this quickly, running this command should work: f config chatTagInsertIndex 0"); + Factions.log(Level.SEVERE, "For a more proper fix, please read the chat configuration notes on the configuration page of the Factions user guide."); ex.printStackTrace(); return; } @@ -123,10 +126,8 @@ public class FactionsPlayerListener extends PlayerListener{ @Override public void onPlayerJoin(PlayerJoinEvent event) { - final Player player = event.getPlayer(); - // Make sure that all online players do have a fplayer. - FPlayer me = FPlayer.get(player); + final FPlayer me = FPlayer.get(event.getPlayer()); // Update the lastLoginTime for this fplayer me.setLastLoginTime(System.currentTimeMillis()); @@ -135,12 +136,15 @@ public class FactionsPlayerListener extends PlayerListener{ FPlayer.autoLeaveOnInactivityRoutine(); FPlayer.autoLeaveOnInactivityRoutine(); + SpoutFeatures.updateTerritoryDisplay(me); + // Appearance updates which are run when a player joins don't apply properly for other clients, so they need to be delayed slightly Factions.instance.getServer().getScheduler().scheduleSyncDelayedTask(Factions.instance, new Runnable() { public void run() { - SpoutFeatures.updateAppearances(player); + SpoutFeatures.updateAppearances(me.getPlayer()); + SpoutFeatures.updateTerritoryDisplay(me); } - }); + }, 20); } @Override @@ -152,6 +156,7 @@ public class FactionsPlayerListener extends PlayerListener{ if (myFaction != null) { myFaction.memberLoggedOff(); } + SpoutFeatures.playerDisconnect(me); } @Override @@ -215,11 +220,6 @@ public class FactionsPlayerListener extends PlayerListener{ me.sendMessage("You can't claim more land! You need more power!"); me.enableAutoClaim(false); } - else if (!Econ.canAfford(player.getName(), cost)) { - String costString = Econ.moneyString(cost); - me.sendMessage("Claiming this land will cost "+costString+", which you can't currently afford."); - me.enableAutoClaim(false); - } else me.attemptClaim(false); } @@ -262,7 +262,7 @@ public class FactionsPlayerListener extends PlayerListener{ return; // clicked in air, apparently } - if ( ! canPlayerUseBlock(player, block)) { + if ( ! canPlayerUseBlock(player, block, false)) { event.setCancelled(true); return; } @@ -271,19 +271,19 @@ public class FactionsPlayerListener extends PlayerListener{ return; // only interested on right-clicks for below } - if ( ! this.playerCanUseItemHere(player, block, event.getMaterial())) { + if ( ! this.playerCanUseItemHere(player, block.getLocation(), event.getMaterial(), false)) { event.setCancelled(true); return; } } - public boolean playerCanUseItemHere(Player player, Block block, Material material) { + public static boolean playerCanUseItemHere(Player player, Location location, Material material, boolean justCheck) { if (Conf.adminBypassPlayers.contains(player.getName())) { return true; } - FLocation loc = new FLocation(block); + FLocation loc = new FLocation(location); Faction otherFaction = Board.getFactionAt(loc); if (otherFaction.hasPlayersOnline()){ @@ -299,24 +299,30 @@ public class FactionsPlayerListener extends PlayerListener{ FPlayer me = FPlayer.get(player); if (otherFaction.isNone()) { - if (!Conf.wildernessDenyUseage || Factions.hasPermAdminBypass(player) || Conf.worldsNoWildernessProtection.contains(block.getWorld().getName())) { + if (!Conf.wildernessDenyUseage || Factions.hasPermAdminBypass(player) || Conf.worldsNoWildernessProtection.contains(location.getWorld().getName())) { return true; // This is not faction territory. Use whatever you like here. } - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the wilderness."); + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the wilderness."); + } return false; } else if (otherFaction.isSafeZone()) { if (!Conf.safeZoneDenyUseage || Factions.hasPermManageSafeZone(player)) { return true; } - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a safe zone."); + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a safe zone."); + } return false; } else if (otherFaction.isWarZone()) { if (!Conf.warZoneDenyUseage || Factions.hasPermManageWarZone(player)) { return true; } - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a war zone."); + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in a war zone."); + } return false; } @@ -326,19 +332,23 @@ public class FactionsPlayerListener extends PlayerListener{ // Cancel if we are not in our own territory if (!rel.isMember() && rel.confDenyUseage()) { - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); + } return false; } // Also cancel if player doesn't have ownership rights for this claim - else if (ownershipFail && (!rel.isMember() || !Factions.hasPermOwnershipBypass(player))) { - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + else if (rel.isMember() && ownershipFail && !Factions.hasPermOwnershipBypass(player)) { + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + } return false; } return true; } - public boolean canPlayerUseBlock(Player player, Block block) { + public static boolean canPlayerUseBlock(Player player, Block block, boolean justCheck) { if (Conf.adminBypassPlayers.contains(player.getName())) { return true; @@ -347,7 +357,12 @@ public class FactionsPlayerListener extends PlayerListener{ Material material = block.getType(); FLocation loc = new FLocation(block); Faction otherFaction = Board.getFactionAt(loc); - + + // no door/chest/whatever protection in wilderness, war zones, or safe zones + if (!otherFaction.isNormal()) { + return true; + } + // We only care about some material types. if (otherFaction.hasPlayersOnline()){ if ( ! Conf.territoryProtectedMaterials.contains(material)) { @@ -365,13 +380,17 @@ public class FactionsPlayerListener extends PlayerListener{ boolean ownershipFail = Conf.ownedAreasEnabled && Conf.ownedAreaProtectMaterials && !otherFaction.playerHasOwnershipRights(me, loc); // You may use any block unless it is another faction's territory... - if ((rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials)) { - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); + if (rel.isNeutral() || (rel.isEnemy() && Conf.territoryEnemyProtectMaterials) || (rel.isAlly() && Conf.territoryAllyProtectMaterials)) { + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in the territory of "+otherFaction.getTag(myFaction)); + } return false; } // Also cancel if player doesn't have ownership rights for this claim - else if (ownershipFail && (!rel.isMember() || !Factions.hasPermOwnershipBypass(player))) { - me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + else if (rel.isMember() && ownershipFail && !Factions.hasPermOwnershipBypass(player)) { + if (!justCheck) { + me.sendMessage("You can't use "+TextUtil.getMaterialName(material)+" in this territory, it is owned by: "+myFaction.getOwnerListString(loc)); + } return false; } @@ -400,7 +419,7 @@ public class FactionsPlayerListener extends PlayerListener{ Block block = event.getBlockClicked(); Player player = event.getPlayer(); - if ( ! this.playerCanUseItemHere(player, block, event.getBucket())) { + if ( ! this.playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { event.setCancelled(true); return; } @@ -414,7 +433,7 @@ public class FactionsPlayerListener extends PlayerListener{ Block block = event.getBlockClicked(); Player player = event.getPlayer(); - if ( ! this.playerCanUseItemHere(player, block, event.getBucket())) { + if ( ! this.playerCanUseItemHere(player, block.getLocation(), event.getBucket(), false)) { event.setCancelled(true); return; } @@ -494,4 +513,23 @@ public class FactionsPlayerListener extends PlayerListener{ return false; } + @Override + public void onPlayerKick(PlayerKickEvent event) { + if (event.isCancelled()) { + return; + } + + FPlayer badGuy = FPlayer.get(event.getPlayer()); + if (badGuy == null) { + return; + } + + SpoutFeatures.playerDisconnect(badGuy); + + // if player was banned (not just kicked), get rid of their stored info + if (event.getReason().equals("Banned by admin.")) { + badGuy.leave(false); + badGuy.markForDeletion(true); + } + } } diff --git a/src/com/massivecraft/factions/listeners/FactionsServerListener.java b/src/com/massivecraft/factions/listeners/FactionsServerListener.java index e394d024..d5bbdded 100644 --- a/src/com/massivecraft/factions/listeners/FactionsServerListener.java +++ b/src/com/massivecraft/factions/listeners/FactionsServerListener.java @@ -5,17 +5,20 @@ import org.bukkit.event.server.ServerListener; import org.bukkit.event.server.PluginDisableEvent; import org.bukkit.event.server.PluginEnableEvent; -import com.massivecraft.factions.Econ; -import com.massivecraft.factions.SpoutFeatures; +import com.massivecraft.factions.integration.Econ; +import com.massivecraft.factions.integration.SpoutFeatures; public class FactionsServerListener extends ServerListener { - @Override - public void onPluginDisable(PluginDisableEvent event) { + @Override + public void onPluginDisable(PluginDisableEvent event) { String name = event.getPlugin().getDescription().getName(); - if (Econ.iConomyHooked() && name.equals("iConomy")) { + if (Econ.registerHooked() && name.equals("Register")) { + Econ.registerSet(false); + } + else if (Econ.iConomyHooked() && name.equals("iConomy")) { Econ.iConomySet(false); - } + } else if (Econ.essentialsEcoHooked() && name.equals("Essentials")) { Econ.essentialsEcoSet(false); } @@ -24,18 +27,21 @@ public class FactionsServerListener extends ServerListener { } } - @Override - public void onPluginEnable(PluginEnableEvent event) { + @Override + public void onPluginEnable(PluginEnableEvent event) { Plugin plug = event.getPlugin(); String name = plug.getDescription().getName(); - if (!Econ.iConomyHooked() && name.equals("iConomy") && plug.getClass().getName().equals("com.iConomy.iConomy")) { + if (!Econ.registerHooked() && name.equals("Register") && plug.getClass().getName().equals("com.nijikokun.register.Register")) { + Econ.registerSet(true); + } + else if (!Econ.iConomyHooked() && name.equals("iConomy") && plug.getClass().getName().equals("com.iConomy.iConomy")) { Econ.iConomySet(true); } else if (!Econ.essentialsEcoHooked() && name.equals("Essentials")) { Econ.essentialsEcoSet(true); - } + } else if (name.equals("Spout")) { SpoutFeatures.setAvailable(true, plug.getDescription().getFullName()); } - } + } } \ No newline at end of file diff --git a/src/com/massivecraft/factions/struct/ChatMode.java b/src/com/massivecraft/factions/struct/ChatMode.java new file mode 100644 index 00000000..86fb9fd7 --- /dev/null +++ b/src/com/massivecraft/factions/struct/ChatMode.java @@ -0,0 +1,28 @@ +package com.massivecraft.factions.struct; + +public enum ChatMode { + FACTION(2, "faction chat"), + ALLIANCE(1, "alliance chat"), + PUBLIC(0, "public chat"); + + public final int value; + public final String nicename; + + private ChatMode(final int value, final String nicename) { + this.value = value; + this.nicename = nicename; + } + + public boolean isAtLeast(ChatMode role) { + return this.value >= role.value; + } + + public boolean isAtMost(ChatMode role) { + return this.value <= role.value; + } + + @Override + public String toString() { + return this.nicename; + } +} diff --git a/src/plugin.yml b/src/plugin.yml index a6eed97c..3060ead1 100644 --- a/src/plugin.yml +++ b/src/plugin.yml @@ -1,5 +1,5 @@ name: Factions -version: 1.4.7 +version: 1.5.1_dev main: com.massivecraft.factions.Factions softdepend: - Permissions @@ -12,6 +12,7 @@ softdepend: - ChatManager - AuthMe - iConomy + - Register - Spout - WorldEdit - WorldGuard @@ -26,6 +27,7 @@ permissions: factions.participate: true factions.create: true factions.viewAnyPower: true + factions.viewAnyFactionBalance: true factions.peacefulExplosionToggle: true factions.adminBypass: true factions.config: true @@ -37,6 +39,7 @@ permissions: factions.reload: true factions.saveall: true factions.setPeaceful: true + factions.setPermanent: true factions.commandDisable.none: true factions.participate: description: Allows the player to participate in a faction @@ -47,6 +50,9 @@ permissions: factions.viewAnyPower: description: Allows the player to view the power level of anyone else default: true + factions.viewAnyFactionBalance: + description: Allows the player to view the faction bank balance for any faction + default: true factions.peacefulExplosionToggle: description: Allows peaceful faction admins and moderators to disable explosions in their territory default: true @@ -80,6 +86,9 @@ permissions: factions.setPeaceful: description: Can designate specific factions as "peaceful" (no PvP, no land stealing, etc.) default: op + factions.setPermanent: + description: Can designate specific factions as permanent (not disbanded even with no members) + default: op factions.commandDisable.none: description: no commands disabled (ignore all other commandDisable permissions) default: op @@ -95,6 +104,9 @@ permissions: factions.commandDisable.autowar: description: autowar command disabled default: false + factions.commandDisable.balance: + description: balance/money command disabled + default: false factions.commandDisable.bypass: description: bypass command disabled default: false @@ -116,6 +128,9 @@ permissions: factions.commandDisable.deinv: description: deinvite command disabled default: false + factions.commandDisable.deposit: + description: deposit command disabled + default: false factions.commandDisable.desc: description: desc command disabled default: false @@ -164,6 +179,9 @@ permissions: factions.commandDisable.mod: description: mod command disabled default: false + factions.commandDisable.money: + description: balance/money command disabled + default: false factions.commandDisable.noboom: description: noboom command disabled default: false @@ -179,9 +197,15 @@ permissions: factions.commandDisable.ownerlist: description: ownerlist command disabled default: false + factions.commandDisable.pay: + description: pay command disabled + default: false factions.commandDisable.peaceful: description: peaceful command disabled default: false + factions.commandDisable.permanent: + description: permanent command disabled + default: false factions.commandDisable.power: description: power command disabled default: false @@ -260,6 +284,9 @@ permissions: factions.commandDisable.wardeclaimall: description: warunclaimall command disabled default: false + factions.commandDisable.withdraw: + description: withdraw command disabled + default: false factions.commandDisable.worldnoclaim: description: worldnoclaim command disabled default: false