Implement chunk loading

This commit is contained in:
Thinkofname 2016-03-21 14:05:13 +00:00
parent 8476f992e1
commit ce1c286801
8 changed files with 190 additions and 7 deletions

View File

@ -35,6 +35,13 @@ impl ChunkBuilder {
}
}
pub fn wait_for_builders(&mut self) {
while self.free_builders.len() != NUM_WORKERS {
let (id, _) = self.built_recv.recv().unwrap();
self.free_builders.push(id);
}
}
pub fn tick(&mut self, world: &mut world::World, renderer: &mut render::Renderer) {
while let Ok((id, val)) = self.built_recv.try_recv() {
world.reset_building_flag(val.position);

View File

@ -107,6 +107,7 @@ impl Game {
Ok(val) => {
self.screen_sys.pop_screen();
self.renderer.clear_chunks();
self.chunk_builder.wait_for_builders();
self.server = val;
},
Err(err) => {
@ -194,9 +195,6 @@ fn main() {
chunk_builder: chunk_builder::ChunkBuilder::new(textures),
connect_reply: None,
};
game.renderer.camera.pos.x = 0.5;
game.renderer.camera.pos.z = 0.5;
game.renderer.camera.pos.y = 15.0;
while !game.should_close {
{
@ -210,7 +208,7 @@ fn main() {
let (width, height) = window.get_inner_size_pixels().unwrap();
game.tick(delta);
game.server.tick(delta);
game.server.tick(&mut game.renderer, delta);
game.chunk_builder.tick(&mut game.server.world, &mut game.renderer);

View File

@ -309,6 +309,16 @@ impl Serializable for u16 {
}
}
impl Serializable for u64 {
fn read_from(buf: &mut io::Read) -> Result<u64, io::Error> {
Result::Ok(try!(buf.read_u64::<BigEndian>()))
}
fn write_to(&self, buf: &mut io::Write) -> Result<(), io::Error> {
try!(buf.write_u64::<BigEndian>(*self));
Result::Ok(())
}
}
impl Serializable for f32 {
fn read_from(buf: &mut io::Read) -> Result<f32, io::Error> {
Result::Ok(try!(buf.read_f32::<BigEndian>()))

View File

@ -12,24 +12,43 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use protocol::{self, mojang};
use protocol::{self, mojang, packet};
use world;
use world::block::{self, BlockSet};
use rand::{self, Rng};
use std::sync::{Arc, RwLock, Mutex};
use std::sync::mpsc;
use std::thread;
use resources;
use openssl;
use console;
use render;
use auth;
use cgmath::{self, Vector};
pub struct Server {
conn: Option<protocol::Conn>,
read_queue: Option<mpsc::Receiver<Result<packet::Packet, protocol::Error>>>,
pub world: world::World,
resources: Arc<RwLock<resources::Manager>>,
console: Arc<Mutex<console::Console>>,
version: usize,
position: cgmath::Vector3<f64>,
}
macro_rules! handle_packet {
($s:ident $pck:ident {
$($packet:ident => $func:ident,)*
}) => (
match $pck {
$(
protocol::packet::Packet::$packet(val) => $s.$func(val),
)*
_ => {},
}
)
}
impl Server {
@ -100,13 +119,29 @@ impl Server {
}
}
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
loop {
let pck = read.read_packet();
let was_error = pck.is_err();
if let Err(_) = tx.send(pck) {
return;
}
if was_error {
return;
}
}
});
let version = resources.read().unwrap().version();
Ok(Server {
conn: Some(write),
read_queue: Some(rx),
world: world::World::new(),
resources: resources,
console: console,
version: version,
position: cgmath::Vector3::zero(),
})
}
@ -124,11 +159,13 @@ impl Server {
let version = resources.read().unwrap().version();
Server {
conn: None,
read_queue: None,
world: world,
version: version,
resources: resources,
console: console,
position: cgmath::Vector3::new(0.5, 13.2, 0.5),
}
}
@ -136,11 +173,66 @@ impl Server {
self.conn.is_some()
}
pub fn tick(&mut self, delta: f64) {
pub fn tick(&mut self, renderer: &mut render::Renderer, _delta: f64) {
let version = self.resources.read().unwrap().version();
if version != self.version {
self.version = version;
self.world.flag_dirty_all();
}
if let Some(rx) = self.read_queue.take() {
while let Ok(pck) = rx.try_recv() {
match pck {
Ok(pck) => handle_packet!{
self pck {
KeepAliveClientbound => on_keep_alive,
ChunkData => on_chunk_data,
TeleportPlayer => on_teleport,
}
},
Err(err) => panic!("Err: {:?}", err),
}
}
self.read_queue = Some(rx);
}
// Copy to camera
renderer.camera.pos = cgmath::Point::from_vec(self.position + cgmath::Vector3::new(0.0, 1.8, 0.0));
}
pub fn write_packet<T: protocol::PacketType>(&mut self, p: T) {
self.conn.as_mut().unwrap().write_packet(p).unwrap(); // TODO handle errors
}
pub fn on_keep_alive(&mut self, keep_alive: packet::play::clientbound::KeepAliveClientbound) {
self.write_packet(packet::play::serverbound::KeepAliveServerbound {
id: keep_alive.id,
});
}
pub fn on_teleport(&mut self, teleport: packet::play::clientbound::TeleportPlayer) {
// TODO: relative teleports
self.position.x = teleport.x;
self.position.y = teleport.y;
self.position.z = teleport.z;
self.write_packet(packet::play::serverbound::PlayerPositionLook {
x: teleport.x,
y: teleport.y,
z: teleport.z,
yaw: teleport.yaw,
pitch: teleport.pitch,
on_ground: false,
});
}
pub fn on_chunk_data(&mut self, chunk_data: packet::play::clientbound::ChunkData) {
self.world.load_chunk(
chunk_data.chunk_x,
chunk_data.chunk_z,
chunk_data.new,
chunk_data.bitmask.0 as u16,
chunk_data.data.data
).unwrap();
}
}

View File

@ -59,6 +59,13 @@ impl Map {
}
map
}
pub fn from_raw(bits: Vec<u64>, size: usize) -> Map {
Map {
length: (bits.len()*64 + 63) / size,
bit_size: size,
bits: bits,
}
}
pub fn resize(&self, size: usize) -> Map {
let mut n = Map::new(self.length, size);

View File

@ -14,7 +14,7 @@
pub struct Array {
data: Vec<u8>,
pub data: Vec<u8>,
}
impl Array {

View File

@ -111,6 +111,10 @@ impl BlockManager {
fn get_block_by_steven_id(&self, id: usize) -> &'static Block {
self.steven_id[id]
}
fn get_block_by_vanilla_id(&self, id: usize) -> &'static Block {
self.vanilla_id.get(id).and_then(|v| *v).unwrap_or(MISSING.base())
}
}
pub fn force_init() {
@ -121,6 +125,10 @@ pub fn get_block_by_steven_id(id: usize) -> &'static Block {
MANAGER.get_block_by_steven_id(id)
}
pub fn get_block_by_vanilla_id(id: usize) -> &'static Block {
MANAGER.get_block_by_vanilla_id(id)
}
define_blocks! {
AIR InvisibleBlockSet = InvisibleBlockSet::new("air");
MISSING SimpleBlockSet = SimpleBlockSet::new("missing");

View File

@ -18,6 +18,7 @@ use self::block::BlockSet;
use std::collections::HashMap;
use types::bit;
use types::nibble;
use protocol;
pub struct World {
chunks: HashMap<CPos, Chunk>,
@ -148,6 +149,66 @@ impl World {
snapshot
}
pub fn load_chunk(&mut self, x: i32, z: i32, new: bool, mask: u16, data: Vec<u8>) -> Result<(), protocol::Error> {
use std::io::{Cursor, Read};
use byteorder::ReadBytesExt;
use protocol::{VarInt, Serializable, LenPrefixed};
let mut data = Cursor::new(data);
let cpos = CPos(x, z);
let chunk = if new {
self.chunks.insert(cpos, Chunk::new(cpos));
self.chunks.get_mut(&cpos).unwrap()
} else {
if !self.chunks.contains_key(&cpos) {
return Ok(());
}
self.chunks.get_mut(&cpos).unwrap()
};
for i in 0 .. 16 {
if mask & (1 << i) == 0 {
continue;
}
if chunk.sections[i].is_none() {
chunk.sections[i] = Some(Section::new(i as u8));
}
let section = chunk.sections[i as usize].as_mut().unwrap();
let bit_size = try!(data.read_u8());
let mut block_map = HashMap::new();
if bit_size <= 8 {
let count = try!(VarInt::read_from(&mut data)).0;
for i in 0 .. count {
let id = try!(VarInt::read_from(&mut data)).0;
block_map.insert(i as usize, id);
}
}
let bits = try!(LenPrefixed::<VarInt, u64>::read_from(&mut data)).data;
let m = bit::Map::from_raw(bits, bit_size as usize);
for i in 0 .. 4096 {
let val = m.get(i);
let block_id = block_map.get(&val).map(|v| *v as usize).unwrap_or(val);
let block = block::get_block_by_vanilla_id(block_id);
let i = i as i32;
section.set_block(
i & 0xF,
i >> 8,
(i >> 4) & 0xF,
block
);
}
try!(data.read_exact(&mut section.block_light.data));
try!(data.read_exact(&mut section.sky_light.data));
}
Ok(())
}
}
pub struct Snapshot {