/// <summary> /// Loads a plane from a given nplane file. /// </summary> /// <param name="planeDirectory">The directory from which the plane should be loaded.</param> /// <returns>The loaded plane.</returns> public static async Task <Plane> FromDirectory(string planeDirectory) { PlaneInfo planeInfo = JsonConvert.DeserializeObject <PlaneInfo>( File.ReadAllText(CalcPaths.PlaneIndex(planeDirectory)) ); Plane loadedPlane = new Plane(planeInfo, planeDirectory); // Load the primary chunks into the plane await loadedPlane.LoadPrimaryChunks(); return(loadedPlane); }
public static async Task <RippleSpaceManager> FromDirectory(string sourceDirectory) { RippleSpaceManager rippleSpace = new RippleSpaceManager(sourceDirectory); if (!Directory.Exists(sourceDirectory)) { Log.WriteLine($"[Core] Creating new ripplespace in {sourceDirectory}."); return(rippleSpace); } Log.WriteLine($"[Core] Loading ripplespace from {sourceDirectory}."); // Load the planes in if (!File.Exists(Path.Combine(rippleSpace.SourceDirectory, "index.list"))) { Log.WriteLine($"[Core] Warning: The ripplespace at {sourceDirectory} doesn't appear to contain an index file."); return(rippleSpace); } Log.WriteLine("[Core] Importing planes"); Stopwatch timer = Stopwatch.StartNew(); StreamReader planeList = new StreamReader(Path.Combine(sourceDirectory, "index.list")); List <Task <Plane> > planeLoaders = new List <Task <Plane> >(); string nextPlaneName = string.Empty; while ((nextPlaneName = await planeList.ReadLineAsync()) != null) { string nextPlaneDirectory = CalcPaths.PlaneDirectory(sourceDirectory, nextPlaneName); if (!Directory.Exists(nextPlaneDirectory)) { Log.WriteLine($"[Core] Warning: Couldn't find listed plane {nextPlaneName} when loading ripplespace."); continue; } planeLoaders.Add(Plane.FromDirectory(nextPlaneDirectory)); } await Task.WhenAll(planeLoaders); rippleSpace.Planes.AddRange( planeLoaders.Select((Task <Plane> planeLoader) => planeLoader.Result) ); long msTaken = timer.ElapsedMilliseconds; Log.WriteLine($"[Core] done! {rippleSpace.Planes.Count} plane{(rippleSpace.Planes.Count != 1?"s":"")} loaded in {msTaken}ms."); return(rippleSpace); }
/// <summary> /// Creates a new plane, adds it to this RippleSpaceManager, and then returns it. /// </summary> /// <param name="newPlaneInfo">The settings for the new plane to create.</param> /// <returns>The newly created plane.</returns> public Plane CreatePlane(PlaneInfo newPlaneInfo) { if (this[newPlaneInfo.Name] != null) { throw new InvalidOperationException($"Error: A plane with the name '{newPlaneInfo.Name}' already exists in this RippleSpaceManager."); } Log.WriteLine("[RippleSpace] Creating plane {0}", newPlaneInfo.Name); Plane newPlane = new Plane( newPlaneInfo, CalcPaths.PlaneDirectory(SourceDirectory, newPlaneInfo.Name) ); Planes.Add(newPlane); return(newPlane); }
public NibriboardServer(string pathToRippleSpace, int inPort = 31586) { Port = inPort; // Load the specified ripple space if it exists - otherwise save it to disk if (Directory.Exists(pathToRippleSpace)) { PlaneManager = RippleSpaceManager.FromDirectory(pathToRippleSpace).Result; } else { Log.WriteLine("[NibriboardServer] Couldn't find packed ripple space at {0} - creating new ripple space instead.", pathToRippleSpace); PlaneManager = new RippleSpace.RippleSpaceManager(pathToRippleSpace); } // Next, load the user account data string accountDataPath = CalcPaths.RippleSpaceAccountData(pathToRippleSpace); AccountManager = new UserManager(); if (File.Exists(accountDataPath)) { AccountManager.LoadUserDataFile(CalcPaths.RippleSpaceAccountData(pathToRippleSpace)).Wait(); } clientSettings = new ClientSettings() { SecureWebSocket = false, WebSocketHost = "192.168.0.56", WebSocketPort = Port, WebSocketPath = "/RipplespaceLink" }; // HTTP / Websockets Server setup SBRL.GlidingSquirrel.Log.LoggingLevel = SBRL.GlidingSquirrel.LogLevel.Info; AppServer = new NibriboardApp(new NibriboardAppStartInfo() { FilePrefix = "Nibriboard.obj.client_dist", ClientSettings = clientSettings, NibriServer = this }, IPAddress.IPv6Any, Port); // Command Console Server setup CommandServer = new CommandConsoleServer(this, CommandPort); }
/// <summary> /// Saves this plane to disk. /// Note that this only affects currently loaded chunks and the plane's metadata. /// Unloaded chunks are already persisted on disk, so they don't need saving. /// </summary> /// <param name="savingMode"> /// What to save to disk. By default both the metatdata and the loaded chunks are /// saved, but this behaviour can be controlled via this argument. /// </param> /// <returns>The total number of bytes written to disk.</returns> public async Task <long> Save(PlaneSavingMode savingMode = PlaneSavingMode.All) { // Create the storage directory on disk if required Directory.CreateDirectory(StorageDirectory); // For calculating the total number of bytes written long totalSize = 0; if (savingMode == PlaneSavingMode.All || savingMode == PlaneSavingMode.ChunkDataOnly) { // Save all the chunks to disk List <Task> chunkSavers = new List <Task>(); foreach (KeyValuePair <ChunkReference, Chunk> loadedChunkItem in loadedChunkspace) { // Figure out where to put the chunk and create the relevant directories string chunkDestinationFilename = CalcPaths.ChunkFilePath(StorageDirectory, loadedChunkItem.Key); Directory.CreateDirectory(Path.GetDirectoryName(chunkDestinationFilename)); // Ask the chunk to save itself, but only if it isn't empty if (loadedChunkItem.Value.IsEmpty) { // Delete the existing chunk file, if it exists if (File.Exists(chunkDestinationFilename)) { File.Delete(chunkDestinationFilename); } continue; } Stream chunkDestination = File.Open(chunkDestinationFilename, FileMode.OpenOrCreate); chunkSavers.Add(loadedChunkItem.Value.SaveTo(chunkDestination)); } await Task.WhenAll(chunkSavers); // Calculate the number of bytes written foreach (KeyValuePair <ChunkReference, Chunk> loadedChunkItem in loadedChunkspace) { string destFilename = CalcPaths.ChunkFilePath(StorageDirectory, loadedChunkItem.Key); if (!File.Exists(destFilename)) // Don't assume that the file exists - it might be an empty chunk { continue; } totalSize += (new FileInfo(destFilename)).Length; } } if (savingMode == PlaneSavingMode.All || savingMode == PlaneSavingMode.MetadataOnly) { // Save the plane information string planeIndexPath = CalcPaths.PlaneIndex(StorageDirectory); StreamWriter planeInfoWriter = new StreamWriter(planeIndexPath); await planeInfoWriter.WriteLineAsync(JsonConvert.SerializeObject(Info)); planeInfoWriter.Close(); totalSize += (new FileInfo(planeIndexPath)).Length; } return(totalSize); }
public async Task SaveUserData() { await AccountManager.SaveUserDataFile( CalcPaths.RippleSpaceAccountData(PlaneManager.SourceDirectory) ); }