protected bool SignalComponent(ref ObjectMeasureData measureData, RootBranchProcessData rootBranch, SignalType signal, bool localOnly = false)
        {
            int originX = measureData.OriginTileLocation.X;
              int originY = measureData.OriginTileLocation.Y;

              switch (measureData.BlockType) {
            case BlockType.Torch:
            case BlockType.XMasLight:
            case BlockType.Candle:
            case BlockType.PlatinumCandle:
            case BlockType.ChainLantern:
            case BlockType.ChineseLantern:
            case BlockType.Candelabra:
            case BlockType.PlatinumCandelabra:
            case BlockType.DiscoBall:
            case BlockType.TikiTorch:
            case BlockType.CopperChandelier:
            case BlockType.SilverChandelier:
            case BlockType.GoldChandelier:
            case BlockType.PlatinumChandelier:
            case BlockType.LampPost:
            case BlockType.MusicBox:
            case BlockType.XSecondTimer:
            case BlockType.WaterFountain:
            case BlockType.BubbleMachine: {
              bool currentState = TerrariaUtils.Tiles.ObjectHasActiveState(measureData);
              bool newState;
              if (signal == SignalType.Swap)
            newState = !currentState;
              else
            newState = AdvancedCircuits.SignalToBool(signal).Value;

              if (measureData.BlockType == BlockType.XSecondTimer) {
            // Directly wired Timers in an Advanced Circuit are not meant to be switched.
            if (this.IsAdvancedCircuit)
              return false;

            if (newState != currentState)
              this.CircuitHandler.RegisterUnregisterTimer(this.TriggeringPlayer, measureData, newState);
              }

              if (newState != currentState)
            TerrariaUtils.Tiles.SetObjectState(measureData, newState, !localOnly);

              return true;
            }
            case BlockType.ActiveStone:
            case BlockType.InactiveStone: {
              bool currentState = (measureData.BlockType == BlockType.ActiveStone);
              bool newState;
              if (signal == SignalType.Swap)
            newState = !currentState;
              else
            newState = AdvancedCircuits.SignalToBool(signal).Value;

              if (newState != currentState) {
            BlockType newBlockType;
            if (newState)
              newBlockType = BlockType.ActiveStone;
            else
              newBlockType = BlockType.InactiveStone;

            TerrariaUtils.Tiles[measureData.OriginTileLocation].type = (byte)newBlockType;
            WorldGen.SquareTileFrame(originX, originY);
            TSPlayer.All.SendTileSquareEx(originX, originY, 1);
              }

              return true;
            }
            case BlockType.DoorClosed:
            case BlockType.DoorOpened: {
              if (this.IsAdvancedCircuit)
            return false;

              this.OpenDoor(measureData, signal);
              return true;
            }
            case BlockType.InletPump:
            case BlockType.OutletPump: {
              if (signal == SignalType.Off)
            return false;

              PumpConfig pumpConfig;
              PaintColor componentPaint = (PaintColor)TerrariaUtils.Tiles[measureData.OriginTileLocation].color();
              if (
            (
              this.CircuitHandler.Config.PumpConfigs.TryGetValue(componentPaint, out pumpConfig) ||
              this.CircuitHandler.Config.PumpConfigs.TryGetValue(PaintColor.None, out pumpConfig)
            ) &&
              pumpConfig.Cooldown == 0 ||
              WorldGen.checkMech(originX, originY, pumpConfig.Cooldown
            )
              ) {
            if (this.Result.SignaledPumps > this.CircuitHandler.Config.MaxPumpsPerCircuit) {
              this.Result.WarnReason = CircuitWarnReason.SignalesTooManyPumps;
              return true;
            }
            if (
              pumpConfig.TriggerPermission != null &&
              this.TriggeringPlayer != TSPlayer.Server &&
              !this.TriggeringPlayer.Group.HasPermission(pumpConfig.TriggerPermission)
            ) {
              this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
              this.Result.WarnRelatedComponentType = measureData.BlockType;
              return true;
            }

            if (measureData.BlockType == BlockType.InletPump)
              this.SignaledInletPumps.Add(new DPoint(originX, originY));
            else
              this.SignaledOutletPumps.Add(new DPoint(originX, originY));

            this.Result.SignaledPumps++;
              }

              return true;
            }
            case BlockType.DartTrap: {
              if (signal == SignalType.Off)
            return false;

              TrapConfig trapConfig;
              Tile componentTile = TerrariaUtils.Tiles[measureData.OriginTileLocation];
              PaintColor componentPaint = (PaintColor)componentTile.color();
              TrapStyle trapStyle = TerrariaUtils.Tiles.GetTrapStyle(componentTile.frameY / 18);
              TrapConfigKey configKey = new TrapConfigKey(trapStyle, componentPaint);
              TrapConfigKey defaultKey = new TrapConfigKey(trapStyle, PaintColor.None);
              if (
            (
              this.CircuitHandler.Config.TrapConfigs.TryGetValue(configKey, out trapConfig) ||
              this.CircuitHandler.Config.TrapConfigs.TryGetValue(defaultKey, out trapConfig)
            ) &&
              trapConfig.Cooldown == 0 ||
              WorldGen.checkMech(originX, originY, trapConfig.Cooldown
            )
              ) {
            if (this.Result.SignaledTraps > this.CircuitHandler.Config.MaxTrapsPerCircuit) {
              this.Result.WarnReason = CircuitWarnReason.SignalesTooManyTraps;
              return true;
            }
            if (
              trapConfig.TriggerPermission != null &&
              this.TriggeringPlayer != TSPlayer.Server &&
              !this.TriggeringPlayer.Group.HasPermission(trapConfig.TriggerPermission)
            ) {
              this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
              this.Result.WarnRelatedComponentType = BlockType.DartTrap;
              return true;
            }

            int projectileIndex = 1000;
            for (int i = 0; i < 1000; ++i) {
              if (!Main.projectile[i].active) {
                projectileIndex = i;
                break;
              }
            }
            if (projectileIndex == 1000)
              return true;

            bool isFacingLeft = (TerrariaUtils.Tiles[originX, originY].frameX == 0);
            float projectileAngle = trapConfig.ProjectileAngle;
            if (isFacingLeft)
              projectileAngle += 180f;

            projectileAngle += CircuitProcessor.Random.Next(-(int)trapConfig.ProjectileAngleVariance, (int)trapConfig.ProjectileAngleVariance + 1);

            Vector2 normalizedPolarOffset = new Vector2(
              (float)Math.Cos(Math.PI * projectileAngle / 180f),
              (float)Math.Sin(Math.PI * projectileAngle / 180f)
            );
            Projectile projectile = Main.projectile[projectileIndex];
            projectile.SetDefaults(trapConfig.ProjectileType);
            Vector2 projectileSpawn = new Vector2(
              (originX * TerrariaUtils.TileSize + (trapConfig.ProjectileOffset * normalizedPolarOffset.X)),
              (originY * TerrariaUtils.TileSize + (trapConfig.ProjectileOffset * normalizedPolarOffset.Y))
            );
            projectileSpawn = projectileSpawn.Add(new Vector2(
              TerrariaUtils.TileSize / 2 - projectile.width / 2,
              TerrariaUtils.TileSize / 2 - projectile.height / 2
            ));
            projectile.position.X = projectileSpawn.X;
            projectile.position.Y = projectileSpawn.Y;
            projectile.owner = Main.myPlayer;
            projectile.velocity.X = (trapConfig.ProjectileSpeed * normalizedPolarOffset.X);
            projectile.velocity.Y = (trapConfig.ProjectileSpeed * normalizedPolarOffset.Y);
            projectile.damage = trapConfig.ProjectileDamage;
            projectile.knockBack = trapConfig.ProjectileKnockback;
            projectile.identity = projectileIndex;
            projectile.timeLeft = trapConfig.ProjectileLifeTime;
            projectile.wet = Collision.WetCollision(projectile.position, projectile.width, projectile.height);
            TSPlayer.All.SendData(PacketTypes.ProjectileNew, string.Empty, projectileIndex);

            this.Result.SignaledTraps++;
              }

              return true;
            }
            case BlockType.Explosives: {
              if (signal == SignalType.Off)
            return false;

              WorldGen.KillTile(originX, originY, false, false, true);
              TSPlayer.All.SendTileSquareEx(originX, originY, 1);
              Projectile.NewProjectile((originX * 16 + 8), (originY * 16 + 8), 0f, 0f, 108, 250, 10f, Main.myPlayer);

              return true;
            }
            case BlockType.Statue: {
              if (signal == SignalType.Off)
            return false;

              StatueStyle statueStyle = TerrariaUtils.Tiles.GetStatueStyle(TerrariaUtils.Tiles[measureData.OriginTileLocation]);
              StatueConfig statueConfig;
              if (
            this.CircuitHandler.Config.StatueConfigs.TryGetValue(statueStyle, out statueConfig) &&
            statueConfig.Actions.Count > 0 && (
              statueConfig.Cooldown == 0 ||
              WorldGen.checkMech(originX, originY, statueConfig.Cooldown)
            )
              ) {
            if (this.Result.SignaledStatues > this.CircuitHandler.Config.MaxStatuesPerCircuit) {
              this.Result.WarnReason = CircuitWarnReason.SignalesTooManyStatues;
              return true;
            }
            if (
              statueConfig.TriggerPermission != null &&
              this.TriggeringPlayer != TSPlayer.Server &&
              !this.TriggeringPlayer.Group.HasPermission(statueConfig.TriggerPermission)
            ) {
              this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
              this.Result.WarnRelatedComponentType = BlockType.Statue;
              return true;
            }

            if (statueConfig.PlayerCheckRange > 0) {
              bool isPlayerInRange = false;
              foreach (TSPlayer player in TShock.Players) {
                if (player == null || !player.Active)
                  continue;
                if (Math.Sqrt(Math.Pow(player.TileX - originX, 2) + Math.Pow(player.TileY - originY, 2)) <= statueConfig.PlayerCheckRange) {
                  isPlayerInRange = true;
                  break;
                }
              }
              if (!isPlayerInRange)
                return true;
            }

            if (statueConfig.ActionsProcessingMethod == ActionListProcessingMethod.ExecuteAll) {
              foreach (NullStatueAction action in statueConfig.Actions)
                this.ExecuteStatueAction(measureData.OriginTileLocation, action);
            } else {
              NullStatueAction randomAction = statueConfig.Actions[CircuitProcessor.Random.Next(0, statueConfig.Actions.Count)];
              this.ExecuteStatueAction(measureData.OriginTileLocation, randomAction);
            }

            this.Result.SignaledStatues++;
              }

              return true;
            }
            case BlockType.Sign: {
              if (!this.IsAdvancedCircuit || signal == SignalType.Off || this.TriggeringPlayer == TSPlayer.Server)
            return false;

              if (this.IsTriggeredPassively && !this.TriggeringPlayer.Group.HasPermission(AdvancedCircuitsPlugin.PassiveTriggerSign_Permission)) {
            this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
            this.Result.WarnRelatedComponentType = BlockType.Sign;
            return false;
              }

              string signText = Main.sign[Sign.ReadSign(originX, originY)].text;
              if (signText == null)
            return false;

              if (
            this.CircuitHandler.PluginCooperationHandler.IsSignCommandsAvailable &&
            this.CircuitHandler.PluginCooperationHandler.SignCommands_CheckIsSignCommand(signText)
              ) {
            if (!this.TriggeringPlayer.Group.HasPermission(AdvancedCircuitsPlugin.TriggerSignCommand_Permission)) {
              this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
              this.Result.WarnRelatedComponentType = BlockType.Sign;
              return false;
            }

            this.CircuitHandler.PluginCooperationHandler.SignCommands_ExecuteSignCommand(
              this.TriggeringPlayer, measureData.OriginTileLocation, signText
            );
            return true;
              }

              if (!WorldGen.checkMech(originX, originY, 300))
            return true;

              string fullText = this.CircuitHandler.Config.SignConfig.ReadPrefix + signText;
              int lineStartIndex = 0;
              int lineLength = 0;
              for (int i = 0; i < fullText.Length; i++) {
            if (lineLength == 60 || fullText[i] == '\n' || (i == fullText.Length - 1 && lineLength > 0)) {
              if (fullText[i] == '\n') {
                if (lineLength > 0)
                  this.TriggeringPlayer.SendInfoMessage(fullText.Substring(lineStartIndex, i - lineStartIndex));
                else
                  this.TriggeringPlayer.SendInfoMessage(string.Empty);

                lineStartIndex = i + 1;
              } else if (i == fullText.Length - 1) {
                this.TriggeringPlayer.SendInfoMessage(fullText.Substring(lineStartIndex, i - lineStartIndex + 1));
                lineStartIndex = i;
              } else {
                this.TriggeringPlayer.SendInfoMessage(fullText.Substring(lineStartIndex, i - lineStartIndex));
                lineStartIndex = i;
              }

              lineLength = 0;
              continue;
            }

            lineLength++;
              }

              return true;
            }
            case BlockType.Boulder: {
              if (!this.IsAdvancedCircuit || signal == SignalType.Off)
            return false;

              WorldGen.KillTile(originX, originY, false, false, true);
              TSPlayer.All.SendTileSquareEx(originX, originY, 2);
              return true;
            }
            case BlockType.LandMine: {
              if (signal == SignalType.Off)
            return false;

              WorldGen.ExplodeMine(originX, originY);
              return true;
            }
            case BlockType.Rocket: {
              if (signal == SignalType.Off)
            return false;

              WorldGen.LaunchRocket(originX, originY);
              return true;
            }
            case BlockType.Teleporter: {
              if (signal == SignalType.Off)
            return false;
              if (TerrariaUtils.Tiles[measureData.OriginTileLocation].wall == (int)WallType.LihzahrdBrickWall && !(originY <= Main.worldSurface || NPC.downedPlantBoss))
            return true;
              if (this.TriggeringPlayer != TSPlayer.Server && !this.TriggeringPlayer.Group.HasPermission(AdvancedCircuitsPlugin.TriggerTeleporter_Permission)) {
            this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
            this.Result.WarnRelatedComponentType = BlockType.Teleporter;
            return false;
              }

              if (rootBranch.TeleporterLocation == DPoint.Empty) {
            rootBranch.TeleporterLocation = measureData.OriginTileLocation;
              } else {
            WorldGen.teleport[0] = rootBranch.TeleporterLocation.ToXnaVector2();
            WorldGen.teleport[1] = measureData.OriginTileLocation.ToXnaVector2();
            WorldGen.Teleport();
            WorldGen.teleport[0] = WorldGen.teleport[1] = new Vector2(-1f, -1f);

            rootBranch.TeleporterLocation = DPoint.Empty;
              }
              return true;
            }
              }

              return false;
        }
        protected virtual void ProcessTile(
            RootBranchProcessData rootBranch, DPoint tileLocation, DPoint adjacentTileLocation, SignalType signal
            )
        {
            if (this.IsCancellationPending)
            return;

              Tile tile = TerrariaUtils.Tiles[tileLocation];

              // If the tile has no wire it might be a AC-Component and thus the adjacent tile would be its port.
              if (!tile.HasWire(rootBranch.WireColor) && tile.active()) {
            if (!this.IsAdvancedCircuit || adjacentTileLocation == DPoint.Empty)
              return;
            if (!AdvancedCircuits.IsPortDefiningComponentBlock((BlockType)tile.type))
              return;
            if (signal == SignalType.Swap)
              throw new ArgumentException("A Port can not receive a Swap signal.", "signal");

            ObjectMeasureData acComponentMeasureData = TerrariaUtils.Tiles.MeasureObject(tileLocation);
            // The origin sender can only signal itself if it is a timer.
            if (
              acComponentMeasureData.OriginTileLocation == this.SenderMeasureData.OriginTileLocation &&
              tile.type != (int)BlockType.XSecondTimer
            ) {
              return;
            }

            int componentSignalCounter;
            this.PortDefiningComponentSignalCounter.TryGetValue(acComponentMeasureData.OriginTileLocation, out componentSignalCounter);
            if (componentSignalCounter > CircuitProcessor.PortDefiningComponentSignalMaximum) {
              this.Result.CancellationReason = CircuitCancellationReason.SignaledSameComponentTooOften;
              this.Result.CancellationRelatedComponentType = acComponentMeasureData.BlockType;
              return;
            }

            if (
              AdvancedCircuits.IsOriginSenderComponent((BlockType)tile.type) &&
              rootBranch.SignaledComponentLocations.Contains(acComponentMeasureData.OriginTileLocation)
            )
              return;

            if (this.SignalPortDefiningComponent(
              rootBranch, acComponentMeasureData, adjacentTileLocation, AdvancedCircuits.SignalToBool(signal).Value
            )) {
              rootBranch.SignaledComponentLocations.Add(acComponentMeasureData.OriginTileLocation);

              if (componentSignalCounter == default(int))
            this.PortDefiningComponentSignalCounter.Add(acComponentMeasureData.OriginTileLocation, 1);
              else
            this.PortDefiningComponentSignalCounter[acComponentMeasureData.OriginTileLocation] = componentSignalCounter + 1;

              this.Result.SignaledPortDefiningComponentsCounter++;
            }

            return;
              }

              if (!tile.HasWire(rootBranch.WireColor))
            return;

              try {
            // Actuator Handling
            if (tile.actuator() && (tile.type != (int)BlockType.LihzahrdBrick || tileLocation.Y <= Main.worldSurface || NPC.downedPlantBoss)) {
              bool currentState = tile.inActive();
              bool newState;
              if (signal == SignalType.Swap)
            newState = !currentState;
              else
            newState = AdvancedCircuits.SignalToBool(signal).Value;

              if (newState != currentState) {
            if (newState)
              WorldGen.DeActive(tileLocation.X, tileLocation.Y);
            else
              WorldGen.ReActive(tileLocation.X, tileLocation.Y);
              }
            }

            // Block Activator tile activation / deactivation.
            if (rootBranch.BlockActivator != null) {
              Tile blockActivatorTile = TerrariaUtils.Tiles[rootBranch.BlockActivatorLocation];
              if (tile.wall == blockActivatorTile.wall) {
            Tile tileAbove = TerrariaUtils.Tiles[tileLocation.OffsetEx(0, -1)];
            if (!tileAbove.active() || tileAbove.type != (int)BlockType.Chest) {
              if (
                signal == SignalType.Off && tile.active() && AdvancedCircuits.IsCustomActivatableBlock((BlockType)tile.type)
              ) {
                if (rootBranch.BlockActivator.RegisteredInactiveBlocks.Count > this.CircuitHandler.Config.BlockActivatorConfig.MaxChangeableBlocks) {
                  this.Result.WarnReason = CircuitWarnReason.BlockActivatorChangedTooManyBlocks;
                  return;
                }

                rootBranch.BlockActivator.RegisteredInactiveBlocks.Add(tileLocation, (BlockType)tile.type);

                tile.type = 0;
                tile.active(false);
                tile.frameX = -1;
                tile.frameY = -1;
                tile.frameNumber(0);
                this.TilesToFrameOnPost.Add(tileLocation);

                return;
              } else if (
                signal == SignalType.On && (rootBranch.BlockActivatorMode == BlockActivatorMode.ReplaceBlocks || !tile.active())
              ) {
                BlockType registeredBlockType;
                if (rootBranch.BlockActivator.RegisteredInactiveBlocks.TryGetValue(tileLocation, out registeredBlockType)) {
                  rootBranch.BlockActivator.RegisteredInactiveBlocks.Remove(tileLocation);

                  tile.type = (byte)registeredBlockType;
                  tile.active(true);
                  this.TilesToFrameOnPost.Add(tileLocation);

                  return;
                }
              }
            }
              }
            }

            if (!tile.active())
              return;

            ObjectMeasureData componentMeasureData = TerrariaUtils.Tiles.MeasureObject(tileLocation);
            if (rootBranch.SignaledComponentLocations.Contains(componentMeasureData.OriginTileLocation))
              return;

            // The origin sender can never signal itself if wired directly.
            if (componentMeasureData.OriginTileLocation == this.SenderMeasureData.OriginTileLocation)
              return;

            // Switches and Levers can not be signaled if they are wired directly.
            if (tile.type == (int)BlockType.Switch || tile.type == (int)BlockType.Lever)
              return;

            if (this.SignalComponent(ref componentMeasureData, rootBranch, signal)) {
              rootBranch.SignaledComponentLocations.Add(componentMeasureData.OriginTileLocation);
              this.Result.SignaledComponentsCounter++;
            }
              } finally {
            this.CircuitLength++;

            if (this.CircuitLength >= this.CircuitHandler.Config.MaxCircuitLength) {
              this.Result.CancellationReason = CircuitCancellationReason.ExceededMaxLength;
              this.PluginTrace.WriteLineInfo(
            "Processing of the circuit at {0} was cancelled because the signal reached the maximum transfer length of {1} wires.",
            this.SenderMeasureData.OriginTileLocation, this.CircuitHandler.Config.MaxCircuitLength
              );
            }
              }
        }
        private bool SignalPortDefiningComponent(RootBranchProcessData rootBranch, ObjectMeasureData measureData, DPoint portLocation, bool signal)
        {
            if (!this.IsAdvancedCircuit)
            throw new InvalidOperationException("This is no advanced circuit.");

              Tile portTile = TerrariaUtils.Tiles[portLocation];
              Tile componentTile = TerrariaUtils.Tiles[measureData.OriginTileLocation];
              if (!portTile.HasWire(rootBranch.WireColor) || componentTile.HasWire())
            return false;

              if (portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_NOTGate && measureData.BlockType != AdvancedCircuits.BlockType_NOTGate)
            signal = !signal;
              else if (portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_XORGate && measureData.BlockType != AdvancedCircuits.BlockType_XORGate)
            signal = false;

              List<DPoint> componentPorts = null;
              bool outputSignal = signal;
              DPoint componentLocation = measureData.OriginTileLocation;
              PaintColor componentPaint = (PaintColor)TerrariaUtils.Tiles[measureData.OriginTileLocation].color();

              BlockActivatorMetadata blockActivatorToRegister = null;
              DPoint blockActivatorLocationToRegister = DPoint.Empty;
              BlockActivatorMode blockActivatorModeToRegister = BlockActivatorMode.Default;

              switch (measureData.BlockType) {
            case BlockType.DoorOpened:
            case BlockType.DoorClosed: {
              for (int y = measureData.OriginTileLocation.Y; y < measureData.OriginTileLocation.Y + measureData.Size.Y; y++)
            if (TerrariaUtils.Tiles[measureData.OriginTileLocation.X, y].HasWire())
              return false;

              if (measureData.BlockType == BlockType.DoorOpened) {
            // Extra check needed if a port of the door is really hit. This is because doors define ports differently than
            // other components if they are opened.
            componentPorts = new List<DPoint>(AdvancedCircuits.EnumerateComponentPortLocations(measureData));
            if (!componentPorts.Contains(portLocation))
              return false;
              }

              this.OpenDoor(measureData, AdvancedCircuits.BoolToSignal(signal));
              break;
            }
            case BlockType.XSecondTimer: {
              if (!portTile.active() || portTile.type != (int)AdvancedCircuits.BlockType_InputPort)
            return false;

              bool currentState = (TerrariaUtils.Tiles.ObjectHasActiveState(measureData));
              if (currentState != signal)
            TerrariaUtils.Tiles.SetObjectState(measureData, signal);

              if (currentState != signal)
            this.CircuitHandler.RegisterUnregisterTimer(this.TriggeringPlayer, measureData, signal);
              else if (signal)
            this.CircuitHandler.ResetTimer(measureData);

              return true;
            }
            case BlockType.Switch:
            case BlockType.Lever: {
              if (measureData.BlockType == BlockType.Lever && TerrariaUtils.Tiles.IsObjectWired(measureData))
            return false;

              bool isInputPort = (portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_InputPort);
              bool currentState = (TerrariaUtils.Tiles.ObjectHasActiveState(measureData));
              if (isInputPort) {
            if (currentState != signal)
              TerrariaUtils.Tiles.SetObjectState(measureData, signal);

            return true;
              } else {
            switch (componentPaint) {
              default:
                if (currentState == signal)
                  return true;

                TerrariaUtils.Tiles.SetObjectState(measureData, signal);
                break;
              case AdvancedCircuits.Paint_Switch_ToggleAndForward:
                if (currentState != signal)
                  TerrariaUtils.Tiles.SetObjectState(measureData, signal);

                break;
              case AdvancedCircuits.Paint_Switch_ForwardIfEqual:
                if (currentState != signal)
                  return true;

                break;
              case AdvancedCircuits.Paint_Switch_ForwardIfEqualByChance:
                if (currentState != signal)
                  return true;

                if (CircuitProcessor.Random.Next(0, 2) == 0)
                  outputSignal = !signal;

                break;
              case AdvancedCircuits.Paint_Switch_ForwardByChance:
                if (CircuitProcessor.Random.Next(0, 2) == 0)
                  return true;

                break;
            }

            if (componentPaint != AdvancedCircuits.Paint_Switch_ToggleAndForward) {
              blockActivatorToRegister = rootBranch.BlockActivator;
              blockActivatorLocationToRegister = rootBranch.BlockActivatorLocation;
              blockActivatorModeToRegister = rootBranch.BlockActivatorMode;
            }
              }

              break;
            }
            case AdvancedCircuits.BlockType_NOTGate: {
              if (!portTile.active() || portTile.type != (int)AdvancedCircuits.BlockType_InputPort)
            return false;

              outputSignal = !signal;

              blockActivatorToRegister = rootBranch.BlockActivator;
              blockActivatorLocationToRegister = rootBranch.BlockActivatorLocation;
              blockActivatorModeToRegister = rootBranch.BlockActivatorMode;

              break;
            }
            case AdvancedCircuits.BlockType_ANDGate:
            case AdvancedCircuits.BlockType_ORGate:
            case AdvancedCircuits.BlockType_XORGate: {
              if (!portTile.active() || portTile.type != (int)AdvancedCircuits.BlockType_InputPort)
            return false;

              GateStateMetadata metadata;
              switch (componentPaint) {
            default:
              if (!this.CircuitHandler.WorldMetadata.GateStates.TryGetValue(componentLocation, out metadata)) {
                metadata = new GateStateMetadata();
                this.CircuitHandler.WorldMetadata.GateStates.Add(componentLocation, metadata);
              }
              break;
            case AdvancedCircuits.Paint_Gate_TemporaryState:
              if (!temporaryGateStates.TryGetValue(componentLocation, out metadata)) {
                metadata = new GateStateMetadata();
                temporaryGateStates.Add(componentLocation, metadata);
              }
              break;
              }

              componentPorts = new List<DPoint>(AdvancedCircuits.EnumerateComponentPortLocations(measureData));
              int inputPorts = 0;
              int signaledPorts = 0;
              bool isInvalid = false;
              for (int i = 0; i < componentPorts.Count; i++) {
            DPoint port = componentPorts[i];
            portTile = TerrariaUtils.Tiles[port];
            if (portTile.HasWire() && portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_InputPort) {
              inputPorts++;

              if (port == portLocation)
                metadata.PortStates[i] = outputSignal;

              if (metadata.PortStates[i] == null)
                isInvalid = true;
            }

            if (metadata.PortStates[i] != null && metadata.PortStates[i].Value)
              signaledPorts++;
              }

              // Gates will not operate as long as the input port states are not clear.
              if (isInvalid)
            return false;

              switch ((BlockType)componentTile.type) {
            case AdvancedCircuits.BlockType_ANDGate:
              outputSignal = (inputPorts == signaledPorts);
              break;
            case AdvancedCircuits.BlockType_ORGate:
              outputSignal = (signaledPorts > 0);
              break;
            case AdvancedCircuits.BlockType_XORGate:
              outputSignal = (signaledPorts != 0 && signaledPorts < inputPorts);
              break;
              }

              blockActivatorToRegister = rootBranch.BlockActivator;
              blockActivatorLocationToRegister = rootBranch.BlockActivatorLocation;
              blockActivatorModeToRegister = rootBranch.BlockActivatorMode;

              break;
            }
            case AdvancedCircuits.BlockType_Swapper: {
              if (!signal)
            return false;

              int swapperCounterValue;
              if (!this.CircuitHandler.WorldMetadata.Swappers.TryGetValue(componentLocation, out swapperCounterValue)) {
            this.CircuitHandler.WorldMetadata.Swappers.Add(componentLocation, 1);

            if (componentPaint == PaintColor.None)
              outputSignal = false;
            else
              return true;
              } else {
            swapperCounterValue++;

            bool sendSignal = true;
            int swapperCounterMax = AdvancedCircuits.SwapperPaintToCount(componentPaint);
            if (swapperCounterValue == swapperCounterMax) {
              outputSignal = false;
            } else if (swapperCounterValue >= swapperCounterMax * 2) {
              outputSignal = true;
              swapperCounterValue = 0;
            } else {
              sendSignal = false;
            }

            this.CircuitHandler.WorldMetadata.Swappers[componentLocation] = swapperCounterValue;
            if (!sendSignal)
              return true;
              }

              blockActivatorToRegister = rootBranch.BlockActivator;
              blockActivatorLocationToRegister = rootBranch.BlockActivatorLocation;
              blockActivatorModeToRegister = rootBranch.BlockActivatorMode;

              break;
            }
            case AdvancedCircuits.BlockType_CrossoverBridge: {
              switch (AdvancedCircuits.DirectionFromTileLocations(componentLocation, portLocation)) {
            case Direction.Left:
              componentPorts = new List<DPoint> { new DPoint(componentLocation.X + 1, componentLocation.Y) };
              break;
            case Direction.Up:
              componentPorts = new List<DPoint> { new DPoint(componentLocation.X, componentLocation.Y + 1) };
              break;
            case Direction.Right:
              componentPorts = new List<DPoint> { new DPoint(componentLocation.X - 1, componentLocation.Y) };
              break;
            case Direction.Down:
              componentPorts = new List<DPoint> { new DPoint(componentLocation.X, componentLocation.Y - 1) };
              break;
            default:
              throw new ArgumentOutOfRangeException();
              }

              blockActivatorToRegister = rootBranch.BlockActivator;
              blockActivatorLocationToRegister = rootBranch.BlockActivatorLocation;
              blockActivatorModeToRegister = rootBranch.BlockActivatorMode;

              break;
            }
            case AdvancedCircuits.BlockType_BlockActivator: {
              if (!portTile.active() || portTile.type != (int)AdvancedCircuits.BlockType_InputPort)
            return false;
              if (
            this.CircuitHandler.Config.BlockActivatorConfig.Cooldown > 0 &&
            !WorldGen.checkMech(componentLocation.X, componentLocation.Y, this.CircuitHandler.Config.BlockActivatorConfig.Cooldown
              ))
            return false;

              if (
            this.TriggeringPlayer != TSPlayer.Server &&
            !this.TriggeringPlayer.Group.HasPermission(AdvancedCircuitsPlugin.TriggerBlockActivator_Permission)
              ) {
            this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
            this.Result.WarnRelatedComponentType = AdvancedCircuits.BlockType_BlockActivator;
            return true;
              }

              BlockActivatorMetadata blockActivator;
              this.CircuitHandler.WorldMetadata.BlockActivators.TryGetValue(componentLocation, out blockActivator);

              if (signal) {
            if (blockActivator == null || blockActivator.IsActivated)
              return true;
              } else {
            if (blockActivator == null) {
              blockActivator = new BlockActivatorMetadata();
              this.CircuitHandler.WorldMetadata.BlockActivators.Add(componentLocation, blockActivator);
            } else {
              // Will do nothing if already deactivated.
              if (!blockActivator.IsActivated)
                return true;

              blockActivator.RegisteredInactiveBlocks.Clear();
            }
              }

              blockActivator.IsActivated = signal;
              if (signal && blockActivator.RegisteredInactiveBlocks.Count == 0)
            return true;

              blockActivatorToRegister = blockActivator;
              blockActivatorLocationToRegister = componentLocation;
              if (componentPaint == AdvancedCircuits.Paint_BlockActivator_Replace)
            blockActivatorModeToRegister = BlockActivatorMode.ReplaceBlocks;

              break;
            }
            case AdvancedCircuits.BlockType_WirelessTransmitter: {
              if (!portTile.active() || portTile.type != (int)AdvancedCircuits.BlockType_InputPort)
            return false;

              WirelessTransmitterConfig transmitterConfig;
              if (
            (
              this.CircuitHandler.Config.WirelessTransmitterConfigs.TryGetValue(componentPaint, out transmitterConfig) ||
              this.CircuitHandler.Config.WirelessTransmitterConfigs.TryGetValue(PaintColor.None, out transmitterConfig)
            ) && (
              transmitterConfig.Cooldown == 0 ||
              WorldGen.checkMech(componentLocation.X, componentLocation.Y, transmitterConfig.Cooldown)
            )
              ) {
            if (
              transmitterConfig.TriggerPermission != null &&
              this.TriggeringPlayer != TSPlayer.Server &&
              !this.TriggeringPlayer.Group.HasPermission(transmitterConfig.TriggerPermission)
            ) {
              this.Result.WarnReason = CircuitWarnReason.InsufficientPermissionToSignalComponent;
              this.Result.WarnRelatedComponentType = AdvancedCircuits.BlockType_WirelessTransmitter;
              return true;
            }

            string sendingTransmitterOwner;
            if (!this.CircuitHandler.WorldMetadata.WirelessTransmitters.TryGetValue(componentLocation, out sendingTransmitterOwner))
              return false;

            bool isBroadcasting = (transmitterConfig.Network == 0);
            double sendingSquareRange = 0;
            if (transmitterConfig.Range > 0)
              sendingSquareRange = Math.Pow(transmitterConfig.Range + 1, 2);

            DPoint portOffset = new DPoint(portLocation.X - componentLocation.X, portLocation.Y - componentLocation.Y);
            foreach (KeyValuePair<DPoint,string> pair in this.CircuitHandler.WorldMetadata.WirelessTransmitters) {
              DPoint receivingTransmitterLocation = pair.Key;
              if (receivingTransmitterLocation == componentLocation)
                continue;

              string receivingTransmitterOwner = pair.Value;
              if (receivingTransmitterOwner != sendingTransmitterOwner)
                continue;

              Tile transmitterTile = TerrariaUtils.Tiles[receivingTransmitterLocation];
              if (!transmitterTile.active() || transmitterTile.type != (int)AdvancedCircuits.BlockType_WirelessTransmitter || transmitterTile.HasWire())
                continue;

              if (
                sendingSquareRange > 0 &&
                sendingSquareRange <= (
                  Math.Pow(receivingTransmitterLocation.X - componentLocation.X, 2) +
                  Math.Pow(receivingTransmitterLocation.Y - componentLocation.Y, 2)
                )
              )
                continue;

              DPoint outputPortLocation = receivingTransmitterLocation.OffsetEx(portOffset.X, portOffset.Y);
              Tile outputPortTile = TerrariaUtils.Tiles[outputPortLocation];
              if (!outputPortTile.HasWire() || (outputPortTile.active() && outputPortTile.type == (int)AdvancedCircuits.BlockType_InputPort))
                continue;

              if (!isBroadcasting) {
                PaintColor receiverPaint = (PaintColor)TerrariaUtils.Tiles[receivingTransmitterLocation].color();
                WirelessTransmitterConfig receiverConfig;
                if (!this.CircuitHandler.Config.WirelessTransmitterConfigs.TryGetValue(receiverPaint, out receiverConfig))
                  receiverConfig = this.CircuitHandler.Config.WirelessTransmitterConfigs[PaintColor.None];

                if (receiverConfig.Network != 0 && receiverConfig.Network != transmitterConfig.Network)
                  continue;
              }

              bool portOutputSignal = outputSignal;
              if (outputPortTile.active() && outputPortTile.type == (int)AdvancedCircuits.BlockType_NOTGate)
                portOutputSignal = !portOutputSignal;
              else if (outputPortTile.active() && outputPortTile.type == (int)AdvancedCircuits.BlockType_XORGate)
                portOutputSignal = false;

              foreach (WireColor wireColor in AdvancedCircuits.EnumerateWireColors()) {
                if (!outputPortTile.HasWire(wireColor))
                  continue;

                this.QueuedRootBranches.Add(new RootBranchProcessData(receivingTransmitterLocation, outputPortLocation, AdvancedCircuits.BoolToSignal(portOutputSignal), wireColor) {
                  BlockActivator = rootBranch.BlockActivator,
                  BlockActivatorLocation = rootBranch.BlockActivatorLocation,
                  BlockActivatorMode = rootBranch.BlockActivatorMode,
                  TeleporterLocation = rootBranch.TeleporterLocation
                });
              }
            }

            return true;
              }

              break;
            }
            default:
              return false;
              }

              if (componentPorts == null)
            componentPorts = new List<DPoint>(AdvancedCircuits.EnumerateComponentPortLocations(measureData));

              for (int i = 0; i < componentPorts.Count; i++) {
            DPoint port = componentPorts[i];
            // A component shouldn't send a signal through a port where it just received one.
            if (port == portLocation) {
              componentPorts.RemoveAt(i--);
              continue;
            }

            portTile = TerrariaUtils.Tiles[port];
            if (!portTile.HasWire() || (portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_InputPort))
              componentPorts.RemoveAt(i--);
              }

              foreach (DPoint port in componentPorts) {
            portTile = TerrariaUtils.Tiles[port];
            bool portOutputSignal = outputSignal;
            if (
              portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_NOTGate &&
              measureData.BlockType != AdvancedCircuits.BlockType_NOTGate
            ) {
              portOutputSignal = !portOutputSignal;
            } else if (
              portTile.active() && portTile.type == (int)AdvancedCircuits.BlockType_XORGate &&
              measureData.BlockType != AdvancedCircuits.BlockType_XORGate
            ) {
              portOutputSignal = false;
            }

            foreach (WireColor wireColor in AdvancedCircuits.EnumerateWireColors()) {
              if (!portTile.HasWire(wireColor))
            continue;

              RootBranchProcessData newRootBranch = new RootBranchProcessData(
            componentLocation, port, AdvancedCircuits.BoolToSignal(portOutputSignal), wireColor
              );
              if (blockActivatorToRegister != null) {
            newRootBranch.BlockActivator = blockActivatorToRegister;
            newRootBranch.BlockActivatorLocation = blockActivatorLocationToRegister;
            newRootBranch.BlockActivatorMode = blockActivatorModeToRegister;
              }
              newRootBranch.TeleporterLocation = rootBranch.TeleporterLocation;

              this.QueuedRootBranches.Add(newRootBranch);
            }
              }

              return true;
        }
        protected void ProcessRootBranch(RootBranchProcessData rootBranch)
        {
            if (this.IsCancellationPending)
            return;

              Tile startTile = TerrariaUtils.Tiles[rootBranch.FirstWireLocation];
              if (
            !startTile.HasWire(rootBranch.WireColor) || (
              this.IsAdvancedCircuit &&
              this.SenderMeasureData.BlockType != BlockType.PressurePlate &&
              startTile.type == (int)AdvancedCircuits.BlockType_InputPort
            )
              )
            return;

              SignalType signal = rootBranch.Signal;
              Direction direction = rootBranch.Direction;
              result.ProcessedBranchCount++;
              List<BranchProcessData> subBranches = new List<BranchProcessData>();
              // "Move" straight through the branch and register the initial adjacent sub-branches.
              {
            DPoint previousTileLocation = DPoint.Empty;
            DPoint currentTileLocation = rootBranch.FirstWireLocation;
            Tile currentTile = TerrariaUtils.Tiles[currentTileLocation];
            while (currentTile.HasWire(rootBranch.WireColor) && !this.IsCancellationPending) {
              this.ProcessTile(rootBranch, currentTileLocation, previousTileLocation, signal);

              DPoint adjacentTileLocation1;
              DPoint adjacentTileLocation2;
              if (direction == Direction.Left || direction == Direction.Right) {
            adjacentTileLocation1 = new DPoint(currentTileLocation.X, currentTileLocation.Y - 1);
            adjacentTileLocation2 = new DPoint(currentTileLocation.X, currentTileLocation.Y + 1);
              } else {
            adjacentTileLocation1 = new DPoint(currentTileLocation.X + 1, currentTileLocation.Y);
            adjacentTileLocation2 = new DPoint(currentTileLocation.X - 1, currentTileLocation.Y);
              }

              Tile adjacentTile1 = TerrariaUtils.Tiles[adjacentTileLocation1];
              Tile adjacentTile2 = TerrariaUtils.Tiles[adjacentTileLocation2];
              if (adjacentTile1.HasWire(rootBranch.WireColor))
            subBranches.Add(new BranchProcessData(currentTileLocation, adjacentTileLocation1, signal));
              else
            this.ProcessTile(rootBranch, adjacentTileLocation1, currentTileLocation, signal);

              if (adjacentTile2.HasWire(rootBranch.WireColor))
            subBranches.Add(new BranchProcessData(currentTileLocation, adjacentTileLocation2, signal));
              else
            this.ProcessTile(rootBranch, adjacentTileLocation2, currentTileLocation, signal);

              // Next tile
              previousTileLocation = currentTileLocation;
              currentTileLocation = currentTileLocation.OffsetTowards(direction);
              currentTile = TerrariaUtils.Tiles[currentTileLocation];
            }

            // The tile above the "peak" of the branch may also contain a Port Defining Component.
            if (this.IsAdvancedCircuit)
              this.ProcessTile(rootBranch, currentTileLocation, previousTileLocation, signal);

            rootBranch.LastWireLocation = previousTileLocation;
              }

              if (this.IsCancellationPending)
            return;

              this.ProcessSubBranches(rootBranch, subBranches);
        }
        private void ProcessSubBranches(RootBranchProcessData rootBranch, List<BranchProcessData> subBranches)
        {
            SignalType signal = rootBranch.Signal;

              // Process all Sub-Branches and their Sub-Branches
              List<BranchProcessData> processedSubBranches = new List<BranchProcessData>();
              processedSubBranches.Add(rootBranch.ToBranchProcessData());

              while (subBranches.Count > 0) {
            int currentBranchIndex = subBranches.Count - 1;
            BranchProcessData currentBranch = subBranches[currentBranchIndex];
            result.ProcessedBranchCount++;

            DPoint previousTileLocation = currentBranch.BranchingTileLocation;
            DPoint currentTileLocation = currentBranch.FirstWireLocation;
            Tile currentTile = TerrariaUtils.Tiles[currentTileLocation];
            while (currentTile.HasWire(rootBranch.WireColor) && !this.IsCancellationPending) {
              bool alreadyProcessed = false;
              for (int i = 0; i < processedSubBranches.Count; i++) {
            if (processedSubBranches[i].IsTileInBetween(currentTileLocation)) {
              alreadyProcessed = true;
              break;
            }
              }
              if (!alreadyProcessed)
            this.ProcessTile(rootBranch, currentTileLocation, previousTileLocation, signal);

              DPoint adjacentTileLocation1;
              DPoint adjacentTileLocation2;
              if (currentBranch.Direction == Direction.Left || currentBranch.Direction == Direction.Right) {
            adjacentTileLocation1 = new DPoint(currentTileLocation.X, currentTileLocation.Y - 1);
            adjacentTileLocation2 = new DPoint(currentTileLocation.X, currentTileLocation.Y + 1);
              } else {
            adjacentTileLocation1 = new DPoint(currentTileLocation.X + 1, currentTileLocation.Y);
            adjacentTileLocation2 = new DPoint(currentTileLocation.X - 1, currentTileLocation.Y);
              }

              Tile adjacentTile1 = TerrariaUtils.Tiles[adjacentTileLocation1];
              Tile adjacentTile2 = TerrariaUtils.Tiles[adjacentTileLocation2];
              if (adjacentTile1.HasWire(rootBranch.WireColor)) {
            alreadyProcessed = false;
            for (int i = 0; i < processedSubBranches.Count; i++) {
              if (processedSubBranches[i].IsTileInBetween(adjacentTileLocation1)) {
                alreadyProcessed = true;
                break;
              }
            }

            if (!alreadyProcessed) {
              bool alreadyQueued = false;
              for (int i = 0; i < subBranches.Count; i++) {
                if (
                  subBranches[i].FirstWireLocation == adjacentTileLocation1 ||
                  subBranches[i].LastWireLocation == adjacentTileLocation1
                ) {
                  alreadyQueued = true;
                  break;
                }
              }

              if (!alreadyQueued)
                subBranches.Add(new BranchProcessData(currentTileLocation, adjacentTileLocation1, signal));
            }
              } else {
            this.ProcessTile(rootBranch, adjacentTileLocation1, currentTileLocation, signal);
              }
              if (adjacentTile2.HasWire(rootBranch.WireColor)) {
            alreadyProcessed = false;
            for (int i = 0; i < processedSubBranches.Count; i++) {
              if (processedSubBranches[i].IsTileInBetween(adjacentTileLocation2)) {
                alreadyProcessed = true;
                break;
              }
            }

            if (!alreadyProcessed) {
              bool alreadyQueued = false;
              for (int i = 0; i < subBranches.Count; i++) {
                if (
                  subBranches[i].FirstWireLocation == adjacentTileLocation2 ||
                  subBranches[i].LastWireLocation == adjacentTileLocation2
                ) {
                  alreadyQueued = true;
                  break;
                }
              }

              if (!alreadyQueued)
                subBranches.Add(new BranchProcessData(currentTileLocation, adjacentTileLocation2, signal));
            }
              } else {
            this.ProcessTile(rootBranch, adjacentTileLocation2, currentTileLocation, signal);
              }

              // Next tile
              previousTileLocation = currentTileLocation;
              currentTileLocation = currentTileLocation.OffsetTowards(currentBranch.Direction);
              currentTile = TerrariaUtils.Tiles[currentTileLocation];
            }

            // The tile above the "peak" of the branch may also contain a Port Defining Component.
            if (this.IsAdvancedCircuit)
              this.ProcessTile(rootBranch, currentTileLocation, previousTileLocation, signal);

            currentBranch.LastWireLocation = previousTileLocation;
            processedSubBranches.Add(currentBranch);

            subBranches.RemoveAt(currentBranchIndex);
              }
        }