alex/beta-minecraft-rust
Minecraft Beta 1.7.3 Rewrite
BRANCH main
SNAPSHOT Draw terrain GPU-driven from packed per-section buffers with GPU occlusion culling, add a render distance slider (2-128) with a quad/disk shape, cut chunk bookkeeping at high render distances, and fix a light underflow at y=0
DOWNLOAD
root crates server src entity painting.rs
use common::entity::Entity;
use common::entity::painting::{ART, Painting};
use common::item::{Item, ItemStack};
use common::math::floor_f64;
use common::world::shape::BlockView;
use super::Kind;
use crate::level::Level;
impl Level {
pub fn place_painting(&mut self, anchor: [i32; 3], side: u8) -> bool {
let direction = match side {
2 => 0,
4 => 1,
3 => 2,
5 => 3,
_ => return false,
};
let mut painting = Painting {
art: 0,
anchor,
direction,
};
let mut stored = self.entities.create(Kind::Painting { painting, check: 0 });
let choices: Vec<u8> = (0..ART.len() as u8)
.filter(|&art| self.valid_painting(Painting { art, ..painting }))
.collect();
if choices.is_empty() {
return false;
}
let entity = &mut stored.entity;
painting.art = choices[entity.rand.next_int(choices.len() as i32) as usize];
entity.set_location_and_angles(painting.position(), f32::from(direction) * 90.0, 0.0);
entity.bb = painting.bounds();
stored.kind = Kind::Painting { painting, check: 0 };
self.spawn(stored);
true
}
/// The painting item of a removed painting, collectable at once.
pub(crate) fn drop_painting(&mut self, entity: &Entity) {
self.dropped_items.push(crate::level::DroppedItem {
x: entity.pos.x,
y: entity.pos.y,
z: entity.pos.z,
stack: ItemStack::one(Item::PAINTING),
motion: None,
impulse: glam::DVec3::ZERO,
pickup_delay: 0,
});
}
pub(super) fn valid_painting(&self, painting: Painting) -> bool {
let bounds = painting.bounds();
let overlaps = |is: fn(&Kind) -> bool| {
self.entities
.iter()
.any(|e| !e.entity.dead && is(&e.kind) && e.entity.bb.intersects(&bounds))
};
// `getCollidingBoundingBoxes`: blocks and boats
if !self.block_boxes(&bounds).is_empty() || overlaps(|k| matches!(k, Kind::Boat(_))) {
return false;
}
let [width, height] = painting.art().size.map(|v| i32::from(v / 16));
let pos = painting.position();
let x = floor_f64(pos.x - f64::from(width) / 2.0);
let y = floor_f64(pos.y - f64::from(height) / 2.0);
let z = floor_f64(pos.z - f64::from(width) / 2.0);
let [ax, _, az] = painting.anchor;
for col in 0..width {
for row in 0..height {
let block = if painting.direction & 1 == 0 {
self.block(x + col, y + row, az)
} else {
self.block(ax, y + row, z + col)
};
if !block.material().is_solid() {
return false;
}
}
}
!overlaps(|k| matches!(k, Kind::Painting { .. }))
}
pub(super) fn tick_painting(
&mut self,
entity: &mut Entity,
painting: Painting,
check: &mut u32,
) {
if *check == 100 {
*check = 0;
if !self.valid_painting(painting) {
entity.dead = true;
self.drop_painting(entity);
}
} else {
*check += 1;
}
}
}