public int CountFilesWithRoot(FileLocation fileLocation, string fileNameRoot) { EnsureFolderStructureExistence(); var location = ResolveLocationEnum(fileLocation); return(DirectoryOp.GetFiles(location).Count(f => f.StartsWith(location + fileNameRoot))); }
public IEnumerable <string> ListFilesWithRoot(FileLocation fileLocation, string fileNameRoot, FileExtension fileExtension = FileExtension.json) { EnsureFolderStructureExistence(); var location = ResolveLocationEnum(fileLocation); var extension = ResolveExtensionEnum(fileExtension); return(DirectoryOp.GetFiles(location).Where(f => f.StartsWith(location + fileNameRoot)).Select(x => x.Replace(location, "").Replace(extension, ""))); }
public EpisodeSelectSection() { JsonParser jsonParser = new JsonParser(); IImageCodec imageCodec = ImageCodec.GetRead(ImageCodec.FormatPng); foreach (string episode in DirectoryOp.GetDirectories(PathOp.Combine(DualityApp.DataDirectory, "Episodes"))) { string pathAbsolute = PathOp.Combine(episode, ".res"); if (FileOp.Exists(pathAbsolute)) { Episode json; using (Stream s = DualityApp.SystemBackend.FileSystem.OpenFile(pathAbsolute, FileAccessMode.Read)) { json = jsonParser.Parse <Episode>(s); } json.Token = PathOp.GetFileName(episode); if (!DirectoryOp.Exists(PathOp.Combine(episode, json.FirstLevel))) { continue; } EpisodeEntry entry; entry.Episode = json; if (json.PreviousEpisode != null) { int time = Preferences.Get <int>("EpisodeEnd_Time_" + json.PreviousEpisode); entry.IsAvailable = (time > 0); } else { entry.IsAvailable = true; } entry.CanContinue = Preferences.Get <byte[]>("EpisodeContinue_Misc_" + entry.Episode.Token) != null; string logoPath = PathOp.Combine(episode, ".png"); if (FileOp.Exists(logoPath)) { PixelData pixelData; using (Stream s = FileOp.Open(logoPath, FileAccessMode.Read)) { pixelData = imageCodec.Read(s); } Texture texture = new Texture(new Pixmap(pixelData), TextureSizeMode.NonPowerOfTwo); entry.Logo = new Material(DrawTechnique.Alpha, texture); } else { entry.Logo = null; } episodes.Add(entry); } } episodes.Sort((x, y) => x.Episode.Position.CompareTo(y.Episode.Position)); }
/// <summary> /// Returns all Resource files that are located in the specified directory. This doesn't affect /// any actual content- or load states. /// </summary> /// <param name="folderPath"></param> public static IEnumerable <string> GetResourceFiles(string folderPath = null) { if (string.IsNullOrEmpty(folderPath)) { folderPath = DualityApp.DataDirectory; } IEnumerable <string> resFiles = DirectoryOp.GetFiles(folderPath, true); return(resFiles.Where(path => path.EndsWith(Resource.FileExt, StringComparison.OrdinalIgnoreCase))); }
/// <summary> /// Loads the Resource from the specified <see cref="Stream"/>. You shouldn't need this method in almost all cases. /// Only use it when you know exactly what you're doing. Consider requesting the Resource from the <see cref="ContentProvider"/> instead. /// </summary> /// <typeparam name="T"> /// Desired Type of the returned reference. Does not affect the loaded Resource in any way - it is simply returned as T. /// Results in returning null if the loaded Resource's Type isn't assignable to T. /// </typeparam> /// <param name="str">The stream to load the Resource from.</param> /// <param name="resPath">The path that is assumed as the loaded Resource's origin.</param> /// <param name="loadCallback">An optional callback that is invoked right after loading the Resource, but before initializing it.</param> /// <param name="initResource"> /// Specifies whether or not the Resource is initialized by calling <see cref="Resource.OnLoaded"/>. Never attempt to use /// uninitialized Resources or register them in the ContentProvider. /// </param> /// <returns>The Resource that has been loaded.</returns> //public static T Load<T>(Serializer formatter, string resPath = null, Action<T> loadCallback = null, bool initResource = true) where T : Resource //{ // T newContent = null; // // try { // Resource res = formatter.ReadObject<Resource>(); // if (res == null) throw new Exception("Loading Resource failed"); // // res.initState = InitState.Initializing; // res.path = resPath; // if (loadCallback != null) loadCallback(res as T); // Callback before initializing. // if (initResource) Init(res); // newContent = res as T; // } catch (Exception e) { // Console.WriteLine("Can't load {0} from '{1}', because an error occurred: {3}{2}", // /*Log.Type(*/typeof(T)/*)*/, // resPath ?? formatter.ToString(), // /*Log.Exception(*/e/*)*/, // Environment.NewLine); // } // // return newContent; //} /// <summary> /// Initializes a Resource that has been loaded without initialization. You shouldn't need this method in almost all cases. /// Only use it when you know exactly what you're doing. Consider requesting the Resource from the <see cref="ContentProvider"/> instead. /// </summary> /// <param name="res">The Resource to initialize.</param> //public static void Init(Resource res) //{ // if (res.initState != InitState.Initializing) return; // res.OnLoaded(); // if (ResourceLoaded != null) ResourceLoaded(res, new ResourceEventArgs(res)); // res.initState = InitState.Initialized; //} /// <summary> /// Determines whether or not the specified path points to a Duality Resource file. /// </summary> /// <param name="filePath"></param> /// <returns></returns> //public static bool IsResourceFile(string filePath) //{ // return string.Equals(PathOp.GetExtension(filePath), FileExt, StringComparison.OrdinalIgnoreCase); //} /// <summary> /// Returns all Resource files that are located in the specified directory. This doesn't affect /// any actual content- or load states. /// </summary> /// <param name="folderPath"></param> /// <returns></returns> public static IEnumerable <string> GetResourceFiles(string folderPath = null) { // ToDo: Root directory instead of "." if (string.IsNullOrEmpty(folderPath)) { folderPath = "."; } IEnumerable <string> resFiles = DirectoryOp.GetFiles(folderPath, true); return(resFiles.Where(path => path.EndsWith(Resource.FileExt, StringComparison.OrdinalIgnoreCase))); }
private void CheckAndCreateFolder(string path) { if (!DirectoryOp.Exists(path)) { Log.Game.Write($"Folder: [{path}] doesn't exist - creating"); DirectoryOp.Create(path); } else { Log.Game.Write($"Folder: [{path}] exists"); } }
/// <summary> /// Saves an object to the specified data file. If it already exists, the file will be overwritten. /// Automatically creates the appropriate directory structure, if it doesn't exist yet. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <param name="file"></param> /// <param name="preferredSerializer"></param> public static void WriteObject <T>(T obj, string file, Type preferredSerializer = null) { string dirName = PathOp.GetDirectoryName(file); if (!string.IsNullOrEmpty(dirName) && !DirectoryOp.Exists(dirName)) { DirectoryOp.Create(dirName); } using (Stream str = FileOp.Create(file)) { Serializer.WriteObject <T>(obj, str, preferredSerializer); } }
/// <summary> /// Saves the Resource to the specified path. /// </summary> /// <param name="saveAsPath">The path to which this Resource is saved to. If null, the Resources <see cref="Path"/> is used as destination.</param> /// <param name="makePermanent"> /// When true, the Resource will be made permanently available from now on. If it has been generated at runtime /// or was loaded explicitly outside the ContentProvider, this will set the Resources <see cref="Path"/> Property /// and register it in the <see cref="ContentProvider"/>. If the Resource already is a permanent, this parameter will be ignored. /// </param> public void Save(string saveAsPath = null, bool makePermanent = true) { if (this.Disposed) { throw new ObjectDisposedException("Can't save a Resource that has been disposed."); } if (string.IsNullOrWhiteSpace(saveAsPath)) { saveAsPath = this.path; if (string.IsNullOrWhiteSpace(saveAsPath)) { throw new ArgumentException("Can't save a Resource to an undefined path.", "saveAsPath"); } } // Prepare saving the Resource and abort if an error occurred in the process bool preparedSuccessfully = this.CheckedOnSaving(saveAsPath); if (!preparedSuccessfully) { return; } // We're saving a new Resource for the first time: Register it in the library bool isPermanent = !string.IsNullOrWhiteSpace(this.path); if (makePermanent && !isPermanent) { this.path = saveAsPath; ContentProvider.AddContent(this.path, this); } string dirName = PathOp.GetDirectoryName(saveAsPath); if (!string.IsNullOrEmpty(dirName) && !DirectoryOp.Exists(dirName)) { DirectoryOp.Create(dirName); } using (Stream str = FileOp.Create(saveAsPath)) { this.WriteToStream(str); } this.CheckedOnSaved(saveAsPath); }
internal static void InitDefaultMethod() { // By default, assume one of the builtin serializers, depending on execution environment if (DualityApp.ExecEnvironment == DualityApp.ExecutionEnvironment.Editor) { defaultSerializer = typeof(XmlSerializer); } else { defaultSerializer = typeof(BinarySerializer); } // Search for actual Resource files and detect their serialization format if (DirectoryOp.Exists(DualityApp.DataDirectory)) { foreach (string resFile in DirectoryOp.GetFiles(DualityApp.DataDirectory, true)) { if (!resFile.EndsWith(Resource.FileExt, StringComparison.OrdinalIgnoreCase)) { continue; } using (Stream stream = FileOp.Open(resFile, FileAccessMode.Read)) { try { Type matchingSerializer = Detect(stream); if (matchingSerializer != null) { defaultSerializer = matchingSerializer; break; } } catch (Exception) {} } } } }
public CustomLevelSelectSection() { levelList = new List <CustomLevel>(); isLoading = true; isLoadingAnimation = 1f; ThreadPool.UnsafeQueueUserWorkItem(_ => { JsonParser json = new JsonParser(); try { string path = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "unknown"); if (DirectoryOp.Exists(path)) { foreach (string levelPath in DirectoryOp.GetFiles(path)) { if (api == null) { break; } if (!levelPath.EndsWith(".level")) { continue; } IFileSystem levelPackage = new CompressedContent(levelPath); using ( Stream s = levelPackage.OpenFile(".res", FileAccessMode.Read)) { string levelToken = PathOp.GetFileNameWithoutExtension(levelPath); LevelConfigJson config = json.Parse <LevelConfigJson>(s); string icon = ""; #if DEBUG if ((config.Description.Flags & LevelFlags.FastCamera) != 0) { icon += " Fast"; } if ((config.Description.Flags & LevelFlags.HasPit) != 0) { icon += " Pit"; } #endif if ((config.Description.Flags & LevelFlags.Multiplayer) != 0 && (config.Description.Flags & (LevelFlags.MultiplayerRace | LevelFlags.MultiplayerFlags)) == 0) { icon += " Battle"; } if ((config.Description.Flags & LevelFlags.MultiplayerRace) != 0) { icon += " Race"; } if ((config.Description.Flags & LevelFlags.MultiplayerFlags) != 0) { icon += " CTF"; } levelList.Add(new CustomLevel(config.Description.Name, "unknown", levelToken, icon)); } } levelList.Sort((x, y) => { string xs = BitmapFont.StripFormatting(x.DisplayName); string ys = BitmapFont.StripFormatting(y.DisplayName); int i = string.Compare(xs, ys, StringComparison.InvariantCulture); if (i != 0) { return(i); } return(string.Compare(x.LevelName, y.LevelName, StringComparison.InvariantCulture)); }); } } catch { // ToDo: Handle exceptions } finally { isLoading = false; } }, null); }
private void PrerenderTexturedBackground() { try { IImageCodec codec = ImageCodec.GetRead(ImageCodec.FormatPng); // Try to use "The Secret Files" background string levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "secretf", "01_easter1"); if (!DirectoryOp.Exists(levelPath)) { // Try to use "Base Game" background levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "prince", "03_carrot1"); if (!DirectoryOp.Exists(levelPath)) { // Try to use "Holiday Hare '98" background levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "xmas98", "03_xmas3"); if (!DirectoryOp.Exists(levelPath)) { // Try to use "Christmas Chronicles" background levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "xmas99", "03_xmas3"); if (!DirectoryOp.Exists(levelPath)) { // Try to use "Shareware Demo" background; levelPath = PathOp.Combine(DualityApp.DataDirectory, "Episodes", "share", "02_share2"); if (!DirectoryOp.Exists(levelPath)) { // No usable background found throw new FileNotFoundException(); } } } } } // Load metadata JsonParser json = new JsonParser(); LevelHandler.LevelConfigJson config; using (Stream s = FileOp.Open(PathOp.Combine(levelPath, ".res"), FileAccessMode.Read)) { config = json.Parse <LevelHandler.LevelConfigJson>(s); } LevelHandler.LevelConfigJson.LayerSection layer; if (config.Layers.TryGetValue("Sky", out layer)) { if (layer.BackgroundColor != null && layer.BackgroundColor.Count >= 3) { horizonColor = new Vector4(layer.BackgroundColor[0] / 255f, layer.BackgroundColor[1] / 255f, layer.BackgroundColor[2] / 255f, 1f); } switch ((BackgroundStyle)layer.BackgroundStyle) { case BackgroundStyle.Sky: default: texturedBackgroundShader = ContentResolver.Current.RequestShader("TexturedBackground"); break; case BackgroundStyle.Circle: texturedBackgroundShader = ContentResolver.Current.RequestShader("TexturedBackgroundCircle"); break; } } // Render background layer to texture string tilesetPath = PathOp.Combine(DualityApp.DataDirectory, "Tilesets", config.Description.DefaultTileset); ColorRgba[] tileMapPalette = TileSet.LoadPalette(PathOp.Combine(tilesetPath, ".palette")); ContentResolver.Current.ApplyBasePalette(tileMapPalette); TileSet levelTileset = new TileSet(config.Description.DefaultTileset); if (!levelTileset.IsValid) { throw new InvalidDataException(); } using (Stream s = FileOp.Open(PathOp.Combine(levelPath, "Sky.layer"), FileAccessMode.Read)) { using (DeflateStream deflate = new DeflateStream(s, CompressionMode.Decompress)) using (BinaryReader r = new BinaryReader(deflate)) { int width = r.ReadInt32(); int height = r.ReadInt32(); TileMapLayer newLayer = new TileMapLayer(); newLayer.Layout = new LayerTile[width * height]; for (int i = 0; i < newLayer.Layout.Length; i++) { ushort tileType = r.ReadUInt16(); byte flags = r.ReadByte(); if (flags == 0) { newLayer.Layout[i] = levelTileset.GetDefaultTile(tileType); continue; } bool isFlippedX = (flags & 0x01) > 0; bool isFlippedY = (flags & 0x02) > 0; bool isAnimated = (flags & 0x04) > 0; bool legacyTranslucent = (flags & 0x80) > 0; // Invalid tile numbers (higher than tileset tile amount) are silently changed to empty tiles if (tileType >= levelTileset.TileCount && !isAnimated) { tileType = 0; } LayerTile tile; // Copy the default tile and do stuff with it tile = levelTileset.GetDefaultTile(tileType); tile.IsFlippedX = isFlippedX; tile.IsFlippedY = isFlippedY; tile.IsAnimated = isAnimated; if (legacyTranslucent) { tile.MaterialAlpha = /*127*/ 140; } newLayer.Layout[i] = tile; } newLayer.LayoutWidth = width; RecreateTexturedBackground(levelTileset, ref newLayer); } } } catch (Exception ex) { Console.WriteLine("Cannot prerender textured background: " + ex); cachedTexturedBackground = new Texture(new Pixmap(new PixelData(2, 2, ColorRgba.Black))); } }
void IPreferencesBackend.Commit() { if (!dirty) { return; } dirty = false; string path = PathOp.Combine(PathOp.GetDirectoryName(Assembly.GetEntryAssembly().Location), "Jazz2.settings"); if (!FileOp.Exists(path)) { path = PathOp.Combine(DualityApp.SystemBackend.GetNamedPath(NamedDirectory.ApplicationData), "Jazz2", "Jazz2.settings"); } try { DirectoryOp.Create(PathOp.GetDirectoryName(path)); } catch { // Nothing to do... } try { using (Stream s = FileOp.Create(path)) using (BinaryWriter w = new BinaryWriter(s)) { w.Write((ushort)data.Count); foreach (var pair in data) { w.Write(pair.Key); switch (pair.Value) { case string value: { w.Write((byte)0); w.Write(value); break; } case bool value: { w.Write((byte)1); w.Write(value); break; } case byte value: { w.Write((byte)2); w.Write(value); break; } case int value: { w.Write((byte)3); w.Write(value); break; } case long value: { w.Write((byte)4); w.Write(value); break; } case short value: { w.Write((byte)5); w.Write(value); break; } case uint value: { w.Write((byte)6); w.Write(value); break; } case string[] value: { w.Write((byte)10); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } case bool[] value: { w.Write((byte)11); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } case byte[] value: { w.Write((byte)12); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } case int[] value: { w.Write((byte)13); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } case long[] value: { w.Write((byte)14); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } case short[] value: { w.Write((byte)15); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } case uint[] value: { w.Write((byte)16); w.Write((byte)value.Length); for (int j = 0; j < value.Length; j++) { w.Write(value[j]); } break; } default: Log.Write(LogType.Warning, "Unknown preference type: " + pair.Value.GetType().FullName); break; } } } } catch (Exception ex) { Log.Write(LogType.Error, "Can't save preferences: " + ex); } }