Skip to content

Commit

Permalink
Start work on CRC/ResMgr subsystem
Browse files Browse the repository at this point in the history
  • Loading branch information
Xiphoseer committed Dec 8, 2021
1 parent b4a276d commit b41a6ca
Show file tree
Hide file tree
Showing 21 changed files with 640 additions and 130 deletions.
13 changes: 5 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ authors = ["Xiphoseer <[email protected]>"]
edition = "2018"

[dependencies]
assembly-core = { git = "https://github.com/Xiphoseer/assembly_rs.git" }
assembly-maps = { git = "https://github.com/Xiphoseer/assembly_rs.git" }
assembly-pack = { git = "https://github.com/Xiphoseer/assembly_rs.git" }
assembly-fdb = { git = "https://github.com/Xiphoseer/assembly_rs.git", default-features = false, features = ["serde-derives"] }
assembly-xml = { git = "https://github.com/Xiphoseer/assembly_rs.git" }
base64 = "0.13"
handlebars = "3.5"
pretty_env_logger = "0.4.0"
Expand All @@ -27,14 +32,6 @@ version = "0.3"
features = ["tls", "multipart"]
default-features = false

[dependencies.assembly-core]
version = "0.2.1"

[dependencies.assembly-data]
version = "0.3.0"
default-features = false
features = ["serde-derives"]

# Holds data in insertion order
[dependencies.linked-hash-map]
version = "0.5.3"
Expand Down
53 changes: 41 additions & 12 deletions src/api/adapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use std::iter::Copied;
use std::slice::Iter;
use std::{collections::BTreeMap, fmt};

use assembly_data::xml::localization::LocaleNode;
use paradox_typed_db::typed_rows::TypedRow;
use assembly_xml::localization::LocaleNode;
use paradox_typed_db::TypedRow;
use serde::{ser::SerializeMap, Serialize};

pub(crate) trait FindHash {
Expand Down Expand Up @@ -90,24 +90,53 @@ where
}
}

pub(crate) struct TableMultiIter<'a, 'b, R, K, F>
where
K: Iterator<Item = i32>,
F: FindHash,
R: TypedRow<'a, 'b>,
{
pub(crate) index: F,
pub(crate) key_iter: K,
pub(crate) table: &'b R::Table,
pub(crate) id_col: usize,
}

impl<'a, 'b, R, K, F> Iterator for TableMultiIter<'a, 'b, R, K, F>
where
K: Iterator<Item = i32>,
F: FindHash,
R: TypedRow<'a, 'b>,
{
type Item = (i32, R);

fn next(&mut self) -> Option<Self::Item> {
for key in &mut self.key_iter {
if let Some(hash) = self.index.find_hash(key) {
if let Some(r) = R::get(self.table, hash, key, self.id_col) {
return Some((key, r));
}
}
}
None
}
}

impl<'b, 'a: 'b, R, F, K> TypedTableIterAdapter<'a, 'b, R, F, K>
where
R: TypedRow<'a, 'b> + 'b,
{
pub(crate) fn to_iter(&self, id_col: usize) -> impl Iterator<Item = (i32, R)> + 'b
pub(crate) fn to_iter(&self, id_col: usize) -> TableMultiIter<'a, 'b, R, K::IntoIter, F>
where
F: FindHash + Copy + 'b,
K: IntoIterator<Item = i32> + Clone + 'b,
{
let table: &'b R::Table = self.table;
let i = self.index;
let iter = self.keys.clone().into_iter();
let mapper = move |key| {
let hash = i.find_hash(key)?;
let r = R::get(table, hash, key, id_col)?;
Some((key, r))
};
iter.filter_map(mapper)
TableMultiIter {
index: self.index,
key_iter: self.keys.clone().into_iter(),
table: self.table,
id_col,
}
}
}

Expand Down
47 changes: 47 additions & 0 deletions src/api/files.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use assembly_pack::pki::core::PackFileRef;
use color_eyre::eyre::Context;
use serde::Serialize;
use std::{path::Path, sync::Arc};
use tracing::error;

use warp::{
filters::BoxedFilter,
hyper::StatusCode,
reply::{json, with_status, Json, WithStatus},
Filter,
};

use crate::data::fs::{Loader, Node};

#[derive(Serialize)]
struct CRCReply<'a> {
fs: Option<&'a Node>,
pk: Option<&'a PackFileRef>,
}

/// Lookup information on a CRC i.e. a file path in the client
pub fn make_crc_lookup_filter(
res_path: &Path,
pki_path: Option<&Path>,
) -> BoxedFilter<(WithStatus<Json>,)> {
let mut loader = Loader::new();
loader.load_dir(Path::new("client/res"), res_path);
if let Some(pki_path) = pki_path {
if let Err(e) = loader
.load_pki(pki_path)
.with_context(|| format!("Failed to load PKI file at '{}'", pki_path.display()))
{
error!("{}", e);
}
}

let loader = Arc::new(loader);

warp::path::param()
.map(move |crc: u32| {
let fs = loader.get(crc).map(|e| &e.public);
let pk = loader.get_pki(crc);
with_status(json(&CRCReply { fs, pk }), StatusCode::OK)
})
.boxed()
}
102 changes: 59 additions & 43 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ use std::{
borrow::Borrow,
convert::Infallible,
error::Error,
path::Path,
str::{FromStr, Utf8Error},
sync::Arc,
};

use assembly_data::{fdb::mem::Database, xml::localization::LocaleNode};
use assembly_fdb::mem::Database;
use assembly_xml::localization::LocaleNode;
use paradox_typed_db::TypedDatabase;
use percent_encoding::percent_decode_str;
use warp::{
Expand All @@ -16,16 +18,18 @@ use warp::{
Filter, Reply,
};

use crate::auth::AuthKind;
use crate::{auth::AuthKind, data::locale::LocaleRoot};

use self::{
adapter::{LocaleAll, LocalePod},
files::make_crc_lookup_filter,
rev::{make_api_rev, ReverseLookup},
tables::{make_api_tables, tables_api},
};

pub mod adapter;
mod docs;
mod files;
pub mod rev;
pub mod tables;

Expand Down Expand Up @@ -149,45 +153,57 @@ pub fn locale_api(lr: Arc<LocaleNode>) -> impl Fn(Tail) -> Option<warp::reply::J
}
}

pub(crate) fn make_api(
url: String,
auth_kind: AuthKind,
db: Database<'static>,
tydb: &'static TypedDatabase<'static>,
rev: &'static ReverseLookup,
lr: Arc<LocaleNode>,
) -> BoxedFilter<(WithStatus<Json>,)> {
let v0_base = warp::path("v0");
let v0_tables = warp::path("tables").and(make_api_tables(db));
let v0_locale = warp::path("locale")
.and(warp::path::tail())
.map(locale_api(lr))
.map(map_opt);

let v0_rev = warp::path("rev").and(make_api_rev(tydb, rev));
let v0_openapi = docs::openapi(url, auth_kind).unwrap();
let v0 = v0_base.and(
v0_tables
.or(v0_locale)
.unify()
.or(v0_rev)
.unify()
.or(v0_openapi)
.unify(),
);

// v1
let dbf = db_filter(db);
let v1_base = warp::path("v1");
let v1_tables_base = dbf.and(warp::path("tables"));
let v1_tables = v1_tables_base
.and(warp::path::end())
.map(tables_api)
.map(map_res);
let v1 = v1_base.and(v1_tables);

// catch all
let catch_all = make_api_catch_all();

v0.or(v1).unify().or(catch_all).unify().boxed()
pub(crate) struct ApiFactory<'a> {
pub url: String,
pub auth_kind: AuthKind,
pub db: Database<'static>,
pub tydb: &'static TypedDatabase<'static>,
pub rev: &'static ReverseLookup,
pub lr: Arc<LocaleNode>,
pub res_path: &'a Path,
pub pki_path: Option<&'a Path>,
}

impl<'a> ApiFactory<'a> {
pub(crate) fn make_api(self) -> BoxedFilter<(WithStatus<Json>,)> {
let loc = LocaleRoot::new(self.lr.clone());

let v0_base = warp::path("v0");
let v0_tables = warp::path("tables").and(make_api_tables(self.db));
let v0_locale = warp::path("locale")
.and(warp::path::tail())
.map(locale_api(self.lr))
.map(map_opt);

let v0_crc = warp::path("crc").and(make_crc_lookup_filter(self.res_path, self.pki_path));

let v0_rev = warp::path("rev").and(make_api_rev(self.tydb, loc, self.rev));
let v0_openapi = docs::openapi(self.url, self.auth_kind).unwrap();
let v0 = v0_base.and(
v0_tables
.or(v0_crc)
.unify()
.or(v0_locale)
.unify()
.or(v0_rev)
.unify()
.or(v0_openapi)
.unify(),
);

// v1
let dbf = db_filter(self.db);
let v1_base = warp::path("v1");
let v1_tables_base = dbf.and(warp::path("tables"));
let v1_tables = v1_tables_base
.and(warp::path::end())
.map(tables_api)
.map(map_res);
let v1 = v1_base.and(v1_tables);

// catch all
let catch_all = make_api_catch_all();

v0.or(v1).unify().or(catch_all).unify().boxed()
}
}
13 changes: 9 additions & 4 deletions src/api/rev/behaviors.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use assembly_core::buffer::CastError;
use paradox_typed_db::{
typed_rows::{BehaviorTemplateRow, TypedRow},
typed_tables::{BehaviorParameterTable, BehaviorTemplateTable},
TypedDatabase,
columns::BehaviorTemplateColumn,
rows::BehaviorTemplateRow,
tables::{BehaviorParameterTable, BehaviorTemplateTable},
TypedDatabase, TypedRow,
};
use serde::ser::SerializeMap;
use serde::Serialize;
Expand Down Expand Up @@ -56,14 +57,18 @@ impl Serialize for EmbeddedBehaviors<'_, '_> {
S: serde::Serializer,
{
let mut m = serializer.serialize_map(Some(self.keys.len()))?;
let col_behavior_id = self
.table_templates
.get_col(BehaviorTemplateColumn::BehaviorId)
.unwrap();
for &behavior_id in self.keys {
m.serialize_key(&behavior_id)?;
let b = Behavior {
template: BehaviorTemplateRow::get(
self.table_templates,
behavior_id,
behavior_id,
self.table_templates.col_behavior_id,
col_behavior_id,
),
parameters: BehaviorParameters {
key: behavior_id,
Expand Down
48 changes: 42 additions & 6 deletions src/api/rev/common.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use std::collections::HashMap;

use assembly_fdb::common::Latin1Str;
use paradox_typed_db::{
typed_rows::{MissionTaskRow, ObjectsRef},
typed_tables::MissionTasksTable,
columns::ObjectsColumn,
rows::{MissionTasksRow, ObjectsRow},
tables::{MissionTasksTable, ObjectsTable},
};
use serde::Serialize;

use crate::api::adapter::{FindHash, I32Slice, IdentityHash, TypedTableIterAdapter};
use crate::api::adapter::{
FindHash, I32Slice, IdentityHash, TableMultiIter, TypedTableIterAdapter,
};

use super::data::MissionTaskUIDLookup;

Expand All @@ -16,8 +20,40 @@ pub struct MapFilter<'a, E> {
keys: &'a [i32],
}

pub(super) type ObjectsRefAdapter<'a, 'b> =
TypedTableIterAdapter<'a, 'b, ObjectsRef<'a, 'b>, IdentityHash, I32Slice<'b>>;
#[derive(Clone)]
pub struct ObjectsRefAdapter<'a, 'b> {
table: &'b ObjectsTable<'a>,
keys: &'b [i32],
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)]
struct ObjectRefData<'a> {
name: &'a Latin1Str,
}

impl<'a, 'b> ObjectsRefAdapter<'a, 'b> {
pub fn new(table: &'b ObjectsTable<'a>, keys: &'b [i32]) -> Self {
Self { table, keys }
}
}

impl<'a, 'b> serde::Serialize for ObjectsRefAdapter<'a, 'b> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let id_col = self.table.get_col(ObjectsColumn::Id).unwrap();
serializer.collect_map(
TableMultiIter {
index: IdentityHash,
key_iter: self.keys.iter().copied(),
table: self.table,
id_col,
}
.map(|(id, row): (i32, ObjectsRow)| (id, ObjectRefData { name: row.name() })),
)
}
}

#[derive(Serialize)]
pub(super) struct ObjectTypeEmbedded<'a, 'b> {
Expand All @@ -44,7 +80,7 @@ impl<'a, E: Serialize> Serialize for MapFilter<'a, E> {
pub(super) type MissionTaskHash<'b> = &'b HashMap<i32, MissionTaskUIDLookup>;

pub(super) type MissionTasks<'a, 'b> =
TypedTableIterAdapter<'a, 'b, MissionTaskRow<'a, 'b>, MissionTaskHash<'b>, I32Slice<'b>>;
TypedTableIterAdapter<'a, 'b, MissionTasksRow<'a, 'b>, MissionTaskHash<'b>, I32Slice<'b>>;

pub(super) struct MissionTaskIconsAdapter<'a, 'b> {
table: &'b MissionTasksTable<'a>,
Expand Down
Loading

0 comments on commit b41a6ca

Please sign in to comment.