private void UnshareCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              if (args.Parameters.Count < 1) {
            args.Player.SendErrorMessage("Proper syntax: /unshare <player name>");
            args.Player.SendErrorMessage("Type /unshare help to get more help to this command.");
            return;
              }

              bool persistentMode;
              string playerName;
              if (args.Parameters[args.Parameters.Count - 1].Equals("+p", StringComparison.InvariantCultureIgnoreCase)) {
            persistentMode = true;
            playerName = args.ParamsToSingleString(0, 1);
              } else {
            persistentMode = false;
            playerName = args.ParamsToSingleString();
              }

              TShockAPI.DB.User tsUser;
              if (!TShockEx.MatchUserByPlayerName(playerName, out tsUser, args.Player))
            return;

              this.StartShareCommandInteraction(args.Player, persistentMode, false, false, false, tsUser.ID, tsUser.Name);
        }
        private void UnshareGroupCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              if (args.Parameters.Count < 1) {
            args.Player.SendErrorMessage("Proper syntax: /unsharegroup <groupname>");
            args.Player.SendErrorMessage("Type /unsharegroup help to get more help to this command.");
            return;
              }

              bool persistentMode;
              string groupName;
              if (args.Parameters[args.Parameters.Count - 1].Equals("+p", StringComparison.InvariantCultureIgnoreCase)) {
            persistentMode = true;
            groupName = args.ParamsToSingleString(0, 1);
              } else {
            persistentMode = false;
            groupName = args.ParamsToSingleString();
              }

              this.StartShareCommandInteraction(args.Player, persistentMode, false, true, false, groupName, groupName);
        }
        private void RefillChestManyCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              if (!args.Player.Group.HasPermission(ProtectorPlugin.SetRefillChests_Permission)) {
            args.Player.SendErrorMessage("You do not have the permission to set up refill chests.");
            return;
              }

              bool? oneLootPerPlayer = null;
              int? lootLimit = null;
              bool? autoLock = null;
              TimeSpan? refillTime = null;
              bool? autoEmpty = null;
              string selector = null;
              bool fairLoot = false;
              bool invalidSyntax = (args.Parameters.Count == 0);
              if (!invalidSyntax) {
            selector = args.Parameters[0].ToLowerInvariant();

            int timeParameters = 0;
            for (int i = 1; i < args.Parameters.Count; i++) {
              string param = args.Parameters[i];
              if (param.Equals("+ot", StringComparison.InvariantCultureIgnoreCase))
            oneLootPerPlayer = true;
              else if (param.Equals("-ot", StringComparison.InvariantCultureIgnoreCase))
            oneLootPerPlayer = false;
              else if (param.Equals("-ll", StringComparison.InvariantCultureIgnoreCase))
            lootLimit = -1;
              else if (param.Equals("+ll", StringComparison.InvariantCultureIgnoreCase)) {
            if (args.Parameters.Count - 1 == i) {
              invalidSyntax = true;
              break;
            }

            int lootTimeAmount;
            if (!int.TryParse(args.Parameters[i + 1], out lootTimeAmount) || lootTimeAmount < 0) {
              invalidSyntax = true;
              break;
            }

            lootLimit = lootTimeAmount;
            i++;
              } else if (param.Equals("+al", StringComparison.InvariantCultureIgnoreCase))
            autoLock = true;
              else if (param.Equals("+fl", StringComparison.InvariantCultureIgnoreCase))
            fairLoot = true;
              else if (param.Equals("-al", StringComparison.InvariantCultureIgnoreCase))
            autoLock = false;
              else if (param.Equals("+ae", StringComparison.InvariantCultureIgnoreCase))
            autoEmpty = true;
              else if (param.Equals("-ae", StringComparison.InvariantCultureIgnoreCase))
            autoEmpty = false;
              else
            timeParameters++;
            }

            if (!invalidSyntax && timeParameters > 0) {
              if (!TimeSpanEx.TryParseShort(
            args.ParamsToSingleString(1, args.Parameters.Count - timeParameters - 1), out refillTime
              )) {
            invalidSyntax = true;
              }
            }
              }

              ChestKind chestKindToSelect = ChestKind.Unknown;
              switch (selector) {
            case "dungeon":
              chestKindToSelect = ChestKind.DungeonChest;
              break;
            case "sky":
              chestKindToSelect = ChestKind.SkyIslandChest;
              break;
            case "ocean":
              chestKindToSelect = ChestKind.OceanChest;
              break;
            case "shadow":
              chestKindToSelect = ChestKind.HellShadowChest;
              break;
            case "hardmodedungeon":
              chestKindToSelect = ChestKind.HardmodeDungeonChest;
              break;
            case "pyramid":
              chestKindToSelect = ChestKind.PyramidChest;
              break;
            default:
              invalidSyntax = true;
              break;
              }

              if (invalidSyntax) {
            args.Player.SendErrorMessage("Proper syntax: /refillchestmany <selector> [time] [+ot|-ot] [+ll amount|-ll] [+al|-al] [+ae|-ae] [+fl]");
            args.Player.SendErrorMessage("Type /refillchestmany help to get more help to this command.");
            return;
              }

              if (chestKindToSelect != ChestKind.Unknown) {
            int createdChestsCounter = 0;
            for (int i = 0; i < Main.chest.Length; i++) {
              Chest chest = Main.chest[i];
              if (chest == null)
            continue;

              DPoint chestLocation = new DPoint(chest.x, chest.y);
              if (!TerrariaUtils.Tiles[chestLocation].active() || TerrariaUtils.Tiles[chestLocation].type != (int)BlockType.Chest)
            continue;

              if (TerrariaUtils.Tiles.GuessChestKind(chestLocation) != chestKindToSelect)
            continue;

              try {
            ProtectionEntry protection = this.ProtectionManager.CreateProtection(args.Player, chestLocation, false);
            protection.IsSharedWithEveryone = this.Config.AutoShareRefillChests;
              } catch (AlreadyProtectedException) {
            if (!this.ProtectionManager.CheckBlockAccess(args.Player, chestLocation, true) && !args.Player.Group.HasPermission(ProtectorPlugin.ProtectionMaster_Permission)) {
              args.Player.SendWarningMessage($"You did not have access to convert chest {TShock.Utils.ColorTag(chestLocation.ToString(), Color.Red)} into a refill chest.");
              continue;
            }
              } catch (Exception ex) {
            this.PluginTrace.WriteLineWarning($"Failed to create protection at {TShock.Utils.ColorTag(chestLocation.ToString(), Color.Red)}: \n{ex}");
              }

              try {
            this.ChestManager.SetUpRefillChest(
              args.Player, chestLocation, refillTime, oneLootPerPlayer, lootLimit, autoLock, autoEmpty, fairLoot
            );
            createdChestsCounter++;
              } catch (Exception ex) {
            this.PluginTrace.WriteLineWarning($"Failed to create / update refill chest at {TShock.Utils.ColorTag(chestLocation.ToString(), Color.Red)}: \n{ex}");
              }
            }

            args.Player.SendSuccessMessage($"{TShock.Utils.ColorTag(createdChestsCounter.ToString(), Color.Red)} refill chests were created / updated.");
              }
        }
        private void RefillChestCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              bool persistentMode = false;
              bool? oneLootPerPlayer = null;
              int? lootLimit = null;
              bool? autoLock = null;
              TimeSpan? refillTime = null;
              bool invalidSyntax = false;
              int timeParameters = 0;
              bool? autoEmpty = null;
              for (int i = 0; i < args.Parameters.Count; i++) {
            string param = args.Parameters[i];
            if (param.Equals("+p", StringComparison.InvariantCultureIgnoreCase))
              persistentMode = true;
            else if (param.Equals("+ot", StringComparison.InvariantCultureIgnoreCase))
              oneLootPerPlayer = true;
            else if (param.Equals("-ot", StringComparison.InvariantCultureIgnoreCase))
              oneLootPerPlayer = false;
            else if (param.Equals("-ll", StringComparison.InvariantCultureIgnoreCase))
              lootLimit = -1;
            else if (param.Equals("+ll", StringComparison.InvariantCultureIgnoreCase)) {
              if (args.Parameters.Count - 1 == i) {
            invalidSyntax = true;
            break;
              }

              int lootTimeAmount;
              if (!int.TryParse(args.Parameters[i + 1], out lootTimeAmount) || lootTimeAmount < 0) {
            invalidSyntax = true;
            break;
              }

              lootLimit = lootTimeAmount;
              i++;
            } else if (param.Equals("+al", StringComparison.InvariantCultureIgnoreCase))
              autoLock = true;
            else if (param.Equals("-al", StringComparison.InvariantCultureIgnoreCase))
              autoLock = false;
            else if (param.Equals("+ae", StringComparison.InvariantCultureIgnoreCase))
              autoEmpty = true;
            else if (param.Equals("-ae", StringComparison.InvariantCultureIgnoreCase))
              autoEmpty = false;
            else
              timeParameters++;
              }

              if (!invalidSyntax && timeParameters > 0) {
            if (!TimeSpanEx.TryParseShort(
              args.ParamsToSingleString(0, args.Parameters.Count - timeParameters), out refillTime
            )) {
              invalidSyntax = true;
            }
              }

              if (invalidSyntax) {
            args.Player.SendErrorMessage("Proper syntax: /refillchest [time] [+ot|-ot] [+ll amount|-ll] [+al|-al] [+ae|-ae] [+p]");
            args.Player.SendErrorMessage("Type /refillchest help to get more help to this command.");
            return;
              }

              CommandInteraction interaction = this.StartOrResetCommandInteraction(args.Player);
              interaction.DoesNeverComplete = persistentMode;
              interaction.TileEditCallback += (playerLocal, editType, tileId, location, objectStyle) => {
            if (
              editType != TileEditType.PlaceTile ||
              editType != TileEditType.PlaceWall ||
              editType != TileEditType.DestroyWall ||
              editType != TileEditType.PlaceActuator
            ) {
              this.TrySetUpRefillChest(playerLocal, location, refillTime, oneLootPerPlayer, lootLimit, autoLock, autoEmpty);

              playerLocal.SendTileSquare(location);
              return new CommandInteractionResult { IsHandled = true, IsInteractionCompleted = true };
            }

            playerLocal.SendTileSquare(location);
            return new CommandInteractionResult { IsHandled = false, IsInteractionCompleted = false };
              };
              interaction.ChestOpenCallback += (playerLocal, location) => {
            this.TrySetUpRefillChest(playerLocal, location, refillTime, oneLootPerPlayer, lootLimit, autoLock, autoEmpty);
            return new CommandInteractionResult { IsHandled = true, IsInteractionCompleted = true };
              };
              interaction.TimeExpiredCallback += (playerLocal) => {
            playerLocal.SendMessage("Waited too long. No refill chest will be created.", Color.Red);
              };

              args.Player.SendInfoMessage("Open a chest to convert it into a refill chest.");
        }
        private void HouseUnshareGroupCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              if (args.Parameters.Count < 2) {
            args.Player.SendErrorMessage("Proper syntax: /house unsharegroup <group name>");
            args.Player.SendInfoMessage("Type /house unsharegroup help to get more information about this command.");
            return;
              }

              string shareTargetRaw = args.ParamsToSingleString(1);
              if (shareTargetRaw.Equals("help", StringComparison.InvariantCultureIgnoreCase)) {
            this.HouseUnshareGroupCommand_HelpCallback(args);
            return;
              }

              Group tsGroup = TShock.Groups.GetGroupByName(shareTargetRaw);
              if (tsGroup == null) {
            args.Player.SendErrorMessage("A group with the name \"{0}\" does not exist.", shareTargetRaw);
            return;
              }

              Region region;
              if (!this.TryGetAccessibleHouseRegionAtPlayer(args.Player, out region))
            return;

              if (!TShock.Regions.RemoveGroup(region.Name, tsGroup.Name)) {
            args.Player.SendErrorMessage("Internal error has occured.");
            return;
              }

              args.Player.SendSuccessMessage("Users of group \"{0}\" have no more build access to this house anymore.", tsGroup.Name);
        }
        private void HouseUnshareCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              if (args.Parameters.Count < 2) {
            args.Player.SendErrorMessage("Proper syntax: /house unshare <user name>");
            args.Player.SendInfoMessage("Type /house unshare help to get more information about this command.");
            return;
              }

              string shareTargetRaw = args.ParamsToSingleString(1);
              if (shareTargetRaw.Equals("help", StringComparison.InvariantCultureIgnoreCase)) {
            this.HouseUnshareCommand_HelpCallback(args);
            return;
              }

              User tsUser;
              if (!TShockEx.MatchUserByPlayerName(shareTargetRaw, out tsUser, args.Player))
            return;

              Region region;
              if (!this.TryGetAccessibleHouseRegionAtPlayer(args.Player, out region))
            return;

              if (!TShock.Regions.RemoveUser(region.Name, tsUser.Name)) {
            args.Player.SendErrorMessage("Internal error has occured.");
            return;
              }

              args.Player.SendSuccessMessage("User \"{0}\" has no more build access to this house anymore.", tsUser.Name);
        }
        private void HouseSetOwnerCommand_Exec(CommandArgs args)
        {
            if (args == null || this.IsDisposed)
            return;

              if (args.Parameters.Count < 2) {
            args.Player.SendErrorMessage("Proper syntax: /house setowner <user name>");
            args.Player.SendInfoMessage("Type /house setowner help to get more information about this command.");
            return;
              }

              string newOwnerRaw = args.ParamsToSingleString(1);
              if (newOwnerRaw.Equals("help", StringComparison.InvariantCultureIgnoreCase)) {
            this.HouseSetOwnerCommand_HelpCallback(args);
            return;
              }

              User tsUser;
              if (!TShockEx.MatchUserByPlayerName(newOwnerRaw, out tsUser, args.Player))
            return;

              Region region;
              if (!this.TryGetAccessibleHouseRegionAtPlayer(args.Player, out region))
            return;

              if (tsUser.Name == region.Owner) {
            args.Player.SendErrorMessage($"{tsUser.Name} is already the owner of this region.");
            return;
              }

              Group tsGroup = TShock.Groups.GetGroupByName(tsUser.Group);
              if (tsGroup == null) {
            args.Player.SendErrorMessage("The new owner's TShock group could not be determined.");
            return;
              }

              try {
            this.HousingManager.CreateHouseRegion(tsUser, tsGroup, region.Area, false, true, false);
              } catch (LimitEnforcementException) {
            args.Player.SendErrorMessage("The new owner of the house would exceed their house limit.");
            return;
              } catch (Exception ex) {
            args.Player.SendErrorMessage("Internal error has occured: " + ex.Message);
            return;
              }

              if (!TShock.Regions.DeleteRegion(region.Name)) {
            args.Player.SendErrorMessage("Internal error has occured when deleting the old house region.");
            return;
              }

              args.Player.SendSuccessMessage($"The owner of this house has been set to \"{tsUser.Name}\" and all shared users and groups were deleted from it.");
        }