/
BlockStorage.java
133 lines (103 loc) · 4.13 KB
/
BlockStorage.java
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
package org.spacehq.mc.protocol.data.game.chunk;
import org.spacehq.mc.protocol.data.game.world.block.BlockState;
import org.spacehq.mc.protocol.util.NetUtil;
import org.spacehq.packetlib.io.NetInput;
import org.spacehq.packetlib.io.NetOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BlockStorage {
private static final BlockState AIR = new BlockState(0, 0);
private int bitsPerEntry;
private List<BlockState> states;
private FlexibleStorage storage;
public BlockStorage() {
this.bitsPerEntry = 4;
this.states = new ArrayList<BlockState>();
this.states.add(AIR);
this.storage = new FlexibleStorage(this.bitsPerEntry, 4096);
}
public BlockStorage(NetInput in) throws IOException {
this.bitsPerEntry = in.readUnsignedByte();
this.states = new ArrayList<BlockState>();
int stateCount = in.readVarInt();
for(int i = 0; i < stateCount; i++) {
this.states.add(NetUtil.readBlockState(in));
}
this.storage = new FlexibleStorage(this.bitsPerEntry, in.readLongs(in.readVarInt()));
}
public void write(NetOutput out) throws IOException {
out.writeByte(this.bitsPerEntry);
out.writeVarInt(this.states.size());
for(BlockState state : this.states) {
NetUtil.writeBlockState(out, state);
}
long[] data = this.storage.getData();
out.writeVarInt(data.length);
out.writeLongs(data);
}
public int getBitsPerEntry() {
return this.bitsPerEntry;
}
public List<BlockState> getStates() {
return Collections.unmodifiableList(this.states);
}
public FlexibleStorage getStorage() {
return this.storage;
}
public BlockState get(int x, int y, int z) {
int id = this.storage.get(index(x, y, z));
return this.bitsPerEntry <= 8 ? (id >= 0 && id < this.states.size() ? this.states.get(id) : AIR) : rawToState(id);
}
public void set(int x, int y, int z, BlockState state) {
int id = this.bitsPerEntry <= 8 ? this.states.indexOf(state) : stateToRaw(state);
if(id == -1) {
this.states.add(state);
if(this.states.size() > 1 << this.bitsPerEntry) {
this.bitsPerEntry++;
List<BlockState> oldStates = this.states;
if(this.bitsPerEntry > 8) {
oldStates = new ArrayList<BlockState>(this.states);
this.states.clear();
this.bitsPerEntry = 13;
}
FlexibleStorage oldStorage = this.storage;
this.storage = new FlexibleStorage(this.bitsPerEntry, this.storage.getSize());
for(int index = 0; index < this.storage.getSize(); index++) {
this.storage.set(index, this.bitsPerEntry <= 8 ? oldStorage.get(index) : stateToRaw(oldStates.get(index)));
}
}
id = this.bitsPerEntry <= 8 ? this.states.indexOf(state) : stateToRaw(state);
}
this.storage.set(index(x, y, z), id);
}
public boolean isEmpty() {
for(int index = 0; index < this.storage.getSize(); index++) {
if(this.storage.get(index) != 0) {
return false;
}
}
return true;
}
private static int index(int x, int y, int z) {
return y << 8 | z << 4 | x;
}
private static BlockState rawToState(int raw) {
return new BlockState(raw >> 4, raw & 0xF);
}
private static int stateToRaw(BlockState state) {
return (state.getId() << 4) | (state.getData() & 0xF);
}
@Override
public boolean equals(Object o) {
return o instanceof BlockStorage && this.bitsPerEntry == ((BlockStorage) o).bitsPerEntry && this.states.equals(((BlockStorage) o).states) && this.storage.equals(((BlockStorage) o).storage);
}
@Override
public int hashCode() {
int result = this.bitsPerEntry;
result = 31 * result + this.states.hashCode();
result = 31 * result + this.storage.hashCode();
return result;
}
}