Basic chunk building (not rendering)
This commit is contained in:
parent
5f17aead7e
commit
ad81ef8f17
|
@ -31,7 +31,7 @@ path = "./resources"
|
||||||
version = "0"
|
version = "0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 2
|
opt-level = 0
|
||||||
debug = true
|
debug = true
|
||||||
rpath = false
|
rpath = false
|
||||||
lto = false
|
lto = false
|
||||||
|
|
|
@ -0,0 +1,209 @@
|
||||||
|
|
||||||
|
use std::thread;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use std::io::Write;
|
||||||
|
use byteorder::{WriteBytesExt, NativeEndian};
|
||||||
|
use world;
|
||||||
|
use render;
|
||||||
|
|
||||||
|
const NUM_WORKERS: usize = 4;
|
||||||
|
|
||||||
|
pub struct ChunkBuilder {
|
||||||
|
threads: Vec<(mpsc::Sender<BuildReq>, thread::JoinHandle<()>)>,
|
||||||
|
free_builders: Vec<usize>,
|
||||||
|
built_recv: mpsc::Receiver<(usize, BuildReply)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChunkBuilder {
|
||||||
|
pub fn new(textures: Arc<RwLock<render::TextureManager>>) -> ChunkBuilder {
|
||||||
|
let mut threads = vec![];
|
||||||
|
let mut free = vec![];
|
||||||
|
let (built_send, built_recv) = mpsc::channel();
|
||||||
|
for i in 0 .. NUM_WORKERS {
|
||||||
|
let built_send = built_send.clone();
|
||||||
|
let (work_send, work_recv) = mpsc::channel();
|
||||||
|
let textures = textures.clone();
|
||||||
|
let id = i;
|
||||||
|
threads.push((work_send, thread::spawn(move || build_func(id, textures, work_recv, built_send))));
|
||||||
|
free.push(i);
|
||||||
|
}
|
||||||
|
ChunkBuilder {
|
||||||
|
threads: threads,
|
||||||
|
free_builders: free,
|
||||||
|
built_recv: built_recv,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(&mut self, world: &mut world::World) {
|
||||||
|
while let Ok((id, val)) = self.built_recv.try_recv() {
|
||||||
|
world.reset_building_flag(val.position);
|
||||||
|
self.free_builders.push(id);
|
||||||
|
}
|
||||||
|
if self.free_builders.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while let Some((x, y, z)) = world.next_dirty_chunk_section() {
|
||||||
|
let t_id = self.free_builders.pop().unwrap();
|
||||||
|
let (cx, cy, cz) = (x << 4, y << 4, z << 4);
|
||||||
|
let mut snapshot = world.capture_snapshot(cx - 2, cy - 2, cz - 2, 20, 20, 20);
|
||||||
|
snapshot.make_relative(-2, -2, -2);
|
||||||
|
self.threads[t_id].0.send(BuildReq {
|
||||||
|
snapshot: snapshot,
|
||||||
|
position: (x, y, z),
|
||||||
|
}).unwrap();
|
||||||
|
if self.free_builders.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BuildReq {
|
||||||
|
snapshot: world::Snapshot,
|
||||||
|
position: (i32, i32, i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BuildReply {
|
||||||
|
position: (i32, i32, i32),
|
||||||
|
solid_buffer: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_recv: mpsc::Receiver<BuildReq>, built_send: mpsc::Sender<(usize, BuildReply)>) {
|
||||||
|
loop {
|
||||||
|
let BuildReq {
|
||||||
|
snapshot,
|
||||||
|
position,
|
||||||
|
} = work_recv.recv().unwrap();
|
||||||
|
println!("Build request for {:?}", position);
|
||||||
|
|
||||||
|
let mut solid_buffer = vec![];
|
||||||
|
|
||||||
|
for y in 0 .. 16 {
|
||||||
|
for x in 0 .. 16 {
|
||||||
|
for z in 0 .. 16 {
|
||||||
|
let block = snapshot.get_block(x, y, z);
|
||||||
|
if !block.render {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for verts in &PRECOMPUTED_VERTS {
|
||||||
|
for vert in verts {
|
||||||
|
let stone = render::Renderer::get_texture(&textures, "minecraft:blocks/stone");
|
||||||
|
|
||||||
|
let mut vert = vert.clone();
|
||||||
|
// TODO
|
||||||
|
vert.r = 255;
|
||||||
|
vert.g = 255;
|
||||||
|
vert.b = 255;
|
||||||
|
|
||||||
|
vert.x += x as f32;
|
||||||
|
vert.y += y as f32;
|
||||||
|
vert.z += z as f32;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
vert.block_light = 15 * 4000;
|
||||||
|
vert.sky_light = 15 * 4000;
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
vert.tatlas = stone.atlas as i16;
|
||||||
|
vert.tx = stone.get_x() as u16;
|
||||||
|
vert.ty = stone.get_y() as u16;
|
||||||
|
vert.tw = stone.get_width() as u16;
|
||||||
|
vert.th = stone.get_height() as u16;
|
||||||
|
|
||||||
|
vert.write(&mut solid_buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("> Build request for {:?}", position);
|
||||||
|
built_send.send((id, BuildReply {
|
||||||
|
position: position,
|
||||||
|
solid_buffer: solid_buffer,
|
||||||
|
})).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const PRECOMPUTED_VERTS: [[BlockVertex; 4]; 6] = [
|
||||||
|
[ // Up
|
||||||
|
BlockVertex::base(0.0, 1.0, 0.0, 0, 0),
|
||||||
|
BlockVertex::base(1.0, 1.0, 0.0, 1, 0),
|
||||||
|
BlockVertex::base(0.0, 1.0, 1.0, 0, 1),
|
||||||
|
BlockVertex::base(1.0, 1.0, 1.0, 1, 1),
|
||||||
|
],
|
||||||
|
[ // Down
|
||||||
|
BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
|
||||||
|
BlockVertex::base(0.0, 0.0, 1.0, 0, 0),
|
||||||
|
BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
|
||||||
|
BlockVertex::base(1.0, 0.0, 1.0, 1, 1),
|
||||||
|
],
|
||||||
|
[ // North
|
||||||
|
BlockVertex::base(0.0, 0.0, 0.0, 1, 1),
|
||||||
|
BlockVertex::base(1.0, 0.0, 0.0, 0, 1),
|
||||||
|
BlockVertex::base(0.0, 1.0, 0.0, 1, 0),
|
||||||
|
BlockVertex::base(1.0, 1.0, 0.0, 0, 0),
|
||||||
|
],
|
||||||
|
[ // South
|
||||||
|
BlockVertex::base(0.0, 0.0, 1.0, 0, 1),
|
||||||
|
BlockVertex::base(0.0, 1.0, 1.0, 0, 0),
|
||||||
|
BlockVertex::base(1.0, 0.0, 1.0, 1, 1),
|
||||||
|
BlockVertex::base(1.0, 1.0, 1.0, 1, 0),
|
||||||
|
],
|
||||||
|
[ // West
|
||||||
|
BlockVertex::base(0.0, 0.0, 0.0, 0, 1),
|
||||||
|
BlockVertex::base(0.0, 1.0, 0.0, 0, 0),
|
||||||
|
BlockVertex::base(0.0, 0.0, 1.0, 1, 1),
|
||||||
|
BlockVertex::base(0.0, 1.0, 1.0, 1, 0),
|
||||||
|
],
|
||||||
|
[ // East
|
||||||
|
BlockVertex::base(1.0, 0.0, 0.0, 1, 1),
|
||||||
|
BlockVertex::base(1.0, 0.0, 1.0, 0, 1),
|
||||||
|
BlockVertex::base(1.0, 1.0, 0.0, 1, 0),
|
||||||
|
BlockVertex::base(1.0, 1.0, 1.0, 0, 0),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct BlockVertex {
|
||||||
|
x: f32, y: f32, z: f32,
|
||||||
|
tx: u16, ty: u16, tw: u16, th: u16,
|
||||||
|
toffsetx: i16, toffsety: i16, tatlas: i16,
|
||||||
|
r: u8, g: u8, b: u8,
|
||||||
|
block_light: u16, sky_light: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlockVertex {
|
||||||
|
const fn base(x: f32, y: f32, z: f32, tx: i16, ty: i16) -> BlockVertex {
|
||||||
|
BlockVertex {
|
||||||
|
x: x, y: y, z: z,
|
||||||
|
tx: 0, ty: 0, tw: 0, th: 0,
|
||||||
|
toffsetx: tx, toffsety: ty, tatlas: 0,
|
||||||
|
r: 0, g: 0, b: 0,
|
||||||
|
block_light: 0, sky_light: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn write<W: Write>(&self, w: &mut W) {
|
||||||
|
let _ = w.write_f32::<NativeEndian>(self.x);
|
||||||
|
let _ = w.write_f32::<NativeEndian>(self.y);
|
||||||
|
let _ = w.write_f32::<NativeEndian>(self.z);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(self.tx);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(self.ty);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(self.tw);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(self.th);
|
||||||
|
let _ = w.write_i16::<NativeEndian>(self.toffsetx);
|
||||||
|
let _ = w.write_i16::<NativeEndian>(self.toffsety);
|
||||||
|
let _ = w.write_i16::<NativeEndian>(self.tatlas);
|
||||||
|
let _ = w.write_i16::<NativeEndian>(0);
|
||||||
|
let _ = w.write_u8(self.r);
|
||||||
|
let _ = w.write_u8(self.g);
|
||||||
|
let _ = w.write_u8(self.b);
|
||||||
|
let _ = w.write_u8(255);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(self.block_light);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(self.sky_light);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(0);
|
||||||
|
let _ = w.write_u16::<NativeEndian>(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#![recursion_limit="200"]
|
#![recursion_limit="200"]
|
||||||
|
#![feature(const_fn)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
pub mod macros;
|
pub mod macros;
|
||||||
|
@ -31,6 +32,7 @@ pub mod screen;
|
||||||
pub mod console;
|
pub mod console;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
pub mod world;
|
pub mod world;
|
||||||
|
pub mod chunk_builder;
|
||||||
|
|
||||||
extern crate glutin;
|
extern crate glutin;
|
||||||
extern crate image;
|
extern crate image;
|
||||||
|
@ -68,6 +70,7 @@ pub struct Game {
|
||||||
mouse_pos: (i32, i32),
|
mouse_pos: (i32, i32),
|
||||||
|
|
||||||
server: server::Server,
|
server: server::Server,
|
||||||
|
chunk_builder: chunk_builder::ChunkBuilder,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -119,6 +122,7 @@ fn main() {
|
||||||
let mut screen_sys = screen::ScreenSystem::new();
|
let mut screen_sys = screen::ScreenSystem::new();
|
||||||
screen_sys.add_screen(Box::new(screen::Login::new()));
|
screen_sys.add_screen(Box::new(screen::Login::new()));
|
||||||
|
|
||||||
|
let textures = renderer.get_textures();
|
||||||
let mut game = Game {
|
let mut game = Game {
|
||||||
renderer: renderer,
|
renderer: renderer,
|
||||||
screen_sys: screen_sys,
|
screen_sys: screen_sys,
|
||||||
|
@ -127,6 +131,7 @@ fn main() {
|
||||||
should_close: false,
|
should_close: false,
|
||||||
mouse_pos: (0, 0),
|
mouse_pos: (0, 0),
|
||||||
server: server::Server::dummy_server(),
|
server: server::Server::dummy_server(),
|
||||||
|
chunk_builder: chunk_builder::ChunkBuilder::new(textures),
|
||||||
};
|
};
|
||||||
|
|
||||||
while !game.should_close {
|
while !game.should_close {
|
||||||
|
@ -140,6 +145,8 @@ fn main() {
|
||||||
let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
|
let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
|
||||||
let (width, height) = window.get_inner_size_pixels().unwrap();
|
let (width, height) = window.get_inner_size_pixels().unwrap();
|
||||||
|
|
||||||
|
game.chunk_builder.tick(&mut game.server.world);
|
||||||
|
|
||||||
game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container);
|
game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container);
|
||||||
game.console
|
game.console
|
||||||
.lock()
|
.lock()
|
||||||
|
|
|
@ -601,7 +601,11 @@ impl TextureManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_texture(&self, name: &str) -> Option<Texture> {
|
fn get_texture(&self, name: &str) -> Option<Texture> {
|
||||||
self.textures.get(name).map(|v| v.clone())
|
if let Some(_) = name.find(':') {
|
||||||
|
self.textures.get(name).map(|v| v.clone())
|
||||||
|
} else {
|
||||||
|
self.textures.get(&format!("minecraft:{}", name)).map(|v| v.clone())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_texture(&mut self, name: &str) {
|
fn load_texture(&mut self, name: &str) {
|
||||||
|
@ -702,10 +706,8 @@ impl TextureManager {
|
||||||
self.pending_uploads.push((atlas, rect, data));
|
self.pending_uploads.push((atlas, rect, data));
|
||||||
|
|
||||||
let mut full_name = String::new();
|
let mut full_name = String::new();
|
||||||
if plugin != "minecraft" {
|
full_name.push_str(plugin);
|
||||||
full_name.push_str(plugin);
|
full_name.push_str(":");
|
||||||
full_name.push_str(":");
|
|
||||||
}
|
|
||||||
full_name.push_str(name);
|
full_name.push_str(name);
|
||||||
|
|
||||||
let tex = Texture {
|
let tex = Texture {
|
||||||
|
|
|
@ -25,7 +25,7 @@ use std::sync::mpsc;
|
||||||
|
|
||||||
const RESOURCES_VERSION: &'static str = "15w39c";
|
const RESOURCES_VERSION: &'static str = "15w39c";
|
||||||
|
|
||||||
pub trait Pack {
|
pub trait Pack: Sync + Send {
|
||||||
fn open(&self, name: &str) -> Option<Box<io::Read>>;
|
fn open(&self, name: &str) -> Option<Box<io::Read>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,8 @@ pub struct Manager {
|
||||||
vanilla_chan: Option<mpsc::Receiver<bool>>,
|
vanilla_chan: Option<mpsc::Receiver<bool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl Sync for Manager {}
|
||||||
|
|
||||||
impl Manager {
|
impl Manager {
|
||||||
pub fn new() -> Manager {
|
pub fn new() -> Manager {
|
||||||
let mut m = Manager {
|
let mut m = Manager {
|
||||||
|
|
|
@ -19,7 +19,7 @@ use rand::{self, Rng};
|
||||||
|
|
||||||
pub struct Server {
|
pub struct Server {
|
||||||
conn: Option<protocol::Conn>,
|
conn: Option<protocol::Conn>,
|
||||||
world: world::World,
|
pub world: world::World,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
|
|
150
src/world/mod.rs
150
src/world/mod.rs
|
@ -44,6 +44,154 @@ impl World {
|
||||||
None => block::AIR,
|
None => block::AIR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn next_dirty_chunk_section(&mut self) -> Option<(i32, i32, i32)> {
|
||||||
|
for (_, chunk) in &mut self.chunks {
|
||||||
|
for sec in &mut chunk.sections {
|
||||||
|
if let Some(sec) = sec.as_mut() {
|
||||||
|
if !sec.building && sec.dirty {
|
||||||
|
sec.building = true;
|
||||||
|
sec.dirty = false;
|
||||||
|
return Some((chunk.position.0, sec.y as i32, chunk.position.1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_building_flag(&mut self, pos: (i32, i32, i32)) {
|
||||||
|
if let Some(chunk) = self.chunks.get_mut(&CPos(pos.0, pos.2)) {
|
||||||
|
if let Some(section) = chunk.sections[pos.1 as usize].as_mut() {
|
||||||
|
section.building = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn capture_snapshot(&self, x: i32, y: i32, z: i32, w: i32, h: i32, d: i32) -> Snapshot {
|
||||||
|
use std::cmp::{min, max};
|
||||||
|
let mut snapshot = Snapshot {
|
||||||
|
blocks: vec![0; (w * h * d) as usize],
|
||||||
|
block_light: nibble::Array::new((w * h * d) as usize),
|
||||||
|
sky_light: nibble::Array::new((w * h * d) as usize),
|
||||||
|
biomes: vec![0; (w * d) as usize],
|
||||||
|
|
||||||
|
x: x, y: y, z: z,
|
||||||
|
w: w, h: h, d: d,
|
||||||
|
};
|
||||||
|
for i in 0 .. (w * h * d) as usize {
|
||||||
|
snapshot.sky_light.set(i, 0xF);
|
||||||
|
snapshot.blocks[i] = block::MISSING.get_id() as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cx1 = x >> 4;
|
||||||
|
let cy1 = y >> 4;
|
||||||
|
let cz1 = z >> 4;
|
||||||
|
let cx2 = (x + w + 15) >> 4;
|
||||||
|
let cy2 = (y + h + 15) >> 4;
|
||||||
|
let cz2 = (z + d + 15) >> 4;
|
||||||
|
|
||||||
|
for cx in cx1 .. cx2 {
|
||||||
|
for cz in cz1 .. cz2 {
|
||||||
|
let chunk = match self.chunks.get(&CPos(cx, cz)) {
|
||||||
|
Some(val) => val,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
let x1 = min(16, max(0, x - (cx<<4)));
|
||||||
|
let x2 = min(16, max(0, x + w - (cx<<4)));
|
||||||
|
let z1 = min(16, max(0, z - (cz<<4)));
|
||||||
|
let z2 = min(16, max(0, z + d - (cz<<4)));
|
||||||
|
|
||||||
|
for cy in cy1 .. cy2 {
|
||||||
|
if cy < 0 || cy > 15 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let section = &chunk.sections[cy as usize];
|
||||||
|
let y1 = min(16, max(0, y - (cy<<4)));
|
||||||
|
let y2 = min(16, max(0, y + h - (cy<<4)));
|
||||||
|
|
||||||
|
for yy in y1 .. y2 {
|
||||||
|
for zz in z1 .. z2 {
|
||||||
|
for xx in x1 .. x2 {
|
||||||
|
let ox = xx + (cx << 4);
|
||||||
|
let oy = yy + (cy << 4);
|
||||||
|
let oz = zz + (cz << 4);
|
||||||
|
match section.as_ref() {
|
||||||
|
Some(sec) => {
|
||||||
|
snapshot.set_block(ox, oy, oz, sec.get_block(xx, yy, zz));
|
||||||
|
snapshot.set_block_light(ox, oy, oz, sec.get_block_light(xx, yy, zz));
|
||||||
|
snapshot.set_sky_light(ox, oy, oz, sec.get_sky_light(xx, yy, zz));
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
snapshot.set_block(ox, oy, oz, block::AIR);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Biomes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Snapshot {
|
||||||
|
blocks: Vec<u16>,
|
||||||
|
block_light: nibble::Array,
|
||||||
|
sky_light: nibble::Array,
|
||||||
|
biomes: Vec<u8>,
|
||||||
|
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
z: i32,
|
||||||
|
w: i32,
|
||||||
|
h: i32,
|
||||||
|
d: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Snapshot {
|
||||||
|
|
||||||
|
pub fn make_relative(&mut self, x: i32, y: i32, z: i32) {
|
||||||
|
self.x = x;
|
||||||
|
self.y = y;
|
||||||
|
self.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block {
|
||||||
|
block::get_block_by_id(self.blocks[self.index(x, y, z)] as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_block(&mut self, x: i32, y: i32, z: i32, b: &'static block::Block) {
|
||||||
|
let idx = self.index(x, y, z);
|
||||||
|
self.blocks[idx] = b.get_id() as u16;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_block_light(&self, x: i32, y: i32, z: i32) -> u8 {
|
||||||
|
self.block_light.get(self.index(x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_block_light(&mut self, x: i32, y: i32, z: i32, l: u8) {
|
||||||
|
let idx = self.index(x, y, z);
|
||||||
|
self.block_light.set(idx, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_sky_light(&self, x: i32, y: i32, z: i32) -> u8 {
|
||||||
|
self.sky_light.get(self.index(x, y, z))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_sky_light(&mut self, x: i32, y: i32, z: i32, l: u8) {
|
||||||
|
let idx = self.index(x, y, z);
|
||||||
|
self.sky_light.set(idx, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn index(&self, x: i32, y: i32, z: i32) -> usize {
|
||||||
|
((x - self.x) + ((z - self.z) * self.w) + ((y - self.y) * self.w * self.d)) as usize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
|
@ -108,6 +256,7 @@ struct Section {
|
||||||
sky_light: nibble::Array,
|
sky_light: nibble::Array,
|
||||||
|
|
||||||
dirty: bool,
|
dirty: bool,
|
||||||
|
building: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Section {
|
impl Section {
|
||||||
|
@ -125,6 +274,7 @@ impl Section {
|
||||||
sky_light: nibble::Array::new(16 * 16 * 16),
|
sky_light: nibble::Array::new(16 * 16 * 16),
|
||||||
|
|
||||||
dirty: false,
|
dirty: false,
|
||||||
|
building: false,
|
||||||
};
|
};
|
||||||
for i in 0 .. 16*16*16 {
|
for i in 0 .. 16*16*16 {
|
||||||
section.sky_light.set(i, 0xF);
|
section.sky_light.set(i, 0xF);
|
||||||
|
|
Loading…
Reference in New Issue