Add basic nameplates to players
This commit is contained in:
parent
ea23219993
commit
548c98edf8
|
@ -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<model::Vertex>,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<model::ModelKey>,
|
||||
skin_url: Option<String>,
|
||||
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
|
||||
]
|
||||
));
|
||||
}
|
||||
|
|
|
@ -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<Collection>,
|
||||
|
@ -369,3 +370,65 @@ pub fn append_box_texture_scale(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FormatState<'a> {
|
||||
pub offset: f32,
|
||||
pub width: f32,
|
||||
pub text: Vec<Vertex>,
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue