示例#1
0
        /// <summary>
        /// Parses a 3d World from an ArrayEntry
        /// </summary>
        /// <param name="objectEntry"></param>
        /// <param name="zone"></param>
        /// <param name="objectsByReference"></param>
        /// <returns></returns>
        public static I3dWorldObject ParseObject(ArrayEntry objectEntry, SM3DWorldZone zone, Dictionary <long, I3dWorldObject> objectsByReference, out bool alreadyInLinks, Dictionary <string, I3dWorldObject> linkedObjsByID, bool isLinked = false)
        {
            ObjectInfo info = GetObjectInfo(ref objectEntry, zone);

            I3dWorldObject obj;
            bool           loadLinks;

            if ((info.ClassName == "Area") || info.ObjectName.Contains("Area") && AreaModelNames.Contains(info.ModelName))
            {
                obj = new AreaObject(in info, zone, out loadLinks);
            }
            else if (info.PropertyEntries.TryGetValue("RailPoints", out DictionaryEntry railPointEntry) && railPointEntry.NodeType == ByamlFile.ByamlNodeType.Array) //at this point we can be sure it's a rail
            {
                obj = new Rail(in info, zone, out loadLinks);
            }
            else
            {
                obj = new General3dWorldObject(in info, zone, out loadLinks);
            }

            if (isLinked && linkedObjsByID != null)
            {
                if (!linkedObjsByID.ContainsKey(info.ID))
                {
                    linkedObjsByID.Add(info.ID, obj);
                }
                else
                {
                    alreadyInLinks = true;

                    obj = linkedObjsByID[info.ID];

                    if (!isLinked)
                    {
                        alreadyInLinks = !zone.LinkedObjects.Remove(obj);
                    }

                    //in case this object was already read in another file
                    if (!objectsByReference.ContainsKey(objectEntry.Position))
                    {
                        objectsByReference.Add(objectEntry.Position, obj);
                    }

                    return(obj);
                }
            }

            alreadyInLinks = false;

            if (!objectsByReference.ContainsKey(objectEntry.Position))
            {
                objectsByReference.Add(objectEntry.Position, obj);
            }
            else if (!isLinked)
            {
                obj = objectsByReference[objectEntry.Position];
                zone.LinkedObjects.Remove(obj);
                return(obj);
            }

            if (loadLinks)
            {
                var links = new Dictionary <string, List <I3dWorldObject> >();
                foreach (DictionaryEntry link in info.LinkEntries.Values)
                {
                    links.Add(link.Key, new List <I3dWorldObject>());
                    foreach (ArrayEntry linked in link.IterArray())
                    {
                        if (objectsByReference.ContainsKey(linked.Position))
                        {
                            links[link.Key].Add(objectsByReference[linked.Position]);
                            objectsByReference[linked.Position].AddLinkDestination(link.Key, obj);
                        }
                        else
                        {
                            I3dWorldObject _obj = ParseObject(linked, zone, objectsByReference, out bool linkedAlreadyReferenced, linkedObjsByID, true);
                            _obj.AddLinkDestination(link.Key, obj);
                            links[link.Key].Add(_obj);
                            if (zone != null && !linkedAlreadyReferenced)
                            {
                                zone.LinkedObjects.Add(_obj);
                            }
                        }
                    }
                }
                if (links.Count > 0)
                {
                    obj.Links = links;
                }
            }

            return(obj);
        }
示例#2
0
        /// <summary>
        /// Parses a 3d World from an ArrayEntry
        /// </summary>
        /// <param name="objectEntry"></param>
        /// <param name="zone"></param>
        /// <param name="objectsByReference"></param>
        /// <returns></returns>
        public static I3dWorldObject ParseObject(ArrayEntry objectEntry, SM3DWorldZone zone, Dictionary <long, I3dWorldObject> objectsByReference, out bool alreadyInLinks, Dictionary <string, I3dWorldObject> linkedObjsByID, bool isLinked = false)
        {
            ObjectInfo info = GetObjectInfo(ref objectEntry, zone);

            I3dWorldObject obj;
            bool           loadLinks;

            if (Enum.GetNames(typeof(Rail.RailObjType)).Contains(info.ClassName))
            {
                obj = new Rail(info, zone, out loadLinks);
            }
            else
            {
                obj = new General3dWorldObject(info, zone, out loadLinks);
            }

            if (linkedObjsByID != null && isLinked)
            {
                if (!linkedObjsByID.ContainsKey(info.ID))
                {
                    linkedObjsByID.Add(info.ID, obj);
                }
                else
                {
                    alreadyInLinks = true;

                    obj = linkedObjsByID[info.ID];

                    if (!isLinked)
                    {
                        alreadyInLinks = !zone.LinkedObjects.Remove(obj);
                    }

                    //in case this object was already read in another file
                    if (!objectsByReference.ContainsKey(objectEntry.Position))
                    {
                        objectsByReference.Add(objectEntry.Position, obj);
                    }

                    return(obj);
                }
            }

            alreadyInLinks = false;

            if (!objectsByReference.ContainsKey(objectEntry.Position))
            {
                objectsByReference.Add(objectEntry.Position, obj);
            }
            else if (!isLinked)
            {
                obj = objectsByReference[objectEntry.Position];
                zone.LinkedObjects.Remove(obj);
                return(obj);
            }

            if (loadLinks)
            {
                obj.Links = new Dictionary <string, List <I3dWorldObject> >();
                foreach (DictionaryEntry link in info.LinkEntries.Values)
                {
                    obj.Links.Add(link.Key, new List <I3dWorldObject>());
                    foreach (ArrayEntry linked in link.IterArray())
                    {
                        if (objectsByReference.ContainsKey(linked.Position))
                        {
                            obj.Links[link.Key].Add(objectsByReference[linked.Position]);
                            objectsByReference[linked.Position].AddLinkDestination(link.Key, obj);
                        }
                        else
                        {
                            I3dWorldObject _obj = ParseObject(linked, zone, objectsByReference, out bool linkedAlreadyReferenced, linkedObjsByID, true);
                            _obj.AddLinkDestination(link.Key, obj);
                            obj.Links[link.Key].Add(_obj);
                            if (zone != null && !linkedAlreadyReferenced)
                            {
                                zone.LinkedObjects.Add(_obj);
                            }
                        }
                    }
                }
                if (obj.Links.Count == 0)
                {
                    obj.Links = null;
                }
            }

            return(obj);
        }