public virtual bool HandleHitSwitch(TSPlayer player, DPoint location)
        {
            if (this.IsDisposed || this.activeCommandInteractions.Count == 0)
            {
                return(false);
            }

            CommandInteraction interaction;

            lock (this.activeCommandInteractionsLock) {
                // Is the player currently interacting with a command?
                if (!this.activeCommandInteractions.TryGetValue(player, out interaction))
                {
                    return(false);
                }

                if (interaction.HitSwitchCallback == null)
                {
                    return(false);
                }

                CommandInteractionResult result = interaction.HitSwitchCallback(player, location);
                if (interaction.DoesNeverComplete)
                {
                    interaction.ResetTimer();
                }
                else if (result.IsInteractionCompleted)
                {
                    this.activeCommandInteractions.Remove(player);
                }

                return(result.IsHandled);
            }
        }
        public virtual bool HandleTileEdit(TSPlayer player, TileEditType editType, BlockType blockType, DPoint location, int objectStyle)
        {
            if (this.IsDisposed || this.activeCommandInteractions.Count == 0)
            {
                return(false);
            }

            lock (this.activeCommandInteractionsLock) {
                CommandInteraction interaction;
                // Is the player currently interacting with a command?
                if (!this.activeCommandInteractions.TryGetValue(player, out interaction))
                {
                    return(false);
                }

                if (interaction.TileEditCallback == null)
                {
                    return(false);
                }

                CommandInteractionResult result = interaction.TileEditCallback(player, editType, blockType, location, objectStyle);
                if (interaction.DoesNeverComplete)
                {
                    interaction.ResetTimer();
                }
                else if (result.IsInteractionCompleted)
                {
                    this.activeCommandInteractions.Remove(player);
                }

                return(result.IsHandled);
            }
        }
        public virtual bool HandleSignEdit(TSPlayer player, int signIndex, DPoint location, string newText)
        {
            if (this.IsDisposed || this.activeCommandInteractions.Count == 0)
            {
                return(false);
            }

            lock (this.activeCommandInteractionsLock) {
                CommandInteraction interaction;
                // Is the player currently interacting with a command?
                if (!this.activeCommandInteractions.TryGetValue(player, out interaction))
                {
                    return(false);
                }

                if (interaction.SignEditCallback == null)
                {
                    return(false);
                }

                CommandInteractionResult result = interaction.SignEditCallback(player, signIndex, location, newText);
                if (interaction.DoesNeverComplete)
                {
                    interaction.ResetTimer();
                }
                else if (result.IsInteractionCompleted)
                {
                    this.activeCommandInteractions.Remove(player);
                }

                return(result.IsHandled);
            }
        }
        private bool TryExecuteSubCommand(string commandNameLC, CommandArgs args)
        {
            switch (commandNameLC) {
            case "commands":
            case "cmds":
              args.Player.SendMessage("Available Sub-Commands:", Color.White);
              args.Player.SendMessage("/ac blocks", Color.Yellow);
              args.Player.SendMessage("/ac toggle|switch", Color.Yellow);

              if (args.Player.Group.HasPermission(AdvancedCircuitsPlugin.ReloadCfg_Permission))
            args.Player.SendMessage("/ac reloadcfg", Color.Yellow);

              return true;
            case "reloadcfg":
              if (args.Player.Group.HasPermission(AdvancedCircuitsPlugin.ReloadCfg_Permission)) {
            this.PluginTrace.WriteLineInfo("Reloading configuration file.");
            try {
              this.ReloadConfigurationCallback();
              this.PluginTrace.WriteLineInfo("Configuration file successfully reloaded.");

              if (args.Player != TSPlayer.Server)
                args.Player.SendMessage("Configuration file successfully reloaded.", Color.Yellow);
            } catch (Exception ex) {
              this.PluginTrace.WriteLineError(
                "Reloading the configuration file failed. Keeping old configuration. Exception details:\n{0}", ex
              );
            }
              } else {
            args.Player.SendErrorMessage("You do not have the necessary permission to do that.");
              }

              return true;
            case "blocks":
            case "ores":
            case "tiles":
              int pageNumber;
              if (!PaginationUtil.TryParsePageNumber(args.Parameters, 1, args.Player, out pageNumber))
            return true;

              PaginationUtil.SendPage(
            args.Player, pageNumber,
            new List<string>() {
              "Copper Ore - OR-Gate",
              "Silver Ore - AND-Gate",
              "Gold Ore - XOR-Gate / XOR-Port",
              "Obsidian - NOT-Gate / NOT-Port",
              "Iron Ore - Swapper",
              "Spike - Crossover Bridge",
              "Glass - Input Port",
              "Active Stone - Active Stone and Block Activator",
              "Adamantite Ore - Wireless Transmitter"
            },
            new PaginationUtil.Settings {
              HeaderFormat = "Advanced Circuits Special Blocks (Page {0} of {1})",
              HeaderTextColor = Color.Lime,
              LineTextColor = Color.LightGray,
              MaxLinesPerPage = 4,
            }
              );

              return true;
            case "toggle":
            case "switch":
              args.Player.SendInfoMessage("Place or destroy a wire on the component you want to toggle.");

              if (args.Parameters.Count > 3) {
            args.Player.SendErrorMessage("Proper syntax: /ac switch [state] [+p]");
            args.Player.SendInfoMessage("Type /ac switch help to get more help to this command.");
            return true;
              }

              bool persistentMode = false;
              bool? newState = null;
              if (args.Parameters.Count > 1) {
            int newStateRaw;
            if (int.TryParse(args.Parameters[1], out newStateRaw))
              newState = (newStateRaw == 1);

            persistentMode = args.ContainsParameter("+p", StringComparison.InvariantCultureIgnoreCase);
              }

              CommandInteraction interaction = this.StartOrResetCommandInteraction(args.Player);
              interaction.DoesNeverComplete = persistentMode;
              interaction.TileEditCallback = (player, editType, blockType, location, blockStyle) => {
            if (
              editType != TileEditType.PlaceTile ||
              editType != TileEditType.PlaceWall ||
              editType != TileEditType.DestroyWall ||
              editType != TileEditType.PlaceActuator
            ) {
              CommandInteractionResult result = new CommandInteractionResult { IsHandled = true, IsInteractionCompleted = true };
              Tile tile = TerrariaUtils.Tiles[location];

              if (
                TShock.CheckTilePermission(args.Player, location.X, location.Y) || (
                  this.PluginCooperationHandler.IsProtectorAvailable &&
                  this.PluginCooperationHandler.Protector_CheckProtected(args.Player, location, false)
                )
              ) {
                player.SendErrorMessage("This object is protected.");
                player.SendTileSquare(location, 1);
                return result;
              }

              BlockType hitBlockType = (BlockType)tile.type;
              if (tile.active() && hitBlockType == BlockType.ActiveStone) {
                if (newState == null || newState == false)
                  TerrariaUtils.Tiles.SetBlock(location, BlockType.InactiveStone);
                else
                  args.Player.SendTileSquare(location);
              } else if (hitBlockType == BlockType.InactiveStone) {
                if (tile.active() &&  newState == null || newState == true)
                  TerrariaUtils.Tiles.SetBlock(location, BlockType.ActiveStone);
                else
                  args.Player.SendTileSquare(location);
              } else if (tile.active() && TerrariaUtils.Tiles.IsMultistateObject(hitBlockType)) {
                ObjectMeasureData measureData = TerrariaUtils.Tiles.MeasureObject(location);
                bool currentState = TerrariaUtils.Tiles.ObjectHasActiveState(measureData);
                if (newState == null)
                  newState = !TerrariaUtils.Tiles.ObjectHasActiveState(measureData);

                if (currentState != newState.Value)
                  TerrariaUtils.Tiles.SetObjectState(measureData, newState.Value);
                else
                  args.Player.SendTileSquare(location);
              } else if (
                hitBlockType == AdvancedCircuits.BlockType_ORGate ||
                hitBlockType == AdvancedCircuits.BlockType_ANDGate ||
                hitBlockType == AdvancedCircuits.BlockType_XORGate
              ) {
                if (
                  TShock.CheckTilePermission(args.Player, location.X, location.Y) || (
                  this.PluginCooperationHandler.IsProtectorAvailable &&
                  this.PluginCooperationHandler.Protector_CheckProtected(args.Player, location, false)
                )) {
                  player.SendErrorMessage("This gate is protected.");
                  player.SendTileSquare(location);
                  return result;
                }

                PaintColor paint = (PaintColor)TerrariaUtils.Tiles[location].color();
                if (paint == AdvancedCircuits.Paint_Gate_TemporaryState) {
                  player.SendErrorMessage("The gate is painted {0}, there's no point in initializing it.", AdvancedCircuits.Paint_Gate_TemporaryState);
                  args.Player.SendTileSquare(location);
                  return result;
                }

                GateStateMetadata gateState;
                if (!this.WorldMetadata.GateStates.TryGetValue(location, out gateState)) {
                  gateState = new GateStateMetadata();
                  this.WorldMetadata.GateStates.Add(location, gateState);
                }

                List<DPoint> gatePortLocations = new List<DPoint>(AdvancedCircuits.EnumerateComponentPortLocations(location, new DPoint(1, 1)));
                for (int i = 0; i < 4; i++) {
                  Tile gatePort = TerrariaUtils.Tiles[gatePortLocations[i]];
                  if (!gatePort.active() || gatePort.type != (int)AdvancedCircuits.BlockType_InputPort)
                    continue;

                  if (newState == null) {
                    if (gateState.PortStates[i] == null)
                      gateState.PortStates[i] = true;
                    else
                      gateState.PortStates[i] = !gateState.PortStates[i];
                  } else {
                    gateState.PortStates[i] = newState.Value;
                  }
                }

                player.SendSuccessMessage("The states of this gate's ports are now:");
                this.SendGatePortStatesInfo(args.Player, gateState);
                args.Player.SendTileSquare(location);
              } else if (tile.active() && tile.type == (int)AdvancedCircuits.BlockType_InputPort) {
                foreach (DPoint adjacentTileLocation in AdvancedCircuits.EnumerateComponentPortLocations(location, new DPoint(1, 1))) {
                  Tile adjacentTile = TerrariaUtils.Tiles[adjacentTileLocation];
                  if (!adjacentTile.active() || !AdvancedCircuits.IsLogicalGate((BlockType)adjacentTile.type))
                    continue;

                  if (
                    TShock.CheckTilePermission(args.Player, adjacentTileLocation.X, adjacentTileLocation.Y) || (
                      this.PluginCooperationHandler.IsProtectorAvailable &&
                      this.PluginCooperationHandler.Protector_CheckProtected(args.Player, adjacentTileLocation, false)
                    )
                  ) {
                    player.SendErrorMessage("This gate is protected.");
                    player.SendTileSquare(location);
                    return result;
                  }

                  PaintColor paint = (PaintColor)TerrariaUtils.Tiles[location].color();
                  if (paint == AdvancedCircuits.Paint_Gate_TemporaryState) {
                    player.SendErrorMessage("The gate is painted {0}, there's no point in initializing it.", AdvancedCircuits.Paint_Gate_TemporaryState);
                    args.Player.SendTileSquare(location);
                    return result;
                  }

                  GateStateMetadata gateState;
                  if (!this.WorldMetadata.GateStates.TryGetValue(adjacentTileLocation, out gateState)) {
                    gateState = new GateStateMetadata();
                    this.WorldMetadata.GateStates.Add(adjacentTileLocation, gateState);
                  }

                  int portIndex;
                  switch (AdvancedCircuits.DirectionFromTileLocations(adjacentTileLocation, location)) {
                    case Direction.Up:
                      portIndex = 0;
                      break;
                    case Direction.Down:
                      portIndex = 1;
                      break;
                    case Direction.Left:
                      portIndex = 2;
                      break;
                    case Direction.Right:
                      portIndex = 3;
                      break;
                    default:
                      return result;
                  }

                  if (newState == null) {
                    if (gateState.PortStates[portIndex] == null)
                      gateState.PortStates[portIndex] = true;
                    else
                      gateState.PortStates[portIndex] = !gateState.PortStates[portIndex];
                  } else {
                    gateState.PortStates[portIndex] = newState.Value;
                  }

                  player.SendSuccessMessage("The states of this gate's ports are now:");
                  this.SendGatePortStatesInfo(args.Player, gateState);
                  args.Player.SendTileSquare(location);
                  return result;
                }

                player.SendErrorMessage(string.Format(
                  "The state of \"{0}\" can not be changed.", TerrariaUtils.Tiles.GetBlockTypeName(hitBlockType)
                ));

                player.SendTileSquare(location);
              }

              return result;
            }

            return new CommandInteractionResult { IsHandled = false, IsInteractionCompleted = false };
              };
              interaction.TimeExpiredCallback = (player) => {
            player.SendErrorMessage("Waited too long, no component will be toggled.");
              };

              args.Player.SendSuccessMessage("Hit an object to change its state.");
              return true;
              }

              return false;
        }