Simplified loader a bit and added more docs

This commit is contained in:
Daniel Cronqvist 2024-09-03 22:52:26 +02:00
parent 738a9fc5a8
commit 247f9294af
3 changed files with 48 additions and 34 deletions

View file

@ -6,13 +6,19 @@ Install DotTiled from NuGet:
dotnet add package DotTiled dotnet add package DotTiled
``` ```
Use the `DotTiled` namespace (if you want).
```csharp
using DotTiled;
```
Or fully qualify all `DotTiled` types e.g. `DotTiled.Loader`.
## Loading a map from the file system ## Loading a map from the file system
This will create a loader that will load files from the underlying file system using <xref:DotTiled.Serialization.FileSystemResourceReader>. It will also be configured to use an in-memory cache to avoid loading the same tileset or template multiple times using <xref:DotTiled.Serialization.DefaultResourceCache>. This will create a loader that will load files from the underlying file system using <xref:DotTiled.Serialization.FileSystemResourceReader>. It will also be configured to use an in-memory cache to avoid loading the same tileset or template multiple times using <xref:DotTiled.Serialization.DefaultResourceCache>.
```csharp ```csharp
using DotTiled;
var loader = Loader.Default(); var loader = Loader.Default();
var map = loader.LoadMap("path/to/map.tmx"); var map = loader.LoadMap("path/to/map.tmx");
``` ```
@ -22,8 +28,6 @@ var map = loader.LoadMap("path/to/map.tmx");
If you want to load resources (maps, tilesets, templates) from a different source than the underlying file system, you can override the <xref:DotTiled.Serialization.FileSystemResourceReader> that is being used with your own implementation of <xref:DotTiled.Serialization.IResourceReader>. If you want to load resources (maps, tilesets, templates) from a different source than the underlying file system, you can override the <xref:DotTiled.Serialization.FileSystemResourceReader> that is being used with your own implementation of <xref:DotTiled.Serialization.IResourceReader>.
```csharp ```csharp
using DotTiled;
var loader = Loader.DefaultWith( var loader = Loader.DefaultWith(
resourceReader: new MyCustomResourceReader()); resourceReader: new MyCustomResourceReader());
var map = loader.LoadMap("path/to/map.tmx"); var map = loader.LoadMap("path/to/map.tmx");
@ -34,8 +38,6 @@ var map = loader.LoadMap("path/to/map.tmx");
Similarly, you can override the <xref:DotTiled.Serialization.DefaultResourceCache> that is being used with your own implementation of <xref:DotTiled.Serialization.IResourceCache>. Similarly, you can override the <xref:DotTiled.Serialization.DefaultResourceCache> that is being used with your own implementation of <xref:DotTiled.Serialization.IResourceCache>.
```csharp ```csharp
using DotTiled;
var loader = Loader.DefaultWith( var loader = Loader.DefaultWith(
resourceReader: new MyCustomResourceReader(), resourceReader: new MyCustomResourceReader(),
resourceCache: new MyCustomResourceCache()); resourceCache: new MyCustomResourceCache());
@ -47,12 +49,21 @@ var map = loader.LoadMap("path/to/map.tmx");
If you have custom types in your map, you can provide any `IEnumerable<ICustomTypeDefinition>` to the loader. This will allow the loader to deserialize the custom types in your map. If you have custom types in your map, you can provide any `IEnumerable<ICustomTypeDefinition>` to the loader. This will allow the loader to deserialize the custom types in your map.
```csharp ```csharp
using DotTiled;
var monsterSpawnerDef = new CustomClassDefinition { ... }; var monsterSpawnerDef = new CustomClassDefinition { ... };
var chestDef = new CustomClassDefinition { ... }; var chestDef = new CustomClassDefinition
{
Name = "Chest",
UseAs = CustomClassUseAs.All,
Members = [
new IntProperty { Name = "coins", Value = 0 },
new BoolProperty { Name = "locked", Value = true }
]
};
var loader = Loader.DefaultWith( var loader = Loader.DefaultWith(
customTypeDefinitions: [monsterSpawnerDef, chestDef]); customTypeDefinitions: [monsterSpawnerDef, chestDef]);
var map = loader.LoadMap("path/to/map.tmx"); var map = loader.LoadMap("path/to/map.tmx");
var chest = map.GetProperty<CustomClassProperty>("chest").Value;
var coinsToSpawn = chest.GetProperty<IntProperty>("coins").Value;
``` ```

View file

@ -1,5 +1,6 @@
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using DotTiled.Serialization;
using NSubstitute; using NSubstitute;
namespace DotTiled.Tests; namespace DotTiled.Tests;

View file

@ -79,39 +79,41 @@ public class Loader
return tilesetReader.ReadTileset(); return tilesetReader.ReadTileset();
} }
private Func<string, Tileset> GetTilesetResolver(string basePath) private Func<string, T> GetResolverFunc<T>(
string basePath,
Func<string, Optional<T>> cacheResolver,
Action<string, T> cacheInsert,
Func<string, T> resolveFromContent)
{ {
return source => return source =>
{ {
var tilesetPath = Path.Combine(basePath, source); var resourcePath = Path.Combine(basePath, source);
var cachedTileset = _resourceCache.GetTileset(source); var cachedResource = cacheResolver(resourcePath);
if (cachedTileset.HasValue) if (cachedResource.HasValue)
return cachedTileset.Value; return cachedResource.Value;
string tilesetContent = _resourceReader.Read(tilesetPath); string tilesetContent = _resourceReader.Read(resourcePath);
var resource = resolveFromContent(tilesetContent);
cacheInsert(resourcePath, resource);
return resource;
};
}
private Func<string, Tileset> GetTilesetResolver(string basePath) =>
GetResolverFunc<Tileset>(basePath, _resourceCache.GetTileset, _resourceCache.InsertTileset,
tilesetContent =>
{
using var tilesetReader = new TilesetReader(tilesetContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver); using var tilesetReader = new TilesetReader(tilesetContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver);
var tileset = tilesetReader.ReadTileset(); return tilesetReader.ReadTileset();
_resourceCache.InsertTileset(source, tileset); });
return tileset;
};
}
private Func<string, Template> GetTemplateResolver(string basePath) private Func<string, Template> GetTemplateResolver(string basePath) =>
GetResolverFunc<Template>(basePath, _resourceCache.GetTemplate, _resourceCache.InsertTemplate,
templateContent =>
{ {
return source =>
{
var templatePath = Path.Combine(basePath, source);
var cachedTemplate = _resourceCache.GetTemplate(source);
if (cachedTemplate.HasValue)
return cachedTemplate.Value;
string templateContent = _resourceReader.Read(templatePath);
using var templateReader = new TemplateReader(templateContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver); using var templateReader = new TemplateReader(templateContent, GetTilesetResolver(basePath), GetTemplateResolver(basePath), CustomTypeResolver);
var template = templateReader.ReadTemplate(); return templateReader.ReadTemplate();
_resourceCache.InsertTemplate(source, template); });
return template;
};
}
private ICustomTypeDefinition CustomTypeResolver(string name) => _customTypeDefinitions[name]; private ICustomTypeDefinition CustomTypeResolver(string name) => _customTypeDefinitions[name];
} }