Exemplo n.º 1
0
 public override void OnUpdateRotation(byte newFlags)
 {
     base.OnUpdateRotation(newFlags);
     this.mFlags    = newFlags;
     this.mForwards = SegmentCustomRenderer.GetRotationQuaternion(this.mFlags) * Vector3.forward;
     this.mForwards.Normalize();
 }
Exemplo n.º 2
0
    public DigArea(CubeCoord origin, int curHeight, int digRadius, int maxHeight, byte flags)
    {
        // Need to know where the block is
        this.Origin = origin;

        // Current dig position (offset from block)
        this.CurHeight = curHeight;

        // Dig settings
        this.DigRadius = digRadius;
        this.MaxHeight = maxHeight;

        Volume = ((digRadius * 2) + 1) * ((digRadius * 2) + 1) * maxHeight;

        // We'll need these to math later
        var rotationQuart = SegmentCustomRenderer.GetRotationQuaternion(flags);

        vectorUp      = rotationQuart * Vector3.up;
        vectorForward = rotationQuart * Vector3.forward;
        vectorRight   = rotationQuart * Vector3.right;

        vectorUp.Normalize();
        vectorForward.Normalize();
        vectorRight.Normalize();
    }
Exemplo n.º 3
0
        public static void FlagsToRelativeForward(Byte flags, out SByte x, out SByte y, out SByte z)
        {
            var v = SegmentCustomRenderer.GetRotationQuaternion(flags) * Vector3.forward;

            x = (SByte)v.x;
            y = (SByte)v.y;
            z = (SByte)v.z;
        }
        private void UpdateFaces(Byte flags)
        {
            Vector3 vector = Vector3.Normalize(SegmentCustomRenderer.GetRotationQuaternion(flags) * Vector3.down);

            TargetXOffset = (SByte)vector.x;
            TargetYOffset = (SByte)vector.y;
            TargetZOffset = (SByte)vector.z;
        }
Exemplo n.º 5
0
 public TourCartStation(ModCreateSegmentEntityParameters parameters)
     : base(parameters)
 {
     this.mbNeedsUnityUpdate        = true;
     this.mbNeedsLowFrequencyUpdate = true;
     this.mForwards = SegmentCustomRenderer.GetRotationQuaternion(parameters.Flags) * Vector3.forward;
     this.mForwards.Normalize();
 }
Exemplo n.º 6
0
 public FreightCartFactory(ModCreateSegmentEntityParameters parameters)
     : base(parameters)
 {
     this.mbNeedsLowFrequencyUpdate = true;
     this.mbNeedsUnityUpdate        = false;
     this.mForwards = SegmentCustomRenderer.GetRotationQuaternion(parameters.Flags) * Vector3.forward;
     this.mForwards.Normalize();
     this.maAttachedHoppers = new StorageMachineInterface[6];
 }
        private void UpdateFaces(Byte flags)
        {
            _targetDirection = Utils.CalcBottomDirection(flags);
            Vector3 vector = Vector3.Normalize(SegmentCustomRenderer.GetRotationQuaternion(flags) * Vector3.down);

            _sourceXOffset = (SByte)vector.x;
            _sourceYOffset = (SByte)vector.y;
            _sourceZOffset = (SByte)vector.z;
        }
Exemplo n.º 8
0
 public override void OnUpdateRotation(byte newFlags)
 {
     this.rotation = SegmentCustomRenderer.GetRotationQuaternion(newFlags);
     //Stupid corner mirroring...
     if (this.mValue == ScrapCornerVal)
     {
         this.rotation *= Quaternion.Euler(Vector3.up * 180);
     }
     base.OnUpdateRotation(newFlags);
 }
Exemplo n.º 9
0
        //=======================================================
        // Rotation Handlers
        //=======================================================
        public override void OnUpdateRotation(byte newFlags)
        {
            base.OnUpdateRotation(newFlags);
            Quaternion rotation = SegmentCustomRenderer.GetRotationQuaternion(newFlags);

            Forward = rotation * Vector3.forward;
            Left    = rotation * Vector3.left;
            Up      = rotation * Vector3.up;

            RotationEvent?.Invoke(this, rotation);
        }
Exemplo n.º 10
0
        private void UpdateRotation(Byte flags)
        {
            _found      = false;
            _searchDist = MinSearchDist;

            _forwards = SegmentCustomRenderer.GetRotationQuaternion(flags) * Vector3.forward;
            _forwards.Normalize();
            _xOffset = (SByte)_forwards.x;
            _yOffset = (SByte)_forwards.y;
            _zOffset = (SByte)_forwards.z;

            _targetDirection = Utils.CalcBackDirction(flags);
        }
Exemplo n.º 11
0
        public void ResetRotation()
        {
            var rotationQuat = SegmentCustomRenderer.GetRotationQuaternion(mFlags);

            Forward = rotationQuat * Vector3.forward;
            Right   = rotationQuat * Vector3.right;
            Up      = rotationQuat * Vector3.up;

            // Normalize vectors so we can easily multiply
            Forward.Normalize();
            Right.Normalize();
            Up.Normalize();

            BoreDistance = 1;
        }
Exemplo n.º 12
0
        public static void SetupSidesPositions(byte flags, MachineSides machineSides)
        {
            Quaternion rotationQuaternion = SegmentCustomRenderer.GetRotationQuaternion(flags);

            machineSides.Front = rotationQuaternion * Vector3.forward;
            machineSides.Front.Normalize();
            machineSides.Back = rotationQuaternion * Vector3.back;
            machineSides.Back.Normalize();
            machineSides.Right = rotationQuaternion * Vector3.right;
            machineSides.Right.Normalize();
            machineSides.Left = rotationQuaternion * Vector3.left;
            machineSides.Left.Normalize();
            machineSides.Top = rotationQuaternion * Vector3.up;
            machineSides.Top.Normalize();
            machineSides.Bottom = rotationQuaternion * Vector3.down;
            machineSides.Bottom.Normalize();
        }
Exemplo n.º 13
0
 public MassGiver(ModCreateSegmentEntityParameters parameters) :
     base(eSegmentEntity.Mod,
          SpawnableObjectEnum.MassStorageOutputPort,
          parameters.X,
          parameters.Y,
          parameters.Z,
          parameters.Cube,
          parameters.Flags,
          parameters.Value,
          parameters.Position,
          parameters.Segment)
 {
     mbNeedsLowFrequencyUpdate = true;
     mbNeedsUnityUpdate        = true;
     batch    = 1;
     forwards = SegmentCustomRenderer.GetRotationQuaternion(parameters.Flags) * Vector3.forward;
     forwards.Normalize();
     drone = new DroneComputer(droneSpeed);
     LookForAttachedModules();
     droneSize = new Vector3(1, 1, 1);
 }
Exemplo n.º 14
0
    public ScrapTrack(ModCreateSegmentEntityParameters parameters)
        : base(parameters)
    {
        mbNeedsUnityUpdate = true;
        Vector3 lUnityPos = WorldScript.instance.mPlayerFrustrum.GetCoordsToUnity(this.mnX, this.mnY, this.mnZ);

        lUnityPos.x  += 0.5f;
        lUnityPos.y  += 0.5f;
        lUnityPos.z  += 0.5f;
        this.position = lUnityPos;
        this.rotation = SegmentCustomRenderer.GetRotationQuaternion(this.mFlags);
        //Stupid corner mirroring...
        if (this.mValue == ScrapCornerVal)
        {
            this.rotation *= Quaternion.Euler(Vector3.up * 180);
        }
        if (this.mValue == ScrapSlopeVal)
        {
            this.position.y += 0.46f;
        }
    }
Exemplo n.º 15
0
    public override void UnityUpdate()
    {
        if (!mbLinkedToGO)
        {
            // Update the instanced version
            //this.instanceID = FreightCartMod.TrackInstances.TryAdd();
            //this.instanceID2 = FreightCartMod.TrackInstances.TryAdd();
            //this.UpdateInstancedBase();
            //if (instanceID != -1 && instanceID2 != -1)
            //{
            //    this.mbLinkedToGO = true;
            //    this.LinkStatusDirty = true;
            //}

            if (this.CrossTrack != null || FreightTrackJunction.TrackMesh == null || FreightTrackJunction.TrackMesh2 == null || FreightTrackJunction.TrackMaterial == null)
            {
                return;
            }

            Quaternion            rot  = SegmentCustomRenderer.GetRotationQuaternion(this.mFlags);
            Quaternion            rot2 = rot * Quaternion.Euler(Vector3.up * 90);
            MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
            materialPropertyBlock.SetColor("_GlowColor", Color.red);
            materialPropertyBlock.SetFloat("_GlowMult", 5f);

            this.CrossTrack = new GameObject();
            JunctionRenderer ren       = this.CrossTrack.AddComponent <JunctionRenderer>();
            Vector3          lUnityPos = WorldScript.instance.mPlayerFrustrum.GetCoordsToUnity(this.mnX, this.mnY, this.mnZ);
            lUnityPos.x  += 0.5f;
            lUnityPos.y  += 0.5f;
            lUnityPos.z  += 0.5f;
            ren.position  = lUnityPos;
            ren.rotation  = rot;
            ren.rotation2 = rot2;
            ren.mpb       = materialPropertyBlock;
            ren.scrap     = this.mValue == FreightTrackJunction.ScrapJunctionVal;

            ren.enabled = true;
            ren.gameObject.SetActive(true);
            this.CrossTrack.SetActive(true);
            this.TrackRenderer = ren;
            this.mbLinkedToGO  = true;

            //if (mWrapper == null || mWrapper.mGameObjectList == null || SpawnableObjectManagerScript.instance == null || SpawnableObjectManagerScript.instance.maSpawnableObjects == null || SpawnableObjectManagerScript.instance.maSpawnableObjects[(int)SpawnableObjectEnum.Minecart_Track_Straight] == null)
            //{
            //    return;
            //}
            //else
            //{
            //    //this.CrossTrack = (GameObject)GameObject.Instantiate(SpawnableObjectManagerScript.instance.maSpawnableObjects[(int)SpawnableObjectEnum.Minecart_Track_Straight]);
            //    //this.CrossTrack.transform.parent = mWrapper.mGameObjectList[0].gameObject.transform;
            //    //this.CrossTrack.transform.localPosition = new Vector3(0, 0f, 0);//put in the correct relative position
            //    //mWrapper.mGameObjectList[0].gameObject.transform.eulerAngles = new Vector3(0, 0, 0);
            //    //this.CrossTrack.transform.eulerAngles = new Vector3(0, 90f, 0);
            //    //this.CrossTrack.transform.localScale = new Vector3(0.99f, 0.99f, 0.99f);
            //    //this.CrossTrack.SetActive(true);
            //}
        }
        if (this.mbLinkedToGO && this.LinkStatusDirty)
        {
            Color value = Color.red;
            int   links = 0;
            for (int n = 0; n < 4; n++)
            {
                if (this.ConnectedJunctions[n] != null)
                {
                    links++;
                }
            }
            switch (links)
            {
            case 1:
                value = new Color(1f, 0.3f, 0, 1f);
                break;

            case 2:
                value = Color.yellow;
                break;

            case 3:
                value = Color.green;
                break;

            case 4:
                value = Color.blue;
                break;
            }
            //Renderer[] componentsInChildren = this.CrossTrack.GetComponentsInChildren<Renderer>();
            //Renderer[] comp2 = this.mWrapper.mGameObjectList[0].GetComponentsInChildren<Renderer>();
            //MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();
            //materialPropertyBlock.SetColor("_GlowColor", value);
            //materialPropertyBlock.SetFloat("_GlowMult", 5f);
            //for (int i = 0; i < componentsInChildren.Length; i++)
            //    componentsInChildren[i].SetPropertyBlock(materialPropertyBlock);
            //for (int i = 0; i < comp2.Length; i++)
            //    comp2[i].SetPropertyBlock(materialPropertyBlock);

            if (this.TrackRenderer != null)
            {
                this.TrackRenderer.mpb.SetColor("_GlowColor", value);
            }

            if (this.instanceID != -1 && this.instanceID2 != -1)
            {
                //Debug.Log("Setting Track instance color as value: " + value.ToString());
                FreightCartMod.TrackInstances.SetCol(this.instanceID, value);
                FreightCartMod.TrackInstances.SetParamVal(this.instanceID, 1f);
                FreightCartMod.TrackInstances.SetCol(this.instanceID2, value);
                FreightCartMod.TrackInstances.SetParamVal(this.instanceID2, 1f);
            }
            this.LinkStatusDirty = false;
        }
    }
Exemplo n.º 16
0
    /// <summary>
    ///     Follows a track segment to find all containing stations until it reaches another junction or determines track is invalid
    /// </summary>
    /// <param name="direction">0 - 3 representing the four directions out of the junction</param>
    /// <returns>True if it found complete segment</returns>
    public bool TrackFollow(int direction)
    {
        //Initialize the check from the junction
        long    nextX  = this.mnX;
        long    nextY  = this.mnY;
        long    nextZ  = this.mnZ;
        Vector3 dirvec = new Vector3();

        //Store the initial junction direction for later recording which direction the connected junction is associated with
        int initialdirection = direction;

        //List of freight cart stations found on this segment -> to be written to the final constructed FreightTrackSegment
        List <FreightCartStation> SegmentStations = new List <FreightCartStation>();

        //Store visited track pieces for catching when the segment enters a closed loop
        List <TrackPiece> VisitedTracks = new List <TrackPiece>();

        //Add a penalty for pathfinding in certain directions to avoid stations and other undesirable routes
        int PathfindPenalty = 0;

        //Begin loop here.  Direction can be set and used to check the next location each time through the loop
        //Allow segments only up to 2048 long due to cost of loop checking - may revise after testing
        for (int n = 0; n < 2048; n++)
        {
            switch (direction)
            {
            case 0:
                nextX++;
                dirvec = Vector3.right;
                break;

            case 1:
                nextZ++;
                dirvec = Vector3.forward;
                break;

            case 2:
                nextX--;
                dirvec = Vector3.left;
                break;

            case 3:
                nextZ--;
                dirvec = Vector3.back;
                break;

            default:
                nextX++;
                break;
            }

            ushort lValue1 = 0;
            byte   lFlags1 = 0;
            ushort type    = this.GetCube(nextX, nextY, nextZ, out lValue1, out lFlags1);
            this.mUnderSegment = this.mPrevGetSeg;
            //Debug.LogWarning("GetCube type: " + type.ToString() + " value: " + lValue1);
            bool foundslope = false;

            //Found air and need to check for a downward slope under it
            if (type == 1)
            {
                ushort  lValue2 = 0;
                byte    lFlags2 = 0;
                ushort  cube    = this.GetCube(nextX, nextY - 1L, nextZ, out lValue2, out lFlags2);
                Segment segment = this.mPrevGetSeg;
                type    = cube;
                lFlags1 = lFlags2;
                lValue1 = lValue2;
                if ((type == 538 && lValue1 == 2) || (type == ScrapTrackType && lValue1 == ScrapSlopeVal))
                {
                    foundslope = true;
                    nextY--; //decrement Y level for next loop through!
                }
                else
                {
                    if (type == 0)
                    {
                        Debug.LogError("Error, track follower has null under segment!");
                    }
                    if (this.mPrevGetSeg == null)
                    {
                        Debug.LogError("Error, prevseg was null!");
                    }
                    if (segment == null)
                    {
                        Debug.LogError("Error, old was null!");
                    }
                    if (this.mPrevGetSeg != segment)
                    {
                        Debug.LogWarning(("Track follower is looking for a slope, and has had to check across segment boundaries for this![Old/New" + segment.GetName() + " -> " + this.mPrevGetSeg.GetName()));
                    }
                    return(false);
                }
            }

            Vector3 trackvec = SegmentCustomRenderer.GetRotationQuaternion(lFlags1) * Vector3.forward;
            bool    oneway   = false;
            trackvec.Normalize();
            trackvec.x = trackvec.x >= -0.5 ? (trackvec.x <= 0.5 ? 0.0f : 1f) : -1f;
            trackvec.y = trackvec.y >= -0.5 ? (trackvec.y <= 0.5 ? 0.0f : 1f) : -1f;
            trackvec.z = trackvec.z >= -0.5 ? (trackvec.z <= 0.5 ? 0.0f : 1f) : -1f;
            //Begin checking track type
            if (type == TRACKTYPE || type == ScrapTrackType)
            {
                if ((type == TRACKTYPE && (lValue1 == TRACKSTRAIGHT || lValue1 == TRACKEMPTY || lValue1 == TRACKFULL)) || (type == ScrapTrackType && lValue1 == ScrapStraightVal))
                {
                    if (trackvec.y > 0.5 || trackvec.y < -0.5)
                    {
                        return(false);
                    }
                    else if (!(trackvec == dirvec) && !(trackvec == -dirvec))
                    {
                        dirvec = new Vector3(trackvec.x, 0f, trackvec.z);
                        oneway = true; // Can't set return path as the same -> they're different!
                    }
                }
                if ((type == TRACKTYPE && lValue1 == TRACKCORNER) || (type == ScrapTrackType && lValue1 == ScrapCornerVal))
                {
                    if (dirvec == new Vector3(-trackvec.z, 0.0f, trackvec.x))
                    {
                        dirvec = new Vector3(dirvec.z, 0.0f, -dirvec.x);
                    }
                    else if (trackvec == -dirvec)
                    {
                        dirvec = new Vector3(-dirvec.z, 0.0f, dirvec.x);
                    }
                    else
                    {
                        return(false);
                    }
                }
                if ((type == TRACKTYPE && lValue1 == TRACKSLOPE) || (type == ScrapTrackType && lValue1 == ScrapSlopeVal))
                {
                    Vector3 vector3_2 = trackvec;
                    dirvec.y = 0.0f;
                    dirvec.Normalize();
                    if (dirvec == trackvec)
                    {
                        if (foundslope)
                        {
                            return(false);
                        }
                        else
                        {
                            nextY++;
                        }
                    }
                    else if (dirvec == -trackvec)
                    {
                        ;
                    }
                }
                if (type == TRACKTYPE && lValue1 == TRACKBUFFER)
                {
                    dirvec = new Vector3(-dirvec.x, 0f, -dirvec.z);
                }
            }
            //Begin checking special types
            else if (type == CONTROLTYPE)
            {
                if (lValue1 == CONTROLLOAD || lValue1 == CONTROLUNLOAD || lValue1 == CONTROLTURBO)
                {
                    if ((trackvec == dirvec) || (trackvec == -dirvec))
                    {
                        //Do nothing... direction doesn't change
                        //Except turbo... reduce the penalty for this path!
                        if (lValue1 == CONTROLTURBO)
                        {
                            PathfindPenalty--;
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            //Check for freight stations
            else if (type == FREIGHTSTATIONTYPE)
            {
                if ((trackvec == dirvec) || (trackvec == -dirvec))
                {
                    Segment segment = this.AttemptGetSegment(nextX, nextY, nextZ);
                    if (segment == null)
                    {
                        segment = WorldScript.instance.GetSegment(nextX, nextY, nextZ);
                        if (segment == null)
                        {
                            Debug.Log((object)"Track junction track follower did not find segment");
                            return(false);
                        }
                    }
                    FreightCartStation fcs = segment.FetchEntity(eSegmentEntity.Mod, nextX, nextY, nextZ) as FreightCartStation;
                    if (fcs == null)
                    {
                        Debug.LogWarning("Track Junction Track Follower tried to get a freight cart station but got other mod machine instead?");
                        return(false);
                    }
                    if (!SegmentStations.Contains(fcs))
                    {
                        SegmentStations.Add(fcs);
                    }
                    fcs.ClosestJunction   = this;
                    fcs.JunctionDirection = initialdirection;
                    // Penalize this route for multidirection pathfinding due to the station
                    PathfindPenalty += 5;
                }
                else
                {
                    return(false);
                }
            }
            //Is it a junction?
            else if (type == JUNCTIONTYPE)
            {
                //Debug.LogWarning("Track follower success!  Found another junction!");
                Segment segment = this.AttemptGetSegment(nextX, nextY, nextZ);
                if (segment == null)
                {
                    segment = WorldScript.instance.GetSegment(nextX, nextY, nextZ);
                    if (segment == null)
                    {
                        Debug.Log((object)"Track junction track follower did not find segment");
                        return(false);
                    }
                }
                FreightTrackJunction junction = segment.FetchEntity(eSegmentEntity.Mod, nextX, nextY, nextZ) as FreightTrackJunction;
                if (junction == null)
                {
                    Debug.LogWarning("Track Junction Track Follower tried to get a track junction but got other mod machine instead?");
                    return(false);
                }
                this.ConnectedJunctions[initialdirection] = junction;
                //Don't let segment distance be negative just to be safe!  This should rarely happen...
                if (PathfindPenalty < 0 && Math.Abs(PathfindPenalty) > n)
                {
                    PathfindPenalty = -n;
                }
                FreightTrackSegment tracksegment = new FreightTrackSegment(this, junction, n + 1 + PathfindPenalty);
                tracksegment.Stations = SegmentStations;
                //Debug.LogWarning("trackseg station count: " + tracksegment.Stations.Count);
                this.ConnectedSegments[initialdirection] = tracksegment;
                this.SegmentDistances[initialdirection]  = n + 1;
                this.LinkStatusDirty = true;

                //handle the connection for the other junction so we don't need to double the work - only if return path is valid!
                //Mirror the direction to reflect the correct side of the connecting junction
                if (!oneway)
                {
                    int mirroreddir = direction += 2;
                    if (mirroreddir > 3)
                    {
                        mirroreddir -= 4;
                    }
                    junction.ConnectedJunctions[mirroreddir] = this;
                    junction.ConnectedSegments[mirroreddir]  = tracksegment;
                    junction.SegmentDistances[mirroreddir]   = n + 1;
                    junction.LinkStatusDirty = true;
                }
                return(true);
            }
            else if (type == TOURSTATIONTYPE)
            {
                if (trackvec != -dirvec)
                {
                    return(false);
                }
                Segment segment = this.AttemptGetSegment(nextX, nextY, nextZ);
                if (segment == null)
                {
                    segment = WorldScript.instance.GetSegment(nextX, nextY, nextZ);
                    if (segment == null)
                    {
                        Debug.Log((object)"Track junction track follower did not find segment");
                        return(false);
                    }
                }
                TourCartStation station = segment.FetchEntity(eSegmentEntity.Mod, nextX, nextY, nextZ) as TourCartStation;
                station.TrackNetwork      = this.TrackNetwork;
                station.ClosestJunction   = this;
                station.JunctionDirection = initialdirection;
                this.ConnectedJunctions[initialdirection] = this;
                FreightTrackSegment tracksegment = new FreightTrackSegment(this, this, 2 * n + 1);
                this.SegmentDistances[initialdirection]  = 2 * n + 1;
                this.ConnectedSegments[initialdirection] = tracksegment;
                this.LinkStatusDirty = true;
                if (!string.IsNullOrEmpty(station.StationName) && !this.TrackNetwork.TourCartStations.ContainsKey(station.StationName))
                {
                    this.TrackNetwork.TourCartStations.Add(station.StationName, station);
                }
                return(true);
            }
            else
            {
                return(false);   //Not a track type
            }
            //Update the direction int based on the changed direction vector
            if (dirvec == Vector3.right)
            {
                direction = 0;
            }
            else if (dirvec == Vector3.forward)
            {
                direction = 1;
            }
            else if (dirvec == Vector3.left)
            {
                direction = 2;
            }
            else if (dirvec == Vector3.back)
            {
                direction = 3;
            }

            TrackPiece visitedpiece = new TrackPiece(new Vector3(nextX - this.mnX, nextY - this.mnY, nextZ - this.mnZ), direction);
            //Debug.LogWarning("Visited track piece: " + new Vector4(nextX - this.mnX, nextY - mnY, nextZ - mnZ, direction).ToString());
            //Store every track piece and check every 10th for monitoring for closed, endless loops of track
            if (n % 10 == 0)
            {
                int count = VisitedTracks.Count;
                for (int m = 0; m < count; m++)
                {
                    TrackPiece piece = VisitedTracks[m];
                    if (piece.Position == visitedpiece.Position && piece.Direction == visitedpiece.Direction)
                    {
                        //Debug.LogWarning("piece position: " + piece.Position.ToString() + " visited: " + visitedpiece.Position.ToString());
                        Debug.LogWarning("TrackJunction followed track route and found a closed loop.  Ending search.");
                        return(false);
                    }
                }
            }
            VisitedTracks.Add(visitedpiece);
            if (n == 2047)
            {
                Debug.LogWarning("Track Junction Found track length > 2048m -> ending search.");
            }
        }
        return(false);
    }
Exemplo n.º 17
0
    /// <summary>
    ///     Follows a track segment to find all containing stations until it reaches another junction or determines track is invalid
    /// </summary>
    /// <param name="direction">0 - 3 representing the four directions out of the junction</param>
    /// <returns>True if it found complete segment</returns>
    public bool TrackFollow(int direction)
    {
        //Initialize the check from the junction
        long    nextX    = this.mnX;
        long    nextY    = this.mnY;
        long    nextZ    = this.mnZ;
        Vector3 dirvec   = new Vector3();
        bool    mirrorOk = true;

        //Store the initial junction direction for later recording which direction the connected junction is associated with
        int initialdirection = direction;

        //There are many ways to derail, so set that result now, and assume it later. Saves much repeat of these lines.
        this.DirectionResults [initialdirection]   = FreightTrackDirectionResults.Bad;
        this.ConnectedJunctions [initialdirection] = null;
        this.ConnectedSegments [initialdirection]  = null;

        //List of freight cart stations found on this segment -> to be written to the final constructed FreightTrackSegment
        List <FreightCartStation> SegmentStations = new List <FreightCartStation>();

        //Store visited track pieces for catching when the segment enters a closed loop
        //We're only testing for a unique key here, so no Tvalue will be used.
        StringDictionary VisitedTracks = new StringDictionary();

        //Begin loop here.  Direction can be set and used to check the next location each time through the loop
        //Allow segments only up to 512m long due to cost of loop checking - may revise after testing
        for (this.SegmentDistances[initialdirection] = 0; this.SegmentDistances[initialdirection] < 2048; this.SegmentDistances[initialdirection]++)
        {
            switch (direction)
            {
            case 0:
                nextX++;
                dirvec = Vector3.right;
                break;

            case 1:
                nextZ++;
                dirvec = Vector3.forward;
                break;

            case 2:
                nextX--;
                dirvec = Vector3.left;
                break;

            case 3:
                nextZ--;
                dirvec = Vector3.back;
                break;

            default:
                nextX++;
                break;
            }

            ushort lValue1 = 0;
            byte   lFlags1 = 0;
            ushort type    = this.GetCube(nextX, nextY, nextZ, out lValue1, out lFlags1);
            this.mUnderSegment = this.mPrevGetSeg;
            //Debug.LogWarning("GetCube type: " + type.ToString() + " value: " + lValue1);
            bool foundslope = false;

            //Found air and need to check for a downward slope under it
            if (type == 1)
            {
                ushort  lValue2 = 0;
                byte    lFlags2 = 0;
                ushort  cube    = this.GetCube(nextX, nextY - 1L, nextZ, out lValue2, out lFlags2);
                Segment segment = this.mPrevGetSeg;
                type    = cube;
                lFlags1 = lFlags2;
                lValue1 = lValue2;
                if ((type == 538 && lValue1 == 2) || (type == ScrapTrackType && lValue1 == ScrapSlopeVal))
                {
                    foundslope = true;
                    nextY--; //decrement Y level for next loop through!
                }
                else
                {
                    if (type == 0)
                    {
                        Debug.LogError("Error, track follower has null under segment!");
                    }
                    if (this.mPrevGetSeg == null)
                    {
                        Debug.LogError("Error, prevseg was null!");
                    }
                    if (segment == null)
                    {
                        Debug.LogError("Error, old was null!");
                    }
                    if (this.mPrevGetSeg != segment)
                    {
                        Debug.LogWarning(("Track follower is looking for a slope, and has had to check across segment boundaries for this![Old/New" + segment.GetName() + " -> " + this.mPrevGetSeg.GetName()));
                    }
                    return(false);
                }
            }

            Vector3 trackvec = SegmentCustomRenderer.GetRotationQuaternion(lFlags1) * Vector3.forward;
            trackvec.Normalize();
            trackvec.x = trackvec.x >= -0.5 ? (trackvec.x <= 0.5 ? 0.0f : 1f) : -1f;
            trackvec.y = trackvec.y >= -0.5 ? (trackvec.y <= 0.5 ? 0.0f : 1f) : -1f;
            trackvec.z = trackvec.z >= -0.5 ? (trackvec.z <= 0.5 ? 0.0f : 1f) : -1f;
            //Begin checking track type
            if (type == TRACKTYPE || type == ScrapTrackType)
            {
                if ((type == TRACKTYPE && (lValue1 == TRACKSTRAIGHT || lValue1 == TRACKEMPTY || lValue1 == TRACKFULL)) || (type == ScrapTrackType && lValue1 == ScrapStraightVal))
                {
                    if (trackvec.y > 0.5 || trackvec.y < -0.5)
                    {
                        return(false);
                    }
                    else if (!(trackvec == dirvec) && !(trackvec == -dirvec))
                    {
                        // Came in from the side, this path is one-way.
                        mirrorOk = false;
                        dirvec   = new Vector3(trackvec.x, 0f, trackvec.z);
                    }
                }
                if ((type == TRACKTYPE && lValue1 == TRACKCORNER) || (type == ScrapTrackType && lValue1 == ScrapCornerVal))
                {
                    if (dirvec == new Vector3(-trackvec.z, 0.0f, trackvec.x))
                    {
                        dirvec = new Vector3(dirvec.z, 0.0f, -dirvec.x);
                    }
                    else if (trackvec == -dirvec)
                    {
                        dirvec = new Vector3(-dirvec.z, 0.0f, dirvec.x);
                    }
                    else
                    {
                        return(false);
                    }
                }
                if ((type == TRACKTYPE && lValue1 == TRACKSLOPE) || (type == ScrapTrackType && lValue1 == ScrapSlopeVal))
                {
                    Vector3 vector3_2 = trackvec;
                    dirvec.y = 0.0f;
                    dirvec.Normalize();
                    if (dirvec == trackvec)
                    {
                        if (foundslope)
                        {
                            return(false);
                        }
                        else
                        {
                            nextY++;
                        }
                    }
                    else if (dirvec == -trackvec)
                    {
                        ;
                    }
                }
                if (type == TRACKTYPE && lValue1 == TRACKBUFFER)
                {
                    dirvec = new Vector3(-dirvec.x, 0f, -dirvec.z);
                }
            }
            //Begin checking special types
            else if (type == CONTROLTYPE)
            {
                if (lValue1 == CONTROLLOAD || lValue1 == CONTROLUNLOAD || lValue1 == CONTROLTURBO)
                {
                    if ((trackvec == dirvec) || (trackvec == -dirvec))
                    {
                        //Do nothing... direction doesn't change
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            //Check for freight stations
            else if (type == FREIGHTSTATIONTYPE)
            {
                if ((trackvec == dirvec) || (trackvec == -dirvec))
                {
                    Segment segment = this.AttemptGetSegment(nextX, nextY, nextZ);
                    if (segment == null)
                    {
                        segment = WorldScript.instance.GetSegment(nextX, nextY, nextZ);
                        if (segment == null)
                        {
                            Debug.Log((object)"Track junction track follower did not find segment");
                            return(false);
                        }
                    }
                    FreightCartStation fcs = segment.FetchEntity(eSegmentEntity.Mod, nextX, nextY, nextZ) as FreightCartStation;
                    if (fcs == null)
                    {
                        Debug.LogWarning("Track Junction Track Follower tried to get a freight cart station but got other mod machine instead?");
                        return(false);
                    }
                    if (!SegmentStations.Contains(fcs))
                    {
                        SegmentStations.Add(fcs);
                    }
                    fcs.ClosestJunction   = this;
                    fcs.JunctionDirection = initialdirection;
                }
                else
                {
                    return(false);
                }
            }
            //Is it a junction?
            else if (type == JUNCTIONTYPE)
            {
                //Debug.LogWarning("Track follower success!  Found another junction!");
                Segment segment = this.AttemptGetSegment(nextX, nextY, nextZ);
                if (segment == null)
                {
                    segment = WorldScript.instance.GetSegment(nextX, nextY, nextZ);
                    if (segment == null)
                    {
                        Debug.Log((object)"Track junction track follower did not find segment");
                        return(false);
                    }
                }
                FreightTrackJunction junction = segment.FetchEntity(eSegmentEntity.Mod, nextX, nextY, nextZ) as FreightTrackJunction;
                if (junction == null)
                {
                    Debug.LogWarning("Track Junction Track Follower tried to get a track junction but got other mod machine instead?");
                    return(false);
                }

                //Mark this segment as a loop coming back to ourselves.
                if (junction == this)
                {
                    this.DirectionResults[initialdirection] = FreightTrackDirectionResults.Self;
                }
                else
                {
                    this.DirectionResults[initialdirection] = FreightTrackDirectionResults.Good;
                }

                this.SegmentDistances[initialdirection]  += 1; // We're going to exit the loop here, messing with loop variable OK'd.
                this.ConnectedJunctions[initialdirection] = junction;
                FreightTrackSegment tracksegment = new FreightTrackSegment(this, junction, this.SegmentDistances[initialdirection]);
                tracksegment.Stations = SegmentStations;
                //Debug.LogWarning("trackseg station count: " + tracksegment.Stations.Count);
                this.ConnectedSegments[initialdirection] = tracksegment;
                this.LinkStatusDirty = true;

                //If path is bi-directional, handle the connection for the other junction so we don't need to double the work
                if (mirrorOk)
                {
                    //Mirror the direction to reflect the correct side of the connecting junction
                    int mirroreddir = direction += 2;
                    if (mirroreddir > 3)
                    {
                        mirroreddir -= 4;
                    }
                    junction.ConnectedJunctions [mirroreddir] = this;
                    junction.ConnectedSegments [mirroreddir]  = tracksegment;
                    junction.SegmentDistances [mirroreddir]   = this.SegmentDistances[initialdirection];
                    junction.DirectionResults[mirroreddir]    = this.DirectionResults[initialdirection];//Either "Good
                    junction.LinkStatusDirty = true;
                }
                return(true);
            }
            else if (type == TOURSTATIONTYPE)
            {
                if (trackvec != -dirvec)
                {
                    return(false);
                }
                Segment segment = this.AttemptGetSegment(nextX, nextY, nextZ);
                if (segment == null)
                {
                    segment = WorldScript.instance.GetSegment(nextX, nextY, nextZ);
                    if (segment == null)
                    {
                        Debug.Log((object)"Track junction track follower did not find segment");
                        return(false);
                    }
                }
                TourCartStation station = segment.FetchEntity(eSegmentEntity.Mod, nextX, nextY, nextZ) as TourCartStation;
                station.TrackNetwork      = this.TrackNetwork;
                station.ClosestJunction   = this;
                station.JunctionDirection = initialdirection;
                this.ConnectedJunctions[initialdirection] = this;
                FreightTrackSegment tracksegment = new FreightTrackSegment(this, this, 2 * this.SegmentDistances[initialdirection] + 1);
                this.SegmentDistances[initialdirection] *= 2;
                this.SegmentDistances[initialdirection] += 1;
                this.ConnectedSegments[initialdirection] = tracksegment;
                this.LinkStatusDirty = true;
                if (!string.IsNullOrEmpty(station.StationName) && !this.TrackNetwork.TourCartStations.ContainsKey(station.StationName))
                {
                    this.TrackNetwork.TourCartStations.Add(station.StationName, station);
                }
                return(true);
            }
            else
            {
                return(false);   //Not a track type
            }
            //Update the direction int based on the changed direction vector
            if (dirvec == Vector3.right)
            {
                direction = 0;
            }
            else if (dirvec == Vector3.forward)
            {
                direction = 1;
            }
            else if (dirvec == Vector3.left)
            {
                direction = 2;
            }
            else if (dirvec == Vector3.back)
            {
                direction = 3;
            }

            //Store a hash of every track piece to check for getting stuck in endless loops.
            //HACK Construct a string to be our HashTable Key.
            //We could implement a fancy struct or something, but this works, and we don't have to make a custom GetHashTag function
            //(Struct.gethash() is apparently very inefficient)
            //And the try/catch construct means we only do one hash lookup even.
            try{
                //Build a string which will be unique for this particular track segment and travel direction. Lots and Lots of implicit casting to string on this line.
                VisitedTracks.Add((nextX - this.mnX) + "," + (nextY - this.mnY) + "," + (nextZ - this.mnZ) + "," + direction, null);
            }
            catch {
                Debug.LogWarning("TrackJunction followed track route and found an infinite loop. Ending search.");
                this.DirectionResults [initialdirection] = FreightTrackDirectionResults.Trap;
                return(false);
            }
        }
        Debug.LogWarning("Track Junction Found track length > 512m -> ending search.");
        return(false);
    }