Now keep track of entity state as well
This commit is contained in:
212
src/parser.rs
212
src/parser.rs
@@ -4,6 +4,8 @@ mod fieldpath;
|
|||||||
pub use fieldpath::{FieldPath, Paths};
|
pub use fieldpath::{FieldPath, Paths};
|
||||||
|
|
||||||
mod decoder;
|
mod decoder;
|
||||||
|
mod entities;
|
||||||
|
mod propcontroller;
|
||||||
mod sendtables;
|
mod sendtables;
|
||||||
mod variant;
|
mod variant;
|
||||||
|
|
||||||
@@ -53,6 +55,7 @@ pub struct FirstPassOutput {
|
|||||||
pub info: crate::csgo_proto::CDemoFileInfo,
|
pub info: crate::csgo_proto::CDemoFileInfo,
|
||||||
pub events: Vec<DemoEvent>,
|
pub events: Vec<DemoEvent>,
|
||||||
pub player_info: std::collections::HashMap<UserId, Player>,
|
pub player_info: std::collections::HashMap<UserId, Player>,
|
||||||
|
pub entity_states: Vec<entities::EntityState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -85,17 +88,22 @@ where
|
|||||||
mapping: std::collections::HashMap::new(),
|
mapping: std::collections::HashMap::new(),
|
||||||
};
|
};
|
||||||
let mut player_info = std::collections::HashMap::new();
|
let mut player_info = std::collections::HashMap::new();
|
||||||
let mut entities = std::collections::HashMap::new();
|
let mut entity_ctx = entities::EntityContext {
|
||||||
let mut cls_to_class = std::collections::HashMap::<u32, Class>::new();
|
entities: std::collections::HashMap::new(),
|
||||||
|
cls_to_class: std::collections::HashMap::new(),
|
||||||
|
};
|
||||||
let mut paths = Paths::new();
|
let mut paths = Paths::new();
|
||||||
let mut qf_mapper = decoder::QfMapper {
|
let mut qf_mapper = decoder::QfMapper {
|
||||||
idx: 0,
|
idx: 0,
|
||||||
map: std::collections::HashMap::new(),
|
map: std::collections::HashMap::new(),
|
||||||
};
|
};
|
||||||
|
let mut prop_controller = propcontroller::PropController::new();
|
||||||
let mut serializers = std::collections::HashMap::new();
|
let mut serializers = std::collections::HashMap::new();
|
||||||
|
|
||||||
let mut baselines = std::collections::HashMap::new();
|
let mut baselines = std::collections::HashMap::new();
|
||||||
|
|
||||||
|
let mut entity_states = Vec::new();
|
||||||
|
|
||||||
for mut frame in frames.into_iter() {
|
for mut frame in frames.into_iter() {
|
||||||
frame
|
frame
|
||||||
.decompress()
|
.decompress()
|
||||||
@@ -117,11 +125,12 @@ where
|
|||||||
&mut events,
|
&mut events,
|
||||||
&mut event_mapping,
|
&mut event_mapping,
|
||||||
&mut player_info,
|
&mut player_info,
|
||||||
&mut entities,
|
&mut entity_ctx,
|
||||||
&mut cls_to_class,
|
|
||||||
&mut paths,
|
&mut paths,
|
||||||
&mut qf_mapper,
|
&mut qf_mapper,
|
||||||
&mut baselines,
|
&mut baselines,
|
||||||
|
&prop_controller,
|
||||||
|
&mut entity_states
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
DemoCommand::FullPacket => {
|
DemoCommand::FullPacket => {
|
||||||
@@ -130,11 +139,12 @@ where
|
|||||||
&mut events,
|
&mut events,
|
||||||
&mut event_mapping,
|
&mut event_mapping,
|
||||||
&mut player_info,
|
&mut player_info,
|
||||||
&mut entities,
|
&mut entity_ctx,
|
||||||
&mut cls_to_class,
|
|
||||||
&mut paths,
|
&mut paths,
|
||||||
&mut qf_mapper,
|
&mut qf_mapper,
|
||||||
&mut baselines,
|
&mut baselines,
|
||||||
|
&prop_controller,
|
||||||
|
&mut entity_states
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
// TODO
|
// TODO
|
||||||
@@ -166,19 +176,23 @@ where
|
|||||||
// std::fs::write("send_table.b", bytes.as_slice());
|
// std::fs::write("send_table.b", bytes.as_slice());
|
||||||
|
|
||||||
assert!(serializers.is_empty());
|
assert!(serializers.is_empty());
|
||||||
serializers = sendtables::get_serializers(&serializer_msg, &mut qf_mapper)?;
|
serializers = sendtables::get_serializers(
|
||||||
|
&serializer_msg,
|
||||||
|
&mut qf_mapper,
|
||||||
|
&mut prop_controller,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
DemoCommand::ClassInfo => {
|
DemoCommand::ClassInfo => {
|
||||||
let raw: crate::csgo_proto::CDemoClassInfo = prost::Message::decode(data)?;
|
let raw: crate::csgo_proto::CDemoClassInfo = prost::Message::decode(data)?;
|
||||||
|
|
||||||
cls_to_class.clear();
|
entity_ctx.cls_to_class.clear();
|
||||||
|
|
||||||
for class_t in raw.classes {
|
for class_t in raw.classes {
|
||||||
let cls_id = class_t.class_id();
|
let cls_id = class_t.class_id();
|
||||||
let network_name = class_t.network_name();
|
let network_name = class_t.network_name();
|
||||||
|
|
||||||
if let Some(ser) = serializers.remove(network_name) {
|
if let Some(ser) = serializers.remove(network_name) {
|
||||||
cls_to_class.insert(
|
entity_ctx.cls_to_class.insert(
|
||||||
cls_id as u32,
|
cls_id as u32,
|
||||||
Class {
|
Class {
|
||||||
name: network_name.to_owned(),
|
name: network_name.to_owned(),
|
||||||
@@ -203,6 +217,7 @@ where
|
|||||||
info,
|
info,
|
||||||
events,
|
events,
|
||||||
player_info,
|
player_info,
|
||||||
|
entity_states,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,11 +226,12 @@ fn parse_fullpacket(
|
|||||||
events: &mut Vec<DemoEvent>,
|
events: &mut Vec<DemoEvent>,
|
||||||
event_mapper: &mut GameEventMapping,
|
event_mapper: &mut GameEventMapping,
|
||||||
player_info: &mut std::collections::HashMap<UserId, Player>,
|
player_info: &mut std::collections::HashMap<UserId, Player>,
|
||||||
entities: &mut std::collections::HashMap<i32, Entity>,
|
entity_ctx: &mut entities::EntityContext,
|
||||||
cls_to_class: &mut std::collections::HashMap<u32, Class>,
|
|
||||||
paths: &mut Paths,
|
paths: &mut Paths,
|
||||||
qf_mapper: &mut decoder::QfMapper,
|
qf_mapper: &mut decoder::QfMapper,
|
||||||
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
||||||
|
prop_controller: &propcontroller::PropController,
|
||||||
|
entity_states: &mut Vec<entities::EntityState>
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let raw: crate::csgo_proto::CDemoFullPacket = prost::Message::decode(data)?;
|
let raw: crate::csgo_proto::CDemoFullPacket = prost::Message::decode(data)?;
|
||||||
|
|
||||||
@@ -232,11 +248,12 @@ fn parse_fullpacket(
|
|||||||
events,
|
events,
|
||||||
event_mapper,
|
event_mapper,
|
||||||
player_info,
|
player_info,
|
||||||
entities,
|
entity_ctx,
|
||||||
cls_to_class,
|
|
||||||
paths,
|
paths,
|
||||||
qf_mapper,
|
qf_mapper,
|
||||||
baselines,
|
baselines,
|
||||||
|
prop_controller,
|
||||||
|
entity_states
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -250,11 +267,12 @@ fn parse_packet(
|
|||||||
events: &mut Vec<DemoEvent>,
|
events: &mut Vec<DemoEvent>,
|
||||||
event_mapper: &mut GameEventMapping,
|
event_mapper: &mut GameEventMapping,
|
||||||
player_info: &mut std::collections::HashMap<UserId, Player>,
|
player_info: &mut std::collections::HashMap<UserId, Player>,
|
||||||
entities: &mut std::collections::HashMap<i32, Entity>,
|
entity_ctx: &mut entities::EntityContext,
|
||||||
cls_to_class: &mut std::collections::HashMap<u32, Class>,
|
|
||||||
paths: &mut Paths,
|
paths: &mut Paths,
|
||||||
qf_mapper: &mut decoder::QfMapper,
|
qf_mapper: &mut decoder::QfMapper,
|
||||||
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
||||||
|
prop_controller: &propcontroller::PropController,
|
||||||
|
entity_states: &mut Vec<entities::EntityState>
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let raw: crate::csgo_proto::CDemoPacket = prost::Message::decode(data)?;
|
let raw: crate::csgo_proto::CDemoPacket = prost::Message::decode(data)?;
|
||||||
|
|
||||||
@@ -263,11 +281,12 @@ fn parse_packet(
|
|||||||
events,
|
events,
|
||||||
event_mapper,
|
event_mapper,
|
||||||
player_info,
|
player_info,
|
||||||
entities,
|
entity_ctx,
|
||||||
cls_to_class,
|
|
||||||
paths,
|
paths,
|
||||||
qf_mapper,
|
qf_mapper,
|
||||||
baselines,
|
baselines,
|
||||||
|
prop_controller,
|
||||||
|
entity_states
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -278,11 +297,12 @@ fn inner_parse_packet(
|
|||||||
events: &mut Vec<DemoEvent>,
|
events: &mut Vec<DemoEvent>,
|
||||||
event_mapper: &mut GameEventMapping,
|
event_mapper: &mut GameEventMapping,
|
||||||
player_info: &mut std::collections::HashMap<UserId, Player>,
|
player_info: &mut std::collections::HashMap<UserId, Player>,
|
||||||
entities: &mut std::collections::HashMap<i32, Entity>,
|
entity_ctx: &mut entities::EntityContext,
|
||||||
cls_to_class: &mut std::collections::HashMap<u32, Class>,
|
|
||||||
paths: &mut Paths,
|
paths: &mut Paths,
|
||||||
qf_mapper: &mut decoder::QfMapper,
|
qf_mapper: &mut decoder::QfMapper,
|
||||||
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
||||||
|
prop_controller: &propcontroller::PropController,
|
||||||
|
entity_states: &mut Vec<entities::EntityState>
|
||||||
) -> Result<(), FirstPassError> {
|
) -> Result<(), FirstPassError> {
|
||||||
let mut bitreader = crate::bitreader::Bitreader::new(raw.data());
|
let mut bitreader = crate::bitreader::Bitreader::new(raw.data());
|
||||||
|
|
||||||
@@ -347,34 +367,32 @@ fn inner_parse_packet(
|
|||||||
|
|
||||||
match bitreader.read_nbits(2)? {
|
match bitreader.read_nbits(2)? {
|
||||||
0b01 | 0b11 => {
|
0b01 | 0b11 => {
|
||||||
entities.remove(&entity_id);
|
entity_ctx.entities.remove(&entity_id);
|
||||||
}
|
}
|
||||||
0b10 => {
|
0b10 => {
|
||||||
let (id, entity) = create_entity(entity_id, &mut bitreader, baselines)?;
|
let cls = entity_ctx.create_entity(entity_id, &mut bitreader)?;
|
||||||
let cls = entity.cls;
|
|
||||||
|
|
||||||
entities.insert(entity_id, entity);
|
|
||||||
if let Some(baseline_bytes) = baselines.get(&cls) {
|
if let Some(baseline_bytes) = baselines.get(&cls) {
|
||||||
let mut br = crate::bitreader::Bitreader::new(&baseline_bytes);
|
let mut br = crate::bitreader::Bitreader::new(&baseline_bytes);
|
||||||
update_entity(
|
let state = update_entity(
|
||||||
entity_id,
|
entity_id,
|
||||||
&mut br,
|
&mut br,
|
||||||
entities,
|
entity_ctx,
|
||||||
cls_to_class,
|
|
||||||
paths,
|
paths,
|
||||||
qf_mapper,
|
qf_mapper,
|
||||||
|
prop_controller,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let state = update_entity(
|
||||||
update_entity(
|
|
||||||
entity_id,
|
entity_id,
|
||||||
&mut bitreader,
|
&mut bitreader,
|
||||||
entities,
|
entity_ctx,
|
||||||
cls_to_class,
|
|
||||||
paths,
|
paths,
|
||||||
qf_mapper,
|
qf_mapper,
|
||||||
|
prop_controller,
|
||||||
)?;
|
)?;
|
||||||
|
entity_states.push(state);
|
||||||
}
|
}
|
||||||
0b00 => {
|
0b00 => {
|
||||||
if raw.has_pvs_vis_bits() > 0 {
|
if raw.has_pvs_vis_bits() > 0 {
|
||||||
@@ -383,22 +401,21 @@ fn inner_parse_packet(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
update_entity(
|
let state = update_entity(
|
||||||
entity_id,
|
entity_id,
|
||||||
&mut bitreader,
|
&mut bitreader,
|
||||||
entities,
|
entity_ctx,
|
||||||
cls_to_class,
|
|
||||||
paths,
|
paths,
|
||||||
qf_mapper,
|
qf_mapper,
|
||||||
|
prop_controller,
|
||||||
)?;
|
)?;
|
||||||
|
entity_states.push(state);
|
||||||
}
|
}
|
||||||
unknown => {
|
unknown => {
|
||||||
panic!("{:?}", unknown);
|
panic!("{:?}", unknown);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// dbg!("PacketEntities");
|
|
||||||
}
|
}
|
||||||
crate::netmessagetypes::NetmessageType::svc_UserCmds => {}
|
crate::netmessagetypes::NetmessageType::svc_UserCmds => {}
|
||||||
crate::netmessagetypes::NetmessageType::GE_SosStartSoundEvent => {}
|
crate::netmessagetypes::NetmessageType::GE_SosStartSoundEvent => {}
|
||||||
@@ -482,84 +499,30 @@ fn inner_parse_packet(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_entity(
|
|
||||||
entity_id: i32,
|
|
||||||
bitreader: &mut crate::bitreader::Bitreader,
|
|
||||||
baselines: &mut std::collections::HashMap<u32, Vec<u8>>,
|
|
||||||
) -> Result<(i32, Entity), FirstPassError> {
|
|
||||||
let cls_id: u32 = bitreader.read_nbits(8)?;
|
|
||||||
let _serial = bitreader.read_nbits(17)?;
|
|
||||||
let _unknown = bitreader.read_varint()?;
|
|
||||||
|
|
||||||
Ok((entity_id, Entity { cls: cls_id }))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_entity(
|
fn update_entity(
|
||||||
entity_id: i32,
|
entity_id: i32,
|
||||||
bitreader: &mut crate::bitreader::Bitreader,
|
bitreader: &mut crate::bitreader::Bitreader,
|
||||||
entities: &mut std::collections::HashMap<i32, Entity>,
|
entity_ctx: &mut entities::EntityContext,
|
||||||
cls_to_class: &mut std::collections::HashMap<u32, Class>,
|
|
||||||
paths: &mut Paths,
|
paths: &mut Paths,
|
||||||
qf_mapper: &mut decoder::QfMapper,
|
qf_mapper: &mut decoder::QfMapper,
|
||||||
) -> Result<(), FirstPassError> {
|
prop_controller: &propcontroller::PropController,
|
||||||
|
) -> Result<entities::EntityState, FirstPassError> {
|
||||||
let n_updates = fieldpath::parse_paths(bitreader, paths)?;
|
let n_updates = fieldpath::parse_paths(bitreader, paths)?;
|
||||||
let n_updated_values = decode_entity_update(
|
let (n_updated_values, entity_state) = entity_ctx.decode_entity_update(
|
||||||
entity_id,
|
entity_id,
|
||||||
bitreader,
|
bitreader,
|
||||||
n_updates,
|
n_updates,
|
||||||
entities,
|
|
||||||
cls_to_class,
|
|
||||||
paths,
|
paths,
|
||||||
qf_mapper,
|
qf_mapper,
|
||||||
|
prop_controller,
|
||||||
)?;
|
)?;
|
||||||
if n_updated_values > 0 {
|
if n_updated_values > 0 {
|
||||||
gather_extra_info()?;
|
// TODO
|
||||||
|
// Gather extra information
|
||||||
|
// gather_extra_info(entity_id, prop_controller)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(entity_state)
|
||||||
}
|
|
||||||
|
|
||||||
fn gather_extra_info() -> Result<(), FirstPassError> {
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn decode_entity_update(
|
|
||||||
entity_id: i32,
|
|
||||||
bitreader: &mut crate::bitreader::Bitreader,
|
|
||||||
n_updates: usize,
|
|
||||||
entities: &mut std::collections::HashMap<i32, Entity>,
|
|
||||||
cls_to_class: &mut std::collections::HashMap<u32, Class>,
|
|
||||||
paths: &mut Paths,
|
|
||||||
qf_mapper: &mut decoder::QfMapper,
|
|
||||||
) -> Result<usize, FirstPassError> {
|
|
||||||
let entity = match entities.get_mut(&entity_id) {
|
|
||||||
Some(e) => e,
|
|
||||||
None => panic!("ID: {:?} - Entities: {:?}", entity_id, entities),
|
|
||||||
};
|
|
||||||
let class = match cls_to_class.get_mut(&entity.cls) {
|
|
||||||
Some(c) => c,
|
|
||||||
None => panic!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// dbg!(&class.name);
|
|
||||||
for path in paths.paths().take(n_updates) {
|
|
||||||
// dbg!(&path);
|
|
||||||
|
|
||||||
let field = path.find(&class.serializer)?;
|
|
||||||
let field_info = field.get_propinfo(path);
|
|
||||||
let decoder = field.get_decoder()?;
|
|
||||||
let result = decoder.decode(bitreader, qf_mapper)?;
|
|
||||||
|
|
||||||
// dbg!(&field, &field_info, &decoder, &result);
|
|
||||||
|
|
||||||
if let Some(fi) = field_info {
|
|
||||||
// dbg!(&fi);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(n_updates)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HUFFMAN_LOOKUP_TABLE: std::sync::LazyLock<Vec<(u8, u8)>> = std::sync::LazyLock::new(|| {
|
static HUFFMAN_LOOKUP_TABLE: std::sync::LazyLock<Vec<(u8, u8)>> = std::sync::LazyLock::new(|| {
|
||||||
@@ -570,54 +533,3 @@ static HUFFMAN_LOOKUP_TABLE: std::sync::LazyLock<Vec<(u8, u8)>> = std::sync::Laz
|
|||||||
}
|
}
|
||||||
huf2
|
huf2
|
||||||
});
|
});
|
||||||
|
|
||||||
fn do_op(
|
|
||||||
symbol: u8,
|
|
||||||
bitreader: &mut crate::bitreader::Bitreader,
|
|
||||||
field_path: &mut FieldPath,
|
|
||||||
) -> Result<(), FirstPassError> {
|
|
||||||
use fieldpath::ops::*;
|
|
||||||
|
|
||||||
match symbol {
|
|
||||||
0 => plus_one(bitreader, field_path),
|
|
||||||
1 => plus_two(bitreader, field_path),
|
|
||||||
2 => plus_three(bitreader, field_path),
|
|
||||||
3 => plus_four(bitreader, field_path),
|
|
||||||
4 => plus_n(bitreader, field_path),
|
|
||||||
5 => push_one_left_delta_zero_right_zero(bitreader, field_path),
|
|
||||||
6 => push_one_left_delta_zero_right_non_zero(bitreader, field_path),
|
|
||||||
7 => push_one_left_delta_one_right_zero(bitreader, field_path),
|
|
||||||
8 => push_one_left_delta_one_right_non_zero(bitreader, field_path),
|
|
||||||
9 => push_one_left_delta_n_right_zero(bitreader, field_path),
|
|
||||||
10 => push_one_left_delta_n_right_non_zero(bitreader, field_path),
|
|
||||||
11 => push_one_left_delta_n_right_non_zero_pack6_bits(bitreader, field_path),
|
|
||||||
12 => push_one_left_delta_n_right_non_zero_pack8_bits(bitreader, field_path),
|
|
||||||
13 => push_two_left_delta_zero(bitreader, field_path),
|
|
||||||
14 => push_two_pack5_left_delta_zero(bitreader, field_path),
|
|
||||||
15 => push_three_left_delta_zero(bitreader, field_path),
|
|
||||||
16 => push_three_pack5_left_delta_zero(bitreader, field_path),
|
|
||||||
17 => push_two_left_delta_one(bitreader, field_path),
|
|
||||||
18 => push_two_pack5_left_delta_one(bitreader, field_path),
|
|
||||||
19 => push_three_left_delta_one(bitreader, field_path),
|
|
||||||
20 => push_three_pack5_left_delta_one(bitreader, field_path),
|
|
||||||
21 => push_two_left_delta_n(bitreader, field_path),
|
|
||||||
22 => push_two_pack5_left_delta_n(bitreader, field_path),
|
|
||||||
23 => push_three_left_delta_n(bitreader, field_path),
|
|
||||||
24 => push_three_pack5_left_delta_n(bitreader, field_path),
|
|
||||||
25 => push_n(bitreader, field_path),
|
|
||||||
26 => push_n_and_non_topological(bitreader, field_path),
|
|
||||||
27 => pop_one_plus_one(bitreader, field_path),
|
|
||||||
28 => pop_one_plus_n(bitreader, field_path),
|
|
||||||
29 => pop_all_but_one_plus_one(bitreader, field_path),
|
|
||||||
30 => pop_all_but_one_plus_n(bitreader, field_path),
|
|
||||||
31 => pop_all_but_one_plus_n_pack3_bits(bitreader, field_path),
|
|
||||||
32 => pop_all_but_one_plus_n_pack6_bits(bitreader, field_path),
|
|
||||||
33 => pop_n_plus_one(bitreader, field_path),
|
|
||||||
34 => pop_n_plus_n(bitreader, field_path),
|
|
||||||
35 => pop_n_and_non_topographical(bitreader, field_path),
|
|
||||||
36 => non_topo_complex(bitreader, field_path),
|
|
||||||
37 => non_topo_penultimate_plus_one(bitreader, field_path),
|
|
||||||
38 => non_topo_complex_pack4_bits(bitreader, field_path),
|
|
||||||
other => todo!("Other OP: {:?}", other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
82
src/parser/entities.rs
Normal file
82
src/parser/entities.rs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
use super::{decoder, propcontroller, Class, Entity, FirstPassError, Paths};
|
||||||
|
|
||||||
|
pub struct EntityContext {
|
||||||
|
pub entities: std::collections::HashMap<i32, Entity>,
|
||||||
|
pub cls_to_class: std::collections::HashMap<u32, Class>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EntityState {
|
||||||
|
pub class: String,
|
||||||
|
pub cls: u32,
|
||||||
|
pub props: Vec<EntityProp>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EntityProp {
|
||||||
|
pub field_info: super::sendtables::FieldInfo,
|
||||||
|
pub prop_info: super::propcontroller::PropInfo,
|
||||||
|
pub value: super::variant::Variant,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntityContext {
|
||||||
|
/// Returns the `cls_id`
|
||||||
|
pub fn create_entity(&mut self, entity_id: i32, bitreader: &mut crate::bitreader::Bitreader) -> Result<u32, super::FirstPassError> {
|
||||||
|
let cls_id: u32 = bitreader.read_nbits(8)?;
|
||||||
|
let _serial = bitreader.read_nbits(17)?;
|
||||||
|
let _unknown = bitreader.read_varint()?;
|
||||||
|
|
||||||
|
self.entities.insert(entity_id, Entity {
|
||||||
|
cls: cls_id,
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(cls_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_entity_update(
|
||||||
|
&mut self,
|
||||||
|
entity_id: i32,
|
||||||
|
bitreader: &mut crate::bitreader::Bitreader,
|
||||||
|
n_updates: usize,
|
||||||
|
paths: &mut Paths,
|
||||||
|
qf_mapper: &mut decoder::QfMapper,
|
||||||
|
prop_controller: &propcontroller::PropController,
|
||||||
|
) -> Result<(usize, EntityState), FirstPassError> {
|
||||||
|
let entity = match self.entities.get_mut(&entity_id) {
|
||||||
|
Some(e) => e,
|
||||||
|
None => panic!("ID: {:?} - Entities: {:?}", entity_id, self.entities),
|
||||||
|
};
|
||||||
|
let class = match self.cls_to_class.get_mut(&entity.cls) {
|
||||||
|
Some(c) => c,
|
||||||
|
None => panic!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut fields = Vec::new();
|
||||||
|
for path in paths.paths().take(n_updates) {
|
||||||
|
let field = path.find(&class.serializer)?;
|
||||||
|
let field_info = field.get_propinfo(path);
|
||||||
|
let decoder = field.get_decoder()?;
|
||||||
|
let result = decoder.decode(bitreader, qf_mapper)?;
|
||||||
|
|
||||||
|
if let Some(fi) = field_info {
|
||||||
|
if let Some(prop_info) = prop_controller
|
||||||
|
.prop_infos
|
||||||
|
.iter()
|
||||||
|
.find(|pi| fi.prop_id == pi.id)
|
||||||
|
{
|
||||||
|
fields.push(EntityProp {
|
||||||
|
field_info: fi,
|
||||||
|
prop_info: prop_info.clone(),
|
||||||
|
value: result,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok((n_updates, EntityState {
|
||||||
|
class: class.name.clone(),
|
||||||
|
cls: entity.cls,
|
||||||
|
props: fields,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ pub fn parse_paths(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
super::do_op(symbol, bitreader, &mut path)?;
|
path.do_op(bitreader, symbol)?;
|
||||||
paths.write(&path, idx);
|
paths.write(&path, idx);
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
@@ -92,320 +92,483 @@ impl FieldPath {
|
|||||||
match self.last {
|
match self.last {
|
||||||
0 => Ok(f),
|
0 => Ok(f),
|
||||||
1 => Ok(f.get_inner(self.path[1] as usize)?),
|
1 => Ok(f.get_inner(self.path[1] as usize)?),
|
||||||
2 => Ok(f.get_inner(self.path[1] as usize)?.get_inner(self.path[2] as usize)?),
|
2 => Ok(f
|
||||||
3 => Ok(f.get_inner(self.path[1] as usize)?.get_inner(self.path[2] as usize)?.get_inner(self.path[3] as usize)?),
|
.get_inner(self.path[1] as usize)?
|
||||||
|
.get_inner(self.path[2] as usize)?),
|
||||||
|
3 => Ok(f
|
||||||
|
.get_inner(self.path[1] as usize)?
|
||||||
|
.get_inner(self.path[2] as usize)?
|
||||||
|
.get_inner(self.path[3] as usize)?),
|
||||||
other => panic!("{:?}", other),
|
other => panic!("{:?}", other),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn do_op(&mut self, bitreader: &mut crate::bitreader::Bitreader, symbol: u8) -> Result<(), super::FirstPassError> {
|
||||||
|
use ops::*;
|
||||||
|
|
||||||
|
match symbol {
|
||||||
|
0 => plus_one(bitreader, self),
|
||||||
|
1 => plus_two(bitreader, self),
|
||||||
|
2 => plus_three(bitreader, self),
|
||||||
|
3 => plus_four(bitreader, self),
|
||||||
|
4 => plus_n(bitreader, self),
|
||||||
|
5 => push_one_left_delta_zero_right_zero(bitreader, self),
|
||||||
|
6 => push_one_left_delta_zero_right_non_zero(bitreader, self),
|
||||||
|
7 => push_one_left_delta_one_right_zero(bitreader, self),
|
||||||
|
8 => push_one_left_delta_one_right_non_zero(bitreader, self),
|
||||||
|
9 => push_one_left_delta_n_right_zero(bitreader, self),
|
||||||
|
10 => push_one_left_delta_n_right_non_zero(bitreader, self),
|
||||||
|
11 => push_one_left_delta_n_right_non_zero_pack6_bits(bitreader, self),
|
||||||
|
12 => push_one_left_delta_n_right_non_zero_pack8_bits(bitreader, self),
|
||||||
|
13 => push_two_left_delta_zero(bitreader, self),
|
||||||
|
14 => push_two_pack5_left_delta_zero(bitreader, self),
|
||||||
|
15 => push_three_left_delta_zero(bitreader, self),
|
||||||
|
16 => push_three_pack5_left_delta_zero(bitreader, self),
|
||||||
|
17 => push_two_left_delta_one(bitreader, self),
|
||||||
|
18 => push_two_pack5_left_delta_one(bitreader, self),
|
||||||
|
19 => push_three_left_delta_one(bitreader, self),
|
||||||
|
20 => push_three_pack5_left_delta_one(bitreader, self),
|
||||||
|
21 => push_two_left_delta_n(bitreader, self),
|
||||||
|
22 => push_two_pack5_left_delta_n(bitreader, self),
|
||||||
|
23 => push_three_left_delta_n(bitreader, self),
|
||||||
|
24 => push_three_pack5_left_delta_n(bitreader, self),
|
||||||
|
25 => push_n(bitreader, self),
|
||||||
|
26 => push_n_and_non_topological(bitreader, self),
|
||||||
|
27 => pop_one_plus_one(bitreader, self),
|
||||||
|
28 => pop_one_plus_n(bitreader, self),
|
||||||
|
29 => pop_all_but_one_plus_one(bitreader, self),
|
||||||
|
30 => pop_all_but_one_plus_n(bitreader, self),
|
||||||
|
31 => pop_all_but_one_plus_n_pack3_bits(bitreader, self),
|
||||||
|
32 => pop_all_but_one_plus_n_pack6_bits(bitreader, self),
|
||||||
|
33 => pop_n_plus_one(bitreader, self),
|
||||||
|
34 => pop_n_plus_n(bitreader, self),
|
||||||
|
35 => pop_n_and_non_topographical(bitreader, self),
|
||||||
|
36 => non_topo_complex(bitreader, self),
|
||||||
|
37 => non_topo_penultimate_plus_one(bitreader, self),
|
||||||
|
38 => non_topo_complex_pack4_bits(bitreader, self),
|
||||||
|
other => todo!("Other OP: {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod ops {
|
pub mod ops {
|
||||||
use super::FieldPath;
|
use super::FieldPath;
|
||||||
use crate::{bitreader::Bitreader, parser::FirstPassError};
|
use crate::{bitreader::Bitreader, parser::FirstPassError};
|
||||||
|
|
||||||
pub fn plus_one(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn plus_one(
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
_bitreader: &mut Bitreader,
|
||||||
Ok(())
|
field_path: &mut FieldPath,
|
||||||
}
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn plus_two(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn plus_two(
|
||||||
*field_path.get_entry_mut(field_path.last)? += 2;
|
_bitreader: &mut Bitreader,
|
||||||
Ok(())
|
field_path: &mut FieldPath,
|
||||||
}
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 2;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn plus_three(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn plus_three(
|
||||||
*field_path.get_entry_mut(field_path.last)? += 3;
|
_bitreader: &mut Bitreader,
|
||||||
Ok(())
|
field_path: &mut FieldPath,
|
||||||
}
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 3;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn plus_four(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn plus_four(
|
||||||
*field_path.get_entry_mut(field_path.last)? += 4;
|
_bitreader: &mut Bitreader,
|
||||||
Ok(())
|
field_path: &mut FieldPath,
|
||||||
}
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 4;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn plus_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn plus_n(
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32 + 5;
|
bitreader: &mut Bitreader,
|
||||||
Ok(())
|
field_path: &mut FieldPath,
|
||||||
}
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32 + 5;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_one_left_delta_zero_right_zero(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_zero_right_zero(
|
||||||
field_path.last += 1;
|
_bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(field_path.last)? = 0;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = 0;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn push_one_left_delta_zero_right_non_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_zero_right_non_zero(
|
||||||
field_path.last += 1;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_one_left_delta_one_right_zero(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = 0;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_one_left_delta_one_right_non_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_one_left_delta_n_right_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = 0;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_one_left_delta_n_right_non_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32 + 2;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_ubit_var_fp()? as i32 + 1;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_one_left_delta_n_right_non_zero_pack6_bits(
|
|
||||||
bitreader: &mut Bitreader,
|
|
||||||
field_path: &mut FieldPath,
|
|
||||||
) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_nbits(3)? + 2) as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = (bitreader.read_nbits(3)? + 1) as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_one_left_delta_n_right_non_zero_pack8_bits(
|
|
||||||
bitreader: &mut Bitreader,
|
|
||||||
field_path: &mut FieldPath,
|
|
||||||
) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_nbits(4)? + 2) as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = (bitreader.read_nbits(4)? + 1) as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_two_left_delta_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_two_pack5_left_delta_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_three_left_delta_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_three_pack5_left_delta_zero(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_two_left_delta_one(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_two_pack5_left_delta_one(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_three_left_delta_one(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_three_pack5_left_delta_one(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_two_left_delta_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_two_pack5_left_delta_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_three_left_delta_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_three_pack5_left_delta_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
field_path.last += 1;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
let n = bitreader.read_u_bit_var()? as i32;
|
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_u_bit_var()? as i32;
|
|
||||||
for _ in 0..n {
|
|
||||||
field_path.last += 1;
|
field_path.last += 1;
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push_n_and_non_topological(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_one_right_zero(
|
||||||
for i in 0..field_path.last + 1 {
|
_bitreader: &mut Bitreader,
|
||||||
if bitreader.read_boolean()? {
|
field_path: &mut FieldPath,
|
||||||
*field_path.get_entry_mut(i)? += bitreader.read_varint32()? + 1;
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = 0;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
let count = bitreader.read_u_bit_var()?;
|
|
||||||
for _ in 0..count {
|
pub fn push_one_left_delta_one_right_non_zero(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
field_path.last += 1;
|
field_path.last += 1;
|
||||||
*field_path.get_entry_mut(field_path.last)? = bitreader.read_ubit_var_fp()? as i32;
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop_one_plus_one(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_n_right_zero(
|
||||||
field_path.pop_special(1)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = 0;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_one_plus_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_n_right_non_zero(
|
||||||
field_path.pop_special(1)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32 + 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32 + 2;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_ubit_var_fp()? as i32 + 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_all_but_one_plus_one(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_n_right_non_zero_pack6_bits(
|
||||||
field_path.pop_special(field_path.last)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(0)? += 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_nbits(3)? + 2) as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = (bitreader.read_nbits(3)? + 1) as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_all_but_one_plus_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_one_left_delta_n_right_non_zero_pack8_bits(
|
||||||
field_path.pop_special(field_path.last)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(0)? += bitreader.read_ubit_var_fp()? as i32 + 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_nbits(4)? + 2) as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = (bitreader.read_nbits(4)? + 1) as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_all_but_one_plus_n_pack3_bits(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_two_left_delta_zero(
|
||||||
field_path.pop_special(field_path.last)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(0)? += bitreader.read_nbits(3)? as i32 + 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_all_but_one_plus_n_pack6_bits(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_two_pack5_left_delta_zero(
|
||||||
field_path.pop_special(field_path.last)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(0)? += bitreader.read_nbits(6)? as i32 + 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_n_plus_one(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_three_left_delta_zero(
|
||||||
field_path.pop_special(bitreader.read_ubit_var_fp()? as usize)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(field_path.last)? += 1;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_n_plus_n(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_three_pack5_left_delta_zero(
|
||||||
field_path.pop_special(bitreader.read_ubit_var_fp()? as usize)?;
|
bitreader: &mut Bitreader,
|
||||||
*field_path.get_entry_mut(field_path.last)? += bitreader.read_varint32()?;
|
field_path: &mut FieldPath,
|
||||||
Ok(())
|
) -> Result<(), FirstPassError> {
|
||||||
}
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_nbits(5)? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop_n_and_non_topographical(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_two_left_delta_one(
|
||||||
field_path.pop_special(bitreader.read_ubit_var_fp()? as usize)?;
|
bitreader: &mut Bitreader,
|
||||||
for i in 0..field_path.last + 1 {
|
field_path: &mut FieldPath,
|
||||||
if bitreader.read_boolean()? {
|
) -> Result<(), FirstPassError> {
|
||||||
*field_path.get_entry_mut(i)? += bitreader.read_varint32()?;
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_two_pack5_left_delta_one(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_three_left_delta_one(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_three_pack5_left_delta_one(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_two_left_delta_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_two_pack5_left_delta_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_three_left_delta_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_three_pack5_left_delta_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += (bitreader.read_u_bit_var()? + 2) as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_nbits(5)? as i32;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
let n = bitreader.read_u_bit_var()? as i32;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_u_bit_var()? as i32;
|
||||||
|
for _ in 0..n {
|
||||||
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32;
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn non_topo_complex(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
pub fn push_n_and_non_topological(
|
||||||
for i in 0..field_path.last + 1 {
|
bitreader: &mut Bitreader,
|
||||||
if bitreader.read_boolean()? {
|
field_path: &mut FieldPath,
|
||||||
*field_path.get_entry_mut(i)? += bitreader.read_varint32()?;
|
) -> Result<(), FirstPassError> {
|
||||||
|
for i in 0..field_path.last + 1 {
|
||||||
|
if bitreader.read_boolean()? {
|
||||||
|
*field_path.get_entry_mut(i)? += bitreader.read_varint32()? + 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
let count = bitreader.read_u_bit_var()?;
|
||||||
Ok(())
|
for _ in 0..count {
|
||||||
}
|
field_path.last += 1;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? = bitreader.read_ubit_var_fp()? as i32;
|
||||||
pub fn non_topo_penultimate_plus_one(_bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
*field_path.get_entry_mut(field_path.last - 1)? += 1;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn non_topo_complex_pack4_bits(bitreader: &mut Bitreader, field_path: &mut FieldPath) -> Result<(), FirstPassError> {
|
|
||||||
for i in 0..field_path.last + 1 {
|
|
||||||
if bitreader.read_boolean()? {
|
|
||||||
*field_path.get_entry_mut(i)? += bitreader.read_nbits(4)? as i32 - 7;
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_one_plus_one(
|
||||||
|
_bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(1)?;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_one_plus_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(1)?;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_ubit_var_fp()? as i32 + 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_all_but_one_plus_one(
|
||||||
|
_bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(field_path.last)?;
|
||||||
|
*field_path.get_entry_mut(0)? += 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_all_but_one_plus_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(field_path.last)?;
|
||||||
|
*field_path.get_entry_mut(0)? += bitreader.read_ubit_var_fp()? as i32 + 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_all_but_one_plus_n_pack3_bits(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(field_path.last)?;
|
||||||
|
*field_path.get_entry_mut(0)? += bitreader.read_nbits(3)? as i32 + 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_all_but_one_plus_n_pack6_bits(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(field_path.last)?;
|
||||||
|
*field_path.get_entry_mut(0)? += bitreader.read_nbits(6)? as i32 + 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_n_plus_one(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(bitreader.read_ubit_var_fp()? as usize)?;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_n_plus_n(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(bitreader.read_ubit_var_fp()? as usize)?;
|
||||||
|
*field_path.get_entry_mut(field_path.last)? += bitreader.read_varint32()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pop_n_and_non_topographical(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
field_path.pop_special(bitreader.read_ubit_var_fp()? as usize)?;
|
||||||
|
for i in 0..field_path.last + 1 {
|
||||||
|
if bitreader.read_boolean()? {
|
||||||
|
*field_path.get_entry_mut(i)? += bitreader.read_varint32()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn non_topo_complex(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
for i in 0..field_path.last + 1 {
|
||||||
|
if bitreader.read_boolean()? {
|
||||||
|
*field_path.get_entry_mut(i)? += bitreader.read_varint32()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn non_topo_penultimate_plus_one(
|
||||||
|
_bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
*field_path.get_entry_mut(field_path.last - 1)? += 1;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn non_topo_complex_pack4_bits(
|
||||||
|
bitreader: &mut Bitreader,
|
||||||
|
field_path: &mut FieldPath,
|
||||||
|
) -> Result<(), FirstPassError> {
|
||||||
|
for i in 0..field_path.last + 1 {
|
||||||
|
if bitreader.read_boolean()? {
|
||||||
|
*field_path.get_entry_mut(i)? += bitreader.read_nbits(4)? as i32 - 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
298
src/parser/propcontroller.rs
Normal file
298
src/parser/propcontroller.rs
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
pub const PLAYER_ENTITY_HANDLE_MISSING: i32 = 2047;
|
||||||
|
pub const SPECTATOR_TEAM_NUM: u32 = 1;
|
||||||
|
pub const BUTTONS_BASEID: u32 = 100000;
|
||||||
|
pub const NORMAL_PROP_BASEID: u32 = 1000;
|
||||||
|
pub const WEAPON_SKIN_NAME: u32 = 420420420;
|
||||||
|
pub const WEAPON_ORIGINGAL_OWNER_ID: u32 = 6942000;
|
||||||
|
pub const MY_WEAPONS_OFFSET: u32 = 500000;
|
||||||
|
pub const GRENADE_AMMO_ID: u32 = 1111111;
|
||||||
|
pub const INVENTORY_ID: u32 = 100000000;
|
||||||
|
pub const IS_ALIVE_ID: u32 = 100000001;
|
||||||
|
pub const GAME_TIME_ID: u32 = 100000002;
|
||||||
|
pub const ENTITY_ID_ID: u32 = 100000003;
|
||||||
|
pub const VELOCITY_X_ID: u32 = 100000004;
|
||||||
|
pub const VELOCITY_Y_ID: u32 = 100000005;
|
||||||
|
pub const VELOCITY_Z_ID: u32 = 100000006;
|
||||||
|
pub const VELOCITY_ID: u32 = 100000007;
|
||||||
|
pub const USERID_ID: u32 = 100000008;
|
||||||
|
pub const AGENT_SKIN_ID: u32 = 100000009;
|
||||||
|
pub const WEAPON_NAME_ID: u32 = 100000010;
|
||||||
|
pub const YAW_ID: u32 = 100000111;
|
||||||
|
pub const PITCH_ID: u32 = 100000012;
|
||||||
|
pub const TICK_ID: u32 = 100000013;
|
||||||
|
pub const STEAMID_ID: u32 = 100000014;
|
||||||
|
pub const NAME_ID: u32 = 100000015;
|
||||||
|
pub const PLAYER_X_ID: u32 = 100000016;
|
||||||
|
pub const PLAYER_Y_ID: u32 = 100000017;
|
||||||
|
pub const PLAYER_Z_ID: u32 = 100000018;
|
||||||
|
pub const WEAPON_STICKERS_ID: u32 = 100000019;
|
||||||
|
pub const INVENTORY_AS_IDS_ID: u32 = 100000020;
|
||||||
|
pub const IS_AIRBORNE_ID: u32 = 100000021;
|
||||||
|
|
||||||
|
pub const WEAPON_SKIN_ID: u32 = 10000000;
|
||||||
|
pub const WEAPON_PAINT_SEED: u32 = 10000001;
|
||||||
|
pub const WEAPON_FLOAT: u32 = 10000002;
|
||||||
|
pub const ITEM_PURCHASE_COUNT: u32 = 200000000;
|
||||||
|
pub const ITEM_PURCHASE_DEF_IDX: u32 = 300000000;
|
||||||
|
pub const ITEM_PURCHASE_COST: u32 = 400000000;
|
||||||
|
pub const ITEM_PURCHASE_HANDLE: u32 = 500000000;
|
||||||
|
pub const ITEM_PURCHASE_NEW_DEF_IDX: u32 = 600000000;
|
||||||
|
pub const FLATTENED_VEC_MAX_LEN: u32 = 100000;
|
||||||
|
|
||||||
|
pub const USERCMD_VIEWANGLE_X: u32 = 100000022;
|
||||||
|
pub const USERCMD_VIEWANGLE_Y: u32 = 100000023;
|
||||||
|
pub const USERCMD_VIEWANGLE_Z: u32 = 100000024;
|
||||||
|
pub const USERCMD_FORWARDMOVE: u32 = 100000025;
|
||||||
|
pub const USERCMD_IMPULSE: u32 = 100000026;
|
||||||
|
pub const USERCMD_MOUSE_DX: u32 = 100000027;
|
||||||
|
pub const USERCMD_MOUSE_DY: u32 = 100000028;
|
||||||
|
pub const USERCMD_BUTTONSTATE_1: u32 = 100000029;
|
||||||
|
pub const USERCMD_BUTTONSTATE_2: u32 = 100000030;
|
||||||
|
pub const USERCMD_BUTTONSTATE_3: u32 = 100000031;
|
||||||
|
pub const USERCMD_CONSUMED_SERVER_ANGLE_CHANGES: u32 = 100000032;
|
||||||
|
pub const USERCMD_LEFTMOVE: u32 = 100000033;
|
||||||
|
pub const USERCMD_WEAPON_SELECT: u32 = 100000034;
|
||||||
|
pub const USERCMD_SUBTICK_MOVE_ANALOG_FORWARD_DELTA: u32 = 100000035;
|
||||||
|
pub const USERCMD_SUBTICK_MOVE_ANALOG_LEFT_DELTA: u32 = 100000036;
|
||||||
|
pub const USERCMD_SUBTICK_MOVE_BUTTON: u32 = 100000037;
|
||||||
|
pub const USERCMD_SUBTICK_MOVE_WHEN: u32 = 100000038;
|
||||||
|
pub const USERCMD_SUBTICK_LEFT_HAND_DESIRED: u32 = 100000039;
|
||||||
|
|
||||||
|
pub const USERCMD_ATTACK_START_HISTORY_INDEX_1: u32 = 100000040;
|
||||||
|
pub const USERCMD_ATTACK_START_HISTORY_INDEX_2: u32 = 100000041;
|
||||||
|
pub const USERCMD_ATTACK_START_HISTORY_INDEX_3: u32 = 100000042;
|
||||||
|
|
||||||
|
pub const USERCMD_INPUT_HISTORY_BASEID: u32 = 100001000;
|
||||||
|
pub const INPUT_HISTORY_X_OFFSET: u32 = 0;
|
||||||
|
pub const INPUT_HISTORY_Y_OFFSET: u32 = 1;
|
||||||
|
pub const INPUT_HISTORY_Z_OFFSET: u32 = 2;
|
||||||
|
pub const INPUT_HISTORY_RENDER_TICK_COUNT_OFFSET: u32 = 3;
|
||||||
|
pub const INPUT_HISTORY_RENDER_TICK_FRACTION_OFFSET: u32 = 4;
|
||||||
|
pub const INPUT_HISTORY_PLAYER_TICK_COUNT_OFFSET: u32 = 5;
|
||||||
|
pub const INPUT_HISTORY_PLAYER_TICK_FRACTION_OFFSET: u32 = 6;
|
||||||
|
|
||||||
|
use super::sendtables::{Field, ValueField};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PropController {
|
||||||
|
pub id: u32,
|
||||||
|
pub special_ids: SpecialIDs,
|
||||||
|
pub name_to_id: HashMap<String, u32>,
|
||||||
|
pub id_to_name: HashMap<u32, String>,
|
||||||
|
pub path_to_name: HashMap<[i32; 7], String>,
|
||||||
|
pub prop_infos: Vec<PropInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SpecialIDs {}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct PropInfo {
|
||||||
|
pub id: u32,
|
||||||
|
// pub prop_type: PropType,
|
||||||
|
pub prop_name: String,
|
||||||
|
// pub prop_friendly_name: String,
|
||||||
|
// pub is_player_prop: bool
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PropController {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
id: NORMAL_PROP_BASEID,
|
||||||
|
special_ids: SpecialIDs::new(),
|
||||||
|
name_to_id: HashMap::new(),
|
||||||
|
id_to_name: HashMap::new(),
|
||||||
|
path_to_name: HashMap::new(),
|
||||||
|
prop_infos: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_prop_name_paths(&mut self, serializer: &mut super::sendtables::Serializer) {
|
||||||
|
self.traverse_fields(&mut serializer.fields, serializer.name.clone(), Vec::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn traverse_fields(&mut self, fields: &mut Vec<Field>, ser_name: String, path_og: Vec<i32>) {
|
||||||
|
for (idx, f) in fields.iter_mut().enumerate() {
|
||||||
|
let mut path = path_og.clone();
|
||||||
|
path.push(idx as i32);
|
||||||
|
|
||||||
|
match f {
|
||||||
|
Field::Value(x) => {
|
||||||
|
let full_name = ser_name.clone() + "." + &x.name;
|
||||||
|
self.handle_prop(&full_name, x, path);
|
||||||
|
}
|
||||||
|
Field::Serializer(ser) => {
|
||||||
|
self.traverse_fields(
|
||||||
|
&mut ser.serializer.fields,
|
||||||
|
ser_name.clone() + "." + &ser.serializer.name,
|
||||||
|
path.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Field::Pointer(ser) => {
|
||||||
|
self.traverse_fields(
|
||||||
|
&mut ser.serializer.fields,
|
||||||
|
ser_name.clone() + "." + &ser.serializer.name,
|
||||||
|
path.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Field::Array(ser) => match &mut ser.field_enum.as_mut() {
|
||||||
|
Field::Value(v) => {
|
||||||
|
self.handle_prop(&(ser_name.clone() + "." + &v.name), v, path);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
Field::Vector(_x) => {
|
||||||
|
let vec_path = path.clone();
|
||||||
|
if let Ok(inner) = f.get_inner_mut(0) {
|
||||||
|
match inner {
|
||||||
|
Field::Serializer(s) => {
|
||||||
|
for (inner_idx, f) in
|
||||||
|
&mut s.serializer.fields.iter_mut().enumerate()
|
||||||
|
{
|
||||||
|
match f {
|
||||||
|
Field::Value(v) => {
|
||||||
|
let mut myp = vec_path.clone();
|
||||||
|
myp.push(inner_idx as i32);
|
||||||
|
self.handle_prop(
|
||||||
|
&(ser_name.clone() + "." + &v.name),
|
||||||
|
v,
|
||||||
|
myp,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.traverse_fields(
|
||||||
|
&mut s.serializer.fields,
|
||||||
|
ser_name.clone() + "." + &s.serializer.name,
|
||||||
|
path_og.clone(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Field::Value(x) => {
|
||||||
|
self.handle_prop(
|
||||||
|
&(ser_name.clone() + "." + &x.name),
|
||||||
|
x,
|
||||||
|
path.clone(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Field::None => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_prop(&mut self, full_name: &str, f: &mut ValueField, path: Vec<i32>) {
|
||||||
|
f.full_name = full_name.to_owned();
|
||||||
|
|
||||||
|
// CAK47.m_iClip1 => ["CAK47", "m_iClip1"]
|
||||||
|
let split_at_dot: Vec<&str> = full_name.split(".").collect();
|
||||||
|
let is_weapon_prop = (split_at_dot[0].contains("Weapon") || split_at_dot[0].contains("AK"))
|
||||||
|
&& !split_at_dot[0].contains("Player")
|
||||||
|
|| split_at_dot[0].contains("Knife")
|
||||||
|
|| split_at_dot[0].contains("CDEagle")
|
||||||
|
|| split_at_dot[0].contains("C4")
|
||||||
|
|| split_at_dot[0].contains("Molo")
|
||||||
|
|| split_at_dot[0].contains("Inc")
|
||||||
|
|| split_at_dot[0].contains("Infer");
|
||||||
|
|
||||||
|
let is_projectile_prop = (split_at_dot[0].contains("Projectile")
|
||||||
|
|| split_at_dot[0].contains("Grenade")
|
||||||
|
|| split_at_dot[0].contains("Flash"))
|
||||||
|
&& !split_at_dot[0].contains("Player");
|
||||||
|
let is_grenade_or_weapon = is_weapon_prop || is_projectile_prop;
|
||||||
|
|
||||||
|
// Strip first part of name from grenades and weapons.
|
||||||
|
// if weapon prop: CAK47.m_iClip1 => m_iClip1
|
||||||
|
// if grenade: CSmokeGrenadeProjectile.CBodyComponentBaseAnimGraph.m_cellX => CBodyComponentBaseAnimGraph.m_cellX
|
||||||
|
let prop_name = match is_grenade_or_weapon {
|
||||||
|
true => split_at_dot[1..].join("."),
|
||||||
|
false => full_name.to_string(),
|
||||||
|
};
|
||||||
|
let mut a = [0, 0, 0, 0, 0, 0, 0];
|
||||||
|
for (idx, v) in path.iter().enumerate() {
|
||||||
|
a[idx] = *v;
|
||||||
|
}
|
||||||
|
self.path_to_name.insert(a, prop_name.to_string());
|
||||||
|
|
||||||
|
let prop_already_exists = self.name_to_id.contains_key(&(prop_name).to_string());
|
||||||
|
self.set_id(&prop_name, f, is_grenade_or_weapon);
|
||||||
|
if !prop_already_exists {
|
||||||
|
self.insert_propinfo(&prop_name, f);
|
||||||
|
}
|
||||||
|
f.should_parse = true;
|
||||||
|
if full_name == "CCSPlayerPawn.CCSPlayer_WeaponServices.m_hMyWeapons" {
|
||||||
|
f.prop_id = MY_WEAPONS_OFFSET as u32;
|
||||||
|
}
|
||||||
|
if full_name
|
||||||
|
== "CCSPlayerPawn.CCSPlayer_ActionTrackingServices.WeaponPurchaseCount_t.m_nCount"
|
||||||
|
{
|
||||||
|
f.prop_id = ITEM_PURCHASE_COUNT as u32;
|
||||||
|
}
|
||||||
|
if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_unDefIdx" {
|
||||||
|
f.prop_id = ITEM_PURCHASE_DEF_IDX as u32;
|
||||||
|
}
|
||||||
|
if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_nCost" {
|
||||||
|
f.prop_id = ITEM_PURCHASE_COST as u32;
|
||||||
|
}
|
||||||
|
if full_name == "CCSPlayerPawn.CCSPlayer_ActionTrackingServices.WeaponPurchaseCount_t.m_nItemDefIndex" {
|
||||||
|
f.prop_id = ITEM_PURCHASE_NEW_DEF_IDX as u32;
|
||||||
|
}
|
||||||
|
if full_name == "CCSPlayerPawn.CCSPlayer_BuyServices.SellbackPurchaseEntry_t.m_hItem" {
|
||||||
|
f.prop_id = ITEM_PURCHASE_HANDLE as u32;
|
||||||
|
}
|
||||||
|
if prop_name.contains("CEconItemAttribute.m_iRawValue32") {
|
||||||
|
f.prop_id = WEAPON_SKIN_ID as u32;
|
||||||
|
}
|
||||||
|
self.id += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_id(&mut self, weap_prop: &str, f: &mut ValueField, is_grenade_or_weapon: bool) {
|
||||||
|
match self.name_to_id.get(weap_prop) {
|
||||||
|
// If we already have an id for prop of same name then use that id.
|
||||||
|
// Mainly for weapon props. For example CAK47.m_iClip1 and CWeaponSCAR20.m_iClip1
|
||||||
|
// are the "same" prop. (they have same path and we want to refer to it with one id not ~20)
|
||||||
|
Some(id) => {
|
||||||
|
f.prop_id = *id as u32;
|
||||||
|
self.id_to_name.insert(*id, weap_prop.to_string());
|
||||||
|
self.set_special_ids(&weap_prop, is_grenade_or_weapon, *id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.name_to_id.insert(weap_prop.to_string(), self.id);
|
||||||
|
self.id_to_name.insert(self.id, weap_prop.to_string());
|
||||||
|
f.prop_id = self.id as u32;
|
||||||
|
self.set_special_ids(&weap_prop, is_grenade_or_weapon, self.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_propinfo(&mut self, prop_name: &str, f: &mut ValueField) {
|
||||||
|
self.prop_infos.push(PropInfo {
|
||||||
|
id: f.prop_id as u32,
|
||||||
|
prop_name: prop_name.to_string(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_special_ids(&mut self, weap_prop: &str, is_grenade_or_weapon: bool, id: u32) {
|
||||||
|
// TODO
|
||||||
|
if is_grenade_or_weapon {
|
||||||
|
match weap_prop {
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
match weap_prop {
|
||||||
|
_ => {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecialIDs {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user