Archived
0

JSON вместо String

This commit is contained in:
2021-04-28 18:47:31 +03:00
parent f4f796c3a4
commit 09a3d16b77
9 changed files with 171 additions and 90 deletions

View File

@@ -15,7 +15,8 @@ ext {
lang3 : 'org.apache.commons:commons-lang3:3.11',
netty : 'io.netty:netty-all:4.1.22.Final',
reactor : 'io.projectreactor:reactor-core:3.4.5',
yaml : 'org.yaml:snakeyaml:1.28'
yaml : 'org.yaml:snakeyaml:1.28',
json : 'com.eclipsesource.minimal-json:minimal-json:0.9.5'
]
libs.logger = [

View File

@@ -4,6 +4,7 @@ dependencies {
implementation libs.netty
implementation libs.reactor
implementation libs.guava
implementation libs.json
testImplementation libs.lang3
}

View File

@@ -10,7 +10,7 @@ import mc.protocol.packets.client.HandshakePacket;
import mc.protocol.packets.client.LoginStartPacket;
import mc.protocol.packets.client.StatusServerRequestPacket;
import mc.protocol.packets.server.DisconnectPacket;
import mc.protocol.packets.server.StatusServerResponsePacket;
import mc.protocol.packets.server.StatusServerResponse;
import javax.annotation.Nullable;
import java.util.Collections;
@@ -31,7 +31,7 @@ public enum State {
),
// server side
Map.of(
StatusServerResponsePacket.class, 0x00,
StatusServerResponse.class, 0x00,
PingPacket.class, 0x01
)
),

View File

@@ -0,0 +1,47 @@
package mc.protocol.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.RequiredArgsConstructor;
import lombok.EqualsAndHashCode;
import java.util.List;
@Getter
@Setter
@ToString
public class ServerInfo {
private final Version version = new Version();
private final Players players = new Players();
private String description;
private String favicon;
@Getter
@Setter
@ToString
public static class Version {
private String name;
private int protocol;
}
@Getter
@Setter
@ToString
public static class Players {
private int max;
private int online;
private List<SamplePlayer> sample;
}
@RequiredArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public static class SamplePlayer {
private final String id;
private final String name;
}
}

View File

@@ -0,0 +1 @@
lombok.accessors.fluent=true

View File

@@ -1,5 +1,6 @@
package mc.protocol.packets.server;
import com.eclipsesource.json.Json;
import lombok.Data;
import mc.protocol.State;
import mc.protocol.io.NetByteBuf;
@@ -12,9 +13,16 @@ import mc.protocol.packets.ServerSidePacket;
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |--------|------|----------------------------------|
* | Reason | Text | Причина отключения. Опционально. |
* | FIELD | TYPE | NOTES |
* |-------------|--------|----------------------------------|
* | JSON Reason | String | Причина отключения. Опционально. |
* </pre>
*
* <p>Пример JSON Reason</p>
* <pre>
* {
* "text": "foo"
* }
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Disconnect_2" target="_top">Disconnect</a>
@@ -25,18 +33,11 @@ public class DisconnectPacket implements ServerSidePacket {
/**
* Причина отключения.
*
* <p>Пример:</p>
* <pre>
* {
* "text": "foo"
* }
* </pre>
*/
private String reason;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeString(reason);
netByteBuf.writeString(Json.object().add("text", reason).toString());
}
}

View File

@@ -0,0 +1,92 @@
package mc.protocol.packets.server;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.Streams;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.ServerInfo;
import mc.protocol.packets.ServerSidePacket;
import java.util.stream.Collector;
/**
* Status server packet, response.
*
* <p>Информация о сервере</p>
*
* <p>Структура пакета
* <pre>
* | FIELD | TYPE | NOTES |
* |---------------|--------|-----------------------------------------|
* | JSON Response | String | Информация о сервере в JSON формате [1] |
*
* [1] - <a href="https://wiki.vg/index.php?title=Server_List_Ping&oldid=7555#Response" target="_top">Server List Ping: Response</a>
* </pre>
*
* <p>Пример JSON Response</p>
* <pre>
* {
* "version": {
* "name": "1.8.7",
* "protocol": 47
* },
* "players": {
* "max": 100,
* "online": 5,
* "sample": [
* {
* "name": "thinkofdeath",
* "id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
* }
* ]
* },
* "description": {
* "text": "Hello world"
* },
* "favicon": "data:image/png;base64,&lt;data&gt;"
* }
* </pre>
*/
@Data
public class StatusServerResponse implements ServerSidePacket {
/**
* Информация о серере.
*/
private ServerInfo info;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeString(Json.object()
.add("version", createVersionObj())
.add("players", createPlayersObj())
.add("description", Json.object().add("text", info.description()))
.toString());
}
private JsonObject createVersionObj() {
return Json.object()
.add("name", info.version().name())
.add("protocol", info.version().protocol());
}
private JsonObject createPlayersObj() {
JsonArray sampleArr = info.players().sample().stream()
.map(samplePlayer -> Json.object()
.add("name", samplePlayer.name())
.add("id", samplePlayer.id()))
.collect(Collector.of(Json::array, JsonArray::add, StatusServerResponse::jsonArrayAddAll));
return Json.object()
.add("max", info.players().max())
.add("online", info.players().online())
.add("sample", sampleArr);
}
private static JsonArray jsonArrayAddAll(JsonArray jsonArrayTo, JsonArray jsonArrayFrom) {
Streams.stream(jsonArrayFrom).forEach(jsonArrayTo::add);
return jsonArrayTo;
}
}

View File

@@ -1,57 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
/**
* Status server packet, response.
*
* <p>Информация о сервере</p>
*
* <p>Структура пакета
* <pre>
* | FIELD | TYPE | NOTES |
* |---------------|--------|-----------------------------------------|
* | JSON Response | String | Информация о сервере в JSON формате [1] |
*
* [1] - <a href="https://wiki.vg/index.php?title=Server_List_Ping&oldid=7555#Response" target="_top">Server List Ping: Response</a>
* </pre></p>
*/
@Data
public class StatusServerResponsePacket implements ServerSidePacket {
/**
* Информация о серере в формате JSON
*
* <p>Пример</p>
* <pre>
* {
* "version": {
* "name": "1.8.7",
* "protocol": 47
* },
* "players": {
* "max": 100,
* "online": 5,
* "sample": [
* {
* "name": "thinkofdeath",
* "id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
* }
* ]
* },
* "description": {
* "text": "Hello world"
* },
* "favicon": "data:image/png;base64,&lt;data&gt;"
* }
* </pre>
*/
private String info;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeString(info);
}
}

View File

@@ -3,18 +3,20 @@ package mc.server;
import lombok.extern.slf4j.Slf4j;
import mc.protocol.NettyServer;
import mc.protocol.ProtocolConstant;
import mc.protocol.model.ServerInfo;
import mc.protocol.packets.PingPacket;
import mc.protocol.packets.client.HandshakePacket;
import mc.protocol.packets.client.LoginStartPacket;
import mc.protocol.packets.client.StatusServerRequestPacket;
import mc.protocol.packets.server.DisconnectPacket;
import mc.protocol.packets.server.StatusServerResponsePacket;
import mc.protocol.packets.server.StatusServerResponse;
import mc.server.config.Config;
import mc.server.di.ConfigModule;
import mc.server.di.DaggerServerComponent;
import mc.server.di.ServerComponent;
import java.nio.file.Paths;
import java.util.Collections;
@Slf4j
public class Main {
@@ -48,21 +50,16 @@ public class Main {
server.packetFlux(StatusServerRequestPacket.class)
.doOnNext(channel -> log.info("{}", channel.getPacket()))
.subscribe(channel -> {
StatusServerResponsePacket response = new StatusServerResponsePacket();
response.setInfo("{\n" +
" \"version\": {\n" +
" \"name\": \"" + ProtocolConstant.PROTOCOL_NAME + "\",\n" +
" \"protocol\": " + ProtocolConstant.PROTOCOL_NUMBER + "\n" +
" },\n" +
" \"players\": {\n" +
" \"max\": " + config.players().maxOnlile() + ",\n" +
" \"online\": " + config.players().onlile() + ",\n" +
" \"sample\": []\n" +
" },\n" +
" \"description\": {\n" +
" \"text\": \"" + config.motd() + "\"\n" +
" }\n" +
"}");
ServerInfo serverInfo = new ServerInfo();
serverInfo.version().name(ProtocolConstant.PROTOCOL_NAME);
serverInfo.version().protocol(ProtocolConstant.PROTOCOL_NUMBER);
serverInfo.players().max(config.players().maxOnlile());
serverInfo.players().online(config.players().onlile());
serverInfo.players().sample(Collections.emptyList());
serverInfo.description(config.motd());
StatusServerResponse response = new StatusServerResponse();
response.setInfo(serverInfo);
channel.getCtx().writeAndFlush(response);
});
@@ -71,9 +68,7 @@ public class Main {
.doOnNext(channel -> log.info("{}", channel.getPacket()))
.subscribe(channel -> {
DisconnectPacket disconnectPacket = new DisconnectPacket();
disconnectPacket.setReason("{\n" +
" \"text\": \"Server is not available.\"\n" +
"}");
disconnectPacket.setReason("Server is not available.");
channel.getCtx().writeAndFlush(disconnectPacket).channel().disconnect();
});