From 548c98edf87943299a70fe61b5dbbf01a898374b Mon Sep 17 00:00:00 2001 From: Thinkofname Date: Thu, 7 Apr 2016 21:30:20 +0100 Subject: [PATCH] Add basic nameplates to players --- src/entity/block_entity/sign.rs | 72 +++------------------------------ src/entity/player.rs | 61 ++++++++++++++++++++++++---- src/render/model.rs | 63 +++++++++++++++++++++++++++++ src/server/mod.rs | 2 +- 4 files changed, 124 insertions(+), 74 deletions(-) diff --git a/src/entity/block_entity/sign.rs b/src/entity/block_entity/sign.rs index 64bad43..e56d1fe 100644 --- a/src/entity/block_entity/sign.rs +++ b/src/entity/block_entity/sign.rs @@ -5,7 +5,7 @@ use shared::{Direction, Position}; use world; use world::block::Block; use render; -use render::model; +use render::model::{self, FormatState}; pub fn add_systems(m: &mut ecs::Manager) { let sys = SignRenderer::new(m); @@ -139,18 +139,22 @@ impl ecs::System for SignRenderer { } for (i, line) in info.lines.iter().enumerate() { + const Y_SCALE: f32 = (6.0 / 16.0) / 4.0; + const X_SCALE: f32 = Y_SCALE / 16.0; let mut state = FormatState { - line: i as f32, width: 0.0, offset: 0.0, text: Vec::new(), renderer: renderer, + y_scale: Y_SCALE, + x_scale: X_SCALE, }; state.build(line, format::Color::Black); let width = state.width; // Center align text for vert in &mut state.text { vert.x += width * 0.5; + vert.y -= (Y_SCALE + 0.4/16.0) * (i as f32); } verts.extend_from_slice(&state.text); } @@ -184,67 +188,3 @@ impl ecs::System for SignRenderer { info.model = None; } } - -struct FormatState<'a> { - line: f32, - offset: f32, - width: f32, - text: Vec, - renderer: &'a mut render::Renderer, -} - -impl <'a> FormatState<'a> { - fn build(&mut self, c: &Component, color: format::Color) { - match c { - &format::Component::Text(ref txt) => { - let col = FormatState::get_color(&txt.modifier, color); - self.append_text(&txt.text, col); - let modi = &txt.modifier; - if let Some(ref extra) = modi.extra { - for e in extra { - self.build(e, col); - } - } - } - } - } - - fn append_text(&mut self, txt: &str, color: format::Color) { - const Y_SCALE: f32 = (6.0 / 16.0) / 4.0; - const X_SCALE: f32 = Y_SCALE / 16.0; - - let (rr, gg, bb) = color.to_rgb(); - for ch in txt.chars() { - if ch == ' ' { - self.offset += 6.0 * X_SCALE; - continue; - } - let texture = self.renderer.ui.character_texture(ch); - let w = self.renderer.ui.size_of_char(ch) as f32; - - for vert in ::model::BlockVertex::face_by_direction(Direction::North) { - self.text.push(model::Vertex { - x: vert.x * X_SCALE * w - (self.offset + w * X_SCALE), - y: vert.y * Y_SCALE - (Y_SCALE + 0.4/16.0) * self.line + 2.1 / 16.0, - z: -0.6 / 16.0, - texture: texture.clone(), - texture_x: vert.toffsetx as f64, - texture_y: vert.toffsety as f64, - r: rr, - g: gg, - b: bb, - a: 255, - id: 0, - }); - } - self.offset += (w + 2.0) * X_SCALE; - } - if self.offset > self.width { - self.width = self.offset; - } - } - - fn get_color(modi: &format::Modifier, color: format::Color) -> format::Color { - modi.color.unwrap_or(color) - } -} diff --git a/src/entity/player.rs b/src/entity/player.rs index 3280bc2..7bb1999 100644 --- a/src/entity/player.rs +++ b/src/entity/player.rs @@ -12,7 +12,7 @@ use super::{ }; use world; use render; -use render::model; +use render::model::{self, FormatState}; use types::Gamemode; use collision::{Aabb, Aabb3}; use cgmath::{self, Point3, Vector3, Matrix4, Decomposed, Rotation3, Rad, Angle, Quaternion}; @@ -21,6 +21,7 @@ use std::hash::BuildHasherDefault; use types::hash::FNVHash; use sdl2::keyboard::Keycode; use shared::Position as BPosition; +use format; pub fn add_systems(m: &mut ecs::Manager) { // Not actually rendering related but the faster @@ -43,11 +44,11 @@ pub fn create_local(m: &mut ecs::Manager) -> ecs::Entity { Point3::new(-0.3, 0.0, -0.3), Point3::new(0.3, 1.8, 0.3) ))); - m.add_component_direct(entity, PlayerModel::new(false, false, true)); + m.add_component_direct(entity, PlayerModel::new("", false, false, true)); entity } -pub fn create_remote(m: &mut ecs::Manager) -> ecs::Entity { +pub fn create_remote(m: &mut ecs::Manager, name: &str) -> ecs::Entity { let entity = m.create_entity(); m.add_component_direct(entity, Position::new(0.0, 0.0, 0.0)); m.add_component_direct(entity, TargetPosition::new(0.0, 0.0, 0.0)); @@ -58,7 +59,7 @@ pub fn create_remote(m: &mut ecs::Manager) -> ecs::Entity { Point3::new(-0.3, 0.0, -0.3), Point3::new(0.3, 1.8, 0.3) ))); - m.add_component_direct(entity, PlayerModel::new(true, true, false)); + m.add_component_direct(entity, PlayerModel::new(name, true, true, false)); entity } @@ -67,6 +68,7 @@ pub struct PlayerModel { model: Option, skin_url: Option, dirty: bool, + name: String, has_head: bool, has_name_tag: bool, @@ -80,11 +82,12 @@ pub struct PlayerModel { } impl PlayerModel { - pub fn new(has_head: bool, has_name_tag: bool, first_person: bool) -> PlayerModel { + pub fn new(name: &str, has_head: bool, has_name_tag: bool, first_person: bool) -> PlayerModel { PlayerModel { model: None, skin_url: None, dirty: false, + name: name.to_owned(), has_head: has_head, has_name_tag: has_name_tag, @@ -137,8 +140,8 @@ enum PlayerModelPart { LegRight = 3, ArmLeft = 4, ArmRight = 5, - Cape = 6, - NameTag = 7 + NameTag = 6, + Cape = 7, } // TODO: Setup culling @@ -186,6 +189,16 @@ impl ecs::System for PlayerRenderer { disp: offset, }); + // TODO This sucks + if player_model.has_name_tag { + let ang = (position.position.x - renderer.camera.pos.x).atan2(position.position.z - renderer.camera.pos.z) as f32; + mdl.matrix[PlayerModelPart::NameTag as usize] = Matrix4::from(Decomposed { + scale: 1.0, + rot: Quaternion::from_angle_y(Rad::new(ang)), + disp: offset + Vector3::new(0.0, (-24.0/16.0) - 0.6, 0.0), + }); + } + mdl.matrix[PlayerModelPart::Head as usize] = offset_matrix * Matrix4::from(Decomposed { scale: 1.0, rot: Quaternion::from_angle_x(Rad::new(-rotation.pitch as f32)), @@ -354,6 +367,39 @@ impl ecs::System for PlayerRenderer { ]); } + let mut name_verts = vec![]; + if player_model.has_name_tag { + let mut state = FormatState { + width: 0.0, + offset: 0.0, + text: Vec::new(), + renderer: renderer, + y_scale: 0.16, + x_scale: 0.01, + }; + let mut name = format::Component::Text(format::TextComponent::new(&player_model.name)); + format::convert_legacy(&mut name); + state.build(&name, format::Color::Black); + let width = state.width; + // Center align text + for vert in &mut state.text { + vert.x += width * 0.5; + vert.r = 64; + vert.g = 64; + vert.b = 64; + } + name_verts.extend_from_slice(&state.text); + for vert in &mut state.text { + vert.x -= 0.01; + vert.y -= 0.01; + vert.z -= 0.05; + vert.r = 255; + vert.g = 255; + vert.b = 255; + } + name_verts.extend_from_slice(&state.text); + } + player_model.model = Some(renderer.model.create_model( model::DEFAULT, vec![ @@ -363,6 +409,7 @@ impl ecs::System for PlayerRenderer { part_verts[1].clone(), part_verts[2].clone(), part_verts[3].clone(), + name_verts ] )); } diff --git a/src/render/model.rs b/src/render/model.rs index fefa5e4..3406343 100644 --- a/src/render/model.rs +++ b/src/render/model.rs @@ -11,6 +11,7 @@ use types::hash::FNVHash; use shared::Direction; use byteorder::{WriteBytesExt, NativeEndian}; use model::BlockVertex; +use format::{self, Component}; pub struct Manager { collections: Vec, @@ -369,3 +370,65 @@ pub fn append_box_texture_scale( } } } + +pub struct FormatState<'a> { + pub offset: f32, + pub width: f32, + pub text: Vec, + pub renderer: &'a mut super::Renderer, + pub y_scale: f32, + pub x_scale: f32, +} + +impl <'a> FormatState<'a> { + pub fn build(&mut self, c: &Component, color: format::Color) { + match c { + &format::Component::Text(ref txt) => { + let col = FormatState::get_color(&txt.modifier, color); + self.append_text(&txt.text, col); + let modi = &txt.modifier; + if let Some(ref extra) = modi.extra { + for e in extra { + self.build(e, col); + } + } + } + } + } + + fn append_text(&mut self, txt: &str, color: format::Color) { + let (rr, gg, bb) = color.to_rgb(); + for ch in txt.chars() { + if ch == ' ' { + self.offset += 6.0 * self.x_scale; + continue; + } + let texture = self.renderer.ui.character_texture(ch); + let w = self.renderer.ui.size_of_char(ch) as f32; + + for vert in ::model::BlockVertex::face_by_direction(Direction::North) { + self.text.push(Vertex { + x: vert.x * self.x_scale * w - (self.offset + w * self.x_scale), + y: vert.y * self.y_scale + 2.1 / 16.0, + z: -0.6 / 16.0, + texture: texture.clone(), + texture_x: vert.toffsetx as f64, + texture_y: vert.toffsety as f64, + r: rr, + g: gg, + b: bb, + a: 255, + id: 0, + }); + } + self.offset += (w + 2.0) * self.x_scale; + } + if self.offset > self.width { + self.width = self.offset; + } + } + + fn get_color(modi: &format::Modifier, color: format::Color) -> format::Color { + modi.color.unwrap_or(color) + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs index f38da72..73abc30 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -601,7 +601,7 @@ impl Server { if let Some(entity) = self.entity_map.remove(&spawn.entity_id.0) { self.entities.remove_entity(entity); } - let entity = entity::player::create_remote(&mut self.entities); + let entity = entity::player::create_remote(&mut self.entities, self.players.get(&spawn.uuid).map_or("MISSING", |v| &v.name)); let position = self.entities.get_component_mut(entity, self.position).unwrap(); let target_position = self.entities.get_component_mut(entity, self.target_position).unwrap(); let rotation = self.entities.get_component_mut(entity, self.rotation).unwrap();