1use crate::chunk::{CompressedChunk, BlockGroup};
2
3use core::marker::PhantomData;
4use core::iter::Iterator;
5use core::convert::Into;
6use core::ops::FnMut;
7use std::boxed::Box;
8use std::sync::Arc;
9use core::cmp::Eq;
10
11
12
13
14
15#[derive(Clone, Debug)]
16pub struct CompressedChunkBytesIter<'a> {
17 chunk:&'a CompressedChunk<'a>,
18 idx:usize
19}
20
21impl<'a> CompressedChunkBytesIter<'a> {
22 #[inline(always)] pub const fn new(chunk:&'a CompressedChunk) -> Self {
23 Self {
24 chunk,
25 idx:0
26 }
27 }
28}
29
30impl<'a> Iterator for CompressedChunkBytesIter<'a> {
31 type Item = u8;
32
33 fn next(&mut self) -> Option<Self::Item> {
34 if self.idx >= self.chunk.len()*2 { return None; }
35
36 let b = unsafe { <BlockGroup as Into<[u8; 2]>>::into(*self.chunk.get_unchecked(self.idx/2))[self.idx % 2] };
37 self.idx += 1;
38 Some(b)
39 }
40}
41
42
43
44pub struct FillParams<'a> {
46 pub(crate) determiner:Box<dyn FnMut((usize, usize, usize, usize))->u8>,
47 pub(crate) rect:Rect4,
48 _lt:PhantomData<&'a ()>
49}
50
51impl<'a> FillParams<'a> {
52 #[inline(always)] pub fn with_determiner<F:FnMut((usize, usize, usize, usize))->u8+'static>(determiner:F, rect:Rect4) -> Self {
53 Self {
54 determiner: Box::new(determiner),
55 rect,
56 _lt: PhantomData
57 }
58 }
59
60 pub fn dither(block_ids:&'a [u8], rect:Rect4) -> Self {
61 let block_ids = Arc::<[u8]>::from(block_ids);
62 let mut n = 0;
63 Self {
64 determiner: Box::new(move |_| {
65 n += 1;
66
67 let block = block_ids[n % block_ids.len()];
68 n %= usize::MAX;
69
70 block
71 }),
72 rect,
73 _lt: PhantomData
74 }
75 }
76
77 #[inline(always)] pub fn hollow(block_id:u8, rect:Rect4) -> Self {
78 Self {
79 determiner: Box::new(move |loc| if rect.has_on_perimeter(loc) { block_id } else { 0 }),
80 rect,
81 _lt: PhantomData
82 }
83 }
84
85 #[inline(always)] pub fn solid(block_id:u8, rect:Rect4) -> Self {
86 Self {
87 determiner: Box::new(move |_| block_id),
88 rect,
89 _lt: PhantomData
90 }
91 }
92}
93
94
95
96#[derive(PartialEq, Clone, Debug, Copy, Eq)]
98#[repr(C)]
99pub struct Rect4 {
100 pub start:(usize, usize, usize, usize),
101 pub end:(usize, usize, usize, usize)
102}
103
104impl Rect4 {
105 #[inline(always)] pub const fn new(start:(usize, usize, usize, usize), end:(usize, usize, usize, usize)) -> Self { Self {start, end} }
106
107 pub const fn has_on_perimeter(&self, point:(usize, usize, usize, usize)) -> bool {
108 ((point.0 == self.start.0 || point.0 == self.end.0) && (
109 point.1 >= self.start.1 && point.1 <= self.end.1 && point.2 >= self.start.2 && point.2 <= self.end.2 &&
110 point.3 >= self.start.3 && point.3 <= self.end.3
111 )) || ((point.1 == self.start.1 || point.1 == self.end.1) && (
112 point.0 >= self.start.0 && point.0 <= self.end.0 && point.2 >= self.start.2 && point.2 <= self.end.2 &&
113 point.3 >= self.start.3 && point.3 <= self.end.3
114 )) || ((point.2 == self.start.2 || point.2 == self.end.2) && (
115 point.0 >= self.start.0 && point.0 <= self.end.0 && point.1 >= self.start.1 && point.1 <= self.end.1 &&
116 point.3 >= self.start.3 && point.3 <= self.end.3
117 )) || ((point.3 == self.start.3 || point.3 == self.end.3) && (
118 point.0 >= self.start.0 && point.0 <= self.end.0 && point.1 >= self.start.1 && point.1 <= self.end.1 &&
119 point.2 >= self.start.2 && point.2 <= self.end.2
120 ))
121 }
122}