Skip to content
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

map: Support tilemap layer versions 3+, improve error handling #26

Conversation

Fireball-Teeworlds
Copy link
Contributor

@Fireball-Teeworlds Fireball-Teeworlds commented Sep 2, 2020

This makes the behavior consistent with DDNet and fixes parsing for some unusual maps (fixes #15).

This makes the behavior consistent with DDNet and fixes parsing for some unusual maps (fixes heinrich5991#16).
@Fireball-Teeworlds
Copy link
Contributor Author

I've tested ddnet_properties for both a map where it worked before and a map where it didn't.

}

let v0 = format::MapItemLayerV1CommonV0::mandatory(raw, TooShort, InvalidVersion)?;
let v2 = format::MapItemLayerV1TilemapV2::mandatory(raw, TooShortV2, InvalidVersion)?;
let v3 = format::MapItemLayerV1TilemapV3::optional(raw, TooShortV3)?;
let flags = v2.flags as u32;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

v2.flags are i32, InvalidFlags() value is i32, but TILELAYERFLAG_* are u32.

I've decided to change a few functions to accept flags as i32 to avoid converting i32 -> u32 -> i32. This has removed the need for a separate u32 variable.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea was that unsigned integers behave more like bit containers than signed integers (see arithmetic right shift of signed integers). The conversions and separate variables only exist in source code, to the CPU and the compiler, they live in the same location.

I'm fine with the change.

Comment on lines +339 to +341
.map_err(|e| match e {
TooShort(_) => too_short(raw.len()),
other_err => other_err,
Copy link
Contributor Author

@Fireball-Teeworlds Fireball-Teeworlds Sep 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we still need different TooShort errors for different types of layers. As of now errors already contain the layer number: Error(Map(Layer(31, Tilemap(TooShortDdraceSwitch(19))))).

} else if version == 2 {
MapItemLayerV1TilemapV2::sum_len()
} else {
MapItemLayerV1TilemapV3::sum_len()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must say that I'm not a fan of lax parsing, trying to recover from bad values we don't know.

On the one hand, if someone actually increased the tilemap versions, introducing new fields, this could would break in inexplicable ways.

On the other hand, one could argue that no one could do this because it would break the DDNet parsing code. What do you think, would it be easier to change DDNet code?

Other possibilities include: Emit some kind of warning on tilemap version >= 2 (hard to do, we don't have a warning infrastructure in place for that); introduce some kind of lax parsing mode that just copies whatever DDNet is doing (also annoying as it's one more parameter to pass around).

Copy link
Contributor Author

@Fireball-Teeworlds Fireball-Teeworlds Sep 2, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could find only one map affected out of DDNet's (def-'s) maps7 collection. That's the map that is mentioned in the issue.

I also can't open it in DDNet (or latest Teeworlds) editor. I think we could keep the parsing logic as is, declare this map corrupted and settle for improved error reporting (I'll submit a separate pull request).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also possible that it's valid for some modded server & editor - but I'm not sure if we want to try to find which mod that was and add support for it.

@heinrich5991
Copy link
Owner

Thanks for being here and improving the library. :)

May I ask you whether you're planning to use this for something or are just generally interested in it?

@Fireball-Teeworlds
Copy link
Contributor Author

I'm just playing around with it - it's interesting to see Teeworlds bits implemented in Rust.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

map_properties: Error(Map(Layer(31, Tilemap(TooShortDdraceSwitch(19)))))
2 participants