From e543d75f89c883510ba0274acb86ce12a5662dfb Mon Sep 17 00:00:00 2001 From: hamusuke2303 Date: Tue, 20 Jun 2023 14:43:25 +0900 Subject: [PATCH] feat: save painter's data --- build.gradle | 3 +- .../hamusuke/paint/server/PaintServer.java | 4 +- .../paint/server/canvas/ServerCanvas.java | 68 +++++++++++++++++-- .../paint/server/network/ServerPainter.java | 17 +++++ .../server/network/ServerPainterData.java | 21 ++++++ .../main/ServerCanvasPacketListenerImpl.java | 7 ++ .../main/ServerCommonPacketListenerImpl.java | 7 ++ .../main/ServerLobbyPacketListenerImpl.java | 2 + 8 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/hamusuke/paint/server/network/ServerPainterData.java diff --git a/build.gradle b/build.gradle index 2083ab7..724c0ff 100644 --- a/build.gradle +++ b/build.gradle @@ -14,12 +14,13 @@ repositories { } dependencies { - implementation 'io.netty:netty-all:4.1.84.Final' + implementation 'io.netty:netty-all:4.1.86.Final' implementation 'com.google.guava:guava:31.1-jre' implementation 'org.apache.logging.log4j:log4j-core:2.19.0' implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'it.unimi.dsi:fastutil:8.5.9' implementation 'com.mojang:brigadier:1.0.18' + implementation 'com.google.code.gson:gson:2.10.1' } jar { diff --git a/src/main/java/com/hamusuke/paint/server/PaintServer.java b/src/main/java/com/hamusuke/paint/server/PaintServer.java index 3b5df7c..b985e62 100644 --- a/src/main/java/com/hamusuke/paint/server/PaintServer.java +++ b/src/main/java/com/hamusuke/paint/server/PaintServer.java @@ -94,7 +94,7 @@ private synchronized void loadAll() { for (File file : files) { ServerCanvas serverCanvas = null; try { - serverCanvas = ServerCanvas.load(file); + serverCanvas = ServerCanvas.load(this, file); } catch (Throwable e) { LOGGER.warn("Error occurred while loading a canvas", e); } @@ -175,7 +175,7 @@ public ServerCanvas getCanvas(int id) { } public void createCanvas(String title, UUID author, int w, int h) { - ServerCanvas serverCanvas = new ServerCanvas(Util.avoidDuplicatingDirectoryName(this.saves, title), UUID.randomUUID(), title, author, w, h); + ServerCanvas serverCanvas = new ServerCanvas(this, Util.avoidDuplicatingDirectoryName(this.saves, title), UUID.randomUUID(), title, author, w, h); this.serverCanvases.add(serverCanvas); serverCanvas.save(); this.getPainterManager().sendPacketToAllInLobby(new CanvasInfoResponseS2CPacket(Collections.singletonList(serverCanvas.getInfo()))); diff --git a/src/main/java/com/hamusuke/paint/server/canvas/ServerCanvas.java b/src/main/java/com/hamusuke/paint/server/canvas/ServerCanvas.java index def67de..608baa3 100644 --- a/src/main/java/com/hamusuke/paint/server/canvas/ServerCanvas.java +++ b/src/main/java/com/hamusuke/paint/server/canvas/ServerCanvas.java @@ -1,8 +1,15 @@ package com.hamusuke.paint.server.canvas; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonWriter; import com.hamusuke.paint.canvas.Canvas; import com.hamusuke.paint.canvas.CanvasInfo; import com.hamusuke.paint.network.LineData; +import com.hamusuke.paint.server.PaintServer; +import com.hamusuke.paint.server.network.ServerPainter; +import com.hamusuke.paint.server.network.ServerPainterData; import com.hamusuke.paint.util.ConcurrentFixedDeque; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -10,28 +17,35 @@ import javax.annotation.Nullable; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; -import java.io.File; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; +import java.io.*; import java.nio.file.Files; import java.util.Deque; import java.util.UUID; public class ServerCanvas extends Canvas { private static final Logger LOGGER = LogManager.getLogger(); + private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + private final PaintServer server; private final File saveDir; + private final File playerSaveDir; private final Deque historic = new ConcurrentFixedDeque<>(10); - public ServerCanvas(File saveDir, UUID uuid, String title, UUID author, int width, int height) { + public ServerCanvas(PaintServer server, File saveDir, UUID uuid, String title, UUID author, int width, int height) { super(uuid, title, author, width, height); + this.server = server; this.saveDir = saveDir; - if (!this.saveDir.exists()) { + if (!this.saveDir.isDirectory() || !this.saveDir.exists()) { this.saveDir.mkdir(); } + + this.playerSaveDir = this.saveDir.toPath().resolve("players").toFile(); + if (!this.playerSaveDir.isDirectory() || !this.playerSaveDir.exists()) { + this.playerSaveDir.mkdir(); + } } @Nullable - public static ServerCanvas load(File saveDir) throws Throwable { + public static ServerCanvas load(PaintServer server, File saveDir) throws Throwable { File[] files = saveDir.listFiles(File::isFile); if (files != null) { CanvasInfo info = null; @@ -47,7 +61,7 @@ public static ServerCanvas load(File saveDir) throws Throwable { } if (info != null && data != null) { - ServerCanvas serverCanvas = new ServerCanvas(saveDir, info.getCanvasUUID(), info.getTitle(), info.getAuthor(), info.getWidth(), info.getHeight()); + ServerCanvas serverCanvas = new ServerCanvas(server, saveDir, info.getCanvasUUID(), info.getTitle(), info.getAuthor(), info.getWidth(), info.getHeight()); serverCanvas.setData(data); return serverCanvas; } @@ -80,5 +94,45 @@ public synchronized void save() { } catch (Exception e) { LOGGER.warn("Error occurred while saving the canvas", e); } + + this.savePlayers(); + } + + private synchronized void savePlayers() { + if (!this.playerSaveDir.exists()) { + this.playerSaveDir.mkdir(); + } + + this.server.getPainterManager().getPainters().stream().filter(painter -> painter.isInCanvas(this)).forEach(this::savePainter); + } + + public void savePainter(ServerPainter painter) { + File data = this.createPlayerDataFile(painter); + try (FileWriter writer = new FileWriter(data)) { + GSON.toJson(painter.serialize(), writer); + } catch (Exception e) { + LOGGER.warn("Error occurred while saving players", e); + } + } + + public void loadPainter(ServerPainter painter) { + File data = this.createPlayerDataFile(painter); + + if (!data.exists()) { + return; + } + + try (FileReader fileReader = new FileReader(data)) { + ServerPainterData painterData = GSON.fromJson(fileReader, ServerPainterData.class); + if (painterData != null) { + painter.deserialize(painterData); + } + } catch (Exception e) { + LOGGER.warn("Error occurred while loading painter data", e); + } + } + + private File createPlayerDataFile(ServerPainter painter) { + return this.playerSaveDir.toPath().resolve(painter.getUuid().toString() + ".json").toFile(); } } diff --git a/src/main/java/com/hamusuke/paint/server/network/ServerPainter.java b/src/main/java/com/hamusuke/paint/server/network/ServerPainter.java index 9210bd4..3c8214b 100644 --- a/src/main/java/com/hamusuke/paint/server/network/ServerPainter.java +++ b/src/main/java/com/hamusuke/paint/server/network/ServerPainter.java @@ -2,6 +2,8 @@ import com.hamusuke.paint.network.Painter; import com.hamusuke.paint.network.protocol.packet.Packet; +import com.hamusuke.paint.network.protocol.packet.s2c.main.ChangeColorS2CPacket; +import com.hamusuke.paint.network.protocol.packet.s2c.main.ChangeWidthS2CPacket; import com.hamusuke.paint.server.PaintServer; import com.hamusuke.paint.server.canvas.ServerCanvas; import com.hamusuke.paint.server.network.main.ServerCommonPacketListenerImpl; @@ -52,4 +54,19 @@ public void sendPacketToOthers(Packet packet, GenericFutureListener packet) { this.server.getPainterManager().sendPacketToAllInCanvas(this, packet); } + + public ServerPainterData serialize() { + return new ServerPainterData(this.getColor(), this.getWidth()); + } + + public void deserialize(ServerPainterData data) { + this.setColor(data.getColor()); + this.setWidth(data.getWidth()); + this.syncPainterData(); + } + + private void syncPainterData() { + this.server.sendPacketToAll(new ChangeColorS2CPacket(this)); + this.server.sendPacketToAll(new ChangeWidthS2CPacket(this)); + } } diff --git a/src/main/java/com/hamusuke/paint/server/network/ServerPainterData.java b/src/main/java/com/hamusuke/paint/server/network/ServerPainterData.java new file mode 100644 index 0000000..a672636 --- /dev/null +++ b/src/main/java/com/hamusuke/paint/server/network/ServerPainterData.java @@ -0,0 +1,21 @@ +package com.hamusuke.paint.server.network; + +import java.awt.*; + +public class ServerPainterData { + private final int color; + private final float width; + + public ServerPainterData(Color color, float width) { + this.color = color.getRGB(); + this.width = width; + } + + public Color getColor() { + return new Color(this.color, true); + } + + public float getWidth() { + return this.width <= 0.0F ? 5.0F : this.width; + } +} diff --git a/src/main/java/com/hamusuke/paint/server/network/main/ServerCanvasPacketListenerImpl.java b/src/main/java/com/hamusuke/paint/server/network/main/ServerCanvasPacketListenerImpl.java index c9bbb9f..36b061d 100644 --- a/src/main/java/com/hamusuke/paint/server/network/main/ServerCanvasPacketListenerImpl.java +++ b/src/main/java/com/hamusuke/paint/server/network/main/ServerCanvasPacketListenerImpl.java @@ -64,8 +64,15 @@ public void handleChangeWidthPacket(ChangeWidthC2SPacket packet) { @Override public void handleLeaveCanvasPacket(LeaveCanvasC2SPacket packet) { + ServerCanvas curCanvas = this.painter.getCurrentCanvas(); + this.painter.joinCanvas(null); new ServerLobbyPacketListenerImpl(this.server, this.connection, this.painter); + + if (curCanvas != null) { + curCanvas.savePainter(this.painter); + } + this.server.sendPacketToAll(new LeaveCanvasS2CPacket(this.painter)); } } diff --git a/src/main/java/com/hamusuke/paint/server/network/main/ServerCommonPacketListenerImpl.java b/src/main/java/com/hamusuke/paint/server/network/main/ServerCommonPacketListenerImpl.java index e3546af..e09c273 100644 --- a/src/main/java/com/hamusuke/paint/server/network/main/ServerCommonPacketListenerImpl.java +++ b/src/main/java/com/hamusuke/paint/server/network/main/ServerCommonPacketListenerImpl.java @@ -11,6 +11,7 @@ import com.hamusuke.paint.network.protocol.packet.s2c.main.PongS2CPacket; import com.hamusuke.paint.network.protocol.packet.s2c.main.RTTS2CPacket; import com.hamusuke.paint.server.PaintServer; +import com.hamusuke.paint.server.canvas.ServerCanvas; import com.hamusuke.paint.server.network.ServerPainter; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -53,6 +54,12 @@ public void handleRTTPacket(RTTC2SPacket packet) { @Override public void onDisconnected() { LOGGER.info("{} lost connection", this.connection.getAddress()); + + ServerCanvas curCanvas = this.painter.getCurrentCanvas(); + if (curCanvas != null) { + curCanvas.savePainter(this.painter); + } + this.painter.sendPacketToOthers(new LeavePainterS2CPacket(this.painter.getId())); this.server.getPainterManager().removePainter(this.painter); if (this.server.isLocal()) { diff --git a/src/main/java/com/hamusuke/paint/server/network/main/ServerLobbyPacketListenerImpl.java b/src/main/java/com/hamusuke/paint/server/network/main/ServerLobbyPacketListenerImpl.java index 257185a..2a9b59c 100644 --- a/src/main/java/com/hamusuke/paint/server/network/main/ServerLobbyPacketListenerImpl.java +++ b/src/main/java/com/hamusuke/paint/server/network/main/ServerLobbyPacketListenerImpl.java @@ -31,6 +31,8 @@ public void handleJoinCanvas(JoinCanvasC2SPacket packet) { this.painter.joinCanvas(canvas); new ServerCanvasPacketListenerImpl(this.server, this.connection, this.painter, canvas); this.server.sendPacketToAll(new JoinCanvasS2CPacket(this.painter, canvas.getInfo())); + + canvas.loadPainter(this.painter); } else { this.connection.sendPacket(new DisconnectS2CPacket(), future -> this.connection.disconnect()); }