コード例 #1
0
        public bool AttemptJoinReservation(ReservationInfo current_reservation, SingleTrack2WSection new_reservation, ushort train_id)
        {
            //do not allow train following if route taken by the train is not guaranteed (train could stop at a station and come back its way for example)
            if (!Mod.allowFollowing || current_reservation.section.containStopStation || new_reservation.containStopStation)
            {
                return(false);
            }

            if (!current_reservation.refuse_following_trains && current_reservation.section.Compare(new_reservation))
            {
                current_reservation.train_ids.Add(train_id);

                //actualize data
                for (int i = 0; i < m_data.reservations.Count; i++)
                {
                    if (m_data.reservations[i].ID == current_reservation.ID)
                    {
                        m_data.reservations[i] = current_reservation;
                        break;
                    }
                }

                return(true);
            }
            return(false);
        }
コード例 #2
0
        public void Recycle()
        {
            //ID_counter++;
            //ID = ID_counter;

            train_ids.Clear();
            //pending_train_ids.Clear();
            refuse_following_trains = false;
            section        = null;
            clearing_timer = 0;
            status         = ReservationStatus.Ineffective;
        }
コード例 #3
0
        public ReservationInfo RegisterNewReservation(SingleTrack2WSection section, ushort leading_vehicle_id, ref ushort blocking_segment_id)
        {
            ReservationInfo ri = new ReservationInfo();

            ri.section          = section;
            blocking_segment_id = RegisterReservation(ri, leading_vehicle_id, false, -1);

            if (!Mod.allowGoAsFarAsPossible && blocking_segment_id != 0) //cache reservation to avoid recreating it many times in a row
            {
                m_data.ClearCacheForTrain(leading_vehicle_id);
                m_data.cached_reservations.Add(leading_vehicle_id, ri);
            }
            return(ri);
        }
コード例 #4
0
        public bool AttemptReservationForNextPendingTrain(ReservationInfo current_reservation, SingleTrack2WSection new_reservation, ushort train_id)
        {
            if (current_reservation.status == ReservationStatus.RecycleForPendingTrain && current_reservation.pending_train_ids.Count > 0 && current_reservation.pending_train_ids[0] == train_id)
            {
                ushort old_id = current_reservation.ID;
                m_data.RemoveReservation(old_id, false);
                current_reservation.Recycle();
                current_reservation.pending_train_ids.RemoveAt(0);
                current_reservation.section = new_reservation;
                RegisterReservation(current_reservation, train_id, true, old_id);
                return(true);
            }

            return(false);
        }
コード例 #5
0
        static void AppendNextConnectedSegmentTheOldWay(SingleTrack2WSection section, uint segment_id)
        {
            NetManager instance = Singleton <NetManager> .instance;

            int           nieghbours_count = 0;
            bool          include_segments = false;
            List <ushort> single_lanes     = new List <ushort>();

            NetNode    node;
            NetSegment seg = instance.m_segments.m_buffer[segment_id];

            List <ushort> nodes_included = new List <ushort>();
            int           n = 0;

            nodes_included.Add(seg.m_endNode);
            nodes_included.Add(seg.m_startNode);

            while (nodes_included.Count > n)
            {
                nieghbours_count = 0;
                single_lanes.Clear();
                include_segments = false;

                node = instance.m_nodes.m_buffer[(int)((UIntPtr)nodes_included[n])];

                //find every segments attached to node
                for (int i = 0; i < 8; i++)
                {
                    if (node.GetSegment(i) != 0)
                    {
                        nieghbours_count++;
                        if (RequireReservation(node.GetSegment(i))) //detect 1 lane 2 ways segments
                        {
                            single_lanes.Add(node.GetSegment(i));
                        }
                    }
                }

                if (nieghbours_count <= 2 && single_lanes.Count > 0) //include single track segments without branching
                {
                    include_segments = true;
                }

                /*else if (nieghbours_count > 2) //include single track segments with branching. All single track 2 ways segments connected together will get booked
                 *  include_segments = true;*/

                if (include_segments)
                {
                    for (int i = 0; i < single_lanes.Count; i++)
                    {
                        if (!section.segment_ids.Contains(single_lanes[i])) //check not already included
                        {
                            section.segment_ids.Add(single_lanes[i]);

                            //activate signal at the end of the single track section
                            CheckSpawnSignals(single_lanes[i]);

                            //get next nodes
                            seg = instance.m_segments.m_buffer[(int)single_lanes[i]];
                            if (!nodes_included.Contains(seg.m_endNode))
                            {
                                nodes_included.Add(seg.m_endNode);
                            }
                            if (!nodes_included.Contains(seg.m_startNode))
                            {
                                nodes_included.Add(seg.m_startNode);
                            }
                        }
                    }
                }
                n++;
            }
        }
コード例 #6
0
        /******** reservation creation algorithm ************/

        public SingleTrack2WSection CreateSingleTrack2WSectionFromTrainPath(ushort vehicle_id, ushort start_segment_id)
        {
            PathManager    instance  = Singleton <PathManager> .instance;
            VehicleManager instance2 = Singleton <VehicleManager> .instance;
            NetManager     instance3 = Singleton <NetManager> .instance;

            Vehicle  vehicleData     = instance2.m_vehicles.m_buffer[vehicle_id];
            PathUnit pathunit        = instance.m_pathUnits.m_buffer[vehicleData.m_path];
            int      posindex        = (vehicleData.m_pathPositionIndex >> 1) + 1;
            bool     continue_search = true;

            bool   found_inspected_segment     = false;
            ushort segments_ahead_from_vehicle = 0;

            SingleTrack2WSection section = new SingleTrack2WSection();
            ushort crt_segment_id        = 0;

            bool buildOldWay = false;

            //browse successive segments in path for single tracks
            while (continue_search)
            {
                continue_search = false;

                if (posindex >= (int)pathunit.m_positionCount)
                {
                    posindex = 0;
                    uint nextPathUnit = pathunit.m_nextPathUnit;
                    if (nextPathUnit == 0u)
                    {
                        //CODebug.Log(LogChannel.Modding, Mod.modName + " - no next path unit ??");

                        //path is at the end, don't know if train will carry after the station
                        //may add further single track segments along the track
                        buildOldWay = true; //start other algorithm, usually in case of a single track station
                        break;
                    }
                    pathunit = instance.m_pathUnits.m_buffer[nextPathUnit];
                }

                PathUnit.Position pathpos;
                if (!pathunit.GetPosition(posindex, out pathpos))
                {
                    return(null);
                }
                crt_segment_id = pathpos.m_segment;

                //activate signal at the end of the single track section
                CheckSpawnSignals(crt_segment_id);

                if (!found_inspected_segment)
                {
                    if (crt_segment_id == start_segment_id)
                    {
                        found_inspected_segment = true;
                    }
                }

                if (found_inspected_segment)
                {
                    if (RequireReservation(crt_segment_id))
                    {
                        section.segment_ids.Add(crt_segment_id);
                        continue_search = true;
                    }
                }

                posindex++;
                segments_ahead_from_vehicle++;
                if (!found_inspected_segment && segments_ahead_from_vehicle < 5)
                {
                    continue_search = true;
                }
            }

            if (buildOldWay && section.segment_ids.Count > 0)
            {
                if (IsStation(section.segment_ids[section.segment_ids.Count - 1]))
                {
                    section.containStopStation = true;


                    //Is use of other algo really needed? Train may or may not go further along the track
                    //Other trains check if other reservation further along the path anyway...

                    // -> yes reserving single tracks after station ensure TrainExitStation is properly resolved
                    // There is not a second, separate reservation made (except when branching...)

                    if (Mod.extendReservationAfterStopStation)
                    {
                        //section.notFromPathSegmentsStartingAt = section.segment_ids.Count; //mark that segments further on have not been path checked
                        AppendNextConnectedSegmentTheOldWay(section, section.segment_ids[section.segment_ids.Count - 1]);
                    }
                }
            }

            if (section.segment_ids.Count > 0)
            {
                return(section);
            }

            return(null);
        }
コード例 #7
0
        //public int notFromPathSegmentsStartingAt = -1;

        public bool Compare(SingleTrack2WSection other)
        {
            return(this.segment_ids[0] == other.segment_ids[0] && this.segment_ids[this.segment_ids.Count - 1] == other.segment_ids[other.segment_ids.Count - 1]);
        }
コード例 #8
0
        private bool CheckSingleTrack2Ways(ushort vehicleID, Vehicle vehicleData, ref float maxSpeed, uint laneID, uint prevLaneID, ref bool mayNeedSingleTrackStationFix)
        {
            NetManager instance        = Singleton <NetManager> .instance;
            ushort     next_segment_id = instance.m_lanes.m_buffer[(int)((UIntPtr)laneID)].m_segment;
            ushort     crt_segment_id  = instance.m_lanes.m_buffer[(int)((UIntPtr)prevLaneID)].m_segment;

            ReservationManager instance2 = ReservationManager.instance;

            ushort leadingVehicleID = vehicleData.GetFirstVehicle(vehicleID);

            ReservationInfo ri = null;
            bool            preventCheckNextLane = false;
            bool            notifyFutureTrack    = false;

            if (ReservationManager.RequireReservation(next_segment_id))
            {
                ri = instance2.GetReservationOnSegment(next_segment_id);
            }


CreateReservation:
            if (ReservationManager.IsSingleTrack2WSegment(next_segment_id)) //train carriage will enter a one lane section
            {
                if (ri == null)                                             //reserve track if it is not reserved by any train
                {
                    ushort blocking_segmentID = 0;

                    ri = ReservationManager.instance.CheckCachedReservation(next_segment_id, leadingVehicleID, ref blocking_segmentID);

                    if (ri == null) //no cached reservation found, create one
                    {
                        SingleTrack2WSection section = instance2.CreateSingleTrack2WSectionFromTrainPath(leadingVehicleID, next_segment_id);
                        if (section != null)
                        {
                            ri = ReservationManager.instance.RegisterNewReservation(section, leadingVehicleID, ref blocking_segmentID);
                        }
                    }

                    if (blocking_segmentID != 0) //reservation blocked by a further segment already reserved, get this reservation
                    {
                        ri = instance2.GetReservationOnSegment(blocking_segmentID);

                        /*ReservationManager.instance.EnqueueReservation(ri, leadingVehicleID);
                         * maxSpeed = 0f;
                         * return true;*/
                    }
                    else
                    {
                        mayNeedSingleTrackStationFix = true; //track reserved by this train
                    }
                }
            }

            if (ri != null)
            {
                if (ReservationManager.IsReservationForTrain(ri, leadingVehicleID)) //track is reserved for this vehicle
                {
                    notifyFutureTrack = true;

                    mayNeedSingleTrackStationFix = true; //track reserved by this train

                    //reset wait counter

                    /* if((vehicleData.m_flags2 & Vehicle.Flags2.Yielding) != (Vehicle.Flags2) 0)
                     * {
                     *   vehicleData.m_flags2 &= ~Vehicle.Flags2.Yielding;
                     *   vehicleData.m_waitCounter = 0;
                     * }*/


                    //return true so that CheckNextLane does not interfere (it causes train to stop when going from one track to double track with a train waiting in the opposite direction)
                    if (Mod.noCheckOverlapOnLastSegment && next_segment_id == ri.section.segment_ids[ri.section.segment_ids.Count - 1])
                    {
                        preventCheckNextLane = true;
                    }
                }
                else //section reserved by another train
                {
                    //train has spawned on a station reserved to another train, though case...
                    //attempt destroy reservation and give priority to this train
                    if (ReservationManager.IsSingleTrackStation(crt_segment_id))
                    {
                        ReservationManager.instance.m_data.RemoveReservation(ri.ID, true);
                        ri = null;
                        goto CreateReservation;
                    }

                    SingleTrack2WSection section = instance2.CreateSingleTrack2WSectionFromTrainPath(leadingVehicleID, next_segment_id);
                    if (!(section != null && ReservationManager.instance.AttemptJoinReservation(ri, section, leadingVehicleID)))                    //can train follow the previous one?
                    {
                        if (!(section != null && ReservationManager.instance.AttemptReservationForNextPendingTrain(ri, section, leadingVehicleID))) //has section been cleared?
                        {
                            //not allowed on this track, stop
                            ReservationManager.instance.EnqueueReservation(ri, leadingVehicleID);
                            maxSpeed = 0f;

                            //increment wait counter

                            /*vehicleData.m_flags2 |= Vehicle.Flags2.Yielding;
                             * vehicleData.m_waitCounter++;*/

                            //set traffic light state

                            /*NetSegment seg = instance.m_segments.m_buffer[crt_segment_id];
                             * RoadBaseAI.SetTrafficLightState(seg.m_endNode, ref seg, 0, RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState.Red, true, false);
                             * RoadBaseAI.SetTrafficLightState(seg.m_startNode, ref seg, 0, RoadBaseAI.TrafficLightState.Red, RoadBaseAI.TrafficLightState.Red, true, false);
                             * instance.m_nodes.m_buffer[seg.m_endNode].m_flags |= NetNode.Flags.TrafficLights;
                             * instance.m_nodes.m_buffer[seg.m_startNode].m_flags |= NetNode.Flags.TrafficLights;
                             *
                             * /*if (vehicleID == leadingVehicleID)
                             * {
                             *  instance.m_segments.m_buffer[crt_segment_id].m_trafficLightState0 = (byte) RoadBaseAI.TrafficLightState.Red;
                             * }*/
                            preventCheckNextLane = true;
                        }
                    }
                }

                //assess if single track station fix is necessary, before Notify which can cancel TrainAtStation status (if new front carriage is out of station for example)
                if (mayNeedSingleTrackStationFix && ri.status != ReservationStatus.TrainAtStation)
                {
                    mayNeedSingleTrackStationFix = false;
                }
            }

            if (ReservationManager.RequireReservation(crt_segment_id)) //train carriage is on a one lane section (or double track station which may belong to a single track section)
            {
                instance2.NotifyReservation(leadingVehicleID, crt_segment_id, true, vehicleData.m_flags);
            }

            if (notifyFutureTrack)
            {
                instance2.NotifyReservation(leadingVehicleID, next_segment_id, false);
            }

            return(preventCheckNextLane);
        }