Skip to content

Commit

Permalink
Add network packets
Browse files Browse the repository at this point in the history
  • Loading branch information
zbx1425 committed Jul 22, 2023
1 parent 33b7c78 commit cce8cd6
Show file tree
Hide file tree
Showing 7 changed files with 201 additions and 31 deletions.
5 changes: 5 additions & 0 deletions common/src/main/java/cn/zbx1425/worldcomment/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import cn.zbx1425.worldcomment.data.Database;
import cn.zbx1425.worldcomment.item.CommentToolItem;
import cn.zbx1425.worldcomment.network.PacketRequestRegionC2S;
import cn.zbx1425.worldcomment.network.PacketSubmitCommentC2S;
import cn.zbx1425.worldcomment.util.RegistriesWrapper;
import cn.zbx1425.worldcomment.util.RegistryObject;
import net.minecraft.world.item.CreativeModeTabs;
Expand All @@ -23,6 +25,9 @@ public class Main {
public static void init(RegistriesWrapper registries) {
registries.registerItem("comment_tool", ITEM_COMMENT_TOOL, CreativeModeTabs.TOOLS_AND_UTILITIES);

ServerPlatform.registerNetworkReceiver(PacketRequestRegionC2S.IDENTIFIER, PacketRequestRegionC2S::handle);
ServerPlatform.registerNetworkReceiver(PacketSubmitCommentC2S.IDENTIFIER, PacketSubmitCommentC2S::handle);

ServerPlatform.registerServerStartingEvent(server -> {
try {
DATABASE = new Database(server);
Expand Down
4 changes: 3 additions & 1 deletion common/src/main/java/cn/zbx1425/worldcomment/MainClient.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package cn.zbx1425.worldcomment;

import cn.zbx1425.worldcomment.network.PacketRegionDataS2C;

public class MainClient {

public static void init() {

ClientPlatform.registerNetworkReceiver(PacketRegionDataS2C.IDENTIFIER, PacketRegionDataS2C.ClientLogics::handle);
}

}
91 changes: 61 additions & 30 deletions common/src/main/java/cn/zbx1425/worldcomment/data/CommentTable.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package cn.zbx1425.worldcomment.data;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.longs.Long2ObjectAVLTreeMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectSortedMap;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;
Expand All @@ -12,7 +15,6 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Stream;

Expand All @@ -22,34 +24,45 @@ public class CommentTable {

Map<ResourceLocation, Long2ObjectMap<List<CommentEntry>>> regionIndex = new HashMap<>();
Map<UUID, List<CommentEntry>> playerIndex = new HashMap<>();
Long2ObjectSortedMap<CommentEntry> timeIndex = new Long2ObjectAVLTreeMap<>(Comparator.reverseOrder());

public CommentTable(Database db) {
this.db = db;
}

public void load() throws IOException {
Files.createDirectories(db.basePath.resolve("regions"));
for (Level level : db.server.getAllLevels()) {
ResourceLocation dimension = level.dimension().location();
Path levelPath = getLevelPath(dimension);
Files.createDirectory(levelPath);
regionIndex.put(dimension, new Long2ObjectOpenHashMap<>());
try (Stream<Path> files = Files.list(levelPath)) {
for (Path file : files.toList()) {
long region = Long.parseUnsignedLong(file.getFileName().toString().substring(1, 9), 16);
List<CommentEntry> regionEntries = new ArrayList<>();
regionIndex.get(dimension).put(region, regionEntries);

byte[] fileContent = Files.readAllBytes(file);
FriendlyByteBuf src = new FriendlyByteBuf(Unpooled.wrappedBuffer(fileContent));
while (src.readerIndex() < fileContent.length - 1) {
CommentEntry entry = new CommentEntry(dimension, src);
regionEntries.add(entry);
playerIndex.computeIfAbsent(entry.initiator, ignored -> new ArrayList<>())
.add(entry);
if (db.isHost) {
Files.createDirectories(db.basePath.resolve("regions"));
for (Level level : db.server.getAllLevels()) {
ResourceLocation dimension = level.dimension().location();
Path levelPath = getLevelPath(dimension);
Files.createDirectory(levelPath);
try (Stream<Path> files = Files.list(levelPath)) {
for (Path file : files.toList()) {
long region = Long.parseUnsignedLong(file.getFileName().toString().substring(1, 9), 16);
byte[] fileContent = Files.readAllBytes(file);
loadRegion(dimension, region, fileContent);
}
}
}
} else {

}
}

public void loadRegion(ResourceLocation dimension, long region, byte[] data) {
synchronized (this) {
List<CommentEntry> regionEntries = new ArrayList<>();
FriendlyByteBuf src = new FriendlyByteBuf(Unpooled.wrappedBuffer(data));
while (src.readerIndex() < data.length) {
CommentEntry entry = new CommentEntry(dimension, src);
regionEntries.add(entry);
playerIndex.computeIfAbsent(entry.initiator, ignored -> new ArrayList<>())
.add(entry);
timeIndex.put(entry.timestamp, entry);
}
regionIndex.computeIfAbsent(dimension, ignored -> new Long2ObjectOpenHashMap<>())
.put(region, regionEntries);
}
}

Expand All @@ -64,19 +77,37 @@ private Path getLevelRegionPath(ResourceLocation dimension, ChunkPos region) {
.resolve("r" + Long.toHexString(region.toLong()) + ".bin");
}

public List<CommentEntry> queryInRegion(ResourceLocation level, ChunkPos region) throws SQLException {
return regionIndex.get(level).get(region.toLong());
public List<CommentEntry> queryRegion(ResourceLocation level, ChunkPos region) {
synchronized (this) {
return regionIndex.get(level).get(region.toLong());
}
}

public List<CommentEntry> queryPlayer(UUID player) {
synchronized (this) {
return playerIndex.get(player);
}
}

public List<CommentEntry> queryLatest(int offset, int count) {
synchronized (this) {
return timeIndex.values().stream().skip(offset).limit(count).toList();
}
}

public void insert(CommentEntry newEntry) throws IOException {
Path targetFile = getLevelRegionPath(newEntry.level, newEntry.region);
try (FileOutputStream oStream = new FileOutputStream(targetFile.toFile(), true)) {
newEntry.writeFileStream(oStream);
synchronized (this) {
if (db.isHost) {
Path targetFile = getLevelRegionPath(newEntry.level, newEntry.region);
try (FileOutputStream oStream = new FileOutputStream(targetFile.toFile(), true)) {
newEntry.writeFileStream(oStream);
}
}
regionIndex.get(newEntry.level)
.computeIfAbsent(newEntry.region.toLong(), ignored -> new ArrayList<>())
.add(newEntry);
playerIndex.computeIfAbsent(newEntry.initiator, ignored -> new ArrayList<>())
.add(newEntry);
}
regionIndex.get(newEntry.level)
.computeIfAbsent(newEntry.region.toLong(), ignored -> new ArrayList<>())
.add(newEntry);
playerIndex.computeIfAbsent(newEntry.initiator, ignored -> new ArrayList<>())
.add(newEntry);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class Database {
public final MinecraftServer server;
public final Path basePath;

public boolean isHost = true;

public final CommentTable comments;

public Database(MinecraftServer server) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,50 @@
package cn.zbx1425.worldcomment.network;

import cn.zbx1425.worldcomment.ClientPlatform;
import cn.zbx1425.worldcomment.Main;
import cn.zbx1425.worldcomment.ServerPlatform;
import cn.zbx1425.worldcomment.data.CommentEntry;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;

import java.util.List;
import java.util.Map;

public class PacketRegionDataS2C {

public static final ResourceLocation IDENTIFIER = new ResourceLocation(Main.MOD_ID, "region_data");

public static void send(ServerPlayer target, ResourceLocation level, Map<ChunkPos, List<CommentEntry>> data) {
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer());
buffer.writeResourceLocation(level);
buffer.writeInt(data.size());
for (Map.Entry<ChunkPos, List<CommentEntry>> entry : data.entrySet()) {
buffer.writeChunkPos(entry.getKey());
buffer.writeInt(entry.getValue().size());
buffer.writeZero(16 - (buffer.writerIndex() % 16));
for (CommentEntry comment : entry.getValue()) {
comment.writeBuffer(buffer);
}
}
ServerPlatform.sendPacketToPlayer(target, IDENTIFIER, buffer);
}

public static class ClientLogics {

public static void handle(FriendlyByteBuf buffer) {
ResourceLocation level = buffer.readResourceLocation();
int regionSize = buffer.readInt();
for (int i = 0; i < regionSize; i++) {
ChunkPos region = buffer.readChunkPos();
int commentSize = buffer.readInt();
buffer.skipBytes(16 - (buffer.readerIndex() % 16));
for (int j = 0; j < commentSize; j++) {
CommentEntry comment = new CommentEntry(level, buffer);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,45 @@
package cn.zbx1425.worldcomment.network;

import cn.zbx1425.worldcomment.ClientPlatform;
import cn.zbx1425.worldcomment.Main;
import cn.zbx1425.worldcomment.data.CommentEntry;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;

import java.util.List;
import java.util.Map;

public class PacketRequestRegionC2S {

public static final ResourceLocation IDENTIFIER = new ResourceLocation(Main.MOD_ID, "request_region");

public static class ClientLogics {

public static void send(ResourceLocation level, List<ChunkPos> requests) {
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer());
buffer.writeResourceLocation(level);
buffer.writeInt(requests.size());
for (ChunkPos request : requests) {
buffer.writeChunkPos(request);
}
ClientPlatform.sendPacketToServer(IDENTIFIER, buffer);
}
}

public static void handle(MinecraftServer server, ServerPlayer initiator, FriendlyByteBuf buffer) {
ResourceLocation level = buffer.readResourceLocation();
Map<ChunkPos, List<CommentEntry>> results = new Object2ObjectArrayMap<>();
int size = buffer.readInt();
for (int i = 0; i < size; i++) {
ChunkPos request = buffer.readChunkPos();
List<CommentEntry> regionResults = Main.DATABASE.comments.queryRegion(level, request);
results.put(request, regionResults);
}
PacketRegionDataS2C.send(initiator, level, results);
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,47 @@
package cn.zbx1425.worldcomment.network;

import cn.zbx1425.worldcomment.ClientPlatform;
import cn.zbx1425.worldcomment.Main;
import cn.zbx1425.worldcomment.data.CommentEntry;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.ChunkPos;

import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class PacketSubmitCommentC2S {

public static final ResourceLocation IDENTIFIER = new ResourceLocation(Main.MOD_ID, "submit_comment");

public static class ClientLogics {

public static void send(CommentEntry comment) {
FriendlyByteBuf buffer = new FriendlyByteBuf(Unpooled.buffer());
buffer.writeResourceLocation(comment.level);
comment.writeBuffer(buffer);
ClientPlatform.sendPacketToServer(IDENTIFIER, buffer);
}
}

public static void handle(MinecraftServer server, ServerPlayer initiator, FriendlyByteBuf buffer) {
ResourceLocation level = buffer.readResourceLocation();
CommentEntry comment = new CommentEntry(level, buffer);
if (!comment.initiator.equals(Util.NIL_UUID)
&& !comment.initiator.equals(initiator.getGameProfile().getId())) {
return;
}
try {
Main.DATABASE.comments.insert(comment);
} catch (IOException e) {
Main.LOGGER.error("Failed to create comment", e);
}
}
}

0 comments on commit cce8cd6

Please sign in to comment.