stevenarella/src/entity/block_entity/sign.rs

191 lines
6.5 KiB
Rust
Raw Normal View History

2016-04-04 17:08:24 -04:00
use crate::ecs;
use crate::format::{self, Component};
use crate::shared::{Direction, Position};
use crate::world;
use crate::world::block::Block;
use crate::render;
use crate::render::model::{self, FormatState};
2016-04-04 17:08:24 -04:00
pub fn add_systems(m: &mut ecs::Manager) {
let sys = SignRenderer::new(m);
m.add_render_system(sys);
}
pub fn init_entity(m: &mut ecs::Manager, e: ecs::Entity) {
m.add_component_direct(e, SignInfo {
model: None,
lines: [
Component::Text(format::TextComponent::new("")),
Component::Text(format::TextComponent::new("")),
Component::Text(format::TextComponent::new("")),
Component::Text(format::TextComponent::new("")),
],
offset_x: 0.0,
offset_y: 0.0,
offset_z: 0.0,
has_stand: false,
rotation: 0.0,
dirty: false,
});
}
pub struct SignInfo {
model: Option<model::ModelKey>,
pub lines: [format::Component; 4],
pub dirty: bool,
offset_x: f64,
offset_y: f64,
offset_z: f64,
has_stand: bool,
rotation: f64,
}
struct SignRenderer {
filter: ecs::Filter,
position: ecs::Key<Position>,
sign_info: ecs::Key<SignInfo>,
}
impl SignRenderer {
fn new(m: &mut ecs::Manager) -> SignRenderer {
let sign_info = m.get_key();
let position = m.get_key();
SignRenderer {
filter: ecs::Filter::new()
.with(position)
.with(sign_info),
position,
sign_info,
2016-04-04 17:08:24 -04:00
}
}
}
impl ecs::System for SignRenderer {
fn filter(&self) -> &ecs::Filter {
&self.filter
}
fn update(&mut self, m: &mut ecs::Manager, world: &mut world::World, renderer: &mut render::Renderer) {
for e in m.find(&self.filter) {
let position = *m.get_component(e, self.position).unwrap();
let info = m.get_component_mut(e, self.sign_info).unwrap();
if info.dirty {
self.entity_removed(m, e, world, renderer);
self.entity_added(m, e, world, renderer);
}
if let Some(model) = info.model {
let mdl = renderer.model.get_model(model).unwrap();
mdl.block_light = world.get_block_light(position) as f32;
mdl.sky_light = world.get_sky_light(position) as f32;
}
}
}
fn entity_added(&mut self, m: &mut ecs::Manager, e: ecs::Entity, world: &mut world::World, renderer: &mut render::Renderer) {
use std::f64::consts::PI;
use cgmath::{Vector3, Matrix4, Decomposed, Rotation3, Rad, Quaternion};
2016-04-04 17:08:24 -04:00
let position = *m.get_component(e, self.position).unwrap();
let info = m.get_component_mut(e, self.sign_info).unwrap();
info.dirty = false;
match world.get_block(position) {
1.13.2 (404) multiprotocol support (#67) Adds support for 1.13.2 protocol (404) Expands https://github.com/iceiix/steven/issues/18 Enhance protocol support Metadata: * Support 1.13.2 slot data format, bool and varint item id, optional damage (moved to NBT) https://wiki.vg/index.php?title=Slot_Data&type=revision&diff=14363&oldid=7835 Packets: * Add 1.13.2 packets, and implement all the command data parsers https://wiki.vg/Command_Data#Parsers * Send new plugin channel minecraft:brand https://wiki.vg/Plugin_channels#minecraft:brand * Add 1.13.2 metadata format, with shifted IDs https://wiki.vg/Entity_metadata#Entity_Metadata_Format * Implement particle entity metadata * Add structures for 16 new packets Blocks: The Flattening: * Assign flattened IDs in correct order using new 'offset' macro token * Assign hierarchical (pre-flattening) block IDs sequentially by counting Some data * Split VANILLA_ID_MAP into flat/hier struct, to support before and after the flattening * Extend travis build time to 20 minutes because the blocks macro takes a long time * Support both flat/hier blocks by passing protocol_version to by_vanilla_id Add block states and offsets for all blocks, replacing metadata for 1.13+: * Add stripped logs and what was Log2 to Log * Add the Wood blocks, should be called bark, previously Axis::None Log * Add leaves distance and offset * Add jungle/acacia to Leaves moved from Leaves2 * Add dispenser offsets, direction * Add note block states * Add offset None to Missing253 and Missing254, no holes in block states of 1.13.2 * Add bed colors * Add seagrass, tall seagrass, remove redundant deadgrass, and piston offset * Add torch, TNT, fire offsets, remove slabs * Add furnance offset, merges lit into a property * Add pressure plate offsets, new pressure plates, redstone ore/lit merged * Add lever offsets, new directions from ceiling/floor, rename LeverDirections * Add redstone torch offsets, new blocks since lit/unlit is now merged, and standing/wall is split * Change lever to split face/facing, rm LeverDirection, add AttachedFace * Add stone button offsets, face/facing similar to lever * Move face/facing data and variant to AttachedFace, reuse for lever/stonebutton * Add data_with_facing_and_powered() to AttachedFace, for lever/stonebutton * Add wooden button offsets each wood * Add pumpkin without a face * Add carved pumpkin, portal offsets * Add lit pumpkin (as jack-o-lantern) offsets after carved pumpkin * Add repeater offsets, merged into Repeater * Change brown mushroom block to booleans instead of MushroomVariant * Add mushroom block offsets, red/brown mushroom blocks, and a new mushroom stem block * Add command block, cobblestone walls, and flower pot offsets Empty flower pot, and potted plants including saplings. Rename variant DarkOak to DarkOakSaplings because it is a sapling, and remove the duplicate Dandelion variant which causes duplicate blocks. * Increase recursion limit in steven_blocks * Add colored banner offsets * Add wooden slab including double slab, in a different position for pre-1.13 and 1.13 * StoneSlabVariant::Wood -> StoneSlabVariant::PetrifiedWood * Add fence_gate_offset() for wooden fence gates * Add frosted ice age, offset * Add new blocks: kelp, turtle egg, coral, coral fans, sea pickle, blue ice, smooth stone * Add new blocks: conduit, void air, cave aid, bubble column, last of the 1.13 blocks
2018-12-29 00:11:42 -05:00
Block::WallSign{facing, ..} => {
2016-04-04 17:08:24 -04:00
info.offset_z = 7.5 / 16.0;
match facing {
Direction::North => {},
Direction::South => info.rotation = PI,
Direction::West => info.rotation = PI / 2.0,
Direction::East => info.rotation = -PI / 2.0,
_ => unreachable!(),
}
},
1.13.2 (404) multiprotocol support (#67) Adds support for 1.13.2 protocol (404) Expands https://github.com/iceiix/steven/issues/18 Enhance protocol support Metadata: * Support 1.13.2 slot data format, bool and varint item id, optional damage (moved to NBT) https://wiki.vg/index.php?title=Slot_Data&type=revision&diff=14363&oldid=7835 Packets: * Add 1.13.2 packets, and implement all the command data parsers https://wiki.vg/Command_Data#Parsers * Send new plugin channel minecraft:brand https://wiki.vg/Plugin_channels#minecraft:brand * Add 1.13.2 metadata format, with shifted IDs https://wiki.vg/Entity_metadata#Entity_Metadata_Format * Implement particle entity metadata * Add structures for 16 new packets Blocks: The Flattening: * Assign flattened IDs in correct order using new 'offset' macro token * Assign hierarchical (pre-flattening) block IDs sequentially by counting Some data * Split VANILLA_ID_MAP into flat/hier struct, to support before and after the flattening * Extend travis build time to 20 minutes because the blocks macro takes a long time * Support both flat/hier blocks by passing protocol_version to by_vanilla_id Add block states and offsets for all blocks, replacing metadata for 1.13+: * Add stripped logs and what was Log2 to Log * Add the Wood blocks, should be called bark, previously Axis::None Log * Add leaves distance and offset * Add jungle/acacia to Leaves moved from Leaves2 * Add dispenser offsets, direction * Add note block states * Add offset None to Missing253 and Missing254, no holes in block states of 1.13.2 * Add bed colors * Add seagrass, tall seagrass, remove redundant deadgrass, and piston offset * Add torch, TNT, fire offsets, remove slabs * Add furnance offset, merges lit into a property * Add pressure plate offsets, new pressure plates, redstone ore/lit merged * Add lever offsets, new directions from ceiling/floor, rename LeverDirections * Add redstone torch offsets, new blocks since lit/unlit is now merged, and standing/wall is split * Change lever to split face/facing, rm LeverDirection, add AttachedFace * Add stone button offsets, face/facing similar to lever * Move face/facing data and variant to AttachedFace, reuse for lever/stonebutton * Add data_with_facing_and_powered() to AttachedFace, for lever/stonebutton * Add wooden button offsets each wood * Add pumpkin without a face * Add carved pumpkin, portal offsets * Add lit pumpkin (as jack-o-lantern) offsets after carved pumpkin * Add repeater offsets, merged into Repeater * Change brown mushroom block to booleans instead of MushroomVariant * Add mushroom block offsets, red/brown mushroom blocks, and a new mushroom stem block * Add command block, cobblestone walls, and flower pot offsets Empty flower pot, and potted plants including saplings. Rename variant DarkOak to DarkOakSaplings because it is a sapling, and remove the duplicate Dandelion variant which causes duplicate blocks. * Increase recursion limit in steven_blocks * Add colored banner offsets * Add wooden slab including double slab, in a different position for pre-1.13 and 1.13 * StoneSlabVariant::Wood -> StoneSlabVariant::PetrifiedWood * Add fence_gate_offset() for wooden fence gates * Add frosted ice age, offset * Add new blocks: kelp, turtle egg, coral, coral fans, sea pickle, blue ice, smooth stone * Add new blocks: conduit, void air, cave aid, bubble column, last of the 1.13 blocks
2018-12-29 00:11:42 -05:00
Block::StandingSign{rotation, ..} => {
2016-04-05 17:28:23 -04:00
info.offset_y = 5.0 / 16.0;
2016-04-04 17:08:24 -04:00
info.has_stand = true;
info.rotation = -(rotation.data() as f64 / 16.0) * PI * 2.0 + PI;
}
_ => return,
}
2016-04-05 17:28:23 -04:00
let tex = render::Renderer::get_texture(renderer.get_textures_ref(), "entity/sign");
2016-04-04 17:08:24 -04:00
macro_rules! rel {
2016-04-05 17:28:23 -04:00
($x:expr, $y:expr, $w:expr, $h:expr) => (
Some(tex.relative(($x) / 64.0, ($y) / 32.0, ($w) / 64.0, ($h) / 32.0))
2016-04-04 17:08:24 -04:00
);
}
let mut verts = vec![];
// Backboard
2016-04-05 17:28:23 -04:00
model::append_box(&mut verts, -0.5, -4.0/16.0, -0.5/16.0, 1.0, 8.0/16.0, 1.0/16.0, [
rel!(26.0, 0.0, 24.0, 2.0), // Down
rel!(2.0, 0.0, 24.0, 2.0), // Up
2016-04-05 17:28:23 -04:00
rel!(2.0, 2.0, 24.0, 12.0), // North
rel!(26.0, 2.0, 24.0, 12.0), // South
rel!(0.0, 2.0, 2.0, 12.0), // West
rel!(50.0, 2.0, 2.0, 12.0), // East
2016-04-04 17:08:24 -04:00
]);
if info.has_stand {
model::append_box(&mut verts, -0.5/16.0, -0.25-9.0/16.0, -0.5/16.0, 1.0/16.0, 9.0/16.0, 1.0/16.0, [
2016-04-05 17:28:23 -04:00
rel!(4.0, 14.0, 2.0, 2.0), // Down
rel!(2.0, 14.0, 2.0, 2.0), // Up
2016-04-05 17:28:23 -04:00
rel!(2.0, 16.0, 2.0, 12.0), // North
rel!(6.0, 16.0, 2.0, 12.0), // South
rel!(0.0, 16.0, 2.0, 12.0), // West
rel!(4.0, 16.0, 2.0, 12.0), // East
2016-04-04 17:08:24 -04:00
]);
}
for (i, line) in info.lines.iter().enumerate() {
2016-04-07 16:30:20 -04:00
const Y_SCALE: f32 = (6.0 / 16.0) / 4.0;
const X_SCALE: f32 = Y_SCALE / 16.0;
2016-04-04 17:08:24 -04:00
let mut state = FormatState {
width: 0.0,
offset: 0.0,
text: Vec::new(),
renderer,
2016-04-07 16:30:20 -04:00
y_scale: Y_SCALE,
x_scale: X_SCALE,
2016-04-04 17:08:24 -04:00
};
state.build(line, format::Color::Black);
let width = state.width;
// Center align text
for vert in &mut state.text {
vert.x += width * 0.5;
2016-04-07 16:30:20 -04:00
vert.y -= (Y_SCALE + 0.4/16.0) * (i as f32);
2016-04-04 17:08:24 -04:00
}
verts.extend_from_slice(&state.text);
}
let model = renderer.model.create_model(
model::DEFAULT,
vec![verts]
);
{
let mdl = renderer.model.get_model(model).unwrap();
mdl.radius = 2.0;
mdl.x = position.x as f32 + 0.5;
mdl.y = position.y as f32 + 0.5;
mdl.z = position.z as f32 + 0.5;
mdl.matrix[0] = Matrix4::from(Decomposed {
scale: 1.0,
rot: Quaternion::from_angle_y(Rad(info.rotation as f32)),
2016-04-04 17:08:24 -04:00
disp: Vector3::new(position.x as f32 + 0.5, -position.y as f32 - 0.5, position.z as f32 + 0.5),
}) * Matrix4::from_translation(Vector3::new(info.offset_x as f32, -info.offset_y as f32, info.offset_z as f32));
}
info.model = Some(model);
}
fn entity_removed(&mut self, m: &mut ecs::Manager, e: ecs::Entity, _: &mut world::World, renderer: &mut render::Renderer) {
let info = m.get_component_mut(e, self.sign_info).unwrap();
if let Some(model) = info.model {
renderer.model.remove_model(model);
}
info.model = None;
}
}