internal static object CustomDeserialize(Package p, Type t, PackageReader r)
        {
            // Props and trees in buildings and parks.
            if (t == typeof(BuildingInfo.Prop))
            {
                PropInfo pi = Get <PropInfo>(r.ReadString()); // old name format (without package name) is possible
                TreeInfo ti = Get <TreeInfo>(r.ReadString()); // old name format (without package name) is possible

                if (instance.report && UsedAssets.instance.GotAnyContainer())
                {
                    if (pi != null)
                    {
                        string n = pi.gameObject.name;

                        if (!string.IsNullOrEmpty(n) && n.IndexOf('.') >= 0)
                        {
                            UsedAssets.instance.IndirectProps.Add(n);
                        }
                    }

                    if (ti != null)
                    {
                        string n = ti.gameObject.name;

                        if (!string.IsNullOrEmpty(n) && n.IndexOf('.') >= 0)
                        {
                            UsedAssets.instance.IndirectTrees.Add(n);
                        }
                    }
                }

                return(new BuildingInfo.Prop
                {
                    m_prop = pi,
                    m_tree = ti,
                    m_position = r.ReadVector3(),
                    m_angle = r.ReadSingle(),
                    m_probability = r.ReadInt32(),
                    m_fixedHeight = r.ReadBoolean()
                });
            }

            // Paths (nets) in buildings.
            if (t == typeof(BuildingInfo.PathInfo))
            {
                string  fullName           = r.ReadString();
                NetInfo ni                 = Get <NetInfo>(fullName);
                BuildingInfo.PathInfo path = new BuildingInfo.PathInfo();
                path.m_netInfo         = ni;
                path.m_nodes           = r.ReadVector3Array();
                path.m_curveTargets    = r.ReadVector3Array();
                path.m_invertSegments  = r.ReadBoolean();
                path.m_maxSnapDistance = r.ReadSingle();

                if (p.version >= 5)
                {
                    path.m_forbidLaneConnection = r.ReadBooleanArray();
                    path.m_trafficLights        = (BuildingInfo.TrafficLights[])(object) r.ReadInt32Array();
                    path.m_yieldSigns           = r.ReadBooleanArray();
                }

                return(path);
            }

            if (t == typeof(Package.Asset))
            {
                return(r.ReadAsset(p));
            }

            // It seems that trailers are listed in the save game so this is not necessary. Better to be safe however
            // because a missing trailer reference is fatal for the simulation thread.
            if (t == typeof(VehicleInfo.VehicleTrailer))
            {
                string      name     = r.ReadString();
                string      fullName = p.packageName + "." + name;
                VehicleInfo vi       = Get <VehicleInfo>(p, fullName, name, false);

                VehicleInfo.VehicleTrailer trailer;
                trailer.m_info              = vi;
                trailer.m_probability       = r.ReadInt32();
                trailer.m_invertProbability = r.ReadInt32();
                return(trailer);
            }

            if (t == typeof(NetInfo.Lane))
            {
                return(new NetInfo.Lane
                {
                    m_position = r.ReadSingle(),
                    m_width = r.ReadSingle(),
                    m_verticalOffset = r.ReadSingle(),
                    m_stopOffset = r.ReadSingle(),
                    m_speedLimit = r.ReadSingle(),
                    m_direction = (NetInfo.Direction)r.ReadInt32(),
                    m_laneType = (NetInfo.LaneType)r.ReadInt32(),
                    m_vehicleType = (VehicleInfo.VehicleType)r.ReadInt32(),
                    m_stopType = (VehicleInfo.VehicleType)r.ReadInt32(),
                    m_laneProps = GetNetLaneProps(p, r),
                    m_allowConnect = r.ReadBoolean(),
                    m_useTerrainHeight = r.ReadBoolean(),
                    m_centerPlatform = r.ReadBoolean(),
                    m_elevated = r.ReadBoolean()
                });
            }

            if (t == typeof(NetInfo.Segment))
            {
                NetInfo.Segment segment  = new NetInfo.Segment();
                string          checksum = r.ReadString();
                segment.m_mesh              = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMesh(checksum, p, true);
                checksum                    = r.ReadString();
                segment.m_material          = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMaterial(checksum, p, true);
                checksum                    = r.ReadString();
                segment.m_lodMesh           = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMesh(checksum, p, false);
                checksum                    = r.ReadString();
                segment.m_lodMaterial       = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMaterial(checksum, p, false);
                segment.m_forwardRequired   = (NetSegment.Flags)r.ReadInt32();
                segment.m_forwardForbidden  = (NetSegment.Flags)r.ReadInt32();
                segment.m_backwardRequired  = (NetSegment.Flags)r.ReadInt32();
                segment.m_backwardForbidden = (NetSegment.Flags)r.ReadInt32();
                segment.m_emptyTransparent  = r.ReadBoolean();
                segment.m_disableBendNodes  = r.ReadBoolean();
                return(segment);
            }

            if (t == typeof(NetInfo.Node))
            {
                NetInfo.Node node     = new NetInfo.Node();
                string       checksum = r.ReadString();
                node.m_mesh             = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMesh(checksum, p, true);
                checksum                = r.ReadString();
                node.m_material         = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMaterial(checksum, p, true);
                checksum                = r.ReadString();
                node.m_lodMesh          = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMesh(checksum, p, false);
                checksum                = r.ReadString();
                node.m_lodMaterial      = string.IsNullOrEmpty(checksum) ? null : Sharing.instance.GetMaterial(checksum, p, false);
                node.m_flagsRequired    = (NetNode.Flags)r.ReadInt32();
                node.m_flagsForbidden   = (NetNode.Flags)r.ReadInt32();
                node.m_connectGroup     = (NetInfo.ConnectGroup)r.ReadInt32();
                node.m_directConnect    = r.ReadBoolean();
                node.m_emptyTransparent = r.ReadBoolean();
                return(node);
            }

            if (t == typeof(NetInfo))
            {
                string name = r.ReadString();
                CustomAssetMetaData.Type type = AssetLoader.instance.GetMetaType(AssetLoader.instance.Current);

                if (type == CustomAssetMetaData.Type.Road || type == CustomAssetMetaData.Type.RoadElevation)
                {
                    return(Get <NetInfo>(p, name));
                }
                else
                {
                    return(Get <NetInfo>(name));
                }
            }

            if (t == typeof(BuildingInfo))
            {
                string name = r.ReadString();
                CustomAssetMetaData.Type type = AssetLoader.instance.GetMetaType(AssetLoader.instance.Current);

                if (type == CustomAssetMetaData.Type.Road || type == CustomAssetMetaData.Type.RoadElevation)
                {
                    return(Get <BuildingInfo>(p, name));
                }
                else
                {
                    return(Get <BuildingInfo>(name));
                }
            }

            // Sub-buildings in buildings.
            if (t == typeof(BuildingInfo.SubInfo))
            {
                string       name     = r.ReadString();
                string       fullName = p.packageName + "." + name;
                BuildingInfo bi       = null;

                if (fullName == AssetLoader.instance.Current.fullName || name == AssetLoader.instance.Current.fullName)
                {
                    Util.DebugPrint("Warning:", fullName, "wants to be a sub-building for itself");
                }
                else
                {
                    bi = Get <BuildingInfo>(p, fullName, name, true);
                }

                BuildingInfo.SubInfo subInfo = new BuildingInfo.SubInfo();
                subInfo.m_buildingInfo = bi;
                subInfo.m_position     = r.ReadVector3();
                subInfo.m_angle        = r.ReadSingle();
                subInfo.m_fixedHeight  = r.ReadBoolean();
                return(subInfo);
            }

            // Prop variations in props.
            if (t == typeof(PropInfo.Variation))
            {
                string   name     = r.ReadString();
                string   fullName = p.packageName + "." + name;
                PropInfo pi       = null;

                if (fullName == AssetLoader.instance.Current.fullName)
                {
                    Util.DebugPrint("Warning:", fullName, "wants to be a prop variation for itself");
                }
                else
                {
                    pi = Get <PropInfo>(p, fullName, name, false);
                }

                return(new PropInfo.Variation
                {
                    m_prop = pi,
                    m_probability = r.ReadInt32()
                });
            }

            // Tree variations in trees.
            if (t == typeof(TreeInfo.Variation))
            {
                string   name     = r.ReadString();
                string   fullName = p.packageName + "." + name;
                TreeInfo ti       = null;

                if (fullName == AssetLoader.instance.Current.fullName)
                {
                    Util.DebugPrint("Warning:", fullName, "wants to be a tree variation for itself");
                }
                else
                {
                    ti = Get <TreeInfo>(p, fullName, name, false);
                }

                return(new TreeInfo.Variation
                {
                    m_tree = ti,
                    m_probability = r.ReadInt32()
                });
            }

            if (t == typeof(VehicleInfo.MeshInfo))
            {
                VehicleInfo.MeshInfo meshinfo = new VehicleInfo.MeshInfo();
                string checksum = r.ReadString();

                if (!string.IsNullOrEmpty(checksum))
                {
                    Package.Asset asset = p.FindByChecksum(checksum);
                    GameObject    go    = AssetDeserializer.Instantiate(asset) as GameObject;
                    meshinfo.m_subInfo = go.GetComponent <VehicleInfoBase>();
                    go.SetActive(false);

                    if (meshinfo.m_subInfo.m_lodObject != null)
                    {
                        meshinfo.m_subInfo.m_lodObject.SetActive(false);
                    }
                }
                else
                {
                    meshinfo.m_subInfo = null;
                }

                meshinfo.m_vehicleFlagsForbidden = (Vehicle.Flags)r.ReadInt32();
                meshinfo.m_vehicleFlagsRequired  = (Vehicle.Flags)r.ReadInt32();
                meshinfo.m_parkedFlagsForbidden  = (VehicleParked.Flags)r.ReadInt32();
                meshinfo.m_parkedFlagsRequired   = (VehicleParked.Flags)r.ReadInt32();
                return(meshinfo);
            }

            return(PackageHelper.CustomDeserialize(p, t, r));
        }