public static NetInfo.Node SetFlags(this NetInfo.Node node, NetNode.Flags required, NetNode.Flags forbidden)
        {
            node.m_flagsRequired = required;
            node.m_flagsForbidden = forbidden;

            return node;
        }
 public override void UpdateLaneConnection(ushort nodeID, ref NetNode data)
 {
     if ((data.m_flags & NetNode.Flags.Temporary) == NetNode.Flags.None)
     {
         uint num = 0u;
         byte offset = 0;
         float num2 = 1E+10f;
         PathUnit.Position pathPos;
         PathUnit.Position position;
         float num3;
         float num4;
         if ((data.m_flags & NetNode.Flags.ForbidLaneConnection) == NetNode.Flags.None && PathManager.FindPathPosition(data.m_position, this.m_netService, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, this.m_vehicleType, true, false, 32f, out pathPos, out position, out num3, out num4) && num3 < num2)
         {
             NetManager instance = Singleton<NetManager>.instance;
             int num5;
             uint num6;
             if (instance.m_segments.m_buffer[(int)pathPos.m_segment].GetClosestLane((int)pathPos.m_lane, NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle, this.m_vehicleType, out num5, out num6))
             {
                 num = PathManager.GetLaneID(pathPos);
                 offset = pathPos.m_offset;
             }
         }
         if (num != data.m_lane)
         {
             if (data.m_lane != 0u)
             {
                 this.RemoveLaneConnection(nodeID, ref data);
             }
             if (num != 0u)
             {
                 this.AddLaneConnection(nodeID, ref data, num, offset);
             }
         }
     }
 }
 public static void GetNodeSegments(NetNode node, IList<NetSegment> list)
 {
     if (node.m_segment0 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment0]);
     }
     if (node.m_segment1 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment1]);
     }
     if (node.m_segment2 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment2]);
     }
     if (node.m_segment3 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment3]);
     }
     if (node.m_segment4 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment4]);
     }
     if (node.m_segment5 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment5]);
     }
     if (node.m_segment6 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment6]);
     }
     if (node.m_segment7 > 0)
     {
         list.Add(NetManager.instance.m_segments.m_buffer[node.m_segment7]);
     }
 }
 public static void GetNodeSegmentIds(NetNode node, IList<ushort> list)
 {
     if (node.m_segment0 > 0)
     {
         list.Add(node.m_segment0);
     }
     if (node.m_segment1 > 0)
     {
         list.Add(node.m_segment1);
     }
     if (node.m_segment2 > 0)
     {
         list.Add(node.m_segment2);
     }
     if (node.m_segment3 > 0)
     {
         list.Add(node.m_segment3);
     }
     if (node.m_segment4 > 0)
     {
         list.Add(node.m_segment4);
     }
     if (node.m_segment5 > 0)
     {
         list.Add(node.m_segment5);
     }
     if (node.m_segment6 > 0)
     {
         list.Add(node.m_segment6);
     }
     if (node.m_segment7 > 0)
     {
         list.Add(node.m_segment7);
     }
 }
 public override void UpdateNode(ushort nodeID, ref NetNode data)
 {
     if ((data.m_flags & NetNode.Flags.Untouchable) != NetNode.Flags.None)
     {
         ushort index = NetNode.FindOwnerBuilding(nodeID, 32f);
         if (index != 0)
         {
             BuildingManager buildingManager = Singleton<BuildingManager>.instance;
             Notification.Problem oldProblems = buildingManager.m_buildings.m_buffer[index].m_problems;
             Notification.Problem newProblems;
             if (data.CountSegments() != 0)
             {
                 newProblems = Notification.RemoveProblems(oldProblems, Notification.Problem.WaterNotConnected);
             }
             else
             {
                 newProblems = Notification.AddProblems(oldProblems, Notification.Problem.WaterNotConnected);
             }
             if (newProblems != oldProblems)
             {
                 buildingManager.m_buildings.m_buffer[index].m_problems = newProblems;
                 buildingManager.UpdateNotifications(index, oldProblems, newProblems);
             }
         }
         data.m_problems = Notification.RemoveProblems(data.m_problems, Notification.Problem.WaterNotConnected);
     }
     float minX = data.m_position.x - 100f;
     float maxX = data.m_position.x + 100f;
     float minZ = data.m_position.z - 100f;
     float maxZ = data.m_position.z + 100f;
     Singleton<WaterManager>.instance.UpdateGrid(minX, minZ, maxX, maxZ);
 }
Exemple #6
0
        private void ChatClient_OnDisconnect(NetNode connection)
        {
            _loggedIn = false;
            _connected = false;
            Console.WriteLine("Disconnected");

            //Connect();
        }
        public static List<NetSegment> GetNodeSegments(NetNode node)
        {
            var list = new List<NetSegment>(node.CountSegments());

            GetNodeSegments(node, list);

            return list;
        }
        public void CustomSimulationStep(ushort nodeId, ref NetNode data)
        {
            var node = GetNodeSimulation(nodeId);

            if (node == null || (node.FlagTimedTrafficLights && !node.TimedTrafficLightsActive))
            {
                OriginalSimulationStep(nodeId, ref data);
            }
        }
Exemple #9
0
        public bool Send(Packet packet, NetNode sendTo, int channel=0)
        {
            var msg = packet.SendMessage(this);
            NetSendResult result = Peer.SendMessage(msg, (NetConnection)sendTo, (Lidgren.Network.NetDeliveryMethod)packet.Method, channel);

            if (result == NetSendResult.Queued || result == NetSendResult.Sent)
                return true;
            else
                return false;
        }
		public void CustomNodeSimulationStep(ushort nodeId, ref NetNode data) {
			try {
				nodeCheckMod = (nodeCheckMod + 1u) & nodeCheckLoadBalanceMod[Options.simAccuracy];
				if ((nodeCheckMod & nodeId) == nodeCheckMod && TrafficLightTool.getToolMode() != ToolMode.AddPrioritySigns)
					TrafficPriority.nodeHousekeeping(nodeId);

				var nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId);
				if (nodeSim == null || (nodeSim.TimedTrafficLights && !nodeSim.TimedTrafficLightsActive)) {
					OriginalSimulationStep(nodeId, ref data);
				}
			} catch (Exception e) {
				Log.Warning($"CustomNodeSimulationStep: An error occurred: {e.ToString()}");
			}
		}
        static void Main(string[] args)
        {
            int port = 12345;

            var messageSerializer = new ProtobufMessageSerializer(
                new Message[] { new JoinRoom(), new Say(), new RoomEvent(), new JoinRoomResponse() },
                new MessageHeader[] { new OperationHeader() });

            var logger = new LoggerConfiguration()
                .ConfigureMOUSETypesDestructure()
                .MinimumLevel.Verbose()
                .WriteTo.ColoredConsole()
                .CreateLogger();

            var coreEventLogger = new SerilogCoreEvents(logger);

            var transport = new LidgrenNetProvider(
                new NetPeerConfiguration("Public")
                {
                    MaximumConnections = 10,
                    AcceptIncomingConnections = true,
                    Port = port,
                    LocalAddress = IPAddress.Loopback
                },
                new SerilogLidgrenEvents(logger));

            var netConfig = new NetNodeConfig()
            {
                ConnectTimeoutSec = 30,
                SendTimeoutSec = 30
            };

            var bufferPool = new WcfBufferPool();

            var node = new NetNode<NetChannel>("server", transport, coreEventLogger, messageSerializer, config: netConfig,
                channelFactory: (n, transportChannel) =>
                    new AsyncProcessingNetChannel(builder => builder
                        .UseFiber(Fiber, config => config
                            .Lock<Say>(LockType.Read)
                            .Lock<JoinRoom>(LockType.Write)
                            .Lock<PeerDisconnected>(LockType.Write))
                        .UseConfigurableDispatcher(config => config
                            .HandleMessage<Say>(OnSay)
                            .HandleMessage<JoinRoom>(OnRoomJoin)
                            .HandleMessage<PeerDisconnected>((msg, o) => OnRoomLeave(o.ReplyChannel))),
                        n, transportChannel, messageSerializer, coreEventLogger, netConfig, bufferPool));
            
            node.Start();
            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            //configure serialization
            var messageSerializer = new ProtobufMessageSerializer(
                new Message[] {new JoinRoom(), new Say(), new RoomEvent(), new JoinRoomResponse()},
                new MessageHeader[] {new OperationHeader()});

            var logger = new LoggerConfiguration()
                .ConfigureMOUSETypesDestructure()
                .MinimumLevel.Verbose()
                .WriteTo.ColoredConsole()
                .CreateLogger();

            var coreEventLogger = new SerilogCoreEvents(logger);

            //configure network transport provider
            var transport = new LidgrenNetProvider(
                new NetPeerConfiguration("Public") { LocalAddress = IPAddress.Loopback },
                new SerilogLidgrenEvents(logger));
            var config = new NetNodeConfig {SendTimeoutSec = 30, ConnectTimeoutSec = 60};


            var node = new NetNode<NetChannel>("client", transport, coreEventLogger, messageSerializer,config : config, 
                channelFactory: (n,transportChannel) =>
                {
                    var peer = new NetChannel(n, transportChannel, messageSerializer, coreEventLogger, config, new WcfBufferPool());
                    //low level channel handling declaration uses Rx channel.OperationReceivedEvent under the hood
                    peer.RegisterHandler<RoomEvent>(msg => Console.WriteLine(msg.UserName + "->" + msg.Text));

                    return peer;
                });

            try
            {
                Run(node).Wait();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            Console.ReadKey();
        }
Exemple #13
0
        private static List <ushort> GetStationNodes(Building building)
        {
            ushort        nodeID         = building.m_netNode;
            List <ushort> stationNodeIDs = null;

            while (nodeID > 0)
            {
                NetNode node = NodeFrom(nodeID);
                if (node.Info != null && (node.Info.IsUndergroundMetroStationTrack() || node.Info.name == "Metro Station Track"))
                {
                    if (stationNodeIDs == null)
                    {
                        stationNodeIDs = new List <ushort>();
                    }
                    stationNodeIDs.Add(nodeID);
                }
                nodeID = NodeFrom(nodeID).m_nextBuildingNode;
            }
            return(stationNodeIDs);
        }
Exemple #14
0
        void RenderOverlayForSegments(RenderManager.CameraInfo cameraInfo, NetNode node)
        {
            LaneChangerPathManager pathManager = (LaneChangerPathManager)PathManager.instance;

            for (int i = 0; i < node.CountSegments(); i++)
            {
                ushort segId = node.GetSegment(i);
                if (segId != currentSegment)
                {
                    if (pathManager.laneChangerSegments[currentSegment].PermittedConnectionTo(segId))
                    {
                        NetTool.RenderOverlay(RenderManager.instance.CurrentCameraInfo, ref NetManager.instance.m_segments.m_buffer[segId], new Color(0.0f, 1f, 0.0f, 0.6f), new Color(0f, 1f, 0f, 0.9f));
                    }
                    else
                    {
                        NetTool.RenderOverlay(RenderManager.instance.CurrentCameraInfo, ref NetManager.instance.m_segments.m_buffer[segId], new Color(1f, 0.0f, 0.0f, 0.6f), new Color(1f, 0f, 0f, 0.9f));
                    }
                }
            }
        }
Exemple #15
0
        private Vector3 CalculateNodePositionForSegment(NetNode node, int segmentId)
        {
            var position = node.m_position;

            var segment = Singleton <NetManager> .instance.m_segments.m_buffer[segmentId];

            if (segment.m_startNode == SelectedNodeId)
            {
                position.x += segment.m_startDirection.x * 10f;
                position.y += segment.m_startDirection.y * 10f;
                position.z += segment.m_startDirection.z * 10f;
            }
            else
            {
                position.x += segment.m_endDirection.x * 10f;
                position.y += segment.m_endDirection.y * 10f;
                position.z += segment.m_endDirection.z * 10f;
            }
            return(position);
        }
        bool IsSuitableJunction()
        {
            if (HoveredNodeId == 0)
            {
                return(false);
            }
            NetNode node = HoveredNodeId.ToNode();

            if (node.CountSegments() < 3)
            {
                return(false);
            }

            if (!node.Info.CanConnectPath())
            {
                return(false);
            }

            return(true);
        }
 public static bool CheckNodeEq(ushort node1, NetNode node2)
 {
     if (Singleton <NetManager> .instance.m_nodes.m_buffer[node1].m_position == node2.m_position)
     {
         if (Singleton <NetManager> .instance.m_nodes.m_buffer[node1].m_nextGridNode == node2.m_nextGridNode)
         {
             if (Singleton <NetManager> .instance.m_nodes.m_buffer[node1].m_flags == node2.m_flags)
             {
                 if (Singleton <NetManager> .instance.m_nodes.m_buffer[node1].m_nextLaneNode == node2.m_nextLaneNode)
                 {
                     if (Singleton <NetManager> .instance.m_nodes.m_buffer[node1].m_elevation == node2.m_elevation)
                     {
                         return(true);
                     }
                 }
             }
         }
     }
     return(false);
 }
Exemple #18
0
        /// <summary>
        /// This handler is executed after a node was refreshed in any way.
        /// </summary>
        /// <param name="node">The node id</param>
        public static void Postfix(ushort node)
        {
            NetNode netNode = Singleton <NetManager> .instance.m_nodes.m_buffer[node];

            ushort[] segments = new ushort[8];
            segments[0] = netNode.m_segment0;
            segments[1] = netNode.m_segment1;
            segments[2] = netNode.m_segment2;
            segments[3] = netNode.m_segment3;
            segments[4] = netNode.m_segment4;
            segments[5] = netNode.m_segment5;
            segments[6] = netNode.m_segment6;
            segments[7] = netNode.m_segment7;
            Command.SendToAll(new NodeUpdateCommand
            {
                Segments = segments,
                NodeID   = node,
                Flags    = netNode.m_flags
            });
        }
 public static void Postfix(ref NetNode __instance)
 {
     if (OptionUI.noJunction)
     {
         NetInfo asset = __instance.Info;
         if (asset != null)
         {
             if (asset.m_netAI is RoadAI)
             {
                 if (CSURUtil.IsCSURNoJunction(asset))
                 {
                     if (__instance.CountSegments() == 2)
                     {
                         __instance.m_flags &= ~NetNode.Flags.Junction;
                     }
                 }
             }
         }
     }
 }
Exemple #20
0
        void SetSegments(ushort segmentId, ushort infoIndex, ref Segment previousSeg)
        {
            NetSegment segment = NetManager.instance.m_segments.m_buffer[segmentId];

            if (segment.m_infoIndex != infoIndex || m_segments.ContainsKey(segmentId))
            {
                return;
            }

            Segment seg = default(Segment);

            seg.m_segmentId = segmentId;

            NetSegment previousSegment = NetManager.instance.m_segments.m_buffer[previousSeg.m_segmentId];
            ushort     nextNode;

            if ((segment.m_startNode == previousSegment.m_endNode) ||
                (segment.m_startNode == previousSegment.m_startNode))
            {
                nextNode         = segment.m_endNode;
                seg.m_targetNode = segment.m_startNode == previousSeg.m_targetNode
                    ? segment.m_endNode
                    : segment.m_startNode;
            }
            else
            {
                nextNode         = segment.m_startNode;
                seg.m_targetNode = segment.m_endNode == previousSeg.m_targetNode
                    ? segment.m_startNode
                    : segment.m_endNode;
            }

            m_segments[segmentId] = seg;

            NetNode node = NetManager.instance.m_nodes.m_buffer[nextNode];

            if (node.CountSegments() == 2)
            {
                SetSegments(node.m_segment0 == segmentId ? node.m_segment1 : node.m_segment0, infoIndex, ref seg);
            }
        }
        private void RebuildVehicleNumDicts(ref NetNode node)
        {
            numVehiclesMovingToSegmentId = new TinyDictionary <ushort, uint> [numLanes];
            numVehiclesGoingToSegmentId  = new TinyDictionary <ushort, uint> [numLanes];

            Constants.ServiceFactory.NetService.IterateSegmentLanes(SegmentId, delegate(uint laneId, ref NetLane lane, NetInfo.Lane laneInfo, ushort segmentId, ref NetSegment segment, byte laneIndex) {
                IDictionary <ushort, uint> numVehicleMoving = new TinyDictionary <ushort, uint>();
                IDictionary <ushort, uint> numVehicleGoing  = new TinyDictionary <ushort, uint>();

                numVehiclesMovingToSegmentId[laneIndex] = numVehicleMoving;
                numVehiclesGoingToSegmentId[laneIndex]  = numVehicleGoing;

                return(true);
            });

            IExtSegmentEndManager segEndMan = Constants.ManagerFactory.ExtSegmentEndManager;

            for (int i = 0; i < 8; ++i)
            {
                ushort segId = node.GetSegment(i);
                if (segId == 0)
                {
                    continue;
                }

                if (!segEndMan.ExtSegmentEnds[segEndMan.GetIndex(segId, (bool)Constants.ServiceFactory.NetService.IsStartNode(segId, NodeId))].outgoing)
                {
                    continue;
                }

                foreach (TinyDictionary <ushort, uint> numVehiclesMovingToSegId in numVehiclesMovingToSegmentId)
                {
                    numVehiclesMovingToSegId[segId] = 0;
                }

                foreach (TinyDictionary <ushort, uint> numVehiclesGoingToSegId in numVehiclesGoingToSegmentId)
                {
                    numVehiclesGoingToSegId[segId] = 0;
                }
            }
        }
Exemple #22
0
        /// <summary>
        /// Adds tags that can't be evaluated through a normal search
        /// </summary>
        /// <param name="segment">The segment to generate extended tags for</param>
        /// <returns>A list of tags generated from this segment</returns>
        public static List <OSMWayTag> AddExtendedWayTags(NetSegment segment)
        {
            List <OSMWayTag> returnList = new List <OSMWayTag>();

            ushort startNodeId = segment.m_endNode;
            ushort endNodeId   = segment.m_startNode;

            NetManager netManager = Singleton <NetManager> .instance;
            NetNode    startNode  = netManager.m_nodes.m_buffer[startNodeId];
            NetNode    endNode    = netManager.m_nodes.m_buffer[endNodeId];

            byte wayElevation   = (byte)(Mathf.Clamp((startNode.m_elevation + endNode.m_elevation) / 2, 0, 255));
            bool wayUnderground = startNode.m_flags.IsFlagSet(NetNode.Flags.Underground) || endNode.m_flags.IsFlagSet(NetNode.Flags.Underground);

            if (wayUnderground && MapperOptionsManager.OptionChecked("tunnels", MapperOptionsManager.exportOptions))
            {
                returnList.Add(new OSMWayTag {
                    k = "tunnel", v = "yes"
                });
                returnList.Add(new OSMWayTag {
                    k = "level", v = (-Mathf.FloorToInt(wayElevation / 12)).ToString()
                });
                returnList.Add(new OSMWayTag {
                    k = "layer", v = (-Mathf.FloorToInt(wayElevation / 12)).ToString()
                });
            }
            else if (wayElevation != 0 && MapperOptionsManager.OptionChecked("bridges", MapperOptionsManager.exportOptions))
            {
                returnList.Add(new OSMWayTag {
                    k = "bridge", v = "yes"
                });
                returnList.Add(new OSMWayTag {
                    k = "level", v = Mathf.FloorToInt(wayElevation / 12).ToString()
                });
                returnList.Add(new OSMWayTag {
                    k = "layer", v = Mathf.FloorToInt(wayElevation / 12).ToString()
                });
            }

            return(returnList);
        }
Exemple #23
0
        internal ushort GetSegmentFromNode()
        {
            bool   considerSegmentLenght = true;
            ushort minSegId = 0;

            if (HoveredNodeId != 0)
            {
                NetNode node      = HoveredNodeId.ToNode();
                Vector3 dir0      = node.m_position - m_mousePosition;
                float   min_angle = float.MaxValue;
                for (int i = 0; i < 8; ++i)
                {
                    ushort segmentId = node.GetSegment(i);
                    if (segmentId == 0)
                    {
                        continue;
                    }
                    NetSegment segment = segmentId.ToSegment();
                    Vector3    dir;
                    if (segment.m_startNode == HoveredNodeId)
                    {
                        dir = segment.m_startDirection;
                    }
                    else
                    {
                        dir = segment.m_endDirection;
                    }
                    float angle = GetAgnele(-dir, dir0);
                    if (considerSegmentLenght)
                    {
                        angle *= segment.m_averageLength;
                    }
                    if (angle < min_angle)
                    {
                        min_angle = angle;
                        minSegId  = segmentId;
                    }
                }
            }
            return(minSegId);
        }
        public override void GetNodeState(ushort nodeID, ref NetNode nodeData, ushort segmentID, ref NetSegment segmentData, out NetNode.Flags flags, out Color color)
        {
            flags = nodeData.m_flags;
            color = Color.gray.gamma;

            if ((nodeData.m_flags & NetNode.Flags.TrafficLights) != 0)
            {
                NetManager netManager = NetManager.instance;
                for (int s = 0; s < 8; s++)
                {
                    ushort segment = nodeData.GetSegment(s);
                    if (segment != 0)
                    {
                        if (netManager.m_segments.m_buffer[segment].m_infoIndex != nodeData.m_infoIndex)
                        {
                            GetLevelCrossingNodeState(nodeID, ref nodeData, segment, ref netManager.m_segments.m_buffer[segment], ref flags, ref color);
                        }
                    }
                }
            }
        }
        private Vector3 CalculateNodePositionForSegment(NetNode node, ref NetSegment segment)
        {
            Vector3 position = node.m_position;

            const float offset = 25f;

            if (segment.m_startNode == SelectedNodeId)
            {
                position.x += segment.m_startDirection.x * offset;
                position.y += segment.m_startDirection.y * offset;
                position.z += segment.m_startDirection.z * offset;
            }
            else
            {
                position.x += segment.m_endDirection.x * offset;
                position.y += segment.m_endDirection.y * offset;
                position.z += segment.m_endDirection.z * offset;
            }

            return(position);
        }
Exemple #26
0
        /// <summary>
        /// returns the segment connected to HoveredNodeId that is closest to the input position.
        /// </summary>
        internal ushort GetHoveredSegmentFromNode(Vector3 hitPos)
        {
            ushort     minSegId    = 0;
            NetManager netManager  = NetManager.instance;
            NetNode    node        = netManager.m_nodes.m_buffer[HoveredNodeId];
            float      minDistance = float.MaxValue;

            for (int i = 0; i < 8; ++i)
            {
                ushort  segmentId = node.GetSegment(i);
                Vector3 pos       = netManager.m_segments.m_buffer[segmentId].GetClosestPosition(hitPos);
                float   distance  = (hitPos - pos).sqrMagnitude;
                if (distance < minDistance)
                {
                    minDistance = distance;
                    minSegId    = segmentId;
                }
            }
            ;
            return(minSegId);
        }
Exemple #27
0
        public static void Postfix(ushort nodeID, ref NetNode data)
        {
            if (Options.automaticallyAddTrafficLightsIfApplicable)
            {
                return;
            }

            // test for not Flags.Junction is unnecessary because tested in IsTrafficLightToggleable
            // but it's a simple and fast exit, while IsTrafficLightToggleable is quite complex
            if (!data.m_flags.IsFlagSet(NetNode.Flags.Junction) || !TrafficLightManager.Instance.CanToggleTrafficLight(nodeID, false, ref data, out _))
            {
                return;
            }

            // UpdateNode is called for new nodes and changed nodes (-> existing AND new junctions)
            // For new junctions this method is called BEFORE traffic lights are set (done in UpdateNodeFlags)
            // Marking junction with CustomTrafficLights prevents the setting of traffic lights
            // For existing junctions this has the additional benefit of not removing the lights when the junction changed

            data.m_flags |= NetNode.Flags.CustomTrafficLights;
        }
Exemple #28
0
        public static bool Filter(NetNode node)
        {
            if (MoveItTool.instance.AlignMode == MoveItTool.AlignModes.Group || MoveItTool.instance.AlignMode == MoveItTool.AlignModes.Inplace)
            {
                return(false);
            }
            if (!MoveItTool.marqueeSelection)
            {
                return(true);
            }

            if (MoveItTool.filterPicker && node.Info == Picker.Info)
            {
                return(true);
            }
            if (MoveItTool.filterNodes)
            {
                return(_networkFilter(node.Info));
            }
            return(false);
        }
        //to detour move it
        public static bool MoveItRayCastNode(ref NetNode node, Segment3 ray, float snapElevation, out float t, out float priority)
        {
            NetInfo info = node.Info;

            // NON-STOCK CODE STARTS
            if (CSUROffset.IsCSUROffset(info.m_netAI.m_info))
            {
                return(RayCastNodeMasked(ref node, ray, snapElevation, false, out t, out priority));
            }
            // NON-STOCK CODE ENDS
            //if ((node.m_flags & (NetNode.Flags.Middle | NetNode.Flags.Outside)) == NetNode.Flags.None)
            //{
            float num = (float)node.m_elevation + info.m_netAI.GetSnapElevation();
            float t2;

            if (info.m_netAI.IsUnderground())
            {
                t2 = Mathf.Clamp01(Mathf.Abs(snapElevation + num) / 12f);
            }
            else
            {
                t2 = Mathf.Clamp01(Mathf.Abs(snapElevation - num) / 12f);
            }
            float collisionHalfWidth = Mathf.Max(3f, info.m_netAI.GetCollisionHalfWidth());
            float num2 = Mathf.Lerp(info.GetMinNodeDistance(), collisionHalfWidth, t2);

            if (Segment1.Intersect(ray.a.y, ray.b.y, node.m_position.y, out t))
            {
                float num3 = Vector3.Distance(ray.Position(t), node.m_position);
                if (num3 < num2)
                {
                    priority = Mathf.Max(0f, num3 - collisionHalfWidth);
                    return(true);
                }
            }
            //}
            t        = 0f;
            priority = 0f;
            return(false);
        }
Exemple #30
0
        private void RenderStopSigns(ushort nodeId, ref NetNode node, RenderManager.CameraInfo cameraInfo)
        {
            //only display stop signs if no traffic lights
            if ((node.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None)
            {
                return;
            }

            var nm    = Singleton <NetManager> .instance;
            var num   = node.Info.m_halfWidth * 0.75f;
            var alpha = MathUtils.SmoothStep(1000f, 500f, Vector3.Distance(cameraInfo.m_position, node.m_position));

            for (var index = 0; index < 8; ++index)
            {
                var segment = node.GetSegment(index);
                if (segment != 0)
                {
                    var info = nm.m_segments.m_buffer[segment].Info;
                    if ((info.m_vehicleTypes & VehicleInfo.VehicleType.Car) != VehicleInfo.VehicleType.None)
                    {
                        var flag3 = nm.m_segments.m_buffer[segment].m_startNode == nodeId;
                        var flag4 = (nm.m_segments.m_buffer[segment].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
                        if ((flag3 != flag4 ? (info.m_hasBackwardVehicleLanes ? 1 : 0) : (info.m_hasForwardVehicleLanes ? 1 : 0)) !=
                            0)
                        {
                            var scale   = _hoveredNodeId == nodeId && _hoveredButtonIndex == index + 1 ? 1.0f : 0.75f;
                            var vector3 = !flag3
                ? nm.m_segments.m_buffer[segment].m_endDirection
                : nm.m_segments.m_buffer[segment].m_startDirection;
                            var position = node.m_position + vector3 * num;
                            var flags    = !flag3 ? NetSegment.Flags.YieldEnd : NetSegment.Flags.YieldStart;
                            var sign     = (nm.m_segments.m_buffer[segment].m_flags & flags) != NetSegment.Flags.None
                ? NotificationEvent.Type.YieldOn
                : NotificationEvent.Type.YieldOff;
                            NotificationEvent.RenderInstance(cameraInfo, sign, position, scale, alpha);
                        }
                    }
                }
            }
        }
Exemple #31
0
        private static bool IsEndTunnel(ref NetNode node)
        {
            if ((node.m_flags & NetNode.Flags.Untouchable) == NetNode.Flags.Untouchable && (node.m_flags & NetNode.Flags.Underground) == NetNode.Flags.Underground)
            {
                return(false);
            }

            int count = 0;

            for (int i = 0; i < 8; i++)
            {
                int segment = node.GetSegment(i);
                if (segment == 0 || (NetManager.instance.m_segments.m_buffer[segment].m_flags & NetSegment.Flags.Created) != NetSegment.Flags.Created)
                {
                    continue;
                }

                NetInfo info = NetManager.instance.m_segments.m_buffer[segment].Info;

                RoadPrefab prefab = RoadPrefab.GetPrefab(info);
                if (prefab == null)
                {
                    return(true);
                }

                if (info != prefab.roadAI.tunnel && info != prefab.roadAI.slope)
                {
                    return(true);
                }

                count++;
            }

            if (TerrainManager.instance.SampleRawHeightSmooth(node.m_position) > node.m_position.y + 8f)
            {
                return(false);
            }

            return(count == 1);
        }
        /* This draws the UI circles on the map */
        protected override void RenderOverlayExtended(RenderManager.CameraInfo cameraInfo)
        {
            try
            {
                if (insideUI)
                {
                    return;
                }

                if (m_hoverNode != 0)
                {
                    NetNode hoveredNode = NetUtil.Node(m_hoverNode);

                    // kinda stole this color from Move It!
                    // thanks to SamsamTS because they're a UI god
                    // ..and then Strad stole it from all of you!!
                    RenderManager.instance.OverlayEffect.DrawCircle(cameraInfo, Color.black, hoveredNode.m_position, 15f, hoveredNode.m_position.y - 1f, hoveredNode.m_position.y + 1f, true, true);
                    float?radius = UIWindow2.instance.P_RoundAboutPanel.RadiusField.Value;
                    if (radius != null)
                    {
                        float roadWidth        = UIWindow2.instance.dropDown.Value.m_halfWidth; // There is a slight chance that this will throw an exception
                        float innerCirleRadius = radius - roadWidth > 0 ? 2 * ((float)radius - roadWidth) : 2 * (float)radius;
                        RenderManager.instance.OverlayEffect.DrawCircle(cameraInfo, Color.red, hoveredNode.m_position, innerCirleRadius, hoveredNode.m_position.y - 2f, hoveredNode.m_position.y + 2f, true, true);
                        RenderManager.instance.OverlayEffect.DrawCircle(cameraInfo, Color.red, hoveredNode.m_position, 2 * ((float)radius + roadWidth /*DISTANCE_PADDING - 5*/), hoveredNode.m_position.y - 1f, hoveredNode.m_position.y + 1f, true, true);
                    }
                    //RenderDirectionVectors(cameraInfo);
                    RenderHoveringLabel("Click to build\nPress +/- to adjust radius");
                }
                else
                {
                    RenderMousePositionCircle(cameraInfo);
                    RenderHoveringLabel("Hover mouse over intersection");
                }
            }
            catch (Exception e)
            {
                Debug.LogError(e);
            }
        }
Exemple #33
0
        private void CleanGhostNodes()
        {
            int count = 0;

            // From moveit
            for (ushort nodeId = 0; nodeId < NetManager.instance.m_nodes.m_buffer.Length && count < 10; nodeId++)
            {
                NetNode node = NetManager.instance.m_nodes.m_buffer[nodeId];
                if ((node.m_flags & NetNode.Flags.Created) == NetNode.Flags.None)
                {
                    continue;
                }
                if ((node.m_flags & NetNode.Flags.Untouchable) != NetNode.Flags.None)
                {
                    continue;
                }
                bool hasSegments = false;

                for (int i = 0; i < 8; i++)
                {
                    if (node.GetSegment(i) > 0)
                    {
                        hasSegments = true;
                        break;
                    }
                }

                if (!hasSegments)
                {
                    count++;
                    NetUtil.ReleaseNode(nodeId);
                }
            }

            if (count > 0)
            {
                Debug.Log($"Removed {count} ghost nodes");
            }
        }
            public static void Change(ushort nodeId, ref NetNode node, Mode mode)
            {
                if (Node.IsValidTrafficLightsIntersection(nodeId, ref node))
                {
                    switch (mode)
                    {
                    case Mode.Add:
                        node.m_flags |= NetNode.Flags.TrafficLights;
                        node.m_flags |= NetNode.Flags.CustomTrafficLights;
                        break;

                    case Mode.Remove:
                        node.m_flags &= ~NetNode.Flags.TrafficLights;
                        node.m_flags |= NetNode.Flags.CustomTrafficLights;
                        break;

                    case Mode.Toggle:
                        node.m_flags ^= NetNode.Flags.TrafficLights;
                        node.m_flags |= NetNode.Flags.CustomTrafficLights;
                        break;

                    case Mode.Reset:
                        if (Node.WantTrafficLights(nodeId, ref node))
                        {
                            node.m_flags |= NetNode.Flags.TrafficLights;
                        }
                        else
                        {
                            node.m_flags &= ~NetNode.Flags.TrafficLights;
                        }
                        node.m_flags &= ~NetNode.Flags.CustomTrafficLights;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(mode), mode, null);
                    }
                    UpdateFlags(nodeId, ref node);
                }
            }
Exemple #35
0
        private static void Connect(ushort node1, ushort node2, Vector3 startDir, Vector3 endDir, NetInfo Info, bool invert = false)
        {
            //Debug.Log("Connectiong nodes " + node1 + " and " + node2);

            NetNode netNode1 = NetAccess.GetNode(node1);
            NetNode netNode2 = NetAccess.GetNode(node2);

            if ((netNode1.m_position - netNode2.m_position).magnitude < MIN_SEGMENT_LENGTH)
            {
                RepairShortSegment(ref endDir, ref node2);
            }

            //NetAccess.CreateSegment(node1,node2,(netNode2.m_position-netNode1.m_position).normalized, (netNode1.m_position - netNode2.m_position).normalized, info, invert);
            try
            {
                NetAccess.CreateSegment(node1, node2, startDir, endDir, Info, invert);
            }
            catch (Exception e)
            {
                Debug.LogWarning(e);
            }
        }
        internal ushort GetSegmentFromNode(Vector3 hitPos)
        {
            if (HoveredNodeId == 0)
            {
                return(0);
            }
            ushort  minSegId    = 0;
            NetNode node        = NetManager.instance.m_nodes.m_buffer[HoveredNodeId];
            float   minDistance = float.MaxValue;

            foreach (ushort segmentId in NetUtil.IterateNodeSegments(HoveredNodeId))
            {
                Vector3 pos      = segmentId.ToSegment().GetClosestPosition(hitPos);
                float   distance = (hitPos - pos).sqrMagnitude;
                if (distance < minDistance)
                {
                    minDistance = distance;
                    minSegId    = segmentId;
                }
            }
            return(minSegId);
        }
Exemple #37
0
        /* If node distance is too short, we travel one segment up from the border node and set the new node as the one to connect to */
        private void RepairShortSegment(ref Vector3 direction, ref ushort node)
        {
            //Debug.Log("Repairing short segment...");

            NetNode netNode = NetUtil.Node(node);

            // If there is more than one segment we cannot safely delete it (we don't even know from which segment we should pick)
            if (netNode.CountSegments() != 1)
            {
                return;
            }

            ushort     segmentId  = NetUtil.GetFirstSegment(netNode);
            NetSegment netSegment = NetUtil.Segment(segmentId);

            WrappedNode nodeW = _networkDictionary.RegisterNode(node);

            if (node == netSegment.m_startNode)
            {
                direction = netSegment.m_endDirection;
                node      = netSegment.m_endNode;
            }
            else
            {
                direction = netSegment.m_startDirection;
                node      = netSegment.m_startNode;
            }

            WrappedSegment segmentW = _networkDictionary.RegisterSegment(segmentId);

            _actionGroup.Actions.Add(segmentW);
            _actionGroup.Actions.Add(nodeW);
            segmentW.Release();
            nodeW.Release();
            segmentW.IsBuildAction = false;
            nodeW.IsBuildAction    = false;

            //NetUtil.ReleaseSegment(segmentId, true);
        }
        public void ToggleTrafficLight(ushort nodeId,
                                       ref NetNode node,
                                       bool showMessageOnError = true)
        {
            ToggleTrafficLightError reason;

            if (!TrafficLightManager.Instance.CanToggleTrafficLight(
                    nodeId,
                    !TrafficLightManager.Instance.HasTrafficLight(
                        nodeId,
                        ref node),
                    ref node,
                    out reason))
            {
                if (showMessageOnError)
                {
                    switch (reason)
                    {
                    case ToggleTrafficLightError.HasTimedLight: {
                        MainTool.WarningPrompt(
                            Translation.TrafficLights.Get("Dialog.Text:Node has timed TL script"));
                        break;
                    }

                    case ToggleTrafficLightError.IsLevelCrossing: {
                        MainTool.WarningPrompt(
                            Translation.TrafficLights.Get("Dialog.Text:Node is level crossing"));
                        break;
                    }
                    }
                }

                return;
            }

            TrafficPriorityManager.Instance.RemovePrioritySignsFromNode(nodeId);
            TrafficLightManager.Instance.ToggleTrafficLight(nodeId, ref node);
        }
        internal static bool Prefix(ushort nodeID, ref NetNode data, ushort segment1, ushort segment2, int index, ref TerrainModify.Surface surface, ref TerrainModify.Heights heights, ref TerrainModify.Edges edges, ref float left, ref float right, ref float leftY, ref float rightY, ref bool __result, NetAI __instance)
        {
            var net = __instance.m_info.GetMetaData();

            if (net is null)
            {
                return(true);
            }

            ProfileSection[] profile = net.QuayRoadsProfile;
            if (profile is null)
            {
                return(true);
            }

            Log.Debug("modifying mask for node " + nodeID.ToString() + ", section " + index);
            NetManager netManager    = Singleton <NetManager> .instance;
            bool       isStartNode   = netManager.m_segments.m_buffer[segment1].m_startNode == nodeID;
            bool       segmentInvert = (netManager.m_segments.m_buffer[segment1].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None;
            bool       invert        = isStartNode ^ segmentInvert;
            float      leftStartY    = leftY;
            float      rightStartY   = rightY;
            float      leftEndY      = leftY;
            float      rightEndY     = rightY;
            bool       result        = ModifyMaskCommon.ModifyMask(profile, invert, index, ref surface, ref heights, ref edges, ref left, ref right, ref leftStartY, ref rightStartY, ref leftEndY, ref rightEndY, ref __result);

            if (isStartNode)
            {
                leftY  = leftStartY;
                rightY = rightStartY;
            }
            else
            {
                leftY  = leftEndY;
                rightY = rightEndY;
            }
            return(result);
        }
Exemple #40
0
        private static void HoverBuilding(RenderManager.CameraInfo cameraInfo, Color toolColor, ushort buildingId)
        {
            BuildingBuffer[buildingId].GetTotalPosition(out Vector3 pos, out Quaternion rot, out Vector3 size);
            var quad = new Quad3(
                (rot * new Vector3(-size.x, 0, size.z) / 2) + pos,
                (rot * new Vector3(-size.x, 0, -size.z) / 2) + pos,
                (rot * new Vector3(size.x, 0, -size.z) / 2) + pos,
                (rot * new Vector3(size.x, 0, size.z) / 2) + pos
                );

            Singleton <RenderManager> .instance.OverlayEffect.DrawQuad(cameraInfo, toolColor, quad, -1f, 1280f, false, true);

            var nets               = BuildingBuffer[buildingId].m_netNode;
            var drawnSegments      = new HashSet <ushort>();
            var netManagerInstance = NetManager.instance;

            while (nets > 0)
            {
                ref NetNode currNode = ref netManagerInstance.m_nodes.m_buffer[nets];
                for (int i = 0; i < 8; i++)
                {
                    var segmentId = currNode.GetSegment(i);
                    if (segmentId == 0)
                    {
                        break;
                    }
                    if (drawnSegments.Contains(segmentId))
                    {
                        continue;
                    }
                    ref NetSegment nextSegment = ref netManagerInstance.m_segments.m_buffer[segmentId];
                    if (netManagerInstance.m_nodes.m_buffer[nextSegment.GetOtherNode(nets)].m_building != buildingId)
                    {
                        continue;
                    }
                    drawnSegments.Add(segmentId);
                    RenderOverlayUtils.RenderNetSegmentOverlay(cameraInfo, toolColor, segmentId);
                }
Exemple #41
0
        public void MarkAsUpdated(ushort nodeId, bool updateSegments = false)
        {
#if DEBUG
            if (DebugSwitch.GeometryDebug.Get())
            {
                Log._Debug(
                    $"GeometryManager.MarkAsUpdated(node {nodeId}): Marking node as updated");
            }
#endif
            lock (updateLock) {
                if (nodeId == 0)
                {
                    return;
                }

                updatedNodeBuckets[nodeId >> 6] |= 1uL << (nodeId & 63);
                stateUpdated = true;

                if (updateSegments)
                {
                    ref NetNode node = ref nodeId.ToNode();
                    for (int i = 0; i < 8; ++i)
                    {
                        ushort segmentId = node.GetSegment(i);
                        if (segmentId != 0)
                        {
                            MarkAsUpdated(
                                ref Constants.ManagerFactory.ExtSegmentManager.ExtSegments[segmentId],
                                false);
                        }
                    }
                }

                if (!Services.NetService.IsNodeValid(nodeId))
                {
                    SimulationStep(true);
                }
            }
        private void ProcessNodes(System.Action <ushort> processNode)
        {
            NetManager instance = Singleton <NetManager> .instance;
            bool       flag     = false;
            NetNode    netNode1 = instance.m_nodes.m_buffer[(int)this.m_InstanceID.NetNode];
            Vector3    position = netNode1.m_position;

            ItemClass.SubService subService = netNode1.Info.m_class.m_subService;
            ushort building = Singleton <BuildingManager> .instance.FindBuilding(position, 100f,
                                                                                 ItemClass.Service.PublicTransport, subService, Building.Flags.Active, Building.Flags.Untouchable);

            if ((int)building != 0)
            {
                ushort[] stationStops = PanelExtenderCityService.GetStationStops(building);
                if (stationStops.Length != 0 &&
                    ((IEnumerable <ushort>)stationStops).Contains <ushort>(this.m_InstanceID.NetNode))
                {
                    flag = true;
                    for (int index = 0; index < stationStops.Length; ++index)
                    {
                        processNode(stationStops[index]);
                    }
                }
            }
            if (flag)
            {
                return;
            }
            for (int index = 0; index < 32768; ++index)
            {
                NetNode netNode2 = instance.m_nodes.m_buffer[index];
                if (netNode2.m_flags != NetNode.Flags.None && (int)netNode2.m_transportLine != 0 &&
                    position == netNode2.m_position)
                {
                    processNode((ushort)index);
                }
            }
        }
		public void CustomNodeSimulationStep(ushort nodeId, ref NetNode data) {
			if (simStartFrame == 0)
				simStartFrame = Singleton<SimulationManager>.instance.m_currentFrameIndex;

			try {
				if (TrafficLightTool.getToolMode() != ToolMode.AddPrioritySigns) {
					try {
						TrafficPriority.nodeHousekeeping(nodeId);
					} catch (Exception e) {
						Log.Error($"Error occured while housekeeping node {nodeId}: " + e.ToString());
					}
				}

				TrafficPriority.TrafficLightSimulationStep();

				var nodeSim = TrafficLightSimulation.GetNodeSimulation(nodeId);
				if (nodeSim == null || !nodeSim.IsSimulationActive()) {
					OriginalSimulationStep(nodeId, ref data);
				}
			} catch (Exception e) {
				Log.Warning($"CustomNodeSimulationStep: An error occurred: {e.ToString()}");
			}
		}
 private static bool ValidCrosswalkNode(ushort nodeid, NetNode node)
 {
     return nodeid != 0 && (node.m_flags & (NetNode.Flags.Transition | NetNode.Flags.TrafficLights)) == NetNode.Flags.None;
 }
        private static int GetNumberOfMainRoads(NetNode node)
        {
            var numMainRoads = 0;
            for (var s = 0; s < 8; s++)
            {
                var segmentId2 = node.GetSegment(s);

                if (segmentId2 == 0 ||
                    !TrafficPriority.IsPrioritySegment(SelectedNode, segmentId2))
                    continue;
                var prioritySegment2 = TrafficPriority.GetPrioritySegment(SelectedNode,
                    segmentId2);

                if (prioritySegment2.Type == PrioritySegment.PriorityType.Main)
                {
                    numMainRoads++;
                }
            }
            return numMainRoads;
        }
        private static Vector3 CalculateNodePositionForSegment(NetNode node, NetSegment segment)
        {
            var position = node.m_position;

            const float offset = 25f;

            if (segment.m_startNode == SelectedNode)
            {
                position.x += segment.m_startDirection.x*offset;
                position.y += segment.m_startDirection.y*offset;
                position.z += segment.m_startDirection.z*offset;
            }
            else
            {
                position.x += segment.m_endDirection.x*offset;
                position.y += segment.m_endDirection.y*offset;
                position.z += segment.m_endDirection.z*offset;
            }
            return position;
        }
        private static Vector3 CalculateNodePositionForSegment(NetNode node, int segmentId)
        {
            var position = node.m_position;

            var segment = Singleton<NetManager>.instance.m_segments.m_buffer[segmentId];
            if (segment.m_startNode == SelectedNode)
            {
                position.x += segment.m_startDirection.x*10f;
                position.y += segment.m_startDirection.y*10f;
                position.z += segment.m_startDirection.z*10f;
            }
            else
            {
                position.x += segment.m_endDirection.x*10f;
                position.y += segment.m_endDirection.y*10f;
                position.z += segment.m_endDirection.z*10f;
            }
            return position;
        }
        private void _guiManualTrafficLightsCrosswalk(NetNode node)
        {
            var hoveredSegment = false;

            var segment1 = 0;
            var segment2 = 0;

            for (var i = 0; i < 8; i++)
            {
                var segmentId = node.GetSegment(i);

                if (segmentId == 0) continue;

                if (segment1 == 0)
                {
                    segment1 = segmentId;
                }
                else
                {
                    segment2 = segmentId;
                }
            }

            var segmentDict1 = TrafficLightsManual.GetSegmentLight(SelectedNode, segment1);
            var segmentDict2 = TrafficLightsManual.GetSegmentLight(SelectedNode, segment2);

            var segment = Singleton<NetManager>.instance.m_segments.m_buffer[segment1];

            var position = node.m_position;

            const float offset = 0f;

            if (segment.m_startNode == SelectedNode)
            {
                position.x += segment.m_startDirection.x * offset;
                position.y += segment.m_startDirection.y * offset;
                position.z += segment.m_startDirection.z * offset;
            }
            else
            {
                position.x += segment.m_endDirection.x * offset;
                position.y += segment.m_endDirection.y * offset;
                position.z += segment.m_endDirection.z * offset;
            }

            var guiColor = GUI.color;

            var screenPos = Camera.main.WorldToScreenPoint(position);
            screenPos.y = Screen.height - screenPos.y;

            var diff = position - Camera.main.transform.position;
            var zoom = 1.0f/diff.magnitude*100f;

            // original / 2.5
            var lightWidth = 41f*zoom;
            var lightHeight = 97f*zoom;

            // SWITCH PEDESTRIAN LIGHT
            var pedestrianWidth = 36f * zoom;
            var pedestrianHeight = 61f * zoom;

            guiColor.a = _hoveredButton[0] == segment1 && _hoveredButton[1] == 0 ? 0.92f : 0.45f;

            GUI.color = guiColor;

            var myRect3 = new Rect(screenPos.x - pedestrianWidth / 2 - lightWidth + 5f * zoom, screenPos.y - pedestrianHeight / 2 + 22f * zoom, pedestrianWidth, pedestrianHeight);

            switch (segmentDict1.LightPedestrian)
            {
                case RoadBaseAI.TrafficLightState.Green:
                    GUI.DrawTexture(myRect3, TrafficLightToolTextureResources.PedestrianGreenLightTexture2D);
                    break;
                case RoadBaseAI.TrafficLightState.Red:
                    GUI.DrawTexture(myRect3, TrafficLightToolTextureResources.PedestrianRedLightTexture2D);
                    break;
            }

            if (myRect3.Contains(Event.current.mousePosition))
            {
                _hoveredButton[0] = segment1;
                _hoveredButton[1] = 0;
                hoveredSegment = true;

                if (Input.GetMouseButtonDown(0) && !_uiClickedSegment)
                {
                    _uiClickedSegment = true;
                }
            }

            // no arrow light
            guiColor.a = _hoveredButton[0] == segment1 && _hoveredButton[1] == 1 ? 0.92f : 0.45f;

            GUI.color = guiColor;

            var myRect4 =
                new Rect(screenPos.x - lightWidth / 2 - lightWidth - pedestrianWidth + 5f * zoom,
                    screenPos.y - lightHeight / 2, lightWidth, lightHeight);

            switch (segmentDict1.LightMain)
            {
                case RoadBaseAI.TrafficLightState.Green:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.GreenLightTexture2D);
                    break;
                case RoadBaseAI.TrafficLightState.Red:
                    GUI.DrawTexture(myRect4, TrafficLightToolTextureResources.RedLightTexture2D);
                    break;
            }

            if (myRect4.Contains(Event.current.mousePosition))
            {
                _hoveredButton[0] = segment1;
                _hoveredButton[1] = 1;
                hoveredSegment = true;

                if (Input.GetMouseButtonDown(0) && !_uiClickedSegment)
                {
                    _uiClickedSegment = true;
                    segmentDict1.ChangeLightMain();
                    segmentDict2.ChangeLightMain();
                }
            }

            if (hoveredSegment) return;

            _hoveredButton[0] = 0;
            _hoveredButton[1] = 0;
        }
        private void TimedLightSelectNodeToolMode(NetNode node)
        {
            if (!TrafficLightsTimed.IsTimedLight(_hoveredNetNodeIdx))
            {
                if ((node.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None)
                {
                    if (ContainsListNode(_hoveredNetNodeIdx))
                    {
                        RemoveListNode(_hoveredNetNodeIdx);
                    }
                    else
                    {
                        AddListNode(_hoveredNetNodeIdx);
                    }
                }
                else
                {
                    ShowToolInfo(true, "Node is not a traffic light", node.m_position);
                }
            }
            else
            {
                if (SelectedNodeIndexes.Count == 0)
                {
                    var timedLight = TrafficLightsTimed.GetTimedLight(_hoveredNetNodeIdx);

                    SelectedNodeIndexes = new List<ushort>(timedLight.NodeGroup);
                    SetToolMode(ToolMode.TimedLightsShowLights);
                }
                else
                {
                    ShowToolInfo(true, "Node is part of timed script", node.m_position);
                }
            }
        }
 private osmNode AddNode(int i, NetNode netNode)
 {
     return AddNode(i, netNode.m_position);
 }
        private void ManualSwitchToolMode(NetNode node)
        {
            if (SelectedNode != 0) return;

            if (!TrafficLightsTimed.IsTimedLight(_hoveredNetNodeIdx))
            {
                if ((node.m_flags & NetNode.Flags.TrafficLights) != NetNode.Flags.None)
                {
                    SelectedNode = _hoveredNetNodeIdx;

                    var node2 = GetNetNode(SelectedNode);

                    CustomRoadAI.AddNodeToSimulation(SelectedNode);
                    var nodeSimulation = CustomRoadAI.GetNodeSimulation(SelectedNode);
                    nodeSimulation.FlagManualTrafficLights = true;

                    for (var s = 0; s < 8; s++)
                    {
                        var segment = node2.GetSegment(s);

                        if (segment != 0 && !TrafficPriority.IsPrioritySegment(SelectedNode, segment))
                        {
                            TrafficPriority.AddPrioritySegment(SelectedNode, segment, PrioritySegment.PriorityType.None);
                        }
                    }
                }
                else
                {
                    ShowToolInfo(true, "Node is not a traffic light", node.m_position);
                }
            }
            else
            {
                if (SelectedNodeIndexes.Count == 0)
                {
                }
                ShowToolInfo(true, "Node is part of timed script", node.m_position);
            }
        }
        /// <summary>
        /// Called when road segment is placed/released.
        /// </summary>
        /// <param name="laneID"></param>
        /// <param name="laneInfo"></param>
        /// <param name="startFlags"></param>
        /// <param name="endFlags"></param>
        /// <param name="invert"></param>
        /// <param name="layer"></param>
        /// <param name="vertexCount"></param>
        /// <param name="triangleCount"></param>
        /// <param name="objectCount"></param>
        /// <param name="vertexArrays"></param>
        /// <param name="hasProps"></param>
        /// <returns></returns>
        public bool CalculateGroupData(uint laneID, NetInfo.Lane laneInfo, NetNode.Flags startFlags, NetNode.Flags endFlags, bool invert, int layer, ref int vertexCount, ref int triangleCount, ref int objectCount, ref RenderGroup.VertexArrays vertexArrays, ref bool hasProps)
        {
            var result = false;
            var laneProps = laneInfo.m_laneProps;
            if (laneProps != null && laneProps.m_props != null)
            {
                var flag = (byte)(laneInfo.m_finalDirection & NetInfo.Direction.Both) == 2 || (byte)(laneInfo.m_finalDirection & NetInfo.Direction.Avoid) == 11;
                if (flag)
                {
                    var flags = startFlags;
                    startFlags = endFlags;
                    endFlags = flags;
                }
                var num = laneProps.m_props.Length;

                // mod begin
                var _this = NetManager.instance.m_lanes.m_buffer[laneID];
                var streetLightPrefabDataIndices = PropCustomizer.Instance.StreetLightPrefabDataIndices;
                var segmentData = SegmentDataManager.Instance.SegmentToSegmentDataMap?[_this.m_segment];
                // mod end

                for (var i = 0; i < num; i++)
                {
                    var prop = laneProps.m_props[i];
                    if (prop.CheckFlags((NetLane.Flags)_this.m_flags, startFlags, endFlags))
                    {
                        if (_this.m_length >= prop.m_minLength)
                        {
                            // mod begin
                            var finalProp = prop.m_finalProp;
                            var finalTree = prop.m_finalTree;
                            var repeatDistance = prop.m_repeatDistance;
                            if (segmentData != null)
                            {
                                // custom street lights
                                if (finalProp != null)
                                {
                                    var customLight = (segmentData.Features & SegmentData.FeatureFlags.StreetLight) != 0;

                                    // Contains seems to be faster than array lookup
                                    if ((customLight || segmentData.RepeatDistances.magnitude > 0f) && streetLightPrefabDataIndices.Contains(finalProp.m_prefabDataIndex))
                                    {
                                        if (customLight)
                                        {
                                            finalProp = segmentData.StreetLightPrefab;
                                        }
                                        if (segmentData.RepeatDistances.w > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.w;
                                        }
                                    }
                                }

                                // custom road trees
                                else if (finalTree != null)
                                {
                                    if (laneInfo.m_position < 0) // Left Trees
                                    {
                                        if ((segmentData.Features & SegmentData.FeatureFlags.TreeLeft) != 0)
                                        {
                                            finalTree = segmentData.TreeLeftPrefab;
                                        }
                                        if (segmentData.RepeatDistances.x > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.x;
                                        }
                                    }
                                    else if (laneInfo.m_position == 0) // Middle Trees
                                    {
                                        if ((segmentData.Features & SegmentData.FeatureFlags.TreeMiddle) != 0)
                                        {
                                            finalTree = segmentData.TreeMiddlePrefab;
                                        }
                                        if (segmentData.RepeatDistances.y > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.y;
                                        }
                                    }
                                    else // Right Trees
                                    {
                                        if ((segmentData.Features & SegmentData.FeatureFlags.TreeRight) != 0)
                                        {
                                            finalTree = segmentData.TreeRightPrefab;
                                        }
                                        if (segmentData.RepeatDistances.z > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.z;
                                        }
                                    }
                                }
                            }
                            // mod end

                            var num2 = 2;
                            if (repeatDistance > 1f)
                            {
                                num2 *= Mathf.Max(1, Mathf.RoundToInt(_this.m_length / repeatDistance));
                            }

                            if (finalProp != null)
                            {
                                hasProps = true;
                                if (finalProp.m_prefabDataLayer == layer || finalProp.m_effectLayer == layer)
                                {
                                    var randomizer = new Randomizer((int)(laneID + (uint)i));
                                    for (var j = 1; j <= num2; j += 2)
                                    {
                                        if (randomizer.Int32(100u) < prop.m_probability)
                                        {
                                            var variation = finalProp.GetVariation(ref randomizer);
                                            randomizer.Int32(10000u);
                                            variation.GetColor(ref randomizer);
                                            if (PropInstance.CalculateGroupData(variation, layer, ref vertexCount, ref triangleCount, ref objectCount, ref vertexArrays))
                                            {
                                                result = true;
                                            }
                                        }
                                    }
                                }
                            }

                            if (finalTree != null)
                            {
                                hasProps = true;
                                if (finalTree.m_prefabDataLayer == layer)
                                {
                                    var randomizer2 = new Randomizer((int)(laneID + (uint)i));
                                    for (var k = 1; k <= num2; k += 2)
                                    {
                                        if (randomizer2.Int32(100u) < prop.m_probability)
                                        {
                                            finalTree.GetVariation(ref randomizer2);
                                            randomizer2.Int32(10000u);
                                            randomizer2.Int32(10000u);
                                            if (global::TreeInstance.CalculateGroupData(ref vertexCount, ref triangleCount, ref objectCount, ref vertexArrays))
                                            {
                                                result = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return result;
        }
		internal static void CheckNodeProblems(ushort nodeID, ref NetNode data) {
			if (data.m_transportLine != 0) {
				bool flag = false;
				if ((data.m_flags & NetNode.Flags.Temporary) == NetNode.Flags.None) {
					NetManager instance = Singleton<NetManager>.instance;
					int num = 0;
					for (int i = 0; i < 8; i++) {
						ushort segment = data.GetSegment(i);
						if (segment != 0) {
							num++;
							if (instance.m_segments.m_buffer[(int)segment].m_path == 0u || (instance.m_segments.m_buffer[(int)segment].m_flags & NetSegment.Flags.PathFailed) != NetSegment.Flags.None) {
								flag = true;
							}
						}
					}
					if (num <= 1) {
						flag = true;
					}
				}
				if (flag) {
					data.m_problems = Notification.AddProblems(data.m_problems, Notification.Problem.LineNotConnected);
				} else {
					data.m_problems = Notification.RemoveProblems(data.m_problems, Notification.Problem.LineNotConnected);
				}
			}
		}
        /// <summary>
        /// Called when road segment is placed/released.
        /// </summary>
        /// <param name="segmentID"></param>
        /// <param name="laneID"></param>
        /// <param name="laneInfo"></param>
        /// <param name="startFlags"></param>
        /// <param name="endFlags"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="invert"></param>
        /// <param name="terrainHeight"></param>
        /// <param name="layer"></param>
        /// <param name="vertexIndex"></param>
        /// <param name="triangleIndex"></param>
        /// <param name="groupPosition"></param>
        /// <param name="data"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <param name="maxRenderDistance"></param>
        /// <param name="maxInstanceDistance"></param>
        /// <param name="hasProps"></param>
        public void PopulateGroupData(ushort segmentID, uint laneID, NetInfo.Lane laneInfo, NetNode.Flags startFlags, NetNode.Flags endFlags, float startAngle, float endAngle, bool invert, bool terrainHeight, int layer, ref int vertexIndex, ref int triangleIndex, Vector3 groupPosition, RenderGroup.MeshData data, ref Vector3 min, ref Vector3 max, ref float maxRenderDistance, ref float maxInstanceDistance, ref bool hasProps)
        {
            var laneProps = laneInfo.m_laneProps;
            if (laneProps != null && laneProps.m_props != null)
            {
                var flag = (byte)(laneInfo.m_finalDirection & NetInfo.Direction.Both) == 2 || (byte)(laneInfo.m_finalDirection & NetInfo.Direction.Avoid) == 11;
                var flag2 = flag != invert;
                if (flag)
                {
                    var flags = startFlags;
                    startFlags = endFlags;
                    endFlags = flags;
                }
                var num = laneProps.m_props.Length;

                // mod begin
                var _this = NetManager.instance.m_lanes.m_buffer[laneID];
                var streetLightPrefabDataIndices = PropCustomizer.Instance.StreetLightPrefabDataIndices;
                var segmentData = SegmentDataManager.Instance.SegmentToSegmentDataMap?[_this.m_segment];
                // mod end

                for (var i = 0; i < num; i++)
                {
                    var prop = laneProps.m_props[i];
                    if (prop.CheckFlags((NetLane.Flags)_this.m_flags, startFlags, endFlags))
                    {
                        if (_this.m_length >= prop.m_minLength)
                        {
                            // mod begin
                            var prop_m_angle = prop.m_angle;
                            var finalProp = prop.m_finalProp;
                            var finalTree = prop.m_finalTree;
                            var repeatDistance = prop.m_repeatDistance;
                            if (segmentData != null)
                            {
                                // custom street lights
                                if (finalProp != null)
                                {
                                    var customLight = (segmentData.Features & SegmentData.FeatureFlags.StreetLight) != 0;

                                    // Contains seems to be faster than array lookup
                                    if ((customLight || segmentData.RepeatDistances.magnitude > 0f) && streetLightPrefabDataIndices.Contains(finalProp.m_prefabDataIndex))
                                    {
                                        if (customLight)
                                        {
                                            finalProp = segmentData.StreetLightPrefab;
                                            if (laneInfo.m_position + prop.m_position.x < 0f) prop_m_angle = 180; //rotate street lights on pedestrian paths correctly
                                        }
                                        if (segmentData.RepeatDistances.w > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.w;
                                        }
                                    }
                                }

                                // custom road trees
                                else if (finalTree != null)
                                {
                                    if (laneInfo.m_position < 0) // Left Trees
                                    {
                                        if ((segmentData.Features & SegmentData.FeatureFlags.TreeLeft) != 0)
                                        {
                                            finalTree = segmentData.TreeLeftPrefab;
                                        }
                                        if (segmentData.RepeatDistances.x > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.x;
                                        }
                                    }
                                    else if (laneInfo.m_position == 0) // Middle Trees
                                    {
                                        if ((segmentData.Features & SegmentData.FeatureFlags.TreeMiddle) != 0)
                                        {
                                            finalTree = segmentData.TreeMiddlePrefab;
                                        }
                                        if (segmentData.RepeatDistances.y > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.y;
                                        }
                                    }
                                    else // Right Trees
                                    {
                                        if ((segmentData.Features & SegmentData.FeatureFlags.TreeRight) != 0)
                                        {
                                            finalTree = segmentData.TreeRightPrefab;
                                        }
                                        if (segmentData.RepeatDistances.z > 0f)
                                        {
                                            repeatDistance = segmentData.RepeatDistances.z;
                                        }
                                    }
                                }
                            }
                            // mod end

                            var num2 = 2;
                            if (repeatDistance > 1f)
                            {
                                num2 *= Mathf.Max(1, Mathf.RoundToInt(_this.m_length / repeatDistance));
                            }
                            var num3 = prop.m_segmentOffset * 0.5f;
                            if (_this.m_length != 0f)
                            {
                                num3 = Mathf.Clamp(num3 + prop.m_position.z / _this.m_length, -0.5f, 0.5f);
                            }
                            if (flag2)
                            {
                                num3 = -num3;
                            }

                            if (finalProp != null)
                            {
                                hasProps = true;
                                if (finalProp.m_prefabDataLayer == layer || finalProp.m_effectLayer == layer)
                                {
                                    var color = Color.white;
                                    var randomizer = new Randomizer((int)(laneID + (uint)i));
                                    for (var j = 1; j <= num2; j += 2)
                                    {
                                        if (randomizer.Int32(100u) < prop.m_probability)
                                        {
                                            var num4 = num3 + (float)j / (float)num2;
                                            var variation = finalProp.GetVariation(ref randomizer);
                                            var scale = variation.m_minScale + (float)randomizer.Int32(10000u) * (variation.m_maxScale - variation.m_minScale) * 0.0001f;
                                            if (prop.m_colorMode == NetLaneProps.ColorMode.Default)
                                            {
                                                color = variation.GetColor(ref randomizer);
                                            }
                                            var vector = _this.m_bezier.Position(num4);
                                            if (terrainHeight)
                                            {
                                                vector.y = Singleton<TerrainManager>.instance.SampleDetailHeight(vector);
                                            }
                                            vector.y += prop.m_position.y;
                                            var vector2 = _this.m_bezier.Tangent(num4);
                                            if (vector2 != Vector3.zero)
                                            {
                                                if (flag2)
                                                {
                                                    vector2 = -vector2;
                                                }
                                                vector2.y = 0f;
                                                if (prop.m_position.x != 0f)
                                                {
                                                    vector2 = Vector3.Normalize(vector2);
                                                    vector.x += vector2.z * prop.m_position.x;
                                                    vector.z -= vector2.x * prop.m_position.x;
                                                }
                                                var num5 = Mathf.Atan2(vector2.x, -vector2.z);
                                                if (prop.m_cornerAngle != 0f || prop.m_position.x != 0f)
                                                {
                                                    var num6 = endAngle - startAngle;
                                                    if (num6 > 3.14159274f)
                                                    {
                                                        num6 -= 6.28318548f;
                                                    }
                                                    if (num6 < -3.14159274f)
                                                    {
                                                        num6 += 6.28318548f;
                                                    }
                                                    var num7 = startAngle + num6 * num4;
                                                    num6 = num7 - num5;
                                                    if (num6 > 3.14159274f)
                                                    {
                                                        num6 -= 6.28318548f;
                                                    }
                                                    if (num6 < -3.14159274f)
                                                    {
                                                        num6 += 6.28318548f;
                                                    }
                                                    num5 += num6 * prop.m_cornerAngle;
                                                    if (num6 != 0f && prop.m_position.x != 0f)
                                                    {
                                                        var num8 = Mathf.Tan(num6);
                                                        vector.x += vector2.x * num8 * prop.m_position.x;
                                                        vector.z += vector2.z * num8 * prop.m_position.x;
                                                    }
                                                }
                                                var id = default(InstanceID);
                                                id.NetSegment = segmentID;
                                                num5 += prop_m_angle * 0.0174532924f;
                                                PropInstance.PopulateGroupData(variation, layer, id, vector, scale, num5, color, ref vertexIndex, ref triangleIndex, groupPosition, data, ref min, ref max, ref maxRenderDistance, ref maxInstanceDistance);
                                            }
                                        }
                                    }
                                }
                            }

                            if (finalTree != null)
                            {
                                hasProps = true;
                                if (finalTree.m_prefabDataLayer == layer)
                                {
                                    var randomizer2 = new Randomizer((int)(laneID + (uint)i));
                                    for (var k = 1; k <= num2; k += 2)
                                    {
                                        if (randomizer2.Int32(100u) < prop.m_probability)
                                        {
                                            var t = num3 + (float)k / (float)num2;
                                            var variation2 = finalTree.GetVariation(ref randomizer2);
                                            var scale2 = variation2.m_minScale + (float)randomizer2.Int32(10000u) * (variation2.m_maxScale - variation2.m_minScale) * 0.0001f;
                                            var brightness = variation2.m_minBrightness + (float)randomizer2.Int32(10000u) * (variation2.m_maxBrightness - variation2.m_minBrightness) * 0.0001f;
                                            var vector3 = _this.m_bezier.Position(t);
                                            if (terrainHeight)
                                            {
                                                vector3.y = Singleton<TerrainManager>.instance.SampleDetailHeight(vector3);
                                            }
                                            vector3.y += prop.m_position.y;
                                            if (prop.m_position.x != 0f)
                                            {
                                                var vector4 = _this.m_bezier.Tangent(t);
                                                if (flag2)
                                                {
                                                    vector4 = -vector4;
                                                }
                                                vector4.y = 0f;
                                                vector4 = Vector3.Normalize(vector4);
                                                vector3.x += vector4.z * prop.m_position.x;
                                                vector3.z -= vector4.x * prop.m_position.x;
                                            }
                                            global::TreeInstance.PopulateGroupData(variation2, vector3, scale2, brightness, ref vertexIndex, ref triangleIndex, groupPosition, data, ref min, ref max, ref maxRenderDistance, ref maxInstanceDistance);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Called 1000s of times every frame! Must be high-performant!
        /// Not called when viewing from distance.
        /// </summary>
        /// <param name="cameraInfo"></param>
        /// <param name="segmentID"></param>
        /// <param name="laneID"></param>
        /// <param name="laneInfo"></param>
        /// <param name="startFlags"></param>
        /// <param name="endFlags"></param>
        /// <param name="startColor"></param>
        /// <param name="endColor"></param>
        /// <param name="startAngle"></param>
        /// <param name="endAngle"></param>
        /// <param name="invert"></param>
        /// <param name="layerMask"></param>
        /// <param name="objectIndex1"></param>
        /// <param name="objectIndex2"></param>
        /// <param name="data"></param>
        /// <param name="propIndex"></param>
        public void RenderInstance(RenderManager.CameraInfo cameraInfo, ushort segmentID, uint laneID, NetInfo.Lane laneInfo, NetNode.Flags startFlags, NetNode.Flags endFlags, Color startColor, Color endColor, float startAngle, float endAngle, bool invert, int layerMask, Vector4 objectIndex1, Vector4 objectIndex2, ref RenderManager.Instance data, ref int propIndex)
        {
            var laneProps = laneInfo.m_laneProps;
            if (laneProps != null && laneProps.m_props != null)
            {
                var flag = (byte)(laneInfo.m_finalDirection & NetInfo.Direction.Both) == 2 || (byte)(laneInfo.m_finalDirection & NetInfo.Direction.Avoid) == 11;
                var flag2 = flag != invert;
                if (flag)
                {
                    var flags = startFlags;
                    startFlags = endFlags;
                    endFlags = flags;
                }
                var num = laneProps.m_props.Length;

                // mod begin
                var _this = NetManager.instance.m_lanes.m_buffer[laneID];
                var streetLightPrefabDataIndices = PropCustomizer.Instance.StreetLightPrefabDataIndices;
                var segmentData = SegmentDataManager.Instance.SegmentToSegmentDataMap?[_this.m_segment];
                // mod end

                for (var i = 0; i < num; i++)
                {
                    var prop = laneProps.m_props[i];
                    if (_this.m_length >= prop.m_minLength)
                    {
                        // mod begin
                        var prop_m_angle = prop.m_angle;
                        var finalProp = prop.m_finalProp;
                        var finalTree = prop.m_finalTree;
                        var repeatDistance = prop.m_repeatDistance;
                        if (segmentData != null)
                        {
                            // custom street lights
                            if (finalProp != null)
                            {
                                var customLight = (segmentData.Features & SegmentData.FeatureFlags.StreetLight) != 0;

                                // Contains seems to be faster than array lookup
                                if ((customLight || segmentData.RepeatDistances.magnitude > 0f) && streetLightPrefabDataIndices.Contains(finalProp.m_prefabDataIndex))
                                {
                                    if (customLight)
                                    {
                                        finalProp = segmentData.StreetLightPrefab;
                                        if (laneInfo.m_position + prop.m_position.x < 0f) prop_m_angle = 180; //rotate street lights on pedestrian paths correctly
                                    }
                                    if (segmentData.RepeatDistances.w > 0f)
                                    {
                                        repeatDistance = segmentData.RepeatDistances.w;
                                    }
                                }
                            }

                            // custom road trees
                            else if (finalTree != null)
                            {
                                if (laneInfo.m_position < 0) // Left Trees
                                {
                                    if ((segmentData.Features & SegmentData.FeatureFlags.TreeLeft) != 0)
                                    {
                                        finalTree = segmentData.TreeLeftPrefab;
                                    }
                                    if (segmentData.RepeatDistances.x > 0f)
                                    {
                                        repeatDistance = segmentData.RepeatDistances.x;
                                    }
                                }
                                else if (laneInfo.m_position == 0) // Middle Trees
                                {
                                    if ((segmentData.Features & SegmentData.FeatureFlags.TreeMiddle) != 0)
                                    {
                                        finalTree = segmentData.TreeMiddlePrefab;
                                    }
                                    if (segmentData.RepeatDistances.y > 0f)
                                    {
                                        repeatDistance = segmentData.RepeatDistances.y;
                                    }
                                }
                                else // Right Trees
                                {
                                    if ((segmentData.Features & SegmentData.FeatureFlags.TreeRight) != 0)
                                    {
                                        finalTree = segmentData.TreeRightPrefab;
                                    }
                                    if (segmentData.RepeatDistances.z > 0f)
                                    {
                                        repeatDistance = segmentData.RepeatDistances.z;
                                    }
                                }
                            }
                        }
                        // mod end

                        var num2 = 2;
                        if (repeatDistance > 1f)
                        {
                            num2 *= Mathf.Max(1, Mathf.RoundToInt(_this.m_length / repeatDistance));
                        }
                        var num3 = propIndex;
                        if (propIndex != -1)
                        {
                            propIndex = num3 + (num2 + 1 >> 1);
                        }
                        if (prop.CheckFlags((NetLane.Flags)_this.m_flags, startFlags, endFlags))
                        {
                            var num4 = prop.m_segmentOffset * 0.5f;
                            if (_this.m_length != 0f)
                            {
                                num4 = Mathf.Clamp(num4 + prop.m_position.z / _this.m_length, -0.5f, 0.5f);
                            }
                            if (flag2)
                            {
                                num4 = -num4;
                            }

                            if (finalProp != null && (layerMask & 1 << finalProp.m_prefabDataLayer) != 0)
                            {
                                var color = (prop.m_colorMode != NetLaneProps.ColorMode.EndState) ? startColor : endColor;
                                var randomizer = new Randomizer((int)(laneID + (uint)i));
                                for (var j = 1; j <= num2; j += 2)
                                {
                                    if (randomizer.Int32(100u) < prop.m_probability)
                                    {
                                        var num5 = num4 + (float)j / (float)num2;
                                        var variation = finalProp.GetVariation(ref randomizer);
                                        var scale = variation.m_minScale + (float)randomizer.Int32(10000u) * (variation.m_maxScale - variation.m_minScale) * 0.0001f;
                                        if (prop.m_colorMode == NetLaneProps.ColorMode.Default)
                                        {
                                            color = variation.GetColor(ref randomizer);
                                        }
                                        var vector = _this.m_bezier.Position(num5);
                                        if (propIndex != -1)
                                        {
                                            vector.y = (float)data.m_extraData.GetUShort(num3++) * 0.015625f;
                                        }
                                        vector.y += prop.m_position.y;
                                        if (cameraInfo.CheckRenderDistance(vector, variation.m_maxRenderDistance))
                                        {
                                            var vector2 = _this.m_bezier.Tangent(num5);
                                            if (vector2 != Vector3.zero)
                                            {
                                                if (flag2)
                                                {
                                                    vector2 = -vector2;
                                                }
                                                vector2.y = 0f;
                                                if (prop.m_position.x != 0f)
                                                {
                                                    vector2 = Vector3.Normalize(vector2);
                                                    vector.x += vector2.z * prop.m_position.x;
                                                    vector.z -= vector2.x * prop.m_position.x;
                                                }
                                                var num6 = Mathf.Atan2(vector2.x, -vector2.z);
                                                if (prop.m_cornerAngle != 0f || prop.m_position.x != 0f)
                                                {
                                                    var num7 = endAngle - startAngle;
                                                    if (num7 > 3.14159274f)
                                                    {
                                                        num7 -= 6.28318548f;
                                                    }
                                                    if (num7 < -3.14159274f)
                                                    {
                                                        num7 += 6.28318548f;
                                                    }
                                                    var num8 = startAngle + num7 * num5;
                                                    num7 = num8 - num6;
                                                    if (num7 > 3.14159274f)
                                                    {
                                                        num7 -= 6.28318548f;
                                                    }
                                                    if (num7 < -3.14159274f)
                                                    {
                                                        num7 += 6.28318548f;
                                                    }
                                                    num6 += num7 * prop.m_cornerAngle;
                                                    if (num7 != 0f && prop.m_position.x != 0f)
                                                    {
                                                        var num9 = Mathf.Tan(num7);
                                                        vector.x += vector2.x * num9 * prop.m_position.x;
                                                        vector.z += vector2.z * num9 * prop.m_position.x;
                                                    }
                                                }
                                                Vector4 objectIndex3 = (num5 <= 0.5f) ? objectIndex1 : objectIndex2;
                                                num6 += prop_m_angle * 0.0174532924f;

                                                PropInstance.RenderInstance(cameraInfo, variation, new InstanceID
                                                {
                                                    NetSegment = segmentID
                                                }, vector, scale, num6, color, objectIndex3, true);
                                                /*
                                                catch // debug code
                                                {
                                                    throw new Exception($"DEBUG: Prop Rendering Error\n" +
                                                              $"Net Name: {NetManager.instance.m_segments.m_buffer[segmentID].Info?.name}\n" +
                                                              $"Prop Name: {finalProp?.name}\n" +
                                                              $"Variation Name: {variation?.name}\n" +
                                                              $"Camera exists? {cameraInfo != null}");
                                                }*/
                                            }
                                        }
                                    }
                                }
                            }

                            if (finalTree != null && (layerMask & 1 << finalTree.m_prefabDataLayer) != 0)
                            {
                                var randomizer2 = new Randomizer((int)(laneID + (uint)i));
                                for (var k = 1; k <= num2; k += 2)
                                {
                                    if (randomizer2.Int32(100u) < prop.m_probability)
                                    {
                                        var t = num4 + (float)k / (float)num2;
                                        var variation2 = finalTree.GetVariation(ref randomizer2);
                                        var scale2 = variation2.m_minScale + (float)randomizer2.Int32(10000u) * (variation2.m_maxScale - variation2.m_minScale) * 0.0001f;
                                        var brightness = variation2.m_minBrightness + (float)randomizer2.Int32(10000u) * (variation2.m_maxBrightness - variation2.m_minBrightness) * 0.0001f;
                                        var position = _this.m_bezier.Position(t);
                                        if (propIndex != -1)
                                        {
                                            position.y = (float)data.m_extraData.GetUShort(num3++) * 0.015625f;
                                        }
                                        position.y += prop.m_position.y;
                                        if (prop.m_position.x != 0f)
                                        {
                                            var vector3 = _this.m_bezier.Tangent(t);
                                            if (flag2)
                                            {
                                                vector3 = -vector3;
                                            }
                                            vector3.y = 0f;
                                            vector3 = Vector3.Normalize(vector3);
                                            position.x += vector3.z * prop.m_position.x;
                                            position.z -= vector3.x * prop.m_position.x;
                                        }
                                        global::TreeInstance.RenderInstance(cameraInfo, variation2, position, scale2, brightness);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #56
0
 public new void UpdateNodeTargetPos(ushort vehicleID, ref Vehicle vehicleData, ushort nodeID, ref NetNode nodeData, ref Vector4 targetPos, int index)
 {
     base.UpdateNodeTargetPos(vehicleID, ref vehicleData, nodeID, ref nodeData, ref targetPos, index);
 }
 private void AddPrioritySignsToolMode(NetNode node)
 {
     if ((node.m_flags & NetNode.Flags.TrafficLights) == NetNode.Flags.None)
     {
         _uiClickedSegment = true;
         SelectedNode = _hoveredNetNodeIdx;
     }
     else
     {
         ShowToolInfo(true, "Node should not be a traffic light", node.m_position);
     }
 }
 private void SwitchTrafficLightToolMode(NetNode node)
 {
     if ((node.m_flags & NetNode.Flags.Junction) != NetNode.Flags.None)
     {
         _switchTrafficLights();
     }
 }
 public static void SetNetNode(ushort index, NetNode node)
 {
     Singleton<NetManager>.instance.m_nodes.m_buffer[index] = node;
 }
 protected virtual void ProcessItem(BufferItem item, ushort nodeID, ref NetNode node, byte connectOffset, bool isMiddle)
 {
     NetManager instance = Singleton<NetManager>.instance;
     bool flag = false;
     bool flag2 = false;
     bool flag3 = false;
     int num = 0;
     NetInfo info = instance.m_segments.m_buffer[(int)item.m_position.m_segment].Info;
     if ((int)item.m_position.m_lane < info.m_lanes.Length)
     {
         NetInfo.Lane lane = info.m_lanes[(int)item.m_position.m_lane];
         flag = (lane.m_laneType == NetInfo.LaneType.Pedestrian);
         flag2 = (lane.m_laneType == NetInfo.LaneType.Vehicle && (lane.m_vehicleType & this.m_vehicleTypes) == VehicleInfo.VehicleType.Bicycle);
         flag3 = lane.m_centerPlatform;
         if ((byte)(lane.m_finalDirection & NetInfo.Direction.Forward) != 0)
         {
             num = lane.m_similarLaneIndex;
         }
         else
         {
             num = lane.m_similarLaneCount - lane.m_similarLaneIndex - 1;
         }
     }
     if (isMiddle)
     {
         for (int i = 0; i < 8; i++)
         {
             ushort segment = node.GetSegment(i);
             if (segment != 0)
             {
                 this.ProcessItem(item, nodeID, segment, ref instance.m_segments.m_buffer[(int)segment], ref num, connectOffset, !flag, flag);
             }
         }
     }
     else if (flag)
     {
         ushort segment2 = item.m_position.m_segment;
         int lane2 = (int)item.m_position.m_lane;
         if (node.Info.m_class.m_service != ItemClass.Service.Beautification)
         {
             bool flag4 = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.Bend | NetNode.Flags.Junction)) != NetNode.Flags.None;
             bool flag5 = flag3 && (node.m_flags & (NetNode.Flags.End | NetNode.Flags.Junction)) == NetNode.Flags.None;
             ushort num2 = segment2;
             ushort num3 = segment2;
             int laneIndex;
             int laneIndex2;
             uint num4;
             uint num5;
             instance.m_segments.m_buffer[(int)segment2].GetLeftAndRightLanes(nodeID, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, lane2, flag5, out laneIndex, out laneIndex2, out num4, out num5);
             if (num4 == 0u || num5 == 0u)
             {
                 ushort leftSegment;
                 ushort rightSegment;
                 instance.m_segments.m_buffer[(int)segment2].GetLeftAndRightSegments(nodeID, out leftSegment, out rightSegment);
                 int num6 = 0;
                 while (leftSegment != 0 && leftSegment != segment2 && num4 == 0u)
                 {
                     int num7;
                     int num8;
                     uint num9;
                     uint num10;
                     instance.m_segments.m_buffer[(int)leftSegment].GetLeftAndRightLanes(nodeID, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, flag5, out num7, out num8, out num9, out num10);
                     if (num10 != 0u)
                     {
                         num2 = leftSegment;
                         laneIndex = num8;
                         num4 = num10;
                     }
                     else
                     {
                         leftSegment = instance.m_segments.m_buffer[(int)leftSegment].GetLeftSegment(nodeID);
                     }
                     if (++num6 == 8)
                     {
                         break;
                     }
                 }
                 num6 = 0;
                 while (rightSegment != 0 && rightSegment != segment2 && num5 == 0u)
                 {
                     int num11;
                     int num12;
                     uint num13;
                     uint num14;
                     instance.m_segments.m_buffer[(int)rightSegment].GetLeftAndRightLanes(nodeID, NetInfo.LaneType.Pedestrian, VehicleInfo.VehicleType.None, -1, flag5, out num11, out num12, out num13, out num14);
                     if (num13 != 0u)
                     {
                         num3 = rightSegment;
                         laneIndex2 = num11;
                         num5 = num13;
                     }
                     else
                     {
                         rightSegment = instance.m_segments.m_buffer[(int)rightSegment].GetRightSegment(nodeID);
                     }
                     if (++num6 == 8)
                     {
                         break;
                     }
                 }
             }
             if (num4 != 0u && (num2 != segment2 || flag4 || flag5))
             {
                 this.ProcessItem(item, nodeID, num2, ref instance.m_segments.m_buffer[(int)num2], connectOffset, laneIndex, num4);
             }
             if (num5 != 0u && num5 != num4 && (num3 != segment2 || flag4 || flag5))
             {
                 this.ProcessItem(item, nodeID, num3, ref instance.m_segments.m_buffer[(int)num3], connectOffset, laneIndex2, num5);
             }
             int laneIndex3;
             uint lane3;
             if ((this.m_vehicleTypes & VehicleInfo.VehicleType.Bicycle) != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)segment2].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Vehicle, VehicleInfo.VehicleType.Bicycle, out laneIndex3, out lane3))
             {
                 this.ProcessItem(item, nodeID, segment2, ref instance.m_segments.m_buffer[(int)segment2], connectOffset, laneIndex3, lane3);
             }
         }
         else
         {
             for (int j = 0; j < 8; j++)
             {
                 ushort segment3 = node.GetSegment(j);
                 if (segment3 != 0 && segment3 != segment2)
                 {
                     this.ProcessItem(item, nodeID, segment3, ref instance.m_segments.m_buffer[(int)segment3], ref num, connectOffset, false, true);
                 }
             }
         }
         NetInfo.LaneType laneType = this.m_laneTypes & ~NetInfo.LaneType.Pedestrian;
         VehicleInfo.VehicleType vehicleType = this.m_vehicleTypes & ~VehicleInfo.VehicleType.Bicycle;
         if ((byte)(item.m_lanesUsed & (NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle)) != 0)
         {
             laneType &= ~(NetInfo.LaneType.Vehicle | NetInfo.LaneType.TransportVehicle);
         }
         int num15;
         uint lane4;
         if (laneType != NetInfo.LaneType.None && vehicleType != VehicleInfo.VehicleType.None && instance.m_segments.m_buffer[(int)segment2].GetClosestLane(lane2, laneType, vehicleType, out num15, out lane4))
         {
             NetInfo.Lane lane5 = info.m_lanes[num15];
             byte connectOffset2;
             if ((instance.m_segments.m_buffer[(int)segment2].m_flags & NetSegment.Flags.Invert) != NetSegment.Flags.None == ((byte)(lane5.m_finalDirection & NetInfo.Direction.Backward) != 0))
             {
                 connectOffset2 = 1;
             }
             else
             {
                 connectOffset2 = 254;
             }
             this.ProcessItem(item, nodeID, segment2, ref instance.m_segments.m_buffer[(int)segment2], connectOffset2, num15, lane4);
         }
     }
     else
     {
         bool flag6 = (node.m_flags & (NetNode.Flags.End | NetNode.Flags.OneWayOut)) != NetNode.Flags.None;
         bool flag7 = (byte)(this.m_laneTypes & NetInfo.LaneType.Pedestrian) != 0;
         bool enablePedestrian = false;
         byte connectOffset3 = 0;
         if (flag7)
         {
             if (flag2)
             {
                 connectOffset3 = connectOffset;
                 enablePedestrian = (node.Info.m_class.m_service == ItemClass.Service.Beautification);
             }
             else if (this.m_vehicleLane != 0u)
             {
                 if (this.m_vehicleLane != item.m_laneID)
                 {
                     flag7 = false;
                 }
                 else
                 {
                     connectOffset3 = this.m_vehicleOffset;
                 }
             }
             else if (this.m_stablePath)
             {
                 connectOffset3 = 128;
             }
             else
             {
                 connectOffset3 = (byte)this.m_pathRandomizer.UInt32(1u, 254u);
             }
         }
         ushort num16 = instance.m_segments.m_buffer[(int)item.m_position.m_segment].GetRightSegment(nodeID);
         for (int k = 0; k < 8; k++)
         {
             if (num16 == 0 || num16 == item.m_position.m_segment)
             {
                 break;
             }
             if (this.ProcessItem(item, nodeID, num16, ref instance.m_segments.m_buffer[(int)num16], ref num, connectOffset, true, enablePedestrian))
             {
                 flag6 = true;
             }
             num16 = instance.m_segments.m_buffer[(int)num16].GetRightSegment(nodeID);
         }
         if (flag6 && (this.m_vehicleTypes & VehicleInfo.VehicleType.Tram) == VehicleInfo.VehicleType.None)
         {
             num16 = item.m_position.m_segment;
             this.ProcessItem(item, nodeID, num16, ref instance.m_segments.m_buffer[(int)num16], ref num, connectOffset, true, false);
         }
         if (flag7)
         {
             num16 = item.m_position.m_segment;
             int laneIndex4;
             uint lane6;
             if (instance.m_segments.m_buffer[(int)num16].GetClosestLane((int)item.m_position.m_lane, NetInfo.LaneType.Pedestrian, this.m_vehicleTypes, out laneIndex4, out lane6))
             {
                 this.ProcessItem(item, nodeID, num16, ref instance.m_segments.m_buffer[(int)num16], connectOffset3, laneIndex4, lane6);
             }
         }
     }
     if (node.m_lane != 0u)
     {
         bool targetDisabled = (node.m_flags & NetNode.Flags.Disabled) != NetNode.Flags.None;
         ushort segment4 = instance.m_lanes.m_buffer[(int)((UIntPtr)node.m_lane)].m_segment;
         if (segment4 != 0 && segment4 != item.m_position.m_segment)
         {
             this.ProcessItem(item, nodeID, targetDisabled, segment4, ref instance.m_segments.m_buffer[(int)segment4], node.m_lane, node.m_laneOffset, connectOffset);
         }
     }
 }