aboutsummaryrefslogtreecommitdiff
path: root/client/src/world/tee.rs
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/world/tee.rs')
-rw-r--r--client/src/world/tee.rs166
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()
+}