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
|
use types;
use strings;
type BstateId = u32;
type BlockPropId = u32;
type BlockBstates = struct {
state0: BstateId,
nstates: u32,
props: [](str, []str),
prop_moduli: []u32,
};
type BstateInfo = struct {
block: BlockId,
};
let BLOCKS_BSTATES: []BlockBstates = [];
let BSTATES_INFO: []BstateInfo = [];
fn bstates_handle_blocks_onregister(blk: BlockId) void = {
append(BLOCKS_BSTATES, BlockBstates { ... });
};
fn block_addprop(blk: BlockId, name: str, values: []str) BlockPropId = {
assert(len(values) != 0, "Block property must have at least 1 value");
const bstates = &BLOCKS_BSTATES[blk];
assert(len(bstates.props) < types::U32_MAX - 1,
"Too many block properties");
append(bstates.props, (strings::dup(name), strings::dupall(values)));
return len(bstates.props): u32 - 1;
};
fn init_bstates() void = {
for (let blk: BlockId = 0; blk < blocks_count(); blk += 1) {
const bstates = &BLOCKS_BSTATES[blk];
bstates.prop_moduli = alloc([], len(bstates.props));
let mod = 1u32;
for (let j = 0z; j < len(bstates.props); j += 1) {
// TODO: overflow...
mod *= len(bstates.props[j].1): u32;
static append(bstates.prop_moduli, mod);
};
bstates.state0 = len(BSTATES_INFO): u32;
bstates.nstates = mod;
assert(bstates.state0 + bstates.nstates > bstates.state0,
"Too many blockstates");
for (let j = 0u32; j < mod; j += 1) {
append(BSTATES_INFO, BstateInfo {
block = blk,
});
};
};
};
fn destroy_bstates() void = {
for (let blk: BlockId = 0; blk < blocks_count(); blk += 1) {
const bstates = &BLOCKS_BSTATES[blk];
for (let i = 0z; i < len(bstates.props); i += 1) {
free(bstates.props[i].0);
strings::freeall(bstates.props[i].1);
};
free(bstates.prop_moduli);
};
free(BLOCKS_BSTATES);
free(BSTATES_INFO);
};
fn block_propcount(blk: BlockId) u32 =
len(BLOCKS_BSTATES[blk].props): u32;
fn block_propname(blk: BlockId, prop: BlockPropId) str =
BLOCKS_BSTATES[blk].props[prop].0;
fn block_findprop(blk: BlockId, name: str) (BlockPropId | void) = {
for (let prop: BlockPropId = 0;
prop < block_propcount(blk); prop += 1) {
if (block_propname(blk, prop) == name)
return prop;
};
};
fn block_propvalcount(blk: BlockId, prop: BlockPropId) u32 =
len(BLOCKS_BSTATES[blk].props[prop].1): u32;
fn block_propvalname(blk: BlockId, prop: BlockPropId, val: u32) str =
BLOCKS_BSTATES[blk].props[prop].1[val];
fn block_findpropval(blk: BlockId, prop: BlockPropId, name: str)
(u32 | void) = {
for (let val = 0u32; val < block_propvalcount(blk, prop); val += 1) {
if (block_propvalname(blk, prop, val) == name)
return val;
};
};
fn bstate_getblock(bstate: BstateId) BlockId =
BSTATES_INFO[bstate].block;
fn bstate_getprop(bstate: BstateId, blk: BlockId, prop: BlockPropId) u32 = {
const bstates = &BLOCKS_BSTATES[blk];
return (bstate - bstates.state0) % bstates.prop_moduli[prop]
/ (if (prop == 0) 1u32 else bstates.prop_moduli[prop - 1]);
};
|