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)]
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 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);
{
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());
fs::write(&path, bundle.to_binary()?)
.await

View file

@ -50,13 +50,13 @@ where
match fmt {
OutputFormat::Text => {
println!("Bundle: {}", bundle.name());
println!("Bundle: {}", bundle.name().display());
for f in bundle.files().iter() {
if f.variants().len() != 1 {
let err = eyre::eyre!("Expected exactly one version for this file.")
.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);
}

View file

@ -5,7 +5,6 @@ use std::path::{Path, PathBuf};
use color_eyre::eyre::{self, Context};
use color_eyre::Result;
use sdk::murmur::Murmur64;
use sdk::Bundle;
use zip::ZipWriter;
@ -70,7 +69,7 @@ impl Archive {
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());
zip.start_file(path.to_string_lossy(), Default::default())?;

View file

@ -38,9 +38,14 @@ pub struct BundleDatabase {
impl BundleDatabase {
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 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 {
name,
stream,
@ -48,7 +53,12 @@ impl BundleDatabase {
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() {
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::bundle::file::Properties;
use crate::murmur::{HashGroup, Murmur64};
use crate::murmur::{HashGroup, IdString64, Murmur64};
pub(crate) mod database;
pub(crate) mod file;
@ -46,13 +46,13 @@ pub struct Bundle {
format: BundleFormat,
properties: [Murmur64; 32],
files: Vec<BundleFile>,
name: String,
name: IdString64,
}
impl Bundle {
pub fn new(name: String) -> Self {
pub fn new<S: Into<IdString64>>(name: S) -> Self {
Self {
name,
name: name.into(),
format: BundleFormat::F8,
properties: [0.into(); 32],
files: Vec::new(),
@ -201,7 +201,7 @@ impl Bundle {
}
Ok(Self {
name: bundle_name,
name: bundle_name.into(),
format,
files,
properties,
@ -281,7 +281,7 @@ impl Bundle {
Ok(w.into_inner())
}
pub fn name(&self) -> &String {
pub fn name(&self) -> &IdString64 {
&self.name
}

View file

@ -289,9 +289,9 @@ impl IdString64 {
}
}
impl From<String> for IdString64 {
fn from(value: String) -> Self {
Self::String(value)
impl<S: Into<String>> From<S> for IdString64 {
fn from(value: S) -> Self {
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);
impl std::fmt::Display for IdString64Display {