Skip to content

feat(ltk_lua): add lua manifest parser and scaffold new crate - #160

Open
Crauzer wants to merge 1 commit into
mainfrom
lua-manifest
Open

feat(ltk_lua): add lua manifest parser and scaffold new crate#160
Crauzer wants to merge 1 commit into
mainfrom
lua-manifest

Conversation

@Crauzer

@Crauzer Crauzer commented Jul 24, 2026

Copy link
Copy Markdown
Member

What and why

Adds a new ltk_lua crate for anything script related in the game. The first thing to be in there is the new LUA Manifest format.

How it was tested

Parses and writes the current manifest one-to-one

The API might need more manual review, this PR was mostly vibe coded as a fun background side project.

@Crauzer
Crauzer requested a review from alanpq July 24, 2026 11:15
@Crauzer Crauzer self-assigned this Jul 24, 2026
@Crauzer Crauzer added area:reading File/format reading/parsing area:writing File/format writing/export area:api Public API design priority:low Low priority labels Jul 24, 2026
#[repr(transparent)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ScriptEntry(pub u64);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

inner u64 shouldn't be public, should have a from_raw instead

/// Lowercasing is ASCII-only, matching the game's `tolower`. Every name in a
/// shipped manifest is ASCII, so the distinction has never mattered in practice.
#[must_use]
pub fn hash_script_name(name: &str) -> u64 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this being a free function feels kinda cringe, i think newtype would be nicer (or even just making this not public)

Ok(())
}

/// Writes a string with a `u32` length prefix (writes 4 + str.len() bytes).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can we leave a TODO here to destroy this in future

#[must_use]
#[allow(clippy::cast_possible_truncation)]
pub const fn dir_index(self) -> u8 {
(self.0 & DIR_INDEX_MASK) as u8

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could we add a test to make this cast never break? (e.g enforce DIR_INDEX_BYTES <= 8)

/// Nothing checks that `entries` and `shared` line up; that join is by hash
/// and is the caller's to maintain (see [`ScriptEntry::new`]).
#[must_use]
pub fn from_parts(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this should take impl IntoIterator's, and should have an unsafe _unchecked variant without the sort (downstream could be upholding the sort themselves w/ priority queue/insertion sort/etc)

/// them. The shared list is observed sorted but is only iterated, and the
/// per-character script lists are **not** sorted in shipped files, so
/// neither is touched beyond the top level.
pub fn sort(&mut self) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this shouldn't be public if the struct is supposed to uphold the sortedness as an invariant :3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:api Public API design area:reading File/format reading/parsing area:writing File/format writing/export priority:low Low priority

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

2 participants