1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
use std::fmt;
use std::io::prelude::*;
use std::io::{self, Cursor};
use packet::Protocol;
use util::ReadExactExt;
pub struct ChunkColumn {
pub chunks: Vec<Chunk>,
pub biomes: Option<[u8; 256]>
}
impl ChunkColumn {
pub fn len(&self) -> usize {
let chunks = self.chunks.iter().map(|x| x.len()).sum::<usize>();
let biomes = match self.biomes {
Some(_) => 256,
None => 0
};
chunks + biomes
}
pub fn encode(&self) -> io::Result<Vec<u8>> {
use byteorder::{LittleEndian, WriteBytesExt};
let mut dst: Cursor<Vec<u8>> = Cursor::new(Vec::new());
for chunk in &self.chunks {
for x in chunk.blocks.iter() {
try!(dst.write_u16::<LittleEndian>(*x));
}
}
for chunk in &self.chunks {
try!(dst.write_all(&chunk.block_light));
}
for chunk in &self.chunks {
match chunk.sky_light {
Some(xs) => try!(dst.write_all(&xs)),
None => {}
}
}
match self.biomes {
Some(xs) => try!(dst.write_all(&xs)),
None => {}
}
Ok(dst.into_inner())
}
pub fn decode(mut src: &mut Read, mask: u16, continuous: bool, sky_light: bool) -> io::Result<ChunkColumn> {
let num_chunks = mask.count_ones();
let mut chunks = Vec::new();
for _ in 0..num_chunks {
chunks.push(Chunk::default());
}
let mut column = ChunkColumn{
chunks: chunks,
biomes: None
};
for chunk in &mut column.chunks {
for x in chunk.blocks.iter_mut() {
*x = try!(<u16 as Protocol>::proto_decode(src));
}
}
for chunk in &mut column.chunks {
for x in chunk.block_light.iter_mut() {
*x = try!(<u8 as Protocol>::proto_decode(src));
}
}
for chunk in &mut column.chunks {
if sky_light {
let mut sl = [0u8; 2048];
for x in sl.iter_mut() {
*x = try!(<u8 as Protocol>::proto_decode(src));
}
chunk.sky_light = Some(sl);
}
}
if continuous {
let biomes = try!(src.read_exact(256));
let mut bs = [0u8; 256];
for (idx, elt) in biomes.into_iter().enumerate() {
bs[idx] = elt;
}
column.biomes = Some(bs)
}
Ok(column)
}
}
impl fmt::Debug for ChunkColumn {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ChunkColumn chunks={} biomes={}", self.chunks.len(), self.biomes.is_some())
}
}
pub struct Chunk {
pub blocks: [u16; 4096],
pub block_light: [u8; 2048],
pub sky_light: Option<[u8; 2048]>,
}
impl Chunk {
pub fn len(&self) -> usize {
let sky = match self.sky_light {
Some(_) => 2048,
None => 0
};
8192 + 2048 + sky
}
pub fn new(block: u16, light: u8) -> Chunk {
Chunk {
blocks: [block; 4096],
block_light: [light; 2048],
sky_light: Some([light; 2048])
}
}
}
impl Default for Chunk {
fn default() -> Chunk {
Chunk {
blocks: [0u16; 4096],
block_light: [0u8; 2048],
sky_light: None
}
}
}
impl fmt::Debug for Chunk {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Chunk blocks=[{}, {}, {}, ..] block_light=[{}, {}, {}, ..] sky_light={}",
self.blocks[0], self.blocks[1], self.blocks[2],
self.block_light[0], self.block_light[1], self.block_light[2],
self.sky_light.is_some())
}
}