/* Called when an asset is saved */
        public void OnAssetSaved(string name, object asset, out Dictionary <string, byte[]> userData)
        {
            Debug.Log("TMPE: OnAssetSaved");

            userData = null;

            if (!LoadingExtension.IsInAssetEditor)
            {
                return;
            }

            BuildingInfo info = asset as BuildingInfo;

            if (info == null)
            {
                return;
            }

            bool success = true;

            TmpeAssetData data = new TmpeAssetData();

            data.Segments = BuildingDecorationPatch.m_pendingSegments;
            Configuration config = SerializableDataExtension.CreateConfiguration(ref success);

            userData = new Dictionary <string, byte[]>();

            // ??? !!!
            SerializableDataExtension.OnBeforeGameSaved(ref success);
            data.TmpeConfiguration = SerializableDataExtension.Serialize(config, ref success);
            SerializableDataExtension.OnAfterGameSaved(ref success);

            if (!success)
            {
                return;
            }

            if (BuildingDecorationPatch.m_pendingSegments?.Count > 0)
            {
                userData.Add(SerializableDataExtension.DataId + segmentsString, SerializableDataExtension.Serialize <List <IdentificationTool.AssetSegment> >(data.Segments, ref success));
                userData.Add(SerializableDataExtension.DataId + dataString, data.TmpeConfiguration);
                AssetDataManager.Instance.AssetsWithData[IdentificationTool.GetNameWithoutPrefix(info.name)] = data;
            }
        }
Example #2
0
        public static List <IdentificationTool.AssetSegment> m_pendingSegments; // Segments pending to be saved

        public static void ProcessNewPaths(List <ushort> segments, BuildingInfo info)
        {
            try
            {
#if DEBUG
                Debug.Log("Loading TMPE settings...");
#endif
                TmpeAssetData data = AssetDataManager.Instance.AssetsWithData[IdentificationTool.GetNameWithoutPrefix(info.name)];

                Debug.Log("Hoooray! Tmpe settings loaded");

                Configuration config = SerializableDataExtension.DeserializeData(data.TmpeConfiguration, out bool error);
                if (error)
                {
                    throw new Exception("Tmpe: Failed to deserialize data");
                }

                /* We identify the old ids with the new ids */
                IdentificationTool.CreateDictionaries(segments, data.Segments, out Dictionary <ushort, ushort> segmentPairs,
                                                      out Dictionary <ushort, ushort> nodePairs, out Dictionary <uint, uint> lanePairs);
                IdentificationTool.TranslateGameConfiguration(config, segmentPairs, nodePairs, lanePairs);

                /*SerializableDataExtension.LoadDataState(config, out bool error2);
                 * if (error2)
                 *  throw new Exception("Tmpe: error when applying loaded data");*/

                /* Apply settings after some time elapses (hack) */
                ProvisionalDataLoader.StartTimer(config);
            }
            catch (Exception ex)
            {
#if DEBUG
                Debug.Log(ex);
#endif
            }
        }
        /* Called when the savegame/asset is loading. Does not work when Loading Screen mod is enabled due to a bug */
        public void OnAssetLoaded(string name, object asset, Dictionary <string, byte[]> userData)
        {
            BuildingInfo info = asset as BuildingInfo;

            if (info != null)
            {
                try
                {
                    TmpeAssetData data = new TmpeAssetData();
                    data.TmpeConfiguration = userData[SerializableDataExtension.DataId + dataString];
                    //data.TmpeConfiguration = SerializableDataExtension.DeserializeData(userData[SerializableDataExtension.DataId + dataString], out bool error);
                    data.Segments = Deserialize <List <IdentificationTool.AssetSegment> >(userData[SerializableDataExtension.DataId + segmentsString]);

                    AssetDataManager.Instance.AssetsWithData[IdentificationTool.GetNameWithoutPrefix(info.name)] = data;
#if DEBUG
                    Debug.Log("Successfully deserialized TMPE asset data (" + info.name + ")");
#endif
                }
                catch (Exception e)
                {
                    Debug.Log(e);
                }
            }
        }
Example #4
0
        /* STOCK CODE START */

        /* Called when building (intersection) loads its segments. Detoured method. Added code is marked 'ns'
         * We obrain a list with all the segments and pass them to the ProcessNewPaths method. We create our own list for that purpose instead of
         * using instance.m_tempSegmentBuffer because it almost seems that the game can create multiple segments per one saved path in the file which
         * makes absolutely no sense at all but would lead to our list being shifted compared to the (third) one in which we had saved the ids of the
         * old segments. Whatever, you don't really have to understand this, I studied it a lot when creating my previous mods and it's the part I
         * understand the most compared to the rest */
        public static void LoadPaths(BuildingInfo info, ushort buildingID, ref Building data, float elevation)
        {
#if DEBUG
            Debug.Log("LoadPaths TMPE detour");
#endif

            // ns
            Dictionary <string, TmpeAssetData> dict = AssetDataManager.Instance.AssetsWithData;
            bool          isAssetWithTmpeSettings   = dict.ContainsKey(IdentificationTool.GetNameWithoutPrefix(info.name));
            List <ushort> CreatedSegments           = null;
            if (isAssetWithTmpeSettings)
            {
                CreatedSegments = new List <ushort>();
            }
            // ns end

            if (info.m_paths != null)
            {
                NetManager instance = Singleton <NetManager> .instance;
                instance.m_tempNodeBuffer.Clear();
                instance.m_tempSegmentBuffer.Clear();
                for (int i = 0; i < info.m_paths.Length; i++)
                {
                    // ns
                    if (isAssetWithTmpeSettings)
                    {
                        CreatedSegments.Add(0);
                    }
                    // ns end

                    BuildingInfo.PathInfo pathInfo = info.m_paths[i];
                    if (pathInfo.m_finalNetInfo != null && pathInfo.m_nodes != null && pathInfo.m_nodes.Length != 0)
                    {
                        Vector3 vector = data.CalculatePosition(pathInfo.m_nodes[0]);
                        bool    flag   = /*BuildingDecoration.*/ RequireFixedHeight(info, pathInfo.m_finalNetInfo, pathInfo.m_nodes[0]);
                        if (!flag)
                        {
                            vector.y = NetSegment.SampleTerrainHeight(pathInfo.m_finalNetInfo, vector, false, pathInfo.m_nodes[0].y + elevation);
                        }
                        Ray ray = new Ray(vector + new Vector3(0f, 8f, 0f), Vector3.down);
                        NetTool.ControlPoint controlPoint;
                        if (!/*BuildingDecoration.*/ FindConnectNode(instance.m_tempNodeBuffer, vector, pathInfo.m_finalNetInfo, out controlPoint))
                        {
                            if (NetTool.MakeControlPoint(ray, 16f, pathInfo.m_finalNetInfo, true, NetNode.Flags.Untouchable, NetSegment.Flags.Untouchable, Building.Flags.All, pathInfo.m_nodes[0].y + elevation - pathInfo.m_finalNetInfo.m_buildHeight, true, out controlPoint))
                            {
                                Vector3 vector2 = controlPoint.m_position - vector;
                                if (!flag)
                                {
                                    vector2.y = 0f;
                                }
                                float sqrMagnitude = vector2.sqrMagnitude;
                                if (sqrMagnitude > pathInfo.m_maxSnapDistance * pathInfo.m_maxSnapDistance)
                                {
                                    controlPoint.m_position  = vector;
                                    controlPoint.m_elevation = 0f;
                                    controlPoint.m_node      = 0;
                                    controlPoint.m_segment   = 0;
                                }
                                else
                                {
                                    controlPoint.m_position.y = vector.y;
                                }
                            }
                            else
                            {
                                controlPoint.m_position = vector;
                            }
                        }
                        ushort num;
                        ushort num2;
                        int    num3;
                        int    num4;
                        if (controlPoint.m_node != 0)
                        {
                            instance.m_tempNodeBuffer.Add(controlPoint.m_node);
                        }
                        else if (NetTool.CreateNode(pathInfo.m_finalNetInfo, controlPoint, controlPoint, controlPoint, NetTool.m_nodePositionsSimulation, 0, false, false, false, false, pathInfo.m_invertSegments, false, 0, out num, out num2, out num3, out num4) == ToolBase.ToolErrors.None)
                        {
                            instance.m_tempNodeBuffer.Add(num);
                            controlPoint.m_node = num;
                            if (pathInfo.m_forbidLaneConnection != null && pathInfo.m_forbidLaneConnection.Length > 0 && pathInfo.m_forbidLaneConnection[0])
                            {
                                NetNode[] buffer = instance.m_nodes.m_buffer;
                                ushort    num5   = num;
                                buffer[(int)num5].m_flags = (buffer[(int)num5].m_flags | NetNode.Flags.ForbidLaneConnection);
                            }
                            if (pathInfo.m_trafficLights != null && pathInfo.m_trafficLights.Length > 0)
                            {
                                /*BuildingDecoration.*/
                                TrafficLightsToFlags(pathInfo.m_trafficLights[0], ref instance.m_nodes.m_buffer[(int)num].m_flags);
                            }
                        }
                        for (int j = 1; j < pathInfo.m_nodes.Length; j++)
                        {
                            vector = data.CalculatePosition(pathInfo.m_nodes[j]);
                            bool flag2 = /*BuildingDecoration.*/ RequireFixedHeight(info, pathInfo.m_finalNetInfo, pathInfo.m_nodes[j]);
                            if (!flag2)
                            {
                                vector.y = NetSegment.SampleTerrainHeight(pathInfo.m_finalNetInfo, vector, false, pathInfo.m_nodes[j].y + elevation);
                            }
                            ray = new Ray(vector + new Vector3(0f, 8f, 0f), Vector3.down);
                            NetTool.ControlPoint controlPoint2;
                            if (!/*BuildingDecoration.*/ FindConnectNode(instance.m_tempNodeBuffer, vector, pathInfo.m_finalNetInfo, out controlPoint2))
                            {
                                if (NetTool.MakeControlPoint(ray, 16f, pathInfo.m_finalNetInfo, true, NetNode.Flags.Untouchable, NetSegment.Flags.Untouchable, Building.Flags.All, pathInfo.m_nodes[j].y + elevation - pathInfo.m_finalNetInfo.m_buildHeight, true, out controlPoint2))
                                {
                                    Vector3 vector3 = controlPoint2.m_position - vector;
                                    if (!flag2)
                                    {
                                        vector3.y = 0f;
                                    }
                                    float sqrMagnitude2 = vector3.sqrMagnitude;
                                    if (sqrMagnitude2 > pathInfo.m_maxSnapDistance * pathInfo.m_maxSnapDistance)
                                    {
                                        controlPoint2.m_position  = vector;
                                        controlPoint2.m_elevation = 0f;
                                        controlPoint2.m_node      = 0;
                                        controlPoint2.m_segment   = 0;
                                    }
                                    else
                                    {
                                        controlPoint2.m_position.y = vector.y;
                                    }
                                }
                                else
                                {
                                    controlPoint2.m_position = vector;
                                }
                            }
                            NetTool.ControlPoint middlePoint = controlPoint2;
                            if (pathInfo.m_curveTargets != null && pathInfo.m_curveTargets.Length >= j)
                            {
                                middlePoint.m_position = data.CalculatePosition(pathInfo.m_curveTargets[j - 1]);
                                if (!flag || !flag2)
                                {
                                    middlePoint.m_position.y = NetSegment.SampleTerrainHeight(pathInfo.m_finalNetInfo, middlePoint.m_position, false, pathInfo.m_curveTargets[j - 1].y + elevation);
                                }
                            }
                            else
                            {
                                middlePoint.m_position = (controlPoint.m_position + controlPoint2.m_position) * 0.5f;
                            }
                            middlePoint.m_direction   = VectorUtils.NormalizeXZ(middlePoint.m_position - controlPoint.m_position);
                            controlPoint2.m_direction = VectorUtils.NormalizeXZ(controlPoint2.m_position - middlePoint.m_position);
                            ushort num6;
                            ushort num7;
                            ushort num8;
                            int    num9;
                            int    num10;
                            if (NetTool.CreateNode(pathInfo.m_finalNetInfo, controlPoint, middlePoint, controlPoint2, NetTool.m_nodePositionsSimulation, 1, false, false, false, false, false, pathInfo.m_invertSegments, false, 0, out num6, out num7, out num8, out num9, out num10) == ToolBase.ToolErrors.None)
                            {
                                instance.m_tempNodeBuffer.Add(num7);
                                instance.m_tempSegmentBuffer.Add(num8);

                                // ns
                                if (isAssetWithTmpeSettings)
                                {
                                    CreatedSegments[CreatedSegments.Count - 1] = num8;
                                }
                                // ns end

                                controlPoint2.m_node = num7;
                                if (pathInfo.m_forbidLaneConnection != null && pathInfo.m_forbidLaneConnection.Length > j && pathInfo.m_forbidLaneConnection[j])
                                {
                                    NetNode[] buffer2 = instance.m_nodes.m_buffer;
                                    ushort    num11   = num7;
                                    buffer2[(int)num11].m_flags = (buffer2[(int)num11].m_flags | NetNode.Flags.ForbidLaneConnection);
                                }
                                if (pathInfo.m_trafficLights != null && pathInfo.m_trafficLights.Length > j)
                                {
                                    /*BuildingDecoration.*/
                                    TrafficLightsToFlags(pathInfo.m_trafficLights[j], ref instance.m_nodes.m_buffer[(int)num7].m_flags);
                                }
                                if (pathInfo.m_yieldSigns != null && pathInfo.m_yieldSigns.Length >= j * 2)
                                {
                                    if (pathInfo.m_yieldSigns[j * 2 - 2])
                                    {
                                        NetSegment[] buffer3 = instance.m_segments.m_buffer;
                                        ushort       num12   = num8;
                                        buffer3[(int)num12].m_flags = (buffer3[(int)num12].m_flags | NetSegment.Flags.YieldStart);
                                    }
                                    if (pathInfo.m_yieldSigns[j * 2 - 1])
                                    {
                                        NetSegment[] buffer4 = instance.m_segments.m_buffer;
                                        ushort       num13   = num8;
                                        buffer4[(int)num13].m_flags = (buffer4[(int)num13].m_flags | NetSegment.Flags.YieldEnd);
                                    }
                                }
                            }
                            controlPoint = controlPoint2;
                            flag         = flag2;
                        }
                    }
                }
                for (int k = 0; k < instance.m_tempNodeBuffer.m_size; k++)
                {
                    ushort num14 = instance.m_tempNodeBuffer.m_buffer[k];
                    if ((instance.m_nodes.m_buffer[(int)num14].m_flags & NetNode.Flags.Untouchable) == NetNode.Flags.None)
                    {
                        if (buildingID != 0)
                        {
                            if ((data.m_flags & Building.Flags.Active) == Building.Flags.None && instance.m_nodes.m_buffer[(int)num14].Info.m_canDisable)
                            {
                                NetNode[] buffer5 = instance.m_nodes.m_buffer;
                                ushort    num15   = num14;
                                buffer5[(int)num15].m_flags = (buffer5[(int)num15].m_flags | NetNode.Flags.Disabled);
                            }
                            NetNode[] buffer6 = instance.m_nodes.m_buffer;
                            ushort    num16   = num14;
                            buffer6[(int)num16].m_flags = (buffer6[(int)num16].m_flags | NetNode.Flags.Untouchable);
                            instance.UpdateNode(num14);
                            instance.m_nodes.m_buffer[(int)num14].m_nextBuildingNode = data.m_netNode;
                            data.m_netNode = num14;
                        }
                        else
                        {
                            instance.UpdateNode(num14);
                        }
                    }
                }
                for (int l = 0; l < instance.m_tempSegmentBuffer.m_size; l++)
                {
                    ushort num17 = instance.m_tempSegmentBuffer.m_buffer[l];
                    if ((instance.m_segments.m_buffer[(int)num17].m_flags & NetSegment.Flags.Untouchable) == NetSegment.Flags.None)
                    {
                        if (buildingID != 0)
                        {
                            NetSegment[] buffer7 = instance.m_segments.m_buffer;
                            ushort       num18   = num17;
                            buffer7[(int)num18].m_flags = (buffer7[(int)num18].m_flags | NetSegment.Flags.Untouchable);
                            instance.UpdateSegment(num17);
                        }
                        else
                        {
                            if ((Singleton <ToolManager> .instance.m_properties.m_mode & ItemClass.Availability.AssetEditor) != ItemClass.Availability.None)
                            {
                                NetInfo info2 = instance.m_segments.m_buffer[(int)num17].Info;
                                if ((info2.m_availableIn & ItemClass.Availability.AssetEditor) == ItemClass.Availability.None)
                                {
                                    NetSegment[] buffer8 = instance.m_segments.m_buffer;
                                    ushort       num19   = num17;
                                    buffer8[(int)num19].m_flags = (buffer8[(int)num19].m_flags | NetSegment.Flags.Untouchable);
                                }
                            }
                            instance.UpdateSegment(num17);
                        }
                    }
                }

                // ns
                if (isAssetWithTmpeSettings && CreatedSegments.Count > 0)
                {
                    if (CreatedSegments.Last() == 0)
                    {
                        CreatedSegments.RemoveAt(CreatedSegments.Count - 1);
                    }

                    ProcessNewPaths(CreatedSegments, info);
                }
                // ns end

                instance.m_tempNodeBuffer.Clear();
                instance.m_tempSegmentBuffer.Clear();
            }
        }