Beispiel #1
0
        public Ets2NavigationRoute(Ets2Item start, Ets2Item end, Ets2Point from, Ets2Point to, Ets2Mapper mapper)
        {
            Start = start;
            End = end;
            From = from;
            To = to;
            Mapper = mapper;

            if (Start != End)
            ThreadPool.QueueUserWorkItem(new WaitCallback(FindRoute));
        }
Beispiel #2
0
        public Ets2Item FindItem(ulong uid)
        {
            Tuple <string, int> inp;

            if (uid == 0)
            {
                return(null);
            }

            /*if (Mapper.ItemCache.TryGetValue(uid, out inp))
             * {
             *  var item = new Ets2Item(uid,
             *      Mapper.Sectors.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x.FilePath) == inp.Item1),
             *      inp.Item2);
             *  if (!item.Valid)
             *  {
             *      lock (Mapper.ItemCache)
             *      {
             *          Mapper.ItemCache.Remove(uid);
             *      }
             *  }
             *  else
             *  {
             *      return item;
             *  }
             * }*/
            var pos = SearchUID(BitConverter.GetBytes(uid));

            foreach (var off in pos)
            {
                var offs = off - 4;

                var type = BitConverter.ToUInt32(Stream, offs);

                if (type < 0x40 && type != 0)
                {
                    var item = new Ets2Item(uid, this, offs);
                    if (item.Valid)
                    {
                        /*lock (Mapper.ItemCache)
                         * {
                         *  Mapper.ItemCache.Add(uid,
                         *      new Tuple<string, int>(Path.GetFileNameWithoutExtension(FilePath), offs));
                         * }*/

                        return(item);
                    }
                }
            }

            return(null);
        }
        public Ets2NavigationRoute(Ets2Item start, Ets2Item end, Ets2Point from, Ets2Point to, Ets2Mapper mapper)
        {
            Start  = start;
            End    = end;
            From   = from;
            To     = to;
            Mapper = mapper;

            if (Start != End)
            {
                ThreadPool.QueueUserWorkItem(new WaitCallback(FindRoute));
            }
        }
        public Ets2NavigationSegment(Ets2Item prefab)
        {
            Type = Ets2NavigationSegmentType.Prefab;

            Prefab = prefab;
        }
Beispiel #5
0
        public Ets2NavigationSegment(Ets2Item prefab)
        {
            Type = Ets2NavigationSegmentType.Prefab;

            Prefab = prefab;
        }
Beispiel #6
0
        private float RoadDistance(Ets2Item road, float x, float y)
        {
            if (road == null)
                return float.MaxValue;
            if (road.StartNode == null || road.EndNode == null)
                return float.MaxValue;

            if (Math.Abs(road.StartNode.X - x) > 500)
                return float.MaxValue;
            if (Math.Abs(road.StartNode.Z - y) > 500)
                return float.MaxValue;
            if (road.RoadPolygons == null)
                road.GenerateRoadPolygon(64);

            var minPerPoint = float.MaxValue;

            foreach (var pt in road.RoadPolygons)
            {

                var dx1 = pt.X - x;
                var dy1 = pt.Y - y;
                var r1 = (float)Math.Sqrt(dx1 * dx1 + dy1 * dy1);

                if (minPerPoint >= r1)
                    minPerPoint = r1;
            }

            return minPerPoint;
        }
Beispiel #7
0
        private bool OutsideRoad(Ets2Item road, float x, float y)
        {
            if (road == null)
                return true;
            if (road.StartNode == null || road.EndNode == null)
                return true;
            var minX = Math.Min(road.StartNode.X, road.EndNode.X);
            var maxX = Math.Max(road.StartNode.X, road.EndNode.X);
            var minY = Math.Min(road.StartNode.Z, road.EndNode.Z);
            var maxY = Math.Max(road.StartNode.Z, road.EndNode.Z);

            var margin = 10.5f;
            if (minX - margin >= x && maxX + margin <= x &&
                minY - margin >= y && maxY + margin <= y)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
Beispiel #8
0
        public void Parse()
        {
            ThreadPool.SetMaxThreads(2, 2);
            Loading = true;

            // First load prefabs
            PrefabsLookup = PrefabFiles.Select(x => new Ets2Prefab(this, x)).ToList();

            // Load all LUTs
            LoadLUT();

            ItemSearchRequests = new List <Ets2ItemSearchRequest>();
            Sectors            = SectorFiles.Select(x => new Ets2Sector(this, x)).ToList();

            // 2-stage process so we can validate node UID's at item stage
            ThreadPool.SetMaxThreads(1, 1);
            Parallel.ForEach(Sectors, (sec) => sec.ParseNodes());
            Parallel.ForEach(Sectors, (sec) => sec.ParseItems());

            Loading = false;

            // Now find all that were not ofund
            ItemSearchRequests.Clear();
            Console.WriteLine(ItemSearchRequests.Count +
                              " were not found; attempting to search them through all sectors");
            foreach (var req in ItemSearchRequests)
            {
                Ets2Item item = Sectors.Select(sec => sec.FindItem(req.ItemUID)).FirstOrDefault(tmp => tmp != null);

                if (item == null)
                {
                    Console.WriteLine("Still couldn't find node " + req.ItemUID.ToString("X16"));
                }
                else
                {
                    if (req.IsBackward)
                    {
                        item.Apply(req.Node);
                        req.Node.BackwardItem = item;
                    }
                    if (req.IsForward)
                    {
                        item.Apply(req.Node);
                        req.Node.ForwardItem = item;
                    }

                    if (item.StartNode == null && item.StartNodeUID != null)
                    {
                        Ets2Node startNode;
                        if (Nodes.TryGetValue(item.StartNodeUID, out startNode))
                        {
                            item.Apply(startNode);
                        }
                    }
                    if (item.EndNode == null && item.EndNodeUID != null)
                    {
                        Ets2Node endNode;
                        if (Nodes.TryGetValue(item.EndNodeUID, out endNode))
                        {
                            item.Apply(endNode);
                        }
                    }

                    Console.Write(".");
                }
            }

            // Navigation cache
            BuildNavigationCache();

            // Lookup all cities
            Cities = Items.Values.Where(x => x.Type == Ets2ItemType.City).GroupBy(x => x.City).Select(x => x.FirstOrDefault()).ToDictionary(x => x.City, x => x);

            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.Building) + " buildings were found");
            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.Road) + " roads were found");
            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.Prefab) + " prefabs were found");
            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.Prefab && x.Prefab != null && x.Prefab.Curves.Any()) + " road prefabs were found");
            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.Service) + " service points were found");
            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.Company) + " companies were found");
            Console.WriteLine(Items.Values.Count(x => x.Type == Ets2ItemType.City) + " cities were found");
        }
        private void FindRoute(object state)
        {
            Loading = true;

            Dictionary <ulong, Tuple <float, Ets2Item> > nodeMap = new Dictionary <ulong, Tuple <float, Ets2Item> >();
            List <Ets2Item> nodesToWalk = new List <Ets2Item>();

            // Fill node map
            foreach (var node in Mapper.Items.Values.Where(x => x.Type == Ets2ItemType.Prefab && x.HideUI == false))
            {
                nodesToWalk.Add(node);
                nodeMap.Add(node.ItemUID, new Tuple <float, Ets2Item>(float.MaxValue, null));
            }

            // Walk first node (START)
            if (nodeMap.ContainsKey(Start.ItemUID) == false)
            {
                // Nope
                return;
            }
            if (nodeMap.ContainsKey(End.ItemUID) == false)
            {
                // Nope
                return;
            }

            // <Weight, LastItem>
            nodeMap[Start.ItemUID] = new Tuple <float, Ets2Item>(0, null);

            while (nodesToWalk.Any())
            {
                float    distanceWalked = float.MaxValue;
                Ets2Item toWalk         = null;
                foreach (var node in nodesToWalk)
                {
                    var dTmp = nodeMap[node.ItemUID].Item1;
                    if (dTmp != float.MaxValue && distanceWalked > dTmp)
                    {
                        distanceWalked = dTmp;
                        toWalk         = node;
                    }
                }
                if (toWalk == null)
                {
                    break;
                }

                nodesToWalk.Remove(toWalk);

                var currentWeight = nodeMap[toWalk.ItemUID].Item1;

                // Iterate all destination nodes from this node
                foreach (var jump in toWalk.Navigation)
                {
                    var newWeight = jump.Value.Item1 + currentWeight;
                    var newNode   = jump.Key;

                    if (nodeMap.ContainsKey(newNode.ItemUID) && nodeMap[newNode.ItemUID].Item1 > newWeight)
                    {
                        nodeMap[newNode.ItemUID] = new Tuple <float, Ets2Item>(newWeight, toWalk);
                    }
                    // add route with weight + previous node
                }
            }

            List <Ets2Item> routeNodes            = new List <Ets2Item>();
            List <Ets2Item> routeRoads            = new List <Ets2Item>();
            List <Ets2NavigationSegment> segments = new List <Ets2NavigationSegment>();

            var goingViaNode = (ulong)0;
            var route        = End;

            while (route != null)
            {
                // we add this prefab to the route list
                routeNodes.Add(route);
                var prefabSeg = new Ets2NavigationSegment(route);
                segments.Add(prefabSeg);

                // find the next prefab in the route description
                var gotoNew = nodeMap[route.ItemUID].Item2;
                if (gotoNew == null)
                {
                    break;
                }

                // get a path from the current prefab to the new one
                var path     = route.Navigation[gotoNew];
                var roadPath = path.Item3;

                // add the path to road list
                routeRoads.AddRange(roadPath);
                segments.Add(new Ets2NavigationSegment(roadPath, prefabSeg));

                // Set the new prefab as route
                route = gotoNew;
            }
            routeNodes.Add(Start);
            segments.Reverse();

            // Find entry/exit of start/end segment
            var foundDst  = float.MaxValue;
            var foundNode = default(Ets2Node);

            // Find the closest road to startpoint
            foreach (var node in segments[0].Prefab.NodesList)
            {
                var dst = node.Value.Point.DistanceTo(From);
                if (foundDst > dst)
                {
                    foundDst  = dst;
                    foundNode = node.Value;
                }
            }

            // We found the  node; find the road that exists at this point
            segments[0].Entry = foundNode;

            foundDst  = float.MaxValue;
            foundNode = default(Ets2Node);
            // Find the closest road to startpoint
            foreach (var node in segments[segments.Count - 1].Prefab.NodesList)
            {
                var dst = node.Value.Point.DistanceTo(To);
                if (foundDst > dst)
                {
                    foundDst  = dst;
                    foundNode = node.Value;
                }
            }

            // We found the  node; find the road that exists at this point
            segments[segments.Count - 1].Exit = foundNode;

            // Iterate all segments
            for (int seg = 0; seg < segments.Count; seg++)
            {
                // Generate prefab routes
                if (segments[seg].Type == Ets2NavigationSegmentType.Prefab)
                {
                    var prevRoad = seg > 0 ? segments[seg - 1] : null;
                    var nextRoad = seg + 1 < segments.Count ? segments[seg + 1] : null;

                    // Link segments together
                    if (prevRoad != null)
                    {
                        segments[seg].Entry = prevRoad.Entry;
                    }
                    if (nextRoad != null)
                    {
                        segments[seg].Exit = nextRoad.Exit;
                    }

                    segments[seg].GenerateOptions(prevRoad, nextRoad);
                }

                // Generate lane data
                if (segments[seg].Type == Ets2NavigationSegmentType.Road)
                {
                    var prefFab = seg > 0 ? segments[seg - 1] : null;
                    var nextFab = seg + 1 < segments.Count ? segments[seg + 1] : null;

                    segments[seg].GenerateOptions(prefFab, nextFab);
                }
            }

            //for (int seg = 1; seg < segments.Count - 1; seg++)
            for (int seg = 0; seg < segments.Count; seg++)
            {
                // Validate routes
                if (segments[seg].Type == Ets2NavigationSegmentType.Prefab)
                {
                    var prevRoad = seg > 0 ? segments[seg - 1] : null;
                    var nextRoad = seg + 1 < segments.Count ? segments[seg + 1] : null;

                    foreach (var opt in segments[seg].Options)
                    {
                        if (prevRoad == null)
                        {
                            // start point; validate if it is close to our start node
                            if (opt.Points.FirstOrDefault().DistanceTo(segments[seg].Entry.Point) < 10)
                            {
                                opt.EntryLane = 0; // yep; sure
                            }
                        }
                        else
                        {
                            var entryPoint = opt.Points.FirstOrDefault();
                            foreach (var roadOpt in prevRoad.Options)
                            {
                                if (roadOpt.Points.Any(x => x.CloseTo(entryPoint)))
                                {
                                    // We've got a match ! :D
                                    opt.EntryLane = roadOpt.ExitLane;
                                    roadOpt.Valid = roadOpt.EntryLane >= 0 && roadOpt.ExitLane >= 0;
                                }
                            }
                        }

                        if (nextRoad == null)
                        {
                            // last point.
                            if (opt.Points.FirstOrDefault().DistanceTo(segments[seg].Exit.Point) < 10)
                            {
                                opt.ExitLane = 0; // yep; sure
                            }
                        }
                        else
                        {
                            var exitPoint = opt.Points.LastOrDefault();
                            foreach (var roadOpt in nextRoad.Options)
                            {
                                if (roadOpt.Points.Any(x => x.CloseTo(exitPoint)))
                                {
                                    // We've got a match ! :D
                                    opt.ExitLane  = roadOpt.EntryLane;
                                    roadOpt.Valid = roadOpt.EntryLane >= 0 && roadOpt.ExitLane >= 0;
                                }
                            }
                        }

                        opt.Valid = opt.EntryLane >= 0 && opt.ExitLane >= 0;
                    }
                }

                // Generate prefab routes
                if (segments[seg].Type == Ets2NavigationSegmentType.Road && false)
                {
                    var nextPrefab = segments[seg + 1];
                    var prevPrefab = segments[seg - 1];

                    if (nextPrefab.Type != Ets2NavigationSegmentType.Prefab || prevPrefab.Type != Ets2NavigationSegmentType.Prefab)
                    {
                        continue;
                    }

                    // Deduct road options by matching entry/exits
                    for (int solI = 0; solI < segments[seg].Options.Count; solI++)
                    {
                        // Find if there is any route in prefab that matches our entry lane
                        var okStart = prevPrefab.Options.Any(x => segments[seg].MatchEntry(solI, prevPrefab));
                        var okEnd   = nextPrefab.Options.Any(x => segments[seg].MatchExit(solI, nextPrefab));

                        // This road has a valid end & Start
                        if (okStart && okEnd)
                        {
                            segments[seg].Options[solI].Valid = true;
                        }
                    }
                }
            }

            // There is probably only 1 valid solution for entry/exit
            //if (segments[0].Options.Any()) segments[0].Options[0].Valid = true;
            //if (segments[segments.Count - 1].Options.Any()) segments[segments.Count - 1].Options[0].Valid = true;

            Segments = segments;
            var pts = Segments.SelectMany(x => x.Solutions).SelectMany(x => x.Points).ToList();

            Roads   = routeRoads;
            Prefabs = routeNodes.Select(x => new Tuple <Ets2Item, int, int>(x, 0, 0)).ToList();
            Loading = false;
        }
Beispiel #10
0
        public Ets2Item FindItem(ulong uid)
        {
            Tuple<string, int> inp;
            if (uid == 0)
                return null;
            /*if (Mapper.ItemCache.TryGetValue(uid, out inp))
            {
                var item = new Ets2Item(uid,
                    Mapper.Sectors.FirstOrDefault(x => Path.GetFileNameWithoutExtension(x.FilePath) == inp.Item1),
                    inp.Item2);
                if (!item.Valid)
                {
                    lock (Mapper.ItemCache)
                    {
                        Mapper.ItemCache.Remove(uid);
                    }
                }
                else
                {
                    return item;
                }
            }*/
            var pos = SearchUID(BitConverter.GetBytes(uid));

            foreach (var off in pos)
            {
                var offs = off - 4;

                var type = BitConverter.ToUInt32(Stream, offs);

                if (type < 0x40 && type != 0)
                {
                    var item = new Ets2Item(uid, this, offs);
                    if (item.Valid)
                    {
                        /*lock (Mapper.ItemCache)
                        {
                            Mapper.ItemCache.Add(uid,
                                new Tuple<string, int>(Path.GetFileNameWithoutExtension(FilePath), offs));
                        }*/

                        return item;
                    }
                }
            }

            return null;
        }