Add support for config component overrides

This commit is contained in:
lcdr
2021-03-03 15:57:46 +01:00
parent 431b7cffce
commit cb6a4aaaef
3 changed files with 62 additions and 42 deletions
+7 -29
View File
@@ -20,8 +20,6 @@ use self::zip_context::ZipContext;
static mut PRINT_PACKETS: bool = false;
const COMP_ORDER : [u32; 28] = [108, 1, 3, 40, 98, 7, 23, 110, 109, 106, 4, 26, 17, 5, 9, 60, 11, 48, 25, 16, 100, 39, 42, 6, 49, 2, 44, 107];
pub struct Cdclient {
conn: Connection,
comp_cache: HashMap<Lot, Vec<u32>>,
@@ -31,31 +29,8 @@ impl Cdclient {
fn get_comps(&mut self, lot: Lot) -> &Vec<u32> {
if !self.comp_cache.contains_key(&lot) {
let mut stmt = self.conn.prepare("select component_type from componentsregistry where id = ?").unwrap();
let mut rows: Vec<_> = stmt.query_map(params![lot], |row| row.get(0)).unwrap().map(|x| x.unwrap()).collect();
rows.sort_by_key(|x| COMP_ORDER.iter().position(|y| y == x).unwrap_or(usize::MAX));
let mut comps = vec![];
for row in rows {
// special case: utter bodge
match row {
2 => { comps.push(44); }
4 => { comps.push(110); comps.push(109); comps.push(106); }
7 => { comps.push(98); }
23 | 48 => {
if !comps.contains(&7) {
comps.push(7);
}
}
_ => {},
}
comps.push(row);
}
// special case: utter bodge
if comps.contains(&26) {
comps.remove(comps.iter().position(|&x| x == 11).unwrap());
comps.remove(comps.iter().position(|&x| x == 42).unwrap());
}
dbg!(&comps);
self.comp_cache.insert(lot, comps);
let rows: Vec<_> = stmt.query_map(params![lot], |row| row.get(0)).unwrap().map(|x| x.unwrap()).collect();
self.comp_cache.insert(lot, rows);
}
&self.comp_cache.get(&lot).unwrap()
}
@@ -81,7 +56,7 @@ fn parse(path: &Path, cdclient: &mut Cdclient) -> Res<usize> {
let src = BufReader::new(File::open(path).unwrap());
let mut zip = ZipArchive::new(src).unwrap();
let mut lots = HashMap::new();
let mut comps = HashMap::new();
let mut i = 0;
let mut packet_count = 0;
while i < zip.len() {
@@ -178,14 +153,17 @@ fn parse(path: &Path, cdclient: &mut Cdclient) -> Res<usize> {
&& !file.name().contains("(6290)")
&& !file.name().contains("(6319)")
&& !file.name().contains("(7001)")
&& !file.name().contains("(7100)")
&& !file.name().contains("(7282)")
&& !file.name().contains("(7796)")
&& !file.name().contains("(8304)")
&& !file.name().contains("(8575)")
&& !file.name().contains("(9741)")
&& !file.name().contains("(10042)")
&& !file.name().contains("(10046)")
&& !file.name().contains("(10055)")
&& !file.name().contains("(10097)")
&& !file.name().contains("(12916)")
&& !file.name().contains("(13773)")
&& !file.name().contains("(14376)")
&& !file.name().contains("(14447)")
@@ -205,7 +183,7 @@ fn parse(path: &Path, cdclient: &mut Cdclient) -> Res<usize> {
&& !file.name().contains("(14547)"))
|| file.name().contains("[27]")
{
let mut ctx = ZipContext { zip: file, lots: &mut lots, cdclient, assert_fully_read: true };
let mut ctx = ZipContext { zip: file, comps: &mut comps, cdclient, assert_fully_read: true };
let msg: WorldClientMessage = ctx.read().expect(&format!("Zip: {}, Filename: {}, {} bytes", path.to_str().unwrap(), ctx.zip.name(), ctx.zip.size()));
file = ctx.zip;
if unsafe { PRINT_PACKETS } {
+52 -10
View File
@@ -3,6 +3,7 @@ use std::io::Result as Res;
use endio_bit::BEBitReader;
use lu_packets::{
lu,
raknet::client::replica::{
ComponentConstruction, ComponentSerialization, ReplicaContext,
base_combat_ai::{BaseCombatAiConstruction, BaseCombatAiSerialization},
@@ -33,15 +34,17 @@ use lu_packets::{
switch::{SwitchConstruction, SwitchSerialization},
vendor::{VendorConstruction, VendorSerialization},
},
world::Lot,
world::{Lot, LuNameValue, LnvValue},
};
use zip::read::ZipFile;
use super::Cdclient;
const COMP_ORDER : [u32; 28] = [108, 1, 3, 40, 98, 7, 23, 110, 109, 106, 4, 26, 17, 5, 9, 60, 11, 48, 25, 16, 100, 39, 42, 6, 49, 2, 44, 107];
pub struct ZipContext<'a> {
pub zip: ZipFile<'a>,
pub lots: &'a mut HashMap<u16, Lot>,
pub comps: &'a mut HashMap<u16, Vec<u32>>,
pub cdclient: &'a mut Cdclient,
pub assert_fully_read: bool,
}
@@ -54,13 +57,53 @@ impl std::io::Read for ZipContext<'_> {
// hacky hardcoded components to be able to read player replicas without DB lookup
impl ReplicaContext for ZipContext<'_> {
fn get_comp_constructions<R: std::io::Read>(&mut self, network_id: u16, lot: Lot) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>> {
fn get_comp_constructions<R: std::io::Read>(&mut self, network_id: u16, lot: Lot, config: &Option<LuNameValue>) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>> {
use endio::Deserialize;
let comps = self.cdclient.get_comps(lot);
let mut rows = self.cdclient.get_comps(lot).clone();
if rows.contains(&42) {
if let Some(conf) = config {
if let Some(model_type) = conf.get(&lu!("modelType")) {
dbg!(model_type);
if let LnvValue::I32(m_type) = model_type {
if *m_type == 0 {
rows.push(1);
} else {
rows.push(3);
}
}
}
}
}
rows.sort_by_key(|x| COMP_ORDER.iter().position(|y| y == x).unwrap_or(usize::MAX));
let mut comps = vec![];
for row in rows {
// special case: utter bodge
match row {
2 => { comps.push(44); }
4 => { comps.push(110); comps.push(109); comps.push(106); }
7 => { comps.push(98); }
23 | 48 => {
if !comps.contains(&7) {
comps.push(7);
}
}
_ => {},
}
comps.push(row);
}
// special case: utter bodge
if comps.contains(&26) {
comps.remove(comps.iter().position(|&x| x == 11).unwrap());
comps.remove(comps.iter().position(|&x| x == 42).unwrap());
}
dbg!(&comps);
let mut constrs: Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>> = vec![];
for comp in comps {
for comp in &comps {
match comp {
1 => { constrs.push(|x| Ok(Box::new(ControllablePhysicsConstruction::deserialize(x)?))); }
3 => { constrs.push(|x| Ok(Box::new(SimplePhysicsConstruction::deserialize(x)?))); }
@@ -89,19 +132,18 @@ impl ReplicaContext for ZipContext<'_> {
108 => { constrs.push(|x| Ok(Box::new(PossessableConstruction::deserialize(x)?))); }
109 => { constrs.push(|x| Ok(Box::new(LevelProgressionConstruction::deserialize(x)?))); }
110 => { constrs.push(|x| Ok(Box::new(PossessionControlConstruction::deserialize(x)?))); }
2 | 12 | 27 | 31 | 35 | 36 | 43 | 45 | 55 | 56 | 57 | 64 | 65 | 67 | 68 | 73 | 78 | 95 | 104 | 113 | 114 => {},
2 | 12 | 24 | 27 | 31 | 35 | 36 | 43 | 45 | 55 | 56 | 57 | 64 | 65 | 67 | 68 | 73 | 78 | 95 | 104 | 113 | 114 => {},
x => panic!("{}", x),
}
}
self.lots.insert(network_id, lot);
self.comps.insert(network_id, comps);
constrs
}
fn get_comp_serializations<R: std::io::Read>(&mut self, network_id: u16) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentSerialization>>> {
use endio::Deserialize;
if let Some(lot) = self.lots.get(&network_id) {
let comps = self.cdclient.get_comps(*lot);
if let Some(comps) = self.comps.get(&network_id) {
let mut sers: Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentSerialization>>> = vec![];
for comp in comps {
match comp {
@@ -128,7 +170,7 @@ impl ReplicaContext for ZipContext<'_> {
108 => { sers.push(|x| Ok(Box::new(PossessableSerialization::deserialize(x)?))); }
109 => { sers.push(|x| Ok(Box::new(LevelProgressionSerialization::deserialize(x)?))); }
110 => { sers.push(|x| Ok(Box::new(PossessionControlSerialization::deserialize(x)?))); }
2 | 5 | 9 | 12 | 27 | 31 | 35 | 36 | 43 | 44 | 45 | 55 | 56 | 57 | 64 | 65 | 67 | 68 | 73 | 78 | 95 | 98 | 104 | 113 | 114 => {},
2 | 5 | 9 | 12 | 24 | 27 | 31 | 35 | 36 | 43 | 44 | 45 | 55 | 56 | 57 | 64 | 65 | 67 | 68 | 73 | 78 | 95 | 98 | 104 | 113 | 114 => {},
x => panic!("{}", x),
}
}
+3 -3
View File
@@ -98,7 +98,7 @@ pub trait ComponentSerialization: Debug {
}
pub trait ReplicaContext {
fn get_comp_constructions<R: Read>(&mut self, network_id: u16, lot: Lot) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>>;
fn get_comp_constructions<R: Read>(&mut self, network_id: u16, lot: Lot, config: &Option<LuNameValue>) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>>;
fn get_comp_serializations<R: Read>(&mut self, network_id: u16) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentSerialization>>>;
}
@@ -163,7 +163,7 @@ impl<R: Read+ReplicaContext> Deserialize<LE, R> for ReplicaConstruction {
let gm_level = ReplicaD::deserialize(&mut bit_reader)?;
let parent_child_info = ReplicaD::deserialize(&mut bit_reader)?;
let mut components = vec![];
for new in unsafe {bit_reader.get_mut_unchecked()}.get_comp_constructions(network_id, lot) {
for new in unsafe {bit_reader.get_mut_unchecked()}.get_comp_constructions(network_id, lot, &config) {
components.push(new(&mut bit_reader)?);
}
@@ -276,7 +276,7 @@ impl Read for DummyContext<'_> {
#[cfg(test)]
impl ReplicaContext for DummyContext<'_> {
fn get_comp_constructions<R: Read>(&mut self, _network_id: u16, _lot: Lot) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>> {
fn get_comp_constructions<R: Read>(&mut self, _network_id: u16, _lot: Lot, config: &Option<LuNameValue>) -> Vec<fn(&mut BEBitReader<R>) -> Res<Box<dyn ComponentConstruction>>> {
vec![]
}