diff options
Diffstat (limited to 'client/src/world/tee.rs')
-rw-r--r-- | client/src/world/tee.rs | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/client/src/world/tee.rs b/client/src/world/tee.rs new file mode 100644 index 0000000..5458fe6 --- /dev/null +++ b/client/src/world/tee.rs @@ -0,0 +1,166 @@ +use std::collections::BTreeMap; + +use super::helper::Color; +use crate::client::ClientMesgOut; +use gamenet::{ + enums::{Emote, Team, Weapon}, + SnapObj, +}; + +pub struct Tees { + pub inner: BTreeMap<u16, Tee>, +} + +pub struct Tee { + pub name: String, + pub skin: String, + pub clan: String, + + pub local: bool, + pub latency: i32, + pub score: i32, + + pub team: Team, + pub weapon: Weapon, + pub armor: i32, + pub ammo: i32, + pub emote: Emote, + pub attack_tick: i32, + + pub tick: i32, + pub angle: i32, + pub x: i32, + pub y: i32, + pub vel_x: i32, + pub vel_y: i32, + pub hook_x: i32, + pub hook_y: i32, + pub hook_dx: i32, + pub hook_dy: i32, + pub hook_player: i32, + pub hook_state: i32, + + pub color_feet: Color, + pub color_body: Color, + pub use_custom_colors: bool, + pub country: i32, +} + +impl Default for Tee { + fn default() -> Self { + Self { + x: Default::default(), + y: Default::default(), + local: false, + team: Team::Spectators, + latency: Default::default(), + score: Default::default(), + weapon: Weapon::Shotgun, + armor: Default::default(), + ammo: Default::default(), + attack_tick: Default::default(), + emote: Emote::Normal, + tick: Default::default(), + angle: Default::default(), + vel_x: Default::default(), + vel_y: Default::default(), + hook_x: Default::default(), + hook_y: Default::default(), + hook_dx: Default::default(), + hook_dy: Default::default(), + hook_player: Default::default(), + hook_state: Default::default(), + name: Default::default(), + skin: Default::default(), + clan: Default::default(), + color_feet: Color { + a: 0, + b: 0, + g: 0, + r: 0, + }, + color_body: Color { + a: 0, + b: 0, + g: 0, + r: 0, + }, + use_custom_colors: Default::default(), + country: Default::default(), + } + } +} + +impl Tees { + pub fn new() -> Self { + Self { + inner: BTreeMap::new(), + } + } + pub fn update(&mut self, m: &ClientMesgOut) { + match m { + ClientMesgOut::Snaps(s) => { + self.inner.clear(); + for (id, o) in s { + let e = self.inner.entry(*id).or_default(); + match o { + SnapObj::ClientInfo(o) => { + e.name = i32_to_string(o.name); + e.skin = i32_to_string(o.skin); + e.clan = i32_to_string(o.clan); + e.color_feet = unsafe { std::mem::transmute(o.color_feet) }; + e.color_body = unsafe { std::mem::transmute(o.color_body) }; + e.use_custom_colors = o.use_custom_color != 0 + } + SnapObj::PlayerInfo(o) => { + e.local = o.local == 1; + e.team = o.team; + e.latency = o.latency; + e.score = o.score; + } + SnapObj::Character(c) => { + e.ammo = c.ammo_count; + e.weapon = c.weapon; + e.emote = c.emote; + e.attack_tick = c.attack_tick; + + e.x = c.character_core.x; + e.y = c.character_core.y; + e.vel_x = c.character_core.vel_x; + e.vel_y = c.character_core.vel_y; + + e.tick = c.character_core.tick; + e.hook_x = c.character_core.hook_x; + e.hook_y = c.character_core.hook_y; + e.hook_player = c.character_core.hooked_player; + e.hook_dx = c.character_core.hook_dx; + e.hook_dy = c.character_core.hook_dy; + e.hook_state = c.character_core.hook_state; + } + _ => (), + } + } + } + _ => {} + } + } + + pub fn local(&self) -> Option<&Tee> { + self.inner.values().find(|e| e.local) + } +} + +fn i32_to_string<const S: usize>(k: [i32; S]) -> String { + let mut bytes = vec![]; + for i in 0..S { + bytes.push(((((k[i]) >> 24) & 0xff) - 128) as u8); + bytes.push(((((k[i]) >> 16) & 0xff) - 128) as u8); + bytes.push(((((k[i]) >> 8) & 0xff) - 128) as u8); + bytes.push((((k[i]) & 0xff) - 128) as u8); + } + let len = bytes.iter().position(|e| *e == 0).unwrap_or(S); + while bytes.len() > len { + bytes.pop(); + } + String::from_utf8(bytes).unwrap() +} |