First attempt at block handling rework
This commit is contained in:
parent
edee182bf9
commit
189c063f67
|
@ -8,6 +8,7 @@ dependencies = [
|
|||
"glutin 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -17,6 +17,7 @@ rand = "0.3.14"
|
|||
rustc-serialize = "0.3.18"
|
||||
log = "0.3.5"
|
||||
cgmath = "0.7.0"
|
||||
lazy_static = "0.1.15"
|
||||
|
||||
[dependencies.steven_gl]
|
||||
path = "./gl"
|
||||
|
|
|
@ -90,7 +90,7 @@ fn build_func(id: usize, textures: Arc<RwLock<render::TextureManager>>, work_rec
|
|||
for x in 0 .. 16 {
|
||||
for z in 0 .. 16 {
|
||||
let block = snapshot.get_block(x, y, z);
|
||||
if !block.render {
|
||||
if !block.renderable() {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -15,6 +15,22 @@
|
|||
#![recursion_limit="200"]
|
||||
#![feature(const_fn)]
|
||||
|
||||
extern crate glutin;
|
||||
extern crate image;
|
||||
extern crate time;
|
||||
extern crate byteorder;
|
||||
extern crate serde_json;
|
||||
extern crate steven_openssl as openssl;
|
||||
extern crate hyper;
|
||||
extern crate flate2;
|
||||
extern crate rand;
|
||||
extern crate rustc_serialize;
|
||||
extern crate cgmath;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
pub mod ecs;
|
||||
|
@ -34,20 +50,6 @@ pub mod server;
|
|||
pub mod world;
|
||||
pub mod chunk_builder;
|
||||
|
||||
extern crate glutin;
|
||||
extern crate image;
|
||||
extern crate time;
|
||||
extern crate byteorder;
|
||||
extern crate serde_json;
|
||||
extern crate steven_openssl as openssl;
|
||||
extern crate hyper;
|
||||
extern crate flate2;
|
||||
extern crate rand;
|
||||
extern crate rustc_serialize;
|
||||
extern crate cgmath;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::sync::{Arc, RwLock, Mutex};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -74,6 +76,7 @@ pub struct Game {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
world::block::force_init();
|
||||
let con = Arc::new(Mutex::new(console::Console::new()));
|
||||
{
|
||||
let mut con = con.lock().unwrap();
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
use protocol;
|
||||
use world;
|
||||
use world::block;
|
||||
use world::block::{self, BlockSet};
|
||||
use rand::{self, Rng};
|
||||
use std::sync::{Arc, RwLock};
|
||||
use resources;
|
||||
|
@ -35,7 +35,7 @@ impl Server {
|
|||
for z in -7*16 .. 7*16 {
|
||||
let h = rng.gen_range(3, 10);
|
||||
for y in 0 .. h {
|
||||
world.set_block(x, y, z, block::MISSING);
|
||||
world.set_block(x, y, z, block::MISSING.base());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,214 @@
|
|||
|
||||
use std::collections::HashMap;
|
||||
use std::cell::UnsafeCell;
|
||||
|
||||
pub trait BlockSet {
|
||||
fn plugin(&'static self) -> &'static str {
|
||||
"minecraft"
|
||||
}
|
||||
|
||||
fn name(&'static self) -> &'static str;
|
||||
fn blocks(&'static self) -> Vec<&'static Block>;
|
||||
|
||||
fn base(&'static self) -> &'static Block {
|
||||
self.blocks()[0]
|
||||
}
|
||||
}
|
||||
|
||||
pub trait Block: Sync {
|
||||
fn steven_id(&'static self) -> usize;
|
||||
fn vanilla_id(&'static self) -> Option<usize>;
|
||||
fn set_steven_id(&'static self, id: usize);
|
||||
fn set_vanilla_id(&'static self, id: usize);
|
||||
|
||||
fn equals(&'static self, other: &'static Block) -> bool {
|
||||
self.steven_id() == other.steven_id()
|
||||
}
|
||||
|
||||
fn in_set(&'static self, set: &'static BlockSet) -> bool {
|
||||
// TODO: Make faster
|
||||
for block in set.blocks() {
|
||||
if self.equals(block) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn renderable(&'static self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn data(&'static self) -> Option<u8> {
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BlockManager {
|
||||
vanilla_id: Vec<Option<&'static Block>>,
|
||||
steven_id: Vec<&'static Block>,
|
||||
next_id: usize,
|
||||
}
|
||||
|
||||
macro_rules! define_blocks {
|
||||
(
|
||||
$(
|
||||
$internal_name:ident $ty:ty = $bl:expr;
|
||||
)*
|
||||
) => (
|
||||
lazy_static! {
|
||||
$(
|
||||
pub static ref $internal_name: $ty = $bl;
|
||||
)*
|
||||
static ref MANAGER: BlockManager = {
|
||||
let mut manager = BlockManager {
|
||||
vanilla_id: vec![None; 0xFFFF],
|
||||
steven_id: vec![],
|
||||
next_id: 0,
|
||||
};
|
||||
$(
|
||||
manager.register_set(&*$internal_name);
|
||||
)*
|
||||
manager
|
||||
};
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: Replace this with trait fields when supported by rust
|
||||
macro_rules! block_impl {
|
||||
() => (
|
||||
fn steven_id(&'static self) -> usize {
|
||||
unsafe { *self.steven_id_storage.get() }
|
||||
}
|
||||
fn vanilla_id(&'static self) -> Option<usize> {
|
||||
unsafe { *self.vanilla_id_storage.get() }
|
||||
}
|
||||
fn set_steven_id(&'static self, id: usize) {
|
||||
unsafe { *self.steven_id_storage.get() = id; }
|
||||
}
|
||||
fn set_vanilla_id(&'static self, id: usize) {
|
||||
unsafe { *self.vanilla_id_storage.get() = Some(id); }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
impl BlockManager {
|
||||
fn force_init(&self) {}
|
||||
fn register_set(&mut self, set: &'static BlockSet) {
|
||||
for block in set.blocks() {
|
||||
if let Some(data) = block.data() {
|
||||
let id = (self.next_id<<4) | (data as usize);
|
||||
self.vanilla_id[id] = Some(block);
|
||||
block.set_vanilla_id(id);
|
||||
}
|
||||
block.set_steven_id(self.steven_id.len());
|
||||
self.steven_id.push(block);
|
||||
}
|
||||
self.next_id += 1;
|
||||
}
|
||||
|
||||
fn get_block_by_steven_id(&self, id: usize) -> &'static Block {
|
||||
self.steven_id[id]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn force_init() {
|
||||
MANAGER.force_init();
|
||||
}
|
||||
|
||||
pub fn get_block_by_steven_id(id: usize) -> &'static Block {
|
||||
MANAGER.get_block_by_steven_id(id)
|
||||
}
|
||||
|
||||
define_blocks! {
|
||||
AIR InvisibleBlockSet = InvisibleBlockSet::new("air");
|
||||
MISSING SimpleBlockSet = SimpleBlockSet::new("missing");
|
||||
}
|
||||
|
||||
pub struct InvisibleBlockSet {
|
||||
name: &'static str,
|
||||
sub_blocks: Vec<InvisibleBlock>,
|
||||
}
|
||||
|
||||
impl InvisibleBlockSet {
|
||||
fn new(name: &'static str) -> InvisibleBlockSet {
|
||||
let sub_blocks = vec![InvisibleBlock {
|
||||
steven_id_storage: UnsafeCell::new(0),
|
||||
vanilla_id_storage: UnsafeCell::new(None),
|
||||
}];
|
||||
InvisibleBlockSet {
|
||||
name: name,
|
||||
sub_blocks: sub_blocks,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockSet for InvisibleBlockSet {
|
||||
fn name(&'static self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
|
||||
fn blocks(&'static self) -> Vec<&'static Block> {
|
||||
self.sub_blocks.iter().map(|v| v as &Block).collect()
|
||||
}
|
||||
}
|
||||
|
||||
struct InvisibleBlock {
|
||||
steven_id_storage: UnsafeCell<usize>,
|
||||
vanilla_id_storage: UnsafeCell<Option<usize>>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for InvisibleBlock {}
|
||||
impl Block for InvisibleBlock {
|
||||
block_impl!();
|
||||
fn renderable(&'static self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SimpleBlockSet {
|
||||
name: &'static str,
|
||||
sub_blocks: Vec<SimpleBlock>,
|
||||
}
|
||||
|
||||
impl SimpleBlockSet {
|
||||
fn new(name: &'static str) -> SimpleBlockSet {
|
||||
let sub_blocks = vec![SimpleBlock {
|
||||
steven_id_storage: UnsafeCell::new(0),
|
||||
vanilla_id_storage: UnsafeCell::new(None),
|
||||
}];
|
||||
SimpleBlockSet {
|
||||
name: name,
|
||||
sub_blocks: sub_blocks,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockSet for SimpleBlockSet {
|
||||
fn name(&'static self) -> &'static str {
|
||||
self.name
|
||||
}
|
||||
|
||||
fn blocks(&'static self) -> Vec<&'static Block> {
|
||||
self.sub_blocks.iter().map(|v| v as &Block).collect()
|
||||
}
|
||||
}
|
||||
|
||||
struct SimpleBlock {
|
||||
steven_id_storage: UnsafeCell<usize>,
|
||||
vanilla_id_storage: UnsafeCell<Option<usize>>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for SimpleBlock {}
|
||||
impl Block for SimpleBlock {
|
||||
block_impl!();
|
||||
fn renderable(&'static self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Block {
|
||||
pub render: bool,
|
||||
|
@ -46,3 +256,4 @@ pub fn get_block_by_id(id: usize) -> &'static Block {
|
|||
}
|
||||
&BLOCKS[id]
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
pub mod block;
|
||||
use self::block::BlockSet;
|
||||
|
||||
use std::collections::HashMap;
|
||||
use types::bit;
|
||||
|
@ -41,7 +42,7 @@ impl World {
|
|||
pub fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block {
|
||||
match self.chunks.get(&CPos(x >> 4, z >> 4)) {
|
||||
Some(ref chunk) => chunk.get_block(x & 0xF, y, z & 0xF),
|
||||
None => block::AIR,
|
||||
None => block::AIR.base(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -91,7 +92,7 @@ impl World {
|
|||
};
|
||||
for i in 0 .. (w * h * d) as usize {
|
||||
snapshot.sky_light.set(i, 0xF);
|
||||
snapshot.blocks[i] = block::MISSING.get_id() as u16;
|
||||
snapshot.blocks[i] = block::MISSING.base().steven_id() as u16;
|
||||
}
|
||||
|
||||
let cx1 = x >> 4;
|
||||
|
@ -134,7 +135,7 @@ impl World {
|
|||
snapshot.set_sky_light(ox, oy, oz, sec.get_sky_light(xx, yy, zz));
|
||||
},
|
||||
None => {
|
||||
snapshot.set_block(ox, oy, oz, block::AIR);
|
||||
snapshot.set_block(ox, oy, oz, block::AIR.base());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -172,12 +173,12 @@ impl Snapshot {
|
|||
}
|
||||
|
||||
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)
|
||||
block::get_block_by_steven_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;
|
||||
self.blocks[idx] = b.steven_id() as u16;
|
||||
}
|
||||
|
||||
pub fn get_block_light(&self, x: i32, y: i32, z: i32) -> u8 {
|
||||
|
@ -234,7 +235,7 @@ impl Chunk {
|
|||
return;
|
||||
}
|
||||
if self.sections[s_idx as usize].is_none() {
|
||||
if b == block::AIR {
|
||||
if b.in_set(&*block::AIR) {
|
||||
return;
|
||||
}
|
||||
self.sections[s_idx as usize] = Some(Section::new(s_idx as u8));
|
||||
|
@ -246,11 +247,11 @@ impl Chunk {
|
|||
fn get_block(&self, x: i32, y: i32, z: i32) -> &'static block::Block {
|
||||
let s_idx = y >> 4;
|
||||
if s_idx < 0 || s_idx > 15 {
|
||||
return block::AIR;
|
||||
return block::AIR.base();
|
||||
}
|
||||
match self.sections[s_idx as usize].as_ref() {
|
||||
Some(sec) => sec.get_block(x, y & 0xF, z),
|
||||
None => block::AIR,
|
||||
None => block::AIR.base(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -260,7 +261,7 @@ struct Section {
|
|||
|
||||
blocks: bit::Map,
|
||||
block_map: Vec<(&'static block::Block, u32)>,
|
||||
rev_block_map: HashMap<&'static block::Block, usize>,
|
||||
rev_block_map: HashMap<usize, usize>,
|
||||
|
||||
block_light: nibble::Array,
|
||||
sky_light: nibble::Array,
|
||||
|
@ -276,7 +277,7 @@ impl Section {
|
|||
|
||||
blocks: bit::Map::new(4096, 4),
|
||||
block_map: vec![
|
||||
(block::AIR, 0xFFFFFFFF)
|
||||
(block::AIR.base(), 0xFFFFFFFF)
|
||||
],
|
||||
rev_block_map: HashMap::new(),
|
||||
|
||||
|
@ -289,7 +290,7 @@ impl Section {
|
|||
for i in 0 .. 16*16*16 {
|
||||
section.sky_light.set(i, 0xF);
|
||||
}
|
||||
section.rev_block_map.insert(block::AIR, 0);
|
||||
section.rev_block_map.insert(block::AIR.base().steven_id(), 0);
|
||||
section
|
||||
}
|
||||
|
||||
|
@ -300,25 +301,25 @@ impl Section {
|
|||
|
||||
fn set_block(&mut self, x: i32, y: i32, z: i32, b: &'static block::Block) {
|
||||
let old = self.get_block(x, y, z);
|
||||
if old == b {
|
||||
if old.equals(b) {
|
||||
return;
|
||||
}
|
||||
// Clean up old block
|
||||
{
|
||||
let idx = self.rev_block_map[old];
|
||||
let idx = self.rev_block_map[&old.steven_id()];
|
||||
let info = &mut self.block_map[idx];
|
||||
info.1 -= 1;
|
||||
if info.1 == 0 { // None left of this type
|
||||
self.rev_block_map.remove(old);
|
||||
self.rev_block_map.remove(&old.steven_id());
|
||||
}
|
||||
}
|
||||
|
||||
if !self.rev_block_map.contains_key(b) {
|
||||
if !self.rev_block_map.contains_key(&b.steven_id()) {
|
||||
let mut found = false;
|
||||
for (i, ref mut info) in self.block_map.iter_mut().enumerate() {
|
||||
if info.1 == 0 {
|
||||
info.0 = b;
|
||||
self.rev_block_map.insert(b, i);
|
||||
self.rev_block_map.insert(b.steven_id(), i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
@ -329,12 +330,12 @@ impl Section {
|
|||
let new_blocks = self.blocks.resize(new_size);
|
||||
self.blocks = new_blocks;
|
||||
}
|
||||
self.rev_block_map.insert(b, self.block_map.len());
|
||||
self.rev_block_map.insert(b.steven_id(), self.block_map.len());
|
||||
self.block_map.push((b, 0));
|
||||
}
|
||||
}
|
||||
|
||||
let idx = self.rev_block_map[b];
|
||||
let idx = self.rev_block_map[&b.steven_id()];
|
||||
let info = &mut self.block_map[idx];
|
||||
info.1 += 1;
|
||||
self.blocks.set(((y << 8) | (z << 4) | x) as usize, idx);
|
||||
|
|
Loading…
Reference in New Issue