Darktide Mod Manager #39

Merged
lucas merged 91 commits from feat/dtmm into master 2023-03-01 22:27:42 +01:00
6 changed files with 87 additions and 23 deletions
Showing only changes of commit 09f357d72d - Show all commits

View file

@ -202,7 +202,7 @@ fn build_mod_data_lua(state: Arc<State>) -> String {
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
async fn build_bundles(state: Arc<State>) -> Result<()> { async fn build_bundles(state: Arc<State>) -> Result<()> {
let mut bundle = Bundle::new(MOD_BUNDLE_NAME.into()); let mut bundle = Bundle::new(MOD_BUNDLE_NAME);
let mut tasks = Vec::new(); let mut tasks = Vec::new();
let bundle_dir = Arc::new(state.get_game_dir().join("bundle")); let bundle_dir = Arc::new(state.get_game_dir().join("bundle"));
@ -312,7 +312,7 @@ async fn build_bundles(state: Arc<State>) -> Result<()> {
db.add_bundle(&bundle); db.add_bundle(&bundle);
{ {
let path = bundle_dir.join(format!("{:x}", Murmur64::hash(bundle.name()))); let path = bundle_dir.join(format!("{:x}", bundle.name().to_murmur64()));
tracing::trace!("Writing mod bundle to '{}'", path.display()); tracing::trace!("Writing mod bundle to '{}'", path.display());
fs::write(&path, bundle.to_binary()?) fs::write(&path, bundle.to_binary()?)
.await .await

View file

@ -50,13 +50,13 @@ where
match fmt { match fmt {
OutputFormat::Text => { OutputFormat::Text => {
println!("Bundle: {}", bundle.name()); println!("Bundle: {}", bundle.name().display());
for f in bundle.files().iter() { for f in bundle.files().iter() {
if f.variants().len() != 1 { if f.variants().len() != 1 {
let err = eyre::eyre!("Expected exactly one version for this file.") let err = eyre::eyre!("Expected exactly one version for this file.")
.with_section(|| f.variants().len().to_string().header("Bundle:")) .with_section(|| f.variants().len().to_string().header("Bundle:"))
.with_section(|| bundle.name().clone().header("Bundle:")); .with_section(|| bundle.name().display().header("Bundle:"));
tracing::error!("{:#}", err); tracing::error!("{:#}", err);
} }

View file

@ -5,7 +5,6 @@ use std::path::{Path, PathBuf};
use color_eyre::eyre::{self, Context}; use color_eyre::eyre::{self, Context};
use color_eyre::Result; use color_eyre::Result;
use sdk::murmur::Murmur64;
use sdk::Bundle; use sdk::Bundle;
use zip::ZipWriter; use zip::ZipWriter;
@ -70,7 +69,7 @@ impl Archive {
map_entry.insert(file.name(false, None)); map_entry.insert(file.name(false, None));
} }
let name = Murmur64::hash(bundle.name().as_bytes()); let name = bundle.name().to_murmur64();
let path = base_path.join(name.to_string().to_ascii_lowercase()); let path = base_path.join(name.to_string().to_ascii_lowercase());
zip.start_file(path.to_string_lossy(), Default::default())?; zip.start_file(path.to_string_lossy(), Default::default())?;

View file

@ -38,9 +38,14 @@ pub struct BundleDatabase {
impl BundleDatabase { impl BundleDatabase {
pub fn add_bundle(&mut self, bundle: &Bundle) { pub fn add_bundle(&mut self, bundle: &Bundle) {
let hash = Murmur64::hash(bundle.name().as_bytes()); let hash = bundle.name().to_murmur64();
let name = hash.to_string(); let name = hash.to_string();
let stream = format!("{}.stream", &name); let stream = format!("{}.stream", &name);
{
let entry = self.stored_files.entry(hash).or_default();
let existing = entry.iter().position(|f| f.name == name);
let file = BundleFile { let file = BundleFile {
name, name,
stream, stream,
@ -48,7 +53,12 @@ impl BundleDatabase {
platform_specific: false, platform_specific: false,
}; };
self.stored_files.entry(hash).or_default().push(file); entry.push(file);
if let Some(pos) = existing {
entry.swap_remove(pos);
}
}
for f in bundle.files() { for f in bundle.files() {
let file_name = FileName { let file_name = FileName {

View file

@ -8,7 +8,7 @@ use oodle_sys::{OodleLZ_CheckCRC, OodleLZ_FuzzSafe, CHUNK_SIZE};
use crate::binary::sync::*; use crate::binary::sync::*;
use crate::bundle::file::Properties; use crate::bundle::file::Properties;
use crate::murmur::{HashGroup, Murmur64}; use crate::murmur::{HashGroup, IdString64, Murmur64};
pub(crate) mod database; pub(crate) mod database;
pub(crate) mod file; pub(crate) mod file;
@ -46,13 +46,13 @@ pub struct Bundle {
format: BundleFormat, format: BundleFormat,
properties: [Murmur64; 32], properties: [Murmur64; 32],
files: Vec<BundleFile>, files: Vec<BundleFile>,
name: String, name: IdString64,
} }
impl Bundle { impl Bundle {
pub fn new(name: String) -> Self { pub fn new<S: Into<IdString64>>(name: S) -> Self {
Self { Self {
name, name: name.into(),
format: BundleFormat::F8, format: BundleFormat::F8,
properties: [0.into(); 32], properties: [0.into(); 32],
files: Vec::new(), files: Vec::new(),
@ -201,7 +201,7 @@ impl Bundle {
} }
Ok(Self { Ok(Self {
name: bundle_name, name: bundle_name.into(),
format, format,
files, files,
properties, properties,
@ -281,7 +281,7 @@ impl Bundle {
Ok(w.into_inner()) Ok(w.into_inner())
} }
pub fn name(&self) -> &String { pub fn name(&self) -> &IdString64 {
&self.name &self.name
} }

View file

@ -289,9 +289,9 @@ impl IdString64 {
} }
} }
impl From<String> for IdString64 { impl<S: Into<String>> From<S> for IdString64 {
fn from(value: String) -> Self { fn from(value: S) -> Self {
Self::String(value) Self::String(value.into())
} }
} }
@ -313,6 +313,61 @@ impl PartialEq for IdString64 {
} }
} }
impl std::hash::Hash for IdString64 {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
state.write_u64(self.to_murmur64().into());
}
}
impl serde::Serialize for IdString64 {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u64(self.to_murmur64().into())
}
}
struct IdString64Visitor;
impl<'de> serde::de::Visitor<'de> for IdString64Visitor {
type Value = IdString64;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an u64 or a string")
}
fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(IdString64::Hash(value.into()))
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(IdString64::String(v.to_string()))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(IdString64::String(v))
}
}
impl<'de> serde::Deserialize<'de> for IdString64 {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_u64(IdString64Visitor)
}
}
pub struct IdString64Display(String); pub struct IdString64Display(String);
impl std::fmt::Display for IdString64Display { impl std::fmt::Display for IdString64Display {