/// <summary> /// Saves the current data in <see cref="Clusters"/>. /// </summary> public void Save() { m_BuildableDirectory.WaitDestroyHandle(); var river = new RiverExpanded(ServerSavedata.directory + "/" + Provider.serverID + "/Level/" + Level.info.name + "/Bases.dat"); river.WriteInt32(m_BuildableDirectory.Buildables.Count); var clusters = Clusters; river.WriteInt32(clusters.Count); foreach (var cluster in clusters) { river.WriteInt32(cluster.InstanceId); river.WriteBoolean(cluster.IsGlobalCluster); river.WriteInt32(cluster.Buildables.Count); foreach (var build in cluster.Buildables) { river.WriteUInt32(build.InstanceId); river.WriteBoolean(build is StructureBuildable); } } river.CloseRiver(); }
private bool LoadClusters(IEnumerable <Buildable> allBuildables) { var bases = new List <BaseCluster>(); foreach (var c in m_Clusters) { Return(c); } try { var timer = Stopwatch.StartNew(); var river = new RiverExpanded(ServerSavedata.directory + "/" + Provider.serverID + "/Level/" + Level.info.name + "/Bases.dat"); var allBuilds = allBuildables.ToList(); var structures = allBuilds.OfType <StructureBuildable>().ToDictionary(k => k.InstanceId); var barricades = allBuilds.OfType <BarricadeBuildable>().ToDictionary(k => k.InstanceId); var buildableCount = river.ReadInt32(); if (allBuilds.Count != buildableCount) { Logging.Write(m_Plugin, "Warning! Buildable count doesn't match saved count! Buildable save data was most likely modified or lost during server downtime. Clusters will be now rebuilt.", ConsoleColor.Yellow); return(false); } var clusterCount = river.ReadInt32(); var logRate = Math.Floor(clusterCount * 0.085); Logging.Write(m_Plugin, $"Loading saved clusters... 0% [0/{clusterCount}] {timer.ElapsedMilliseconds}ms", ConsoleColor.Cyan); for (var i = 0; i < clusterCount; i++) { var builds = new List <Buildable>(); // Restore of instanceId is needed to maintain something unique to each cluster across restarts. var instanceId = river.ReadInt32(); var global = river.ReadBoolean(); var buildCount = river.ReadInt32(); for (var o = 0; o < buildCount; o++) { var buildInstanceId = river.ReadUInt32(); var isStructure = river.ReadBoolean(); var build = isStructure ? (Buildable)structures[buildInstanceId] : barricades[buildInstanceId]; if (build == null) { Logging.Write(m_Plugin, $"Warning! Buildable with InstanceId {buildInstanceId} [isStructure: {isStructure}] not found! Save data was most likely modified or lost during server downtime. Clusters will be now rebuilt.", ConsoleColor.Yellow); river.CloseRiver(); return(false); } builds.Add(build); } if (global) { if (m_GlobalCluster != null) { m_GlobalCluster.AddBuildables(builds); } else { var cluster = CreateCluster(instanceId, true); cluster.AddBuildables(builds); m_GlobalCluster = cluster; } } else { var cluster = GetOrCreatePooledCluster(); cluster.AddBuildables(builds); bases.Add(cluster); } if ((i + 1) % logRate == 0) { Logging.Write(m_Plugin, $"Loading saved clusters... {Math.Ceiling((i + 1) / (double) clusterCount * 100)}% [{i + 1}/{clusterCount}] {timer.ElapsedMilliseconds}ms", ConsoleColor.Cyan); } } m_Clusters.AddRange(bases); if (Clusters.Count > 0) { m_InstanceIds = Clusters.Max(k => k.InstanceId) + 1; } for (var i = 0; i < m_InstanceIds; i++) { if (Clusters.Any(k => k.InstanceId == i) || m_ClusterPool.Any(k => k.InstanceId == i)) { continue; } m_ClusterPool.Add(CreateCluster(i)); } timer.Stop(); return(true); } catch (Exception ex) { Logging.Write(m_Plugin, $"Warning! An exception was thrown when attempting to load the save file. Assuming the data is corrupted. Clusters will be now rebuilt. Exception: {ex}", ConsoleColor.Yellow); foreach (var b in bases) { Return(b); } return(false); } }