mirror of
https://github.com/LegacyModdingMC/ChunkAPI.git
synced 2026-11-12 16:37:41 +00:00
Merge branch 'master' of https://github.com/Cardinalstars/ChunkAPI-Cardinalstar
This commit is contained in:
commit
68f297faba
4 files changed
+158
-4
No files matched your search
@@ -22,6 +22,7 @@
|
||||
|
||||
package com.falsepattern.chunk.api;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -84,6 +85,9 @@ public interface DataManager {
|
||||
* Serializes your data into a packet.
|
||||
*
|
||||
* @param chunk The chunk to serialize.
|
||||
* @param subChunkMask The mask that controls which subchunks need to be serialized. This will be 0 when cubic chunks is
|
||||
* present - only chunk-specific information (like biomes) should be sent in this case.
|
||||
* @param forceUpdate True when the chunk is first synced.
|
||||
*/
|
||||
@Contract(mutates = "param4")
|
||||
void writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer);
|
||||
@@ -91,13 +95,55 @@ public interface DataManager {
|
||||
/**
|
||||
* Deserializes your data from a packet.
|
||||
*
|
||||
* @param chunk The chunk to deserialize.
|
||||
* @param buffer The packet buffer to read from.
|
||||
* @param chunk The chunk to deserialize.
|
||||
* @param subChunkMask The mask that controls which subchunks need to be deserialized. This will be 0 when cubic chunks is
|
||||
* present - only chunk-specific information (like biomes) should be sent in this case.
|
||||
* @param forceUpdate True when the chunk is first synced.
|
||||
*/
|
||||
@Contract(mutates = "param1,param4")
|
||||
void readFromBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, ByteBuffer buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* A cube-specific variant of {@link PacketDataManager}. This is only used by cubic chunks.
|
||||
*
|
||||
* @author RecursivePineapple
|
||||
* @since 0.7.1
|
||||
* @apiNote Cubes, subchunks, and ExtendedBlockStorages are equivalent. A cube is a subchunk and a cube contains an EBS.
|
||||
* To keep dependencies simple, cube-specific information is not available to this interface, but a cube's location can be
|
||||
* retrieved by combining the chunk location and the EBS Y level. Note that the EBS's Y level can be <0 and >= 16.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
interface CubicPacketDataManager extends DataManager {
|
||||
|
||||
/**
|
||||
* @return The maximum amount of bytes your data can take up in a packet.
|
||||
*
|
||||
* @implSpec This is used to determine the size of the packet compression/decompression buffer.
|
||||
* Only called ONCE, during registration!
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
int maxPacketSizeCubic();
|
||||
|
||||
/**
|
||||
* Serializes your data into a packet.
|
||||
*
|
||||
* @param chunk The chunk that contains the subchunk.
|
||||
* @param blockStorage The subchunk (cube) that was updated.
|
||||
*/
|
||||
@Contract(mutates = "param3")
|
||||
void writeToBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer);
|
||||
|
||||
/**
|
||||
* Deserializes your data from a packet.
|
||||
*
|
||||
* @param chunk The chunk that contains the subchunk.
|
||||
* @param blockStorage The subchunk (cube) that was updated.
|
||||
*/
|
||||
@Contract(mutates = "param1,param2,param3")
|
||||
void readFromBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implement this interface if you additionally want to synchronize your data on single and multi-block updates,
|
||||
* not just chunk updates.
|
||||
|
||||
@@ -59,12 +59,14 @@ public class DataRegistryImpl {
|
||||
private static final Map<String, OrderedManager> managersUnordered = new HashMap<>();
|
||||
private static final SortedSet<OrderedManager> managers = new TreeSet<>();
|
||||
private static final DualMap<PacketManagerInfo> packetManagers = new DualMap<>();
|
||||
private static final DualMap<CubicPacketManagerInfo> cubicPacketManagers = new DualMap<>();
|
||||
private static final DualMap<DataManager.BlockPacketDataManager> blockPacketManagers = new DualMap<>();
|
||||
private static final DualMap<DataManager.StorageDataManager> NBTManagers = new DualMap<>();
|
||||
private static final SortedMap<OrderedManager, DataManager.ChunkDataManager> chunkNBTManagers = new TreeMap<>();
|
||||
private static final SortedMap<OrderedManager, DataManager.SubChunkDataManager> subChunkNBTManagers = new TreeMap<>();
|
||||
private static final Set<String> disabledManagers = new HashSet<>();
|
||||
private static int maxPacketSize = 4;
|
||||
private static int maxPacketSizeCubic = 4;
|
||||
|
||||
@Data
|
||||
private static class PacketManagerInfo {
|
||||
@@ -72,6 +74,12 @@ public class DataRegistryImpl {
|
||||
public final DataManager.PacketDataManager manager;
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class CubicPacketManagerInfo {
|
||||
public final int maxPacketSize;
|
||||
public final DataManager.CubicPacketDataManager manager;
|
||||
}
|
||||
|
||||
public static void registerDataManager(DataManager manager, int ordering) throws IllegalStateException, IllegalArgumentException {
|
||||
if (Loader.instance().getLoaderState() != LoaderState.INITIALIZATION) {
|
||||
throw new IllegalStateException("ChunkDataManager registration is not allowed at this time! Please register your ChunkDataManager in the init phase.");
|
||||
@@ -100,6 +108,12 @@ public class DataRegistryImpl {
|
||||
val blockPacketManager = (DataManager.BlockPacketDataManager) manager;
|
||||
blockPacketManagers.put(ord, blockPacketManager);
|
||||
}
|
||||
if (manager instanceof DataManager.CubicPacketDataManager) {
|
||||
val cubicPacketManager = (DataManager.CubicPacketDataManager) manager;
|
||||
val maxSize = cubicPacketManager.maxPacketSizeCubic();
|
||||
maxPacketSizeCubic += 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + maxSize;
|
||||
cubicPacketManagers.put(ord, new CubicPacketManagerInfo(maxSize, cubicPacketManager));
|
||||
}
|
||||
if (manager instanceof DataManager.StorageDataManager) {
|
||||
NBTManagers.put(ord, (DataManager.StorageDataManager) manager);
|
||||
if (manager instanceof DataManager.ChunkDataManager) {
|
||||
@@ -127,6 +141,10 @@ public class DataRegistryImpl {
|
||||
val removed = packetManagers.remove(ord);
|
||||
maxPacketSize -= 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + removed.maxPacketSize;
|
||||
}
|
||||
if (cubicPacketManagers.containsKey(ord)) {
|
||||
val removed = cubicPacketManagers.remove(ord);
|
||||
maxPacketSizeCubic -= 4 + id.getBytes(StandardCharsets.UTF_8).length + 4 + removed.maxPacketSize;
|
||||
}
|
||||
blockPacketManagers.remove(ord);
|
||||
chunkNBTManagers.remove(ord);
|
||||
subChunkNBTManagers.remove(ord);
|
||||
@@ -141,6 +159,10 @@ public class DataRegistryImpl {
|
||||
return maxPacketSize;
|
||||
}
|
||||
|
||||
public static int maxPacketSizeCubic() {
|
||||
return maxPacketSizeCubic;
|
||||
}
|
||||
|
||||
private static void writeString(ByteBuffer buffer, String string) {
|
||||
val bytes = string.getBytes();
|
||||
buffer.putInt(bytes.length);
|
||||
@@ -177,6 +199,29 @@ public class DataRegistryImpl {
|
||||
}
|
||||
}
|
||||
|
||||
public static void readFromBufferCubic(Chunk chunk, ExtendedBlockStorage blockStorage, byte[] data) {
|
||||
val buf = ByteBuffer.wrap(data);
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
int count = buf.getInt();
|
||||
for (int i = 0; i < count; i++) {
|
||||
val id = readString(buf);
|
||||
val length = buf.getInt();
|
||||
val managerInfo = cubicPacketManagers.get(id);
|
||||
if (managerInfo == null) {
|
||||
Common.LOG.error("Received data for unknown CubicPacketDataManager " + id + ". Skipping.");
|
||||
buf.position(buf.position() + length);
|
||||
continue;
|
||||
}
|
||||
if (length > managerInfo.maxPacketSize) {
|
||||
Common.LOG.error("Received packet larger than max size for CubicPacketDataManager " + id + "! Continuing anyways, things might break!");
|
||||
}
|
||||
int start = buf.position();
|
||||
val slice = createSlice(buf, start, length);
|
||||
managerInfo.manager.readFromBuffer(chunk, blockStorage, slice);
|
||||
buf.position(start + length);
|
||||
}
|
||||
}
|
||||
|
||||
public static int writeToBuffer(Chunk chunk, int subChunkMask, boolean forceUpdate, byte[] data) {
|
||||
val buf = ByteBuffer.wrap(data);
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
@@ -195,6 +240,24 @@ public class DataRegistryImpl {
|
||||
return buf.position();
|
||||
}
|
||||
|
||||
public static int writeToBufferCubic(Chunk chunk, ExtendedBlockStorage blockStorage, byte[] data) {
|
||||
val buf = ByteBuffer.wrap(data);
|
||||
buf.order(ByteOrder.LITTLE_ENDIAN);
|
||||
buf.putInt(cubicPacketManagers.size());
|
||||
for (val pair : cubicPacketManagers.entrySet()) {
|
||||
val ord = pair.getKey();
|
||||
val managerInfo = pair.getValue();
|
||||
writeString(buf, ord.id);
|
||||
int start = buf.position() + 4;
|
||||
val slice = createSlice(buf, start, managerInfo.maxPacketSize);
|
||||
managerInfo.manager.writeToBuffer(chunk, blockStorage, slice);
|
||||
int length = slice.position();
|
||||
buf.putInt(length);
|
||||
buf.position(start + length);
|
||||
}
|
||||
return buf.position();
|
||||
}
|
||||
|
||||
public static void writeBlockToPacket(Chunk chunk, int x, int y, int z, S23PacketBlockChange packet) {
|
||||
for (val manager : blockPacketManagers.values()) {
|
||||
manager.writeBlockToPacket(chunk, x, y, z, packet);
|
||||
|
||||
@@ -40,7 +40,7 @@ import java.nio.ByteBuffer;
|
||||
import static com.falsepattern.chunk.internal.Common.BLOCKS_PER_SUBCHUNK;
|
||||
import static com.falsepattern.chunk.internal.Common.SUBCHUNKS_PER_CHUNK;
|
||||
|
||||
public class BlockIDManager extends VanillaManager implements DataManager.PacketDataManager, DataManager.BlockPacketDataManager, DataManager.SubChunkDataManager {
|
||||
public class BlockIDManager extends VanillaManager implements DataManager.PacketDataManager, DataManager.CubicPacketDataManager, DataManager.BlockPacketDataManager, DataManager.SubChunkDataManager {
|
||||
private static final int LSB_BYTES_PER_SUBCHUNK = BLOCKS_PER_SUBCHUNK;
|
||||
private static final int MSB_BYTES_PER_SUBCHUNK = BLOCKS_PER_SUBCHUNK / 2;
|
||||
private static final int HEADER_SIZE = 2;
|
||||
@@ -100,6 +100,36 @@ public class BlockIDManager extends VanillaManager implements DataManager.Packet
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxPacketSizeCubic() {
|
||||
return HEADER_SIZE + LSB_BYTES_PER_SUBCHUNK + MSB_BYTES_PER_SUBCHUNK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
|
||||
buffer.put(blockStorage.getBlockLSBArray());
|
||||
|
||||
if (blockStorage.getBlockMSBArray() != null) {
|
||||
buffer.put((byte) 1);
|
||||
buffer.put(blockStorage.getBlockMSBArray().data);
|
||||
} else {
|
||||
buffer.put((byte) 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
|
||||
buffer.get(blockStorage.getBlockLSBArray());
|
||||
|
||||
if (buffer.get() != 0) {
|
||||
if (blockStorage.getBlockMSBArray() == null) {
|
||||
blockStorage.createBlockMSBArray();
|
||||
}
|
||||
|
||||
buffer.get(blockStorage.getBlockMSBArray().data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean subChunkPrivilegedAccess() {
|
||||
return true;
|
||||
|
||||
@@ -32,7 +32,7 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public abstract class NibbleManager extends VanillaManager implements DataManager.PacketDataManager {
|
||||
public abstract class NibbleManager extends VanillaManager implements DataManager.PacketDataManager, DataManager.CubicPacketDataManager {
|
||||
public static final int BYTES_PER_SUBCHUNK = Common.BLOCKS_PER_SUBCHUNK / 2;
|
||||
|
||||
protected abstract NibbleArray getNibbleArray(ExtendedBlockStorage subChunk);
|
||||
@@ -67,4 +67,19 @@ public abstract class NibbleManager extends VanillaManager implements DataManage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxPacketSizeCubic() {
|
||||
return BYTES_PER_SUBCHUNK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
|
||||
buffer.put(getNibbleArray(blockStorage).data, 0, BYTES_PER_SUBCHUNK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFromBuffer(Chunk chunk, ExtendedBlockStorage blockStorage, ByteBuffer buffer) {
|
||||
buffer.get(getNibbleArray(blockStorage).data, 0, BYTES_PER_SUBCHUNK);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user