-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Options for more easily opening a map with external files from a special source #37
Comments
Hello, I'm giving a try at making a game in Rust and I also faced this kind of issue. I'm think about using a version of Have a nice day. |
Being able to customize this would also enable you to protect against malicious .tmx files opening arbitrary files on disk, which could be a problem if you want to allow any User Generated Content. I'd even argue for some default sanity checks / sandboxing... This is probably as straightforward as replacing the https://github.com/mattyhall/rs-tiled/blob/06e4ecf4257e4dd0813087e1fcd642d7f0ce7713/src/lib.rs#L432 |
For bonus points, making this async/future based would make it easier to integrate into the browser I believe. |
Trying to address this by supplying a closure for loading external files: #100 |
To deploy on the web I put all the files in the binary and then I implement the loader like this: pub struct MyTiledResourceCache(HashMap<tiled::ResourcePathBuf, Arc<tiled::Tileset>>);
impl tiled::ResourceCache for MyTiledResourceCache {
fn get_tileset(&self, path: impl AsRef<tiled::ResourcePath>) -> Option<Arc<tiled::Tileset>> {
self.0.get(&path.as_ref().to_path_buf()).cloned()
}
fn get_or_try_insert_tileset_with<F, E>(
&mut self,
path: tiled::ResourcePathBuf,
f: F
) -> Result<Arc<tiled::Tileset>, E>
where
F: FnOnce() -> Result<tiled::Tileset, E>
{
match self.0.entry(path.clone()) {
Entry::Occupied(o) => Ok(o.get().clone()),
Entry::Vacant(v) => {
#[cfg(not(target_arch = "wasm32"))]
{
let tileset = f()?;
Ok(v.insert(Arc::new(tileset)).clone())
}
#[cfg(target_arch = "wasm32")]
{
let _ = f;
let loader = tiled::Loader::new();
// in_memory_tiled_files contains all the map and tileset inside the memory
let tileset = loader.load_tsx_tileset_from(in_memory_tiled_files::InMemoryFetcher::fetch(path).unwrap(), &"assets/").unwrap();
Ok(v.insert(Arc::new(tileset)).clone())
}
},
}
}
} But I have an issue that even when using this cache rs-tiled tries to open the file before calling [thiolliere@fedora rs-tiled]$ git diff
diff --git a/src/map.rs b/src/map.rs
index 8871985..807c9e7 100644
--- a/src/map.rs
+++ b/src/map.rs
@@ -188,8 +188,15 @@ impl Map {
let res = Tileset::parse_xml_in_map(parser, attrs, map_path)?;
match res.result_type {
EmbeddedParseResultType::ExternalReference { tileset_path } => {
- let file = File::open(&tileset_path).map_err(|err| Error::CouldNotOpenFile{path: tileset_path.clone(), err })?;
- let tileset = cache.get_or_try_insert_tileset_with(tileset_path.clone(), || crate::parse::xml::parse_tileset(file, &tileset_path))?;
+ let callback = || {
+ let file = File::open(&tileset_path)
+ .map_err(|err| Error::CouldNotOpenFile{path: tileset_path.clone(), err })?;
+ crate::parse::xml::parse_tileset(file, &tileset_path)
+ };
+ let tileset = cache.get_or_try_insert_tileset_with(
+ tileset_path.clone(),
+ callback,
+ )?;
tilesets.push(MapTilesetGid{first_gid: res.first_gid, tileset});
}
EmbeddedParseResultType::Embedded { tileset } => { This way my cache always contains all the external tileset. I am working on a PR to have this File::open inside the callback on master EDIT: I see that the branch next already contains a |
Pretty much solved in 0.11.0. Closing. |
The problem I'm currently running into is that in ggez, opening files from resources is done through a special Filesystem type, which doesn't give the full path of the map file. I want to provide a way for rs-tiled to find the tilesets using this filesystem type, rather than manually finding the full path of the map file and passing that.
The text was updated successfully, but these errors were encountered: