Skip to content

Commit 01de5f5

Browse files
committed
Merge remote-tracking branch 'pr18/cc-compat'
2 parents b94617d + 023d9c9 commit 01de5f5

4 files changed

Lines changed: 158 additions & 4 deletions

File tree

src/main/java/com/falsepattern/chunk/api/DataManager.java

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
package com.falsepattern.chunk.api;
2424

25+
import org.jetbrains.annotations.ApiStatus;
2526
import org.jetbrains.annotations.Contract;
2627
import org.jetbrains.annotations.NotNull;
2728
import org.jetbrains.annotations.Nullable;
@@ -84,20 +85,65 @@ interface PacketDataManager extends DataManager {
8485
* Serializes your data into a packet.
8586
*
8687
* @param chunk The chunk to serialize.
88+
* @param subChunkMask The mask that controls which subchunks need to be serialized. This will be 0 when cubic chunks is
89+
* present - only chunk-specific information (like biomes) should be sent in this case.
90+
* @param forceUpdate True when the chunk is first synced.
8791
*/
8892
@Contract(mutates = "param4")
8993
void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer);
9094

9195
/**
9296
* Deserializes your data from a packet.
9397
*
94-
* @param chunk The chunk to deserialize.
95-
* @param buffer The packet buffer to read from.
98+
* @param chunk The chunk to deserialize.
99+
* @param subChunkMask The mask that controls which subchunks need to be deserialized. This will be 0 when cubic chunks is
100+
* present - only chunk-specific information (like biomes) should be sent in this case.
101+
* @param forceUpdate True when the chunk is first synced.
96102
*/
97103
@Contract(mutates = "param1,param4")
98104
void readFromBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer);
99105
}
100106

107+
/**
108+
* A cube-specific variant of {@link PacketDataManager}. This is only used by cubic chunks.
109+
*
110+
* @author RecursivePineapple
111+
* @since 0.7.1
112+
* @apiNote Cubes, subchunks, and ExtendedBlockStorages are equivalent. A cube is a subchunk and a cube contains an EBS.
113+
* To keep dependencies simple, cube-specific information is not available to this interface, but a cube's location can be
114+
* retrieved by combining the chunk location and the EBS Y level. Note that the EBS's Y level can be <0 and >= 16.
115+
*/
116+
@ApiStatus.Experimental
117+
interface CubicPacketDataManager extends DataManager {
118+
119+
/**
120+
* @return The maximum amount of bytes your data can take up in a packet.
121+
*
122+
* @implSpec This is used to determine the size of the packet compression/decompression buffer.
123+
* Only called ONCE, during registration!
124+
*/
125+
@Contract(pure = true)
126+
int maxPacketSizeCubic();
127+
128+
/**
129+
* Serializes your data into a packet.
130+
*
131+
* @param chunk The chunk that contains the subchunk.
132+
* @param blockStorage The subchunk (cube) that was updated.
133+
*/
134+
@Contract(mutates = "param3")
135+
void writeToBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer);
136+
137+
/**
138+
* Deserializes your data from a packet.
139+
*
140+
* @param chunk The chunk that contains the subchunk.
141+
* @param blockStorage The subchunk (cube) that was updated.
142+
*/
143+
@Contract(mutates = "param1,param2,param3")
144+
void readFromBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer);
145+
}
146+
101147
/**
102148
* Implement this interface if you additionally want to synchronize your data on single and multi-block updates,
103149
* not just chunk updates.

src/main/java/com/falsepattern/chunk/internal/DataRegistryImpl.java

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,27 @@ public class DataRegistryImpl {
5959
private static final Map<String, OrderedManager> managersUnordered = new HashMap<>();
6060
private static final SortedSet<OrderedManager> managers = new TreeSet<>();
6161
private static final DualMap<PacketManagerInfo> packetManagers = new DualMap<>();
62+
private static final DualMap<CubicPacketManagerInfo> cubicPacketManagers = new DualMap<>();
6263
private static final DualMap<DataManager.BlockPacketDataManager> blockPacketManagers = new DualMap<>();
6364
private static final DualMap<DataManager.StorageDataManager> NBTManagers = new DualMap<>();
6465
private static final SortedMap<OrderedManager, DataManager.ChunkDataManager> chunkNBTManagers = new TreeMap<>();
6566
private static final SortedMap<OrderedManager, DataManager.SubChunkDataManager> subChunkNBTManagers = new TreeMap<>();
6667
private static final Set<String> disabledManagers = new HashSet<>();
6768
private static int maxPacketSize = 4;
69+
private static int maxPacketSizeCubic = 4;
6870

6971
@Data
7072
private static class PacketManagerInfo {
7173
public final int maxPacketSize;
7274
public final DataManager.PacketDataManager manager;
7375
}
7476

77+
@Data
78+
private static class CubicPacketManagerInfo {
79+
public final int maxPacketSize;
80+
public final DataManager.CubicPacketDataManager manager;
81+
}
82+
7583
public static void registerDataManager(DataManager manager, int ordering) throws IllegalStateException, IllegalArgumentException {
7684
if (Loader.instance().getLoaderState() != LoaderState.INITIALIZATION) {
7785
throw new IllegalStateException("ChunkDataManager registration is not allowed at this time! Please register your ChunkDataManager in the init phase.");
@@ -100,6 +108,12 @@ public static void registerDataManager(DataManager manager, int ordering) throws
100108
val blockPacketManager = (DataManager.BlockPacketDataManager) manager;
101109
blockPacketManagers.put(ord, blockPacketManager);
102110
}
111+
if (manager instanceof DataManager.CubicPacketDataManager) {
112+
val cubicPacketManager = (DataManager.CubicPacketDataManager) manager;
113+
val maxSize = cubicPacketManager.maxPacketSizeCubic();
114+
maxPacketSizeCubic += 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + maxSize;
115+
cubicPacketManagers.put(ord, new CubicPacketManagerInfo(maxSize, cubicPacketManager));
116+
}
103117
if (manager instanceof DataManager.StorageDataManager) {
104118
NBTManagers.put(ord, (DataManager.StorageDataManager) manager);
105119
if (manager instanceof DataManager.ChunkDataManager) {
@@ -127,6 +141,10 @@ public static void disableDataManager(String domain, String id) {
127141
val removed = packetManagers.remove(ord);
128142
maxPacketSize -= 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + removed.maxPacketSize;
129143
}
144+
if (cubicPacketManagers.containsKey(ord)) {
145+
val removed = cubicPacketManagers.remove(ord);
146+
maxPacketSizeCubic -= 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + removed.maxPacketSize;
147+
}
130148
blockPacketManagers.remove(ord);
131149
chunkNBTManagers.remove(ord);
132150
subChunkNBTManagers.remove(ord);
@@ -141,6 +159,10 @@ public static int maxPacketSize() {
141159
return maxPacketSize;
142160
}
143161

162+
public static int maxPacketSizeCubic() {
163+
return maxPacketSizeCubic;
164+
}
165+
144166
private static void writeString(ByteBuffer buffer, String string) {
145167
val bytes = string.getBytes();
146168
buffer.putInt(bytes.length);
@@ -177,6 +199,29 @@ public static void readFromBuffer(Chunk chunk, int subChunkMask, boolean forceUp
177199
}
178200
}
179201

202+
public static void readFromBufferCubic(Chunk chunk, ExtendedBlockStorage blockStorage, byte[] data) {
203+
val buf = ByteBuffer.wrap(data);
204+
buf.order(ByteOrder.LITTLE_ENDIAN);
205+
int count = buf.getInt();
206+
for (int i = 0; i < count; i++) {
207+
val id = readString(buf);
208+
val length = buf.getInt();
209+
val managerInfo = cubicPacketManagers.get(id);
210+
if (managerInfo == null) {
211+
Common.LOG.error("Received data for unknown CubicPacketDataManager " + id + ". Skipping.");
212+
buf.position(buf.position() + length);
213+
continue;
214+
}
215+
if (length > managerInfo.maxPacketSize) {
216+
Common.LOG.error("Received packet larger than max size for CubicPacketDataManager " + id + "! Continuing anyways, things might break!");
217+
}
218+
int start = buf.position();
219+
val slice = createSlice(buf, start, length);
220+
managerInfo.manager.readFromBuffer(chunk, blockStorage, slice);
221+
buf.position(start + length);
222+
}
223+
}
224+
180225
public static int writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, byte[] data) {
181226
val buf = ByteBuffer.wrap(data);
182227
buf.order(ByteOrder.LITTLE_ENDIAN);
@@ -195,6 +240,24 @@ public static int writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpda
195240
return buf.position();
196241
}
197242

243+
public static int writeToBufferCubic(Chunk chunk, ExtendedBlockStorage blockStorage, byte[] data) {
244+
val buf = ByteBuffer.wrap(data);
245+
buf.order(ByteOrder.LITTLE_ENDIAN);
246+
buf.putInt(cubicPacketManagers.size());
247+
for (val pair : cubicPacketManagers.entrySet()) {
248+
val ord = pair.getKey();
249+
val managerInfo = pair.getValue();
250+
writeString(buf, ord.id);
251+
int start = buf.position() + 4;
252+
val slice = createSlice(buf, start, managerInfo.maxPacketSize);
253+
managerInfo.manager.writeToBuffer(chunk, blockStorage, slice);
254+
int length = slice.position();
255+
buf.putInt(length);
256+
buf.position(start + length);
257+
}
258+
return buf.position();
259+
}
260+
198261
public static void writeBlockToPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet) {
199262
for (val manager : blockPacketManagers.values()) {
200263
manager.writeBlockToPacket(chunk, x, y, z, packet);

src/main/java/com/falsepattern/chunk/internal/vanilla/BlockIDManager.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
import static com.falsepattern.chunk.internal.Common.BLOCKS_PER_SUBCHUNK;
4141
import static com.falsepattern.chunk.internal.Common.SUBCHUNKS_PER_CHUNK;
4242

43-
public class BlockIDManager extends VanillaManager implements DataManager.PacketDataManager, DataManager.BlockPacketDataManager, DataManager.SubChunkDataManager {
43+
public class BlockIDManager extends VanillaManager implements DataManager.PacketDataManager, DataManager.CubicPacketDataManager, DataManager.BlockPacketDataManager, DataManager.SubChunkDataManager {
4444
private static final int LSB_BYTES_PER_SUBCHUNK = BLOCKS_PER_SUBCHUNK;
4545
private static final int MSB_BYTES_PER_SUBCHUNK = BLOCKS_PER_SUBCHUNK / 2;
4646
private static final int HEADER_SIZE = 2;
@@ -100,6 +100,36 @@ public void readFromBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, B
100100
}
101101
}
102102

103+
@Override
104+
public int maxPacketSizeCubic() {
105+
return HEADER_SIZE + LSB_BYTES_PER_SUBCHUNK + MSB_BYTES_PER_SUBCHUNK;
106+
}
107+
108+
@Override
109+
public void writeToBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
110+
buffer.put(blockStorage.getBlockLSBArray());
111+
112+
if (blockStorage.getBlockMSBArray() != null) {
113+
buffer.put((byte) 1);
114+
buffer.put(blockStorage.getBlockMSBArray().data);
115+
} else {
116+
buffer.put((byte) 0);
117+
}
118+
}
119+
120+
@Override
121+
public void readFromBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
122+
buffer.get(blockStorage.getBlockLSBArray());
123+
124+
if (buffer.get() != 0) {
125+
if (blockStorage.getBlockMSBArray() == null) {
126+
blockStorage.createBlockMSBArray();
127+
}
128+
129+
buffer.get(blockStorage.getBlockMSBArray().data);
130+
}
131+
}
132+
103133
@Override
104134
public boolean subChunkPrivilegedAccess() {
105135
return true;

src/main/java/com/falsepattern/chunk/internal/vanilla/NibbleManager.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
import java.nio.ByteBuffer;
3434

35-
public abstract class NibbleManager extends VanillaManager implements DataManager.PacketDataManager {
35+
public abstract class NibbleManager extends VanillaManager implements DataManager.PacketDataManager, DataManager.CubicPacketDataManager {
3636
public static final int BYTES_PER_SUBCHUNK = Common.BLOCKS_PER_SUBCHUNK / 2;
3737

3838
protected abstract NibbleArray getNibbleArray(ExtendedBlockStorage subChunk);
@@ -67,4 +67,19 @@ public void readFromBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, B
6767
}
6868
}
6969
}
70+
71+
@Override
72+
public int maxPacketSizeCubic() {
73+
return BYTES_PER_SUBCHUNK;
74+
}
75+
76+
@Override
77+
public void writeToBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
78+
buffer.put(getNibbleArray(blockStorage).data, 0, BYTES_PER_SUBCHUNK);
79+
}
80+
81+
@Override
82+
public void readFromBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
83+
buffer.get(getNibbleArray(blockStorage).data, 0, BYTES_PER_SUBCHUNK);
84+
}
7085
}

0 commit comments

Comments
 (0)