浏览代码

Added party alliances

Adds the following commands:
`/party alliance`
`/party alliance invite <target>`
`/party alliance accept`

Allies will share party chat and will not be able to harm eachother.
Item and XP sharing is limitied to a single party. Allowing two parties
to team up without sharing resources and XP.

Closes #1009
TfT_02 11 年之前
父节点
当前提交
c729297615
共有 37 个文件被更改,包括 607 次插入40 次删除
  1. 1 0
      Changelog.txt
  2. 13 0
      src/main/java/com/gmail/nossr50/api/PartyAPI.java
  3. 8 0
      src/main/java/com/gmail/nossr50/chat/PartyChatManager.java
  4. 4 0
      src/main/java/com/gmail/nossr50/commands/party/PartyCommand.java
  5. 4 0
      src/main/java/com/gmail/nossr50/commands/party/PartyInfoCommand.java
  6. 5 1
      src/main/java/com/gmail/nossr50/commands/party/PartySubcommandType.java
  7. 34 0
      src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceAcceptCommand.java
  8. 156 0
      src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceCommand.java
  9. 36 0
      src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceDisbandCommand.java
  10. 72 0
      src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceInviteCommand.java
  11. 1 0
      src/main/java/com/gmail/nossr50/config/Config.java
  12. 9 0
      src/main/java/com/gmail/nossr50/datatypes/party/Party.java
  13. 17 0
      src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java
  14. 90 0
      src/main/java/com/gmail/nossr50/events/party/McMMOPartyAllianceChangeEvent.java
  15. 1 1
      src/main/java/com/gmail/nossr50/listeners/EntityListener.java
  16. 101 1
      src/main/java/com/gmail/nossr50/party/PartyManager.java
  17. 1 0
      src/main/resources/config.yml
  18. 3 3
      src/main/resources/locale/locale_cs_CZ.properties
  19. 1 1
      src/main/resources/locale/locale_cy.properties
  20. 1 1
      src/main/resources/locale/locale_da.properties
  21. 1 1
      src/main/resources/locale/locale_de.properties
  22. 15 1
      src/main/resources/locale/locale_en_US.properties
  23. 3 3
      src/main/resources/locale/locale_es.properties
  24. 1 1
      src/main/resources/locale/locale_fi.properties
  25. 1 1
      src/main/resources/locale/locale_fr.properties
  26. 1 1
      src/main/resources/locale/locale_hu_HU.properties
  27. 3 3
      src/main/resources/locale/locale_it.properties
  28. 1 1
      src/main/resources/locale/locale_ja_JP.properties
  29. 1 1
      src/main/resources/locale/locale_lv.properties
  30. 3 3
      src/main/resources/locale/locale_nl.properties
  31. 3 3
      src/main/resources/locale/locale_pl.properties
  32. 3 3
      src/main/resources/locale/locale_ru.properties
  33. 1 1
      src/main/resources/locale/locale_sv.properties
  34. 3 3
      src/main/resources/locale/locale_th_TH.properties
  35. 3 3
      src/main/resources/locale/locale_zh_CN.properties
  36. 3 3
      src/main/resources/locale/locale_zh_TW.properties
  37. 3 0
      src/main/resources/plugin.yml

+ 1 - 0
Changelog.txt

@@ -16,6 +16,7 @@ Version 1.4.08-dev
  + Added automatic cleanup of backups folder.
  + Added bypass permission for finding Fishing traps
  + Added level threshold settings to hardcore modes. When a players skill level is below this threshold, they will not lose any stats
+ + Added party alliances, two parties can now team up. Allies share party chat and cannot harm each other.
  = Fixed bug where LeafBlower permissions were ignored
  = Fixed bug with toggle commands not properly displaying the success message.
  = Fixed IllegalArgumentException caused by an empty Fishing treasure category

+ 13 - 0
src/main/java/com/gmail/nossr50/api/PartyAPI.java

@@ -174,4 +174,17 @@ public final class PartyAPI {
     public static List<Player> getOnlineMembers(Player player) {
         return PartyManager.getOnlineMembers(player);
     }
+
+    public static boolean hasAlly(String partyName) {
+        return PartyManager.getParty(partyName).getAlly() != null;
+    }
+
+    public static String getAllyName(String partyName) {
+        Party ally = PartyManager.getParty(partyName).getAlly();
+        if (ally != null) {
+            return ally.getName();
+        }
+
+        return null;
+    }
 }

+ 8 - 0
src/main/java/com/gmail/nossr50/chat/PartyChatManager.java

@@ -10,6 +10,7 @@ import org.bukkit.plugin.Plugin;
 import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.datatypes.party.Party;
 import com.gmail.nossr50.events.chat.McMMOPartyChatEvent;
+import com.gmail.nossr50.locale.LocaleLoader;
 
 public class PartyChatManager extends ChatManager {
     private Party party;
@@ -37,6 +38,13 @@ public class PartyChatManager extends ChatManager {
             member.sendMessage(message);
         }
 
+        if (party.getAlly() != null) {
+            for (Player member : party.getAlly().getOnlineMembers()) {
+                String allyPrefix = LocaleLoader.formatString(Config.getInstance().getPartyChatPrefixAlly());
+                member.sendMessage(allyPrefix + message);
+            }
+        }
+
         plugin.getLogger().info("[P]<" + party.getName() + ">" + message);
     }
 }

+ 4 - 0
src/main/java/com/gmail/nossr50/commands/party/PartyCommand.java

@@ -14,6 +14,7 @@ import org.bukkit.util.StringUtil;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.commands.chat.PartyChatCommand;
+import com.gmail.nossr50.commands.party.alliance.PartyAllianceCommand;
 import com.gmail.nossr50.commands.party.teleport.PtpCommand;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.locale.LocaleLoader;
@@ -56,6 +57,7 @@ public class PartyCommand implements TabExecutor {
     private CommandExecutor partyHelpCommand           = new PartyHelpCommand();
     private CommandExecutor partyTeleportCommand       = mcMMO.p.getCommand("ptp").getExecutor();
     private CommandExecutor partyChatCommand           = new PartyChatCommand();
+    private CommandExecutor partyAllianceCommand       = new PartyAllianceCommand();
 
     @Override
     public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
@@ -150,6 +152,8 @@ public class PartyCommand implements TabExecutor {
                 return partyChangePasswordCommand.onCommand(sender, command, label, args);
             case RENAME:
                 return partyRenameCommand.onCommand(sender, command, label, args);
+            case ALLIANCE:
+                return partyAllianceCommand.onCommand(sender, command, label, args);
             default:
                 break;
         }

+ 4 - 0
src/main/java/com/gmail/nossr50/commands/party/PartyInfoCommand.java

@@ -93,6 +93,10 @@ public class PartyInfoCommand implements CommandExecutor {
     private void displayPartyHeader(Player player, Party party) {
         player.sendMessage(LocaleLoader.getString("Commands.Party.Header"));
         player.sendMessage(LocaleLoader.getString("Commands.Party.Status", party.getName(), LocaleLoader.getString("Party.Status." + (party.isLocked() ? "Locked" : "Unlocked"))));
+
+        if (party.getAlly() != null) {
+            player.sendMessage(LocaleLoader.getString("Commands.Party.Status.Alliance", party.getAlly().getName()));
+        }
     }
 
     private void displayMemberInfo(Player player, McMMOPlayer mcMMOPlayer, Party party) {

+ 5 - 1
src/main/java/com/gmail/nossr50/commands/party/PartySubcommandType.java

@@ -18,7 +18,8 @@ public enum PartySubcommandType {
     PASSWORD,
     RENAME,
     TELEPORT,
-    CHAT;
+    CHAT,
+    ALLIANCE;
 
     public static PartySubcommandType getSubcommand(String commandName) {
         for (PartySubcommandType command : values()) {
@@ -42,6 +43,9 @@ public enum PartySubcommandType {
         else if (commandName.equalsIgnoreCase("shareitem") || commandName.equalsIgnoreCase("shareitems")) {
             return ITEMSHARE;
         }
+        else if (commandName.equalsIgnoreCase("ally")) {
+            return ALLIANCE;
+        }
 
         return null;
     }

+ 34 - 0
src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceAcceptCommand.java

@@ -0,0 +1,34 @@
+package com.gmail.nossr50.commands.party.alliance;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.party.PartyManager;
+import com.gmail.nossr50.util.player.UserManager;
+
+public class PartyAllianceAcceptCommand implements CommandExecutor {
+    @Override
+    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+        switch (args.length) {
+            case 2:
+                Player player = (Player) sender;
+                McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
+
+                if (!mcMMOPlayer.hasPartyAllianceInvite()) {
+                    sender.sendMessage(LocaleLoader.getString("mcMMO.NoInvites"));
+                    return true;
+                }
+
+                PartyManager.acceptAllianceInvite(mcMMOPlayer);
+                return true;
+
+            default:
+                sender.sendMessage(LocaleLoader.getString("Commands.Usage.2", "party", "alliance", "accept"));
+                return true;
+        }
+    }
+}

+ 156 - 0
src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceCommand.java

@@ -0,0 +1,156 @@
+package com.gmail.nossr50.commands.party.alliance;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.TabExecutor;
+import org.bukkit.entity.Player;
+import org.bukkit.util.StringUtil;
+
+import com.gmail.nossr50.mcMMO;
+import com.gmail.nossr50.config.Config;
+import com.gmail.nossr50.datatypes.party.Party;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.commands.CommandUtils;
+import com.gmail.nossr50.util.player.UserManager;
+
+import com.google.common.collect.ImmutableList;
+
+public class PartyAllianceCommand implements TabExecutor {
+    private Player player;
+    private Party playerParty;
+    private Party targetParty;
+
+    public static final List<String> ALLIANCE_SUBCOMMANDS = ImmutableList.of("invite", "accept", "disband");
+
+    private CommandExecutor partyAllianceInviteCommand = new PartyAllianceInviteCommand();
+    private CommandExecutor partyAllianceAcceptCommand = new PartyAllianceAcceptCommand();
+    private CommandExecutor partyAllianceDisbandCommand = new PartyAllianceDisbandCommand();
+
+    @Override
+    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+        if (CommandUtils.noConsoleUsage(sender)) {
+            return true;
+        }
+
+        player = (Player) sender;
+        McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
+
+        playerParty = mcMMOPlayer.getParty();
+
+        switch (args.length) {
+            case 1:
+                if (playerParty.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ALLIANCE)) {
+                    sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.3"));
+                    return true;
+                }
+
+                if (playerParty.getAlly() == null) {
+                    printUsage();
+                    return true;
+                }
+
+                targetParty = playerParty.getAlly();
+
+                displayPartyHeader();
+                displayMemberInfo();
+                return true;
+
+            case 2:
+            case 3:
+                if (playerParty.getLevel() < Config.getInstance().getPartyFeatureUnlockLevel(PartyFeature.ALLIANCE)) {
+                    sender.sendMessage(LocaleLoader.getString("Party.Feature.Disabled.3"));
+                    return true;
+                }
+
+                if (args[1].equalsIgnoreCase("invite")) {
+                    return partyAllianceInviteCommand.onCommand(sender, command, label, args);
+                }
+
+                if (args[1].equalsIgnoreCase("accept")) {
+                    return partyAllianceAcceptCommand.onCommand(sender, command, label, args);
+                }
+
+                if (args[1].equalsIgnoreCase("disband")) {
+                    return partyAllianceDisbandCommand.onCommand(sender, command, label, args);
+                }
+
+                if (playerParty.getAlly() == null) {
+                    printUsage();
+                    return true;
+                }
+
+                targetParty = playerParty.getAlly();
+
+                displayPartyHeader();
+                displayMemberInfo();
+                return true;
+
+            default:
+                return false;
+        }
+    }
+
+    private boolean printUsage() {
+        player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Help.0"));
+        player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Help.1"));
+        return true;
+    }
+
+    @Override
+    public List<String> onTabComplete(CommandSender commandSender, Command command, String label, String[] args) {
+        switch (args.length) {
+            case 1:
+                List<String> matches = StringUtil.copyPartialMatches(args[0], ALLIANCE_SUBCOMMANDS, new ArrayList<String>(ALLIANCE_SUBCOMMANDS.size()));
+
+                if (matches.size() == 0) {
+                    Set<String> playerNames = UserManager.getPlayerNames();
+                    return StringUtil.copyPartialMatches(args[0], playerNames, new ArrayList<String>(playerNames.size()));
+                }
+
+                return matches;
+            default:
+                return ImmutableList.of();
+        }
+    }
+
+    private void displayPartyHeader() {
+        player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Header"));
+        player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Ally", playerParty.getName(), targetParty.getName()));
+    }
+
+    private void displayMemberInfo() {
+        player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Members.Header"));
+        player.sendMessage(createMembersList(playerParty));
+        player.sendMessage(ChatColor.DARK_GRAY + "----------------------------");
+        player.sendMessage(createMembersList(targetParty));
+    }
+
+    private String createMembersList(Party party) {
+        StringBuilder memberList = new StringBuilder();
+
+        for (String memberName : party.getMembers()) {
+            Player member = mcMMO.p.getServer().getPlayerExact(memberName);
+
+            if (party.getLeader().equalsIgnoreCase(memberName)) {
+                memberList.append(ChatColor.GOLD);
+            }
+            else if (member != null) {
+                memberList.append(ChatColor.WHITE);
+            }
+            else {
+                memberList.append(ChatColor.GRAY);
+            }
+
+            memberList.append(memberName).append(" ");
+        }
+
+        return memberList.toString();
+    }
+}

+ 36 - 0
src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceDisbandCommand.java

@@ -0,0 +1,36 @@
+package com.gmail.nossr50.commands.party.alliance;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.datatypes.party.Party;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.party.PartyManager;
+import com.gmail.nossr50.util.player.UserManager;
+
+public class PartyAllianceDisbandCommand implements CommandExecutor {
+    @Override
+    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+        switch (args.length) {
+            case 2:
+                Player player = (Player) sender;
+                McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
+                Party party = mcMMOPlayer.getParty();
+
+                if (party.getAlly() == null) {
+                    sender.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.None"));
+                    return true;
+                }
+
+                PartyManager.disbandAlliance(player, party, party.getAlly());
+                return true;
+
+            default:
+                sender.sendMessage(LocaleLoader.getString("Commands.Usage.2", "party", "alliance", "disband"));
+                return true;
+        }
+    }
+}

+ 72 - 0
src/main/java/com/gmail/nossr50/commands/party/alliance/PartyAllianceInviteCommand.java

@@ -0,0 +1,72 @@
+package com.gmail.nossr50.commands.party.alliance;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.datatypes.party.Party;
+import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.party.PartyManager;
+import com.gmail.nossr50.util.Misc;
+import com.gmail.nossr50.util.commands.CommandUtils;
+import com.gmail.nossr50.util.player.UserManager;
+
+public class PartyAllianceInviteCommand implements CommandExecutor {
+    @Override
+    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+        switch (args.length) {
+            case 3:
+                String targetName = CommandUtils.getMatchedPlayerName(args[2]);
+                McMMOPlayer mcMMOTarget = UserManager.getPlayer(targetName, true);
+
+                if (!CommandUtils.checkPlayerExistence(sender, targetName, mcMMOTarget)) {
+                    return false;
+                }
+
+                Player target = mcMMOTarget.getPlayer();
+                Player player = (Player) sender;
+                McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
+                String playerName = player.getName();
+
+                if (player.equals(target)) {
+                    sender.sendMessage(LocaleLoader.getString("Party.Invite.Self"));
+                    return true;
+                }
+
+                if (!mcMMOTarget.inParty()) {
+                    player.sendMessage(LocaleLoader.getString("Party.PlayerNotInParty", targetName));
+                    return true;
+                }
+
+                if (PartyManager.inSameParty(player, target)) {
+                    sender.sendMessage(LocaleLoader.getString("Party.Player.InSameParty", targetName));
+                    return true;
+                }
+
+                if (!mcMMOTarget.getParty().getLeader().equalsIgnoreCase(targetName)) {
+                    player.sendMessage(LocaleLoader.getString("Party.Target.NotOwner", targetName));
+                    return true;
+                }
+
+                Party playerParty = mcMMOPlayer.getParty();
+
+                if (playerParty.getAlly() != null) {
+                    player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.AlreadyAllies"));
+                    return true;
+                }
+
+                mcMMOTarget.setPartyAllianceInvite(playerParty);
+
+                sender.sendMessage(LocaleLoader.getString("Commands.Invite.Success"));
+                target.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Invite.0", playerParty.getName(), playerName));
+                target.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Invite.1"));
+                return true;
+
+            default:
+                sender.sendMessage(LocaleLoader.getString("Commands.Usage.3", "party", "alliance", "invite", "<" + LocaleLoader.getString("Commands.Usage.Player") + ">"));
+                return true;
+        }
+    }
+}

+ 1 - 0
src/main/java/com/gmail/nossr50/config/Config.java

@@ -212,6 +212,7 @@ public class Config extends AutoUpdateConfigLoader {
     public String getPartyChatPrefix() { return config.getString("Commands.partychat.Chat_Prefix_Format", "[[GREEN]]([[WHITE]]{0}[[GREEN]])"); }
     public boolean getPartyChatColorLeaderName() { return config.getBoolean("Commands.partychat.Gold_Leader_Name", true); }
     public boolean getPartyDisplayNames() { return config.getBoolean("Commands.partychat.Use_Display_Names", true); }
+    public String getPartyChatPrefixAlly() { return config.getString("Commands.partychat.Chat_Prefix_Format_Ally", "[[GREEN]](A)[[RESET]]"); }
 
     public String getAdminChatPrefix() { return config.getString("Commands.adminchat.Chat_Prefix_Format", "[[AQUA]][[[WHITE]]{0}[[AQUA]]]"); }
     public boolean getAdminDisplayNames() { return config.getBoolean("Commands.adminchat.Use_Display_Names", true); }

+ 9 - 0
src/main/java/com/gmail/nossr50/datatypes/party/Party.java

@@ -15,6 +15,7 @@ public class Party {
     private String name;
     private String password;
     private boolean locked;
+    private Party ally;
 
     private ShareMode xpShareMode   = ShareMode.NONE;
     private ShareMode itemShareMode = ShareMode.NONE;
@@ -83,6 +84,10 @@ public class Party {
         return locked;
     }
 
+    public Party getAlly() {
+        return ally;
+    }
+
     public List<String> getItemShareCategories() {
         List<String> shareCategories = new ArrayList<String>();
 
@@ -111,6 +116,10 @@ public class Party {
         this.locked = locked;
     }
 
+    public void setAlly(Party ally) {
+        this.ally = ally;
+    }
+
     public void setXpShareMode(ShareMode xpShareMode) {
         this.xpShareMode = xpShareMode;
     }

+ 17 - 0
src/main/java/com/gmail/nossr50/datatypes/player/McMMOPlayer.java

@@ -64,6 +64,7 @@ public class McMMOPlayer {
 
     private Party   party;
     private Party   invite;
+    private Party   allianceInvite;
     private int     itemShareModifier;
 
     private PartyTeleportRecord ptpRecord;
@@ -634,6 +635,22 @@ public class McMMOPlayer {
         return ptpRecord;
     }
 
+    public void setPartyAllianceInvite(Party allianceInvite) {
+        this.allianceInvite = allianceInvite;
+    }
+
+    public Party getPartyAllianceInvite() {
+        return allianceInvite;
+    }
+
+    public boolean hasPartyAllianceInvite() {
+        return (allianceInvite != null);
+    }
+
+    public void removePartyAllianceInvite() {
+        allianceInvite = null;
+    }
+
     public int getItemShareModifier() {
         if (itemShareModifier < 10) {
             setItemShareModifier(10);

+ 90 - 0
src/main/java/com/gmail/nossr50/events/party/McMMOPartyAllianceChangeEvent.java

@@ -0,0 +1,90 @@
+package com.gmail.nossr50.events.party;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.HandlerList;
+import org.bukkit.event.player.PlayerEvent;
+
+public class McMMOPartyAllianceChangeEvent extends PlayerEvent implements Cancellable {
+    private String oldAlly;
+    private String newAlly;
+    private EventReason reason;
+    private boolean cancelled;
+
+    public McMMOPartyAllianceChangeEvent(Player player, String oldAlly, String newAlly, EventReason reason) {
+        super(player);
+
+        if (newAlly != null) {
+            newAlly = newAlly.replace(":", ".");
+        }
+
+        this.oldAlly = oldAlly;
+        this.newAlly = newAlly;
+        this.reason = reason;
+        this.cancelled = false;
+    }
+
+    /**
+     * @return The party being left, or null if the player was not in a party
+     */
+    public String getOldAlly() {
+        return oldAlly;
+    }
+
+    /**
+     * @return The party being joined, or null if the player is not joining a new party
+     */
+    public String getNewAlly() {
+        return newAlly;
+    }
+
+    /**
+     * @return The reason for the event being fired
+     */
+    public EventReason getReason() {
+        return reason;
+    }
+
+    /**
+     * A list of reasons why the event may have been fired
+     */
+    public enum EventReason {
+        /**
+         * Formed an alliance for the first time.
+         */
+        FORMED_ALLIANCE,
+
+        /**
+         * Left a party and did not join a new one.
+         */
+        DISBAND_ALLIANCE,
+
+        /**
+         * Any reason that doesn't fit elsewhere.
+         */
+        CUSTOM;
+    }
+
+    /** Following are required for Cancellable **/
+    @Override
+    public boolean isCancelled() {
+        return cancelled;
+    }
+
+    @Override
+    public void setCancelled(boolean cancelled) {
+        this.cancelled = cancelled;
+    }
+
+    /** Rest of file is required boilerplate for custom events **/
+    private static final HandlerList handlers = new HandlerList();
+
+    @Override
+    public HandlerList getHandlers() {
+        return handlers;
+    }
+
+    public static HandlerList getHandlerList() {
+        return handlers;
+    }
+}

+ 1 - 1
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -179,7 +179,7 @@ public class EntityListener implements Listener {
                 return;
             }
 
-            if (PartyManager.inSameParty(defendingPlayer, attackingPlayer) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
+            if ((PartyManager.inSameParty(defendingPlayer, attackingPlayer) || PartyManager.areAllies(defendingPlayer, attackingPlayer)) && !(Permissions.friendlyFire(attackingPlayer) && Permissions.friendlyFire(defendingPlayer))) {
                 event.setCancelled(true);
                 return;
             }

+ 101 - 1
src/main/java/com/gmail/nossr50/party/PartyManager.java

@@ -16,6 +16,7 @@ import com.gmail.nossr50.datatypes.party.ItemShareType;
 import com.gmail.nossr50.datatypes.party.Party;
 import com.gmail.nossr50.datatypes.party.ShareMode;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
+import com.gmail.nossr50.events.party.McMMOPartyAllianceChangeEvent;
 import com.gmail.nossr50.events.party.McMMOPartyChangeEvent;
 import com.gmail.nossr50.events.party.McMMOPartyChangeEvent.EventReason;
 import com.gmail.nossr50.locale.LocaleLoader;
@@ -89,6 +90,17 @@ public final class PartyManager {
         return firstParty.equals(secondParty);
     }
 
+    public static boolean areAllies(Player firstPlayer, Player secondPlayer) {
+        Party firstParty = UserManager.getPlayer(firstPlayer).getParty();
+        Party secondParty = UserManager.getPlayer(secondPlayer).getParty();
+
+        if (firstParty == null || secondParty == null || firstParty.getAlly() == null || secondParty.getAlly() == null) {
+            return false;
+        }
+
+        return firstParty.equals(secondParty.getAlly()) && secondParty.equals(firstParty.getAlly());
+    }
+
     /**
      * Get the near party members.
      *
@@ -318,11 +330,71 @@ public final class PartyManager {
             return;
         }
 
-        mcMMOPlayer.getPlayer().sendMessage(LocaleLoader.getString("Commands.Invite.Accepted", invite.getName()));
+        mcMMOPlayer.getPlayer().sendMessage(LocaleLoader.getString("Commands.Party.Invite.Accepted", invite.getName()));
         mcMMOPlayer.removePartyInvite();
         addToParty(mcMMOPlayer, invite);
     }
 
+    /**
+     * Accept a party alliance invitation
+     *
+     * @param mcMMOPlayer The player who accepts the alliance invite
+     */
+    public static void acceptAllianceInvite(McMMOPlayer mcMMOPlayer) {
+        Party invite = mcMMOPlayer.getPartyAllianceInvite();
+        Player player = mcMMOPlayer.getPlayer();
+
+        // Check if the party still exists, it might have been disbanded
+        if (!parties.contains(invite)) {
+            player.sendMessage(LocaleLoader.getString("Party.Disband"));
+            return;
+        }
+
+        if (!handlePartyChangeAllianceEvent(player, mcMMOPlayer.getParty().getName(), invite.getName(), McMMOPartyAllianceChangeEvent.EventReason.FORMED_ALLIANCE)) {
+            return;
+        }
+
+        player.sendMessage(LocaleLoader.getString("Commands.Party.Alliance.Invite.Accepted", invite.getName()));
+        mcMMOPlayer.removePartyAllianceInvite();
+
+        createAlliance(mcMMOPlayer.getParty(), invite);
+    }
+
+    public static void createAlliance(Party firstParty, Party secondParty) {
+        firstParty.setAlly(secondParty);
+        secondParty.setAlly(firstParty);
+
+        for (Player member : firstParty.getOnlineMembers()) {
+            member.sendMessage(LocaleLoader.getString("Party.Alliance.Formed", secondParty.getName()));
+        }
+
+        for (Player member : secondParty.getOnlineMembers()) {
+            member.sendMessage(LocaleLoader.getString("Party.Alliance.Formed", firstParty.getName()));
+        }
+    }
+
+    public static boolean disbandAlliance(Player player, Party firstParty, Party secondParty){
+        if (!handlePartyChangeAllianceEvent(player, firstParty.getName(), secondParty.getName(), McMMOPartyAllianceChangeEvent.EventReason.DISBAND_ALLIANCE)) {
+            return false;
+        }
+
+        PartyManager.disbandAlliance(firstParty, secondParty);
+        return true;
+    }
+
+    private static void disbandAlliance(Party firstParty, Party secondParty) {
+        firstParty.setAlly(null);
+        secondParty.setAlly(null);
+
+        for (Player member : firstParty.getOnlineMembers()) {
+            member.sendMessage(LocaleLoader.getString("Party.Alliance.Disband", secondParty.getName()));
+        }
+
+        for (Player member : secondParty.getOnlineMembers()) {
+            member.sendMessage(LocaleLoader.getString("Party.Alliance.Disband", firstParty.getName()));
+        }
+    }
+
     /**
      * Add a player to a party
      *
@@ -406,12 +478,19 @@ public final class PartyManager {
 
         YamlConfiguration partiesFile = YamlConfiguration.loadConfiguration(partyFile);
 
+        ArrayList<Party> hasAlly = new ArrayList<Party>();
+
         for (String partyName : partiesFile.getConfigurationSection("").getKeys(false)) {
             Party party = new Party(partyName);
 
             party.setLeader(partiesFile.getString(partyName + ".Leader"));
             party.setPassword(partiesFile.getString(partyName + ".Password"));
             party.setLocked(partiesFile.getBoolean(partyName + ".Locked"));
+
+            if (partiesFile.getString(partyName + ".Ally") != null) {
+                hasAlly.add(party);
+            }
+
             party.setXpShareMode(ShareMode.getShareMode(partiesFile.getString(partyName + ".ExpShareMode", "NONE")));
             party.setItemShareMode(ShareMode.getShareMode(partiesFile.getString(partyName + ".ItemShareMode", "NONE")));
 
@@ -428,6 +507,10 @@ public final class PartyManager {
 
             parties.add(party);
         }
+
+        for (Party party : hasAlly) {
+            party.setAlly(getParty(partiesFile.getString(party.getName() + ".Ally")));
+        }
     }
 
     /**
@@ -446,6 +529,7 @@ public final class PartyManager {
             partiesFile.set(partyName + ".Leader", party.getLeader());
             partiesFile.set(partyName + ".Password", party.getPassword());
             partiesFile.set(partyName + ".Locked", party.isLocked());
+            partiesFile.set(partyName + ".Ally", (party.getAlly() != null) ? party.getAlly().getName() : "");
             partiesFile.set(partyName + ".ExpShareMode", party.getXpShareMode().toString());
             partiesFile.set(partyName + ".ItemShareMode", party.getItemShareMode().toString());
 
@@ -488,6 +572,22 @@ public final class PartyManager {
         return !event.isCancelled();
     }
 
+    /**
+     * Handle party alliance change event.
+     *
+     * @param player The player changing party alliances
+     * @param oldAllyName The name of the old ally
+     * @param newAllyName The name of the new ally
+     * @param reason The reason for changing allies
+     * @return true if the change event was successful, false otherwise
+     */
+    public static boolean handlePartyChangeAllianceEvent(Player player, String oldAllyName, String newAllyName, McMMOPartyAllianceChangeEvent.EventReason reason) {
+        McMMOPartyAllianceChangeEvent event = new McMMOPartyAllianceChangeEvent(player, oldAllyName, newAllyName, reason);
+        mcMMO.p.getServer().getPluginManager().callEvent(event);
+
+        return !event.isCancelled();
+    }
+
     /**
      * Remove party data from the mcMMOPlayer.
      *

+ 1 - 0
src/main/resources/config.yml

@@ -386,6 +386,7 @@ Commands:
     partychat:
         Chat_Prefix_Format: '[[GREEN]]([[WHITE]]{0}[[GREEN]])'
         Use_Display_Names: true
+        Chat_Prefix_Format_Ally: '[[GREEN]](A)[[RESET]]'
     adminchat:
         Chat_Prefix_Format: '[[AQUA]][[[WHITE]]{0}[[AQUA]]]'
         Use_Display_Names: true

+ 3 - 3
src/main/resources/locale/locale_cs_CZ.properties

@@ -366,7 +366,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO Godmod vypnuty
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO Godmod aktivovan
 Commands.GodMode.Forbidden=[mcMMO] M\u00f3d B\u016fh nen\u00ed povolen v tomto sv\u011bt\u011b (pod\u00edvej se do Povolen\u00ed)
 Commands.Inspect=<player> [[RED]]- Shl\u00e9dni detailn\u00ed informace o hr\u00e1\u010di
-Commands.Invite.Accepted=[[GREEN]]Pozvanka prijata. Pridal jsi se k party {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Pozvanka prijata. Pridal jsi se k party {0}
 Commands.Invite.Success=[[GREEN]]Pozv\u00e1nka \u00faspesne odesl\u00e1na.
 Commands.Leaderboards=<skill> <page> [[RED]]- Tabulka nejlep\u0161\u00edch
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO P\u0159\u00edkazy[[RED]][]---
@@ -419,8 +419,8 @@ Commands.Party.None=[RED]]Nejsi v zadne party.
 Commands.Party.Quit=[[RED]]- Opustil jsi svoji aktualni partu
 Commands.Party.Teleport=<hrac> [[RED]]- Teleport ke clenovi party
 Commands.Party.Toggle=[[RED]]- Zapnout party chat
-Commands.Party1=[[RED]]- Vytvo\u0159en\u00ed nov\u00e9 party
-Commands.Party2=[[RED]]- P\u0159ipoj\u00ed se k hr\u00e1\u010dov\u011b part\u011b
+Commands.Party.1=[[RED]]- Vytvo\u0159en\u00ed nov\u00e9 party
+Commands.Party.2=[[RED]]- P\u0159ipoj\u00ed se k hr\u00e1\u010dov\u011b part\u011b
 Commands.ptp.Enabled=Teleportace paret [[GREEN]]zapnut\u00e1
 Commands.ptp.Disabled=Teleportace paret [[RED]]vypnut\u00e1
 Commands.ptp.NoRequests=[[RED]]V tuto chv\u00edli nem\u00e1te \u017e\u00e1dne po\u017eadavky o teleport

+ 1 - 1
src/main/resources/locale/locale_cy.properties

@@ -330,7 +330,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO Godmode Disabled
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO Godmode Enabled
 Commands.GodMode.Forbidden=[mcMMO] God Mode not permitted on this world (See Permissions)
 Commands.Inspect=<player> [[RED]]- View detailed player info
-Commands.Invite.Accepted=[[GREEN]] Gwahodd Derbyniwyd. Yr ydych wedi ymuno parti {0}
+Commands.Party.Invite.Accepted=[[GREEN]] Gwahodd Derbyniwyd. Yr ydych wedi ymuno parti {0}
 Commands.Invite.Success=[[GREEN]]Invite sent successfully.
 Commands.Leaderboards=<skill> <page> [[RED]]- Leaderboards
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO Commands[[RED]][]---

+ 1 - 1
src/main/resources/locale/locale_da.properties

@@ -329,7 +329,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO GudeTilstand Slukket
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO GudeTilstand Aktiveret
 Commands.GodMode.Forbidden=[mcMMO] Gude Tilstand er ikke tilladt i denne verden (Se Tilladelser)
 Commands.Inspect=<player> [[RED]]- Se detaljeret spiller Info
-Commands.Invite.Accepted=[[GREEN]]Invitation Accepteret. Du har sluttet dig til en gruppe {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Invitation Accepteret. Du har sluttet dig til en gruppe {0}
 Commands.Invite.Success=[[GREEN]]Invitation sendt successfuldt
 Commands.Leaderboards=<skill> <page> [[RED]]- Ranglister
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO Kommandoer[[RED]][]---

+ 1 - 1
src/main/resources/locale/locale_de.properties

@@ -340,7 +340,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO Godmode deaktivivert
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO Godmode aktivivert
 Commands.GodMode.Forbidden=[mcMMO] God Mode ist in dieser Welt nicht gestattet (Siehe Permissions)
 Commands.Inspect=<Spieler> [[RED]]- Zeigt detailierte Spielerinfos
-Commands.Invite.Accepted=[[GREEN]]Einladung akzeptiert. Du bist der Gruppe {0} beigetreten
+Commands.Party.Invite.Accepted=[[GREEN]]Einladung akzeptiert. Du bist der Gruppe {0} beigetreten
 Commands.Invite.Success=[[GREEN]]Einladung erfolgreich versendet.
 Commands.Leaderboards=<skill> <seite> [[RED]]- Ranglisten
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO Commands[[RED]][]---

+ 15 - 1
src/main/resources/locale/locale_en_US.properties

@@ -450,7 +450,6 @@ Commands.Healthbars.Changed.BAR=[mcMMO] Your healthbar display type was changed
 Commands.Healthbars.Changed.DISABLED=[mcMMO] Your mob healthbars have been [[GRAY]]disabled[[WHITE]].
 Commands.Healthbars.Invalid=Invalid healthbar type!
 Commands.Inspect=<player> [[GREEN]]- View detailed player info
-Commands.Invite.Accepted=[[GREEN]]Invite Accepted. You have joined party {0}
 Commands.Invite.Success=[[GREEN]]Invite sent successfully.
 Commands.Leaderboards=<skill> <page> [[GREEN]]- Leaderboards
 Commands.mcc.Header=[[RED]]---[][[GREEN]]mcMMO Commands[[RED]][]---
@@ -486,6 +485,7 @@ Commands.Offline=[[RED]]This command does not work for offline players.
 Commands.Other=[[RED]]---[][[GREEN]]OTHER COMMANDS[[RED]][]---
 Commands.Party.Header=[[RED]]-----[][[GREEN]]PARTY[[RED]][]-----
 Commands.Party.Status=[[DARK_GRAY]]NAME: [[WHITE]]{0} {1}
+Commands.Party.Status.Alliance=[[DARK_GRAY]]ALLY: [[WHITE]]{0}
 Commands.Party.ShareMode=[[DARK_GRAY]]SHARE MODE: 
 Commands.Party.ItemShare=[[GRAY]]ITEM [[DARK_AQUA]]({0}) 
 Commands.Party.ExpShare=[[GRAY]]EXP [[DARK_AQUA]]({0})
@@ -498,6 +498,7 @@ Commands.Party.Commands=[[RED]]---[][[GREEN]]PARTY COMMANDS[[RED]][]---
 Commands.Party.Invite.0=[[RED]]ALERT: [[GREEN]]You have received a party invite for {0} from {1}
 Commands.Party.Invite.1=[[YELLOW]]Type [[GREEN]]/party accept[[YELLOW]] to accept the invite
 Commands.Party.Invite=[[GREEN]]- Send party invite
+Commands.Party.Invite.Accepted=[[GREEN]]Invite Accepted. You have joined party {0}
 Commands.Party.Join=[[GRAY]]Joined Party: {0}
 Commands.Party.Create=[[GRAY]]Created Party: {0}
 Commands.Party.Rename=[[GRAY]]Party name changed to: [[WHITE]]{0}
@@ -513,6 +514,16 @@ Commands.Party.Teleport=[[GREEN]]- Teleport to party member
 Commands.Party.Toggle=[[GREEN]]- Toggle Party Chat
 Commands.Party1=[[GREEN]]- Create a new party
 Commands.Party2=[[GREEN]]- Join a players party
+Commands.Party.Alliance.Header=[[RED]]-----[][[GREEN]]PARTY ALLIANCE[[RED]][]-----
+Commands.Party.Alliance.Ally=[[WHITE]]{0} [[DARK_GRAY]]IS ALLIED WITH: [[WHITE]]{1}
+Commands.Party.Alliance.Members.Header=[[RED]]-----[][[GREEN]]ALLIANCE MEMBERS[[RED]][]-----
+Commands.Party.Alliance.Invite.0=[[RED]]ALERT: [[GREEN]]You have received a party alliance invite for {0} from {1}
+Commands.Party.Alliance.Invite.1=[[YELLOW]]Type [[GREEN]]/party alliance accept[[YELLOW]] to accept the invite
+Commands.Party.Alliance.Invite.Accepted=[[GREEN]]Alliance invite Accepted.
+Commands.Party.Alliance.None=[[RED]]Your does not have an ally.
+Commands.Party.Alliance.AlreadyAllies=[[RED]]Your party already has an ally.
+Commands.Party.Alliance.Help.0=[[RED]]This party hasn't formed an alliance. Invite a party leader
+Commands.Party.Alliance.Help.1=[[RED]] to an alliance with [[DARK_AQUA]]/party alliance invite <player>[[RED]].
 Commands.ptp.Enabled=Party teleporting [[GREEN]]enabled
 Commands.ptp.Disabled=Party teleporting [[RED]]disabled
 Commands.ptp.NoRequests=[[RED]]You have no teleport requests at this time
@@ -585,6 +596,7 @@ Party.IsntLocked=[[RED]]This party is not locked!
 Party.Locked=[[RED]]Party is locked, only party leader may invite.
 Party.NotInYourParty=[[DARK_RED]]{0} is not in your party
 Party.NotOwner=[[DARK_RED]]You are not the party leader.
+Party.Target.NotOwner=[[DARK_RED]]{0} is not the party leader.
 Party.Owner.New=[[GREEN]]{0} is the new party leader.
 Party.Owner.NotLeader=[[DARK_RED]]You are no longer the party leader.
 Party.Owner.Player =[[GREEN]]You are now the party leader.
@@ -607,6 +619,8 @@ Party.Rename.Same=[[RED]]That is already the name of your party!
 Party.Join.Self=[[RED]]You can't join yourself!
 Party.Unlocked=[[GRAY]]Party is unlocked
 Party.Disband=[[GRAY]]The party has been disbanded
+Party.Alliance.Formed=[[GRAY]]Your party is now allies with [[GREEN]]{0}
+Party.Alliance.Disband=[[GRAY]]Your party is no longer allies with [[RED]]{0}
 Party.Status.Locked=[[DARK_RED]](INVITE-ONLY)
 Party.Status.Unlocked=[[DARK_GREEN]](OPEN)
 Party.ShareType.Exp=EXP

+ 3 - 3
src/main/resources/locale/locale_es.properties

@@ -370,7 +370,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO Modo Dios Desactivado
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO Modo Dios Activado
 Commands.GodMode.Forbidden=[mcMMO] No se permite Modo Dios en este mundo (Ver permisos)
 Commands.Inspect=<jugador> [[RED]]-Ver informaci\u00f3n detallada del jugador
-Commands.Invite.Accepted=[[GREEN]]Invitaci\u00f3n Aceptada. Te uniste al grupo {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Invitaci\u00f3n Aceptada. Te uniste al grupo {0}
 Commands.Invite.Success=[[GREEN]]Invitaci\u00f3n enviada satisfactoriamente
 Commands.Leaderboards=<habilidad> <p\u00e1gina> [[RED]]- Tabla de posiciones
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]Comandos mcMMO[[RED]][]---
@@ -431,8 +431,8 @@ Commands.Party.None=[[RED]]No est\u00e1s en un grupo.
 Commands.Party.Quit=[[RED]]- Abandona tu grupo actual
 Commands.Party.Teleport=<jugador> [[RED]]- Teletransportarse al miembro del grupo
 Commands.Party.Toggle=[[RED]]- Alternar chat de grupo
-Commands.Party1=[[RED]]- Nuevo grupo creado
-Commands.Party2=[RED]]- Unete a un grupo de jugadores
+Commands.Party.1=[[RED]]- Nuevo grupo creado
+Commands.Party.2=[RED]]- Unete a un grupo de jugadores
 Commands.ptp.Enabled=Teletransportacion de grupo [[GREEN]]activada
 Commands.ptp.Disabled=Teletransportacion de grupo [[RED]]desactivada
 Commands.ptp.NoRequests=[[RED]]No tienes ninguna peticion de teletransporte ahora mismo

+ 1 - 1
src/main/resources/locale/locale_fi.properties

@@ -146,7 +146,7 @@ Commands.AdminChat.Off=Ainoastaan Yll\u00e4pit\u00e4jien keskustelu [[RED]]pois
 Commands.AdminToggle=Kytke adminchat p\u00e4\u00e4lle/pois
 Commands.Disabled=[[RED]]T\u00e4m\u00e4 komento ei ole k\u00e4ytett\u00e4viss\u00e4.
 Commands.DoesNotExist=[[RED]]Player does not exist in the database!
-Commands.Invite.Accepted=[[GREEN]]Kutsu hyv\u00e4ksytty. Liityit ryhm\u00e4\u00e4n {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Kutsu hyv\u00e4ksytty. Liityit ryhm\u00e4\u00e4n {0}
 Commands.Invite.Success=[[GREEN]]Kutsu l\u00e4hetettiin onnistuneesti.
 Commands.mmoedit=[player] <skill> <newvalue> [[RED]] - Muokkaa kohdetta
 Commands.NoConsole=This command does not support console usage.

+ 1 - 1
src/main/resources/locale/locale_fr.properties

@@ -322,7 +322,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO Godmode d\u00e9sactiv\u00e9
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO Godmode activ\u00e9
 Commands.GodMode.Forbidden=[mcMMO] Le Godmode n\'est pas permis sur ce monde (voir les permissions)
 Commands.Inspect=<joueur> [[RED]]- Affiche les informations du joueur
-Commands.Invite.Accepted=[[GREEN]]Invitation accept\u00e9e. Vous avez rejoint le groupe {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Invitation accept\u00e9e. Vous avez rejoint le groupe {0}
 Commands.Invite.Success=[[GREEN]]Invitation envoy\u00e9e.
 Commands.Leaderboards=<talent> <page> [[RED]]- Classement
 Commands.mcgod=[[RED]]- Active / d\u00e9sactive le Godmode

+ 1 - 1
src/main/resources/locale/locale_hu_HU.properties

@@ -102,7 +102,7 @@ Commands.Disabled=[[RED]]Ez a parancs jelenleg le van tiltva.
 Commands.DoesNotExist=[[RED]]Ilyen nev\u0171 j\u00e1t\u00e9kos nincs az adatb\u00e1zisban!
 Commands.GodMode.Disabled=[[YELLOW]]mcMMO Istenm\u00f3d letiltva
 Commands.GodMode.Forbidden=[mcMMO] Istenm\u00f3d nem lehets\u00e9ges ebben a vil\u00e1gban! (N\u00e9zd meg a jogokat)
-Commands.Invite.Accepted=[[GREEN]]Megh\u00edv\u00e1st sikeresen elfogadtad {0} party-ra!
+Commands.Party.Invite.Accepted=[[GREEN]]Megh\u00edv\u00e1st sikeresen elfogadtad {0} party-ra!
 Commands.Invite.Success=[[GREEN]]Megh\u00edv\u00f3 sikeresen elk\u00fcldve.
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO Parancsok[[RED]][]---
 Commands.mcgod=[[RED]]- V\u00e1lt\u00e1s GodModba

+ 3 - 3
src/main/resources/locale/locale_it.properties

@@ -367,7 +367,7 @@ Commands.GodMode.Disabled=[[YELLOW]]Modalit\u00e0 Dio di mcMMO Disabilitata
 Commands.GodMode.Enabled=[[YELLOW]]Modalit\u00e0 Dio di mcMMO Abilitata
 Commands.GodMode.Forbidden=[mcMMO] Modalit\u00e0 Dio non permessa su questo mondo (vedi i Permessi)
 Commands.Inspect=<giocatore> [[RED]]- Visualizza informazioni dettagliate sul giocatore
-Commands.Invite.Accepted=[[GREEN]]Invito Accettato. Ti sei unito alla compagnia {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Invito Accettato. Ti sei unito alla compagnia {0}
 Commands.Invite.Success=[[GREEN]]Invito inviato con successo.
 Commands.Leaderboards=<abilit\u00e0> <pagina> [[RED]]- Classifiche
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]Comandi di mcMMO[[RED]][]---
@@ -420,8 +420,8 @@ Commands.Party.None=[[RED]]Non sei nella compagnia.
 Commands.Party.Quit=[[RED]]- Abbandona la tua attuale compagnia
 Commands.Party.Teleport=<giocatore> [[RED]]- Teletrasportati verso un membro della compagnia
 Commands.Party.Toggle=[[RED]]- Attiva o Disattiva la Chat di Compagnia
-Commands.Party1=[[RED]]- Crea una nuova compagnia
-Commands.Party2=[[RED]]- unisciti a una compagnia di giocatori
+Commands.Party.1=[[RED]]- Crea una nuova compagnia
+Commands.Party.2=[[RED]]- unisciti a una compagnia di giocatori
 Commands.ptp.Enabled=Teletrasporto di compagnia [[GREEN]]abilitato
 Commands.ptp.Disabled=Teletrasporto di compagnia [[GREEN]]disabilitato
 Commands.ptp.NoRequests=[[RED]]Non hai richieste di teletrasporto in questo momento

+ 1 - 1
src/main/resources/locale/locale_ja_JP.properties

@@ -73,7 +73,7 @@ Commands.AdminChat.Off=\u7ba1\u7406\u8005\u5c02\u7528\u30c1\u30e3\u30c3\u30c8\u3
 Commands.AdminToggle=[[RED]]- \u7ba1\u7406\u8005\u30c1\u30e3\u30c3\u30c8\u306b\u5207\u308a\u66ff\u3048
 Commands.Disabled=[[RED]]\u3053\u306e\u30b3\u30de\u30f3\u30c9\u306f\u7121\u52b9\u5316\u3055\u308c\u3066\u3044\u307e\u3059\u3002
 Commands.DoesNotExist=[[RED]]\u305d\u306e\u30d7\u30ec\u30fc\u30e4\u30fc\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u5b58\u5728\u3057\u307e\u305b\u3093\u3002
-Commands.Invite.Accepted=[[GREEN]]\u62db\u5f85\u304c\u627f\u8a8d\u3055\u308c\u307e\u3057\u305f\u3002\u30d1\u30fc\u30c6\u30a3\u30fc {0} \u306b\u53c2\u52a0\u3057\u307e\u3057\u305f\u3002
+Commands.Party.Invite.Accepted=[[GREEN]]\u62db\u5f85\u304c\u627f\u8a8d\u3055\u308c\u307e\u3057\u305f\u3002\u30d1\u30fc\u30c6\u30a3\u30fc {0} \u306b\u53c2\u52a0\u3057\u307e\u3057\u305f\u3002
 Commands.mcgod=[[RED]]- GodMode\u306e\u5207\u308a\u66ff\u3048
 Commands.mmoedit=[player] <skill> <newvalue> [[RED]] - \u30bf\u30fc\u30b2\u30c3\u30c8\u3092\u5909\u66f4\u3057\u307e\u3059
 Commands.Party.Kick=[[RED]]\u3042\u306a\u305f\u306f\u3001\u30d1\u30fc\u30c6\u30a3\u30fc{0}\u304b\u3089\u8ffd\u3044\u51fa\u3055\u308c\u307e\u3057\u305f

+ 1 - 1
src/main/resources/locale/locale_lv.properties

@@ -35,7 +35,7 @@ Combat.TouchedFuzzy=[[DARK_RED]]Piek\u0101ries pl\u016bdu\u0161am. Apdulli.
 Commands.AdminChat.Off=Tikai Adminu \u010dats [[RED]]Izsl\u0113gt
 Commands.AdminToggle=[[RED]]- Tikai administratoru \u010dats
 Commands.Disabled=[[RED]]\u0160\u012b komanda ir atsl\u0113gta
-Commands.Invite.Accepted=[[GREEN]]Iel\u016bgums Apstiprin\u0101ts. Tu pievienojies PARTY\'am {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Iel\u016bgums Apstiprin\u0101ts. Tu pievienojies PARTY\'am {0}
 Commands.NoConsole=\u0160\u012b komanda neatbalsta konsules izmanto\u0161anu.
 Commands.Party.Invite.0=[[RED]]BR\u012aDIN\u0100JUMS: [[GREEN]]Tu sa\u0146\u0113mi PARTY uzaicin\u0101jumu uz {0} no {1}
 Commands.Party.Kick=[[RED]]Tu tiki izmests no PARTY {0}!

+ 3 - 3
src/main/resources/locale/locale_nl.properties

@@ -257,7 +257,7 @@ Commands.DoesNotExist=[[RED]]Speler bestaat niet in de database!
 Commands.GodMode.Disabled=[[YELLOW]]mcMMO GodModus Uitgeschakeld
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO Godmode ag zet het tog uit...
 Commands.GodMode.Forbidden=[mcMMO] God Modus is niet toegestaan in deze wereld (Zie Permissions)
-Commands.Invite.Accepted=[[GREEN]]Uitnodiging geacepteerd. Jij hebt de groep  {0} betreden
+Commands.Party.Invite.Accepted=[[GREEN]]Uitnodiging geacepteerd. Jij hebt de groep  {0} betreden
 Commands.Invite.Success=[[GREEN]]Uitnodiging verstuurd!
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO Commando\'s[[RED]][]---
 Commands.mcgod=[[RED]]- GodModus Schakelen
@@ -292,8 +292,8 @@ Commands.Party.None=[[RED]]Je bent niet in een groep.
 Commands.Party.Quit=[[RED]]- Verlaat je huidige groep
 Commands.Party.Teleport=<player> [[RED]]- Teleport naar een groepslid
 Commands.Party.Toggle=[[RED]]- Zet Party Chat aan/uit
-Commands.Party1=[[RED]]- Maak een nieuwe groep
-Commands.Party2=[[RED]]- Ga bij een spelers groep
+Commands.Party.1=[[RED]]- Maak een nieuwe groep
+Commands.Party.2=[[RED]]- Ga bij een spelers groep
 Commands.ptp.NoRequests=[[RED]] Je hebt geen teleporteren aanvragen op dit moment
 Commands.ptp.RequestExpired=[[RED]]Groep\'s teleport verzoek is verlopen!
 Commands.PowerLevel.Leaderboard=[[YELLOW]]--mcMMO[[BLUE]] Kracht Level [[YELLOW]]Leiderbord--

+ 3 - 3
src/main/resources/locale/locale_pl.properties

@@ -354,7 +354,7 @@ Commands.GodMode.Disabled=[[YELLOW]]Nie\u015bmiertelno\u015b\u0107 wy\u0142\u010
 Commands.GodMode.Enabled=[[YELLOW]]Nie\u015bmiertelno\u015b\u0107 w\u0142\u0105czona
 Commands.GodMode.Forbidden=[mcMMO] Nie\u015bmiertelno\u015b\u0107 nie jest dozwolona na tym \u015bwiecie.
 Commands.Inspect=<player> [[RED]]- Pokazuje informacje o graczu
-Commands.Invite.Accepted=[[GREEN]]Zaproszenie zaakceptowane. Do\u0142\u0105czy\u0142e\u015b do dru\u017cyny {0}
+Commands.Party.Invite.Accepted=[[GREEN]]Zaproszenie zaakceptowane. Do\u0142\u0105czy\u0142e\u015b do dru\u017cyny {0}
 Commands.Invite.Success=[[GREEN]]Pomyslnie wyslano zaproszenie
 Commands.Leaderboards=<skill> <page> [[RED]]- Rankingi
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO Komendy[[RED]][]---
@@ -401,8 +401,8 @@ Commands.Party.None=[[RED]]Nie jestes w druzynie.
 Commands.Party.Quit=[[RED]]- Opuszcza obecn\u0105 dru\u017cyne
 Commands.Party.Teleport=<player> [[RED]]- Teleportacja do czlonka grupy.
 Commands.Party.Toggle=[[RED]]- W\u0142\u0105cza/Wy\u0142\u0105cza czat dla dru\u017cyn
-Commands.Party1=[[RED]]- Tworzy nowa druzyne
-Commands.Party2=[[RED]]- Dolacza do druzyny gracza
+Commands.Party.1=[[RED]]- Tworzy nowa druzyne
+Commands.Party.2=[[RED]]- Dolacza do druzyny gracza
 Commands.ptp.Enabled=Teleportacja druzynowa [[GREEN]]aktywna
 Commands.ptp.Disabled=Teleportacja druzynowa [[RED]]wylaczona
 Commands.ptp.NoRequests=[[RED]]Nie masz zadnych zadan teleportacji w tym momencie

+ 3 - 3
src/main/resources/locale/locale_ru.properties

@@ -384,7 +384,7 @@ Commands.Healthbars.Changed.BAR=[mcMMO] \u0422\u0438\u043f \u043e\u0442\u043e\u0
 Commands.Healthbars.Changed.DISABLED=[mcMMO] \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0448\u043a\u0430\u043b\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u044f \u043c\u043e\u0431\u043e\u0432 [[GRAY]]\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u043e[[WHITE]].
 Commands.Healthbars.Invalid=\u041d\u0435\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0442\u0438\u043f \u0448\u043a\u0430\u043b\u044b \u0437\u0434\u043e\u0440\u043e\u0432\u044c\u044f!
 Commands.Inspect=<player> [[RED]]- \u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0438\u0433\u0440\u043e\u043a\u0435
-Commands.Invite.Accepted=[[GREEN]]\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043d\u044f\u0442\u043e. \u0412\u044b \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0435\u043d\u0438\u043b\u0438\u0441\u044c \u043a \u0433\u0440\u0443\u043f\u0435 {0}
+Commands.Party.Invite.Accepted=[[GREEN]]\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043d\u044f\u0442\u043e. \u0412\u044b \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0435\u043d\u0438\u043b\u0438\u0441\u044c \u043a \u0433\u0440\u0443\u043f\u0435 {0}
 Commands.Invite.Success=[[GREEN]]\u041f\u0440\u0438\u0433\u043b\u0430\u0448\u0435\u043d\u0438\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043e.
 Commands.Leaderboards=<skill> <page> [[RED]]- \u0421\u043f\u0438\u0441\u043a\u0438 \u041b\u0438\u0434\u0435\u0440\u043e\u0432
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]\u041a\u043e\u043c\u0430\u043d\u0434\u044b mcMMO[[RED]][]---
@@ -445,8 +445,8 @@ Commands.Party.None=[[RED]]\u0412\u044b \u043d\u0435 \u0432 \u0433\u0440\u0443\u
 Commands.Party.Quit=[[RED]]- \u041f\u043e\u043a\u0438\u043d\u0443\u0442\u044c \u0442\u0435\u043a\u0443\u0449\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443
 Commands.Party.Teleport=<player> [[RED]]- \u0422\u0435\u043b\u0435\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a \u0447\u043b\u0435\u043d\u0443 \u0433\u0440\u0443\u043f\u043f\u044b
 Commands.Party.Toggle=[[RED]]- \u0412\u043a\u043b./\u043e\u0442\u043a\u043b. \u0433\u0440\u0443\u043f\u043f\u043e\u0432\u043e\u0439 \u0447\u0430\u0442
-Commands.Party1=[[RED]]- \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443
-Commands.Party2=[[RED]]- \u041f\u0440\u0438\u0441\u043e\u0435\u0434\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u043a \u0433\u0440\u0443\u043f\u043f\u0435 \u0438\u0433\u0440\u043e\u043a\u043e\u0432
+Commands.Party.1=[[RED]]- \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u0443\u044e \u0433\u0440\u0443\u043f\u043f\u0443
+Commands.Party.2=[[RED]]- \u041f\u0440\u0438\u0441\u043e\u0435\u0434\u0435\u043d\u0438\u0442\u044c\u0441\u044f \u043a \u0433\u0440\u0443\u043f\u043f\u0435 \u0438\u0433\u0440\u043e\u043a\u043e\u0432
 Commands.ptp.Enabled=\u0422\u0435\u043b\u0435\u043f\u043e\u0440\u0442\u0430\u0446\u0438\u044f \u043a \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c \u0433\u0440\u0443\u043f\u043f\u044b [[GREEN]]\u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430
 Commands.ptp.Disabled=\u0422\u0435\u043b\u0435\u043f\u043e\u0440\u0442\u0430\u0446\u0438\u044f \u043a \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c \u0433\u0440\u0443\u043f\u043f\u044b [[RED]]\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0430
 Commands.ptp.NoRequests=[[RED]]\u041d\u0430 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0442\u0435\u043b\u0435\u043f\u043e\u0440\u0442\u0430\u0446\u0438\u044e \u043a \u0432\u0430\u043c \u043d\u0435\u0442

+ 1 - 1
src/main/resources/locale/locale_sv.properties

@@ -114,7 +114,7 @@ Commands.AdminToggle=[[RED]]- V\u00e4xla admin chat
 Commands.Disabled=[[RED]]Det h\u00e4r kommandot \u00e4r avst\u00e4ngt.
 Commands.DoesNotExist=[[RED]]Spelaren finns inte i databasen!
 Commands.GodMode.Disabled=[[YELLOW]]mcMMO Gudsl\u00e4ge avaktiverat
-Commands.Invite.Accepted=[[GREEN]]F\u00f6rfr\u00e5gan accepterad. Du har nu g\u00e5tt med i gruppen {0}
+Commands.Party.Invite.Accepted=[[GREEN]]F\u00f6rfr\u00e5gan accepterad. Du har nu g\u00e5tt med i gruppen {0}
 Commands.mcgod=[[RED]]- V\u00e4xla till gudsl\u00e4ge
 Commands.mmoedit=[player] <skill> <newvalue> [[RED]] - \u00c4ndra m\u00e5l
 Commands.ModDescription=[[RED]]- L\u00e4s sammanfattad mod beskrivning. 

+ 3 - 3
src/main/resources/locale/locale_th_TH.properties

@@ -365,7 +365,7 @@ Commands.GodMode.Disabled=[[YELLOW]]mcMMO \u0e42\u0e2b\u0e21\u0e14 God \u0e16\u0
 Commands.GodMode.Enabled=[[YELLOW]]mcMMO \u0e42\u0e2b\u0e21\u0e14 God \u0e16\u0e39\u0e01\u0e40\u0e1b\u0e34\u0e14
 Commands.GodMode.Forbidden=[mcMMO] \u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e44\u0e14\u0e49\u0e23\u0e31\u0e1a\u0e2d\u0e19\u0e38\u0e0d\u0e32\u0e15\u0e1a\u0e19\u0e42\u0e25\u0e01\u0e19\u0e35\u0e49 (\u0e14\u0e39 Permissions)
 Commands.Inspect=<player> [[RED]]- \u0e14\u0e39\u0e02\u0e49\u0e2d\u0e21\u0e39\u0e25\u0e23\u0e32\u0e22\u0e25\u0e30\u0e40\u0e2d\u0e35\u0e22\u0e14\u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e49\u0e40\u0e25\u0e48\u0e19
-Commands.Invite.Accepted=[[GREEN]]\u0e22\u0e34\u0e19\u0e22\u0e2d\u0e21\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e40\u0e0a\u0e34\u0e0d. \u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e40\u0e02\u0e49\u0e32 party {0}
+Commands.Party.Invite.Accepted=[[GREEN]]\u0e22\u0e34\u0e19\u0e22\u0e2d\u0e21\u0e01\u0e32\u0e23\u0e23\u0e31\u0e1a\u0e40\u0e0a\u0e34\u0e0d. \u0e04\u0e38\u0e13\u0e44\u0e14\u0e49\u0e40\u0e02\u0e49\u0e32 party {0}
 Commands.Invite.Success=[[GREEN]]\u0e2a\u0e48\u0e07\u0e04\u0e33\u0e40\u0e0a\u0e34\u0e0d\u0e41\u0e25\u0e49\u0e27\u0e1b\u0e23\u0e30\u0e2a\u0e1a\u0e04\u0e27\u0e32\u0e21\u0e2a\u0e33\u0e40\u0e23\u0e47\u0e08.
 Commands.Leaderboards=<skill> <page> [[RED]]- Leaderboards
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]\u0e04\u0e33\u0e2a\u0e31\u0e48\u0e07 mcMMO[[RED]][]---
@@ -417,8 +417,8 @@ Commands.Party.None=[[RED]]\u0e04\u0e38\u0e13\u0e44\u0e21\u0e48\u0e44\u0e14\u0e4
 Commands.Party.Quit=[[RED]]- \u0e2d\u0e2d\u0e01\u0e08\u0e32\u0e01\u0e07\u0e32\u0e19 party \u0e02\u0e2d\u0e07\u0e04\u0e38\u0e13\u0e43\u0e19\u0e1b\u0e31\u0e08\u0e08\u0e38\u0e1a\u0e31\u0e19
 Commands.Party.Teleport=<player> [[RED]]- Teleport to \u0e44\u0e1b\u0e2b\u0e32\u0e2a\u0e21\u0e32\u0e0a\u0e34\u0e01 party
 Commands.Party.Toggle=[[RED]]- \u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e42\u0e2b\u0e21\u0e14 Party Chat
-Commands.Party1=[[RED]]- \u0e2a\u0e23\u0e49\u0e32\u0e07 Party \u0e43\u0e2b\u0e21\u0e48
-Commands.Party2=[[RED]]- \u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21 Party \u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e49\u0e40\u0e25\u0e48\u0e19
+Commands.Party.1=[[RED]]- \u0e2a\u0e23\u0e49\u0e32\u0e07 Party \u0e43\u0e2b\u0e21\u0e48
+Commands.Party.2=[[RED]]- \u0e40\u0e02\u0e49\u0e32\u0e23\u0e48\u0e27\u0e21 Party \u0e02\u0e2d\u0e07\u0e1c\u0e39\u0e49\u0e40\u0e25\u0e48\u0e19
 Commands.ptp.Enabled=Party teleporting [[GREEN]]\u0e16\u0e39\u0e01\u0e40\u0e1b\u0e34\u0e14
 Commands.ptp.Disabled=Party teleporting [[RED]]\u0e16\u0e39\u0e01\u0e1b\u0e34\u0e14
 Commands.ptp.NoRequests=[[RED]]\u0e04\u0e38\u0e13\u0e22\u0e31\u0e07\u0e44\u0e21\u0e48\u0e21\u0e35\u0e01\u0e32\u0e23\u0e23\u0e49\u0e2d\u0e07\u0e02\u0e2d teleport \u0e43\u0e19\u0e40\u0e27\u0e25\u0e32\u0e19\u0e35\u0e49

+ 3 - 3
src/main/resources/locale/locale_zh_CN.properties

@@ -381,7 +381,7 @@ Commands.Healthbars.Changed.BAR=[mcMMO] \u4f60\u7684\u8840\u6761\u663e\u793a\u7c
 Commands.Healthbars.Changed.DISABLED=[mcMMO] \u4f60\u7684\u602a\u7269\u8840\u6761\u663e\u793a\u5df2\u88ab [[GRAY]]\u7981\u7528[[WHITE]].
 Commands.Healthbars.Invalid=\u65e0\u6548\u7684\u8840\u6761\u7c7b\u578b!
 Commands.Inspect=<player> [[RED]]-\u67e5\u770b\u73a9\u5bb6\u8be6\u7ec6\u4fe1\u606f
-Commands.Invite.Accepted=[[GREEN]]\u63a5\u53d7\u9080\u8bf7,\u4f60\u6210\u4e3a\u4e86\u961f\u4f0d {0} \u4e2d\u7684\u4e00\u5458.
+Commands.Party.Invite.Accepted=[[GREEN]]\u63a5\u53d7\u9080\u8bf7,\u4f60\u6210\u4e3a\u4e86\u961f\u4f0d {0} \u4e2d\u7684\u4e00\u5458.
 Commands.Invite.Success=[[GREEN]]\u9080\u8bf7\u53d1\u9001\u6210\u529f.
 Commands.Leaderboards=<skill> <page> [[RED]]- \u6392\u884c\u699c
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO \u6307\u4ee4[[RED]][]---
@@ -442,8 +442,8 @@ Commands.Party.None=[[RED]]\u4f60\u4e0d\u5728\u961f\u4f0d\u4e2d.
 Commands.Party.Quit=[[RED]]- \u79bb\u5f00\u4f60\u73b0\u6709\u7684\u961f\u4f0d
 Commands.Party.Teleport=<player> [[RED]]- \u4f20\u9001\u5230\u961f\u4f0d\u6210\u5458
 Commands.Party.Toggle=[[RED]]- \u5207\u6362\u961f\u4f0d\u804a\u5929
-Commands.Party1=[[RED]]- \u521b\u5efa\u4e00\u4e2a\u65b0\u961f\u4f0d
-Commands.Party2=[[RED]]- \u52a0\u5165\u4e00\u4e2a\u73a9\u5bb6\u7684\u961f\u4f0d
+Commands.Party.1=[[RED]]- \u521b\u5efa\u4e00\u4e2a\u65b0\u961f\u4f0d
+Commands.Party.2=[[RED]]- \u52a0\u5165\u4e00\u4e2a\u73a9\u5bb6\u7684\u961f\u4f0d
 Commands.ptp.Enabled=\u961f\u4f0d\u4f20\u9001 [[GREEN]]\u542f\u7528
 Commands.ptp.Disabled=\u961f\u4f0d\u4f20\u9001 [[RED]]\u7981\u7528
 Commands.ptp.NoRequests=[[RED]]\u5f53\u524d\u6ca1\u6709\u4f20\u9001\u8bf7\u6c42

+ 3 - 3
src/main/resources/locale/locale_zh_TW.properties

@@ -384,7 +384,7 @@ Commands.Healthbars.Changed.BAR=[mcMMO] \u4f60\u7684\u8840\u689d\u986f\u793a\u6a
 Commands.Healthbars.Changed.DISABLED=[mcMMO] \u4f60\u7684\u602a\u7269\u8840\u689d\u5df2 [[GRAY]]\u505c\u7528[[WHITE]].
 Commands.Healthbars.Invalid=\u4e0d\u6b63\u78ba\u7684\u8840\u689d\u985e\u578b!
 Commands.Inspect=<player> [[RED]]-\u67e5\u770b\u73a9\u5bb6\u8a73\u7d30\u8a0a\u606f
-Commands.Invite.Accepted=[[GREEN]]\u63a5\u53d7\u9080\u8acb\uff0c\u4f60\u52a0\u5165\u4e86\u968a\u4f0d {0}
+Commands.Party.Invite.Accepted=[[GREEN]]\u63a5\u53d7\u9080\u8acb\uff0c\u4f60\u52a0\u5165\u4e86\u968a\u4f0d {0}
 Commands.Invite.Success=[[GREEN]]\u9080\u8acb\u8a0a\u606f\u767c\u9001\u6210\u529f
 Commands.Leaderboards=<skill> <page> [[RED]]- \u6392\u884c\u699c
 Commands.mcc.Header=[[RED]]---[][[YELLOW]]mcMMO \u6307\u4ee4[[RED]][]---
@@ -445,8 +445,8 @@ Commands.Party.None=[[RED]]\u4f60\u4e0d\u5728\u968a\u4f0d\u4e2d.
 Commands.Party.Quit=[[RED]]- \u96e2\u958b\u4f60\u73fe\u5728\u7684\u968a\u4f0d
 Commands.Party.Teleport=<player> [[RED]]- \u50b3\u9001\u5230\u968a\u4f0d\u6210\u54e1\u65c1
 Commands.Party.Toggle=[[RED]]- \u5207\u63db\u968a\u4f0d\u804a\u5929
-Commands.Party1=[[RED]]- \u5275\u5efa\u65b0\u7684\u968a\u4f0d
-Commands.Party2=[[RED]]- \u52a0\u5165\u73a9\u5bb6\u7684\u968a\u4f0d\u88e1
+Commands.Party.1=[[RED]]- \u5275\u5efa\u65b0\u7684\u968a\u4f0d
+Commands.Party.2=[[RED]]- \u52a0\u5165\u73a9\u5bb6\u7684\u968a\u4f0d\u88e1
 Commands.ptp.Enabled=\u968a\u4f0d\u50b3\u9001 [[GREEN]]\u5141\u8a31
 Commands.ptp.Disabled=\u968a\u4f0d\u50b3\u9001 [[RED]]\u4e0d\u5141\u8a31
 Commands.ptp.NoRequests=[[RED]]\u4f60\u73fe\u5728\u4e0d\u53ef\u4ee5\u50b3\u9001

+ 3 - 0
src/main/resources/plugin.yml

@@ -938,6 +938,7 @@ permissions:
             mcmmo.commands.party.rename: true
             mcmmo.commands.party.teleport: true
             mcmmo.commands.party.unlock: true
+            mcmmo.commands.party.alliance: true
     mcmmo.commands.party:
         description: Allows access to the party command
     mcmmo.commands.party.accept:
@@ -980,6 +981,8 @@ permissions:
             mcmmo.commands.ptp: true
     mcmmo.commands.party.unlock:
         description: Allows access to the party unlock command
+    mcmmo.commands.party.alliance:
+        description: Allows access to the party alliance command
     mcmmo.commands.ptp.*:
         default: false
         description: Implies access to all mcmmo.commands.ptp permissions.