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', lang3 : 'org.apache.commons:commons-lang3:3.11',
netty : 'io.netty:netty-all:4.1.22.Final', netty : 'io.netty:netty-all:4.1.22.Final',
reactor : 'io.projectreactor:reactor-core:3.4.5', 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 = [ libs.logger = [

View File

@@ -4,6 +4,7 @@ dependencies {
implementation libs.netty implementation libs.netty
implementation libs.reactor implementation libs.reactor
implementation libs.guava implementation libs.guava
implementation libs.json
testImplementation libs.lang3 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.LoginStartPacket;
import mc.protocol.packets.client.StatusServerRequestPacket; import mc.protocol.packets.client.StatusServerRequestPacket;
import mc.protocol.packets.server.DisconnectPacket; import mc.protocol.packets.server.DisconnectPacket;
import mc.protocol.packets.server.StatusServerResponsePacket; import mc.protocol.packets.server.StatusServerResponse;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
@@ -31,7 +31,7 @@ public enum State {
), ),
// server side // server side
Map.of( Map.of(
StatusServerResponsePacket.class, 0x00, StatusServerResponse.class, 0x00,
PingPacket.class, 0x01 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; package mc.protocol.packets.server;
import com.eclipsesource.json.Json;
import lombok.Data; import lombok.Data;
import mc.protocol.State; import mc.protocol.State;
import mc.protocol.io.NetByteBuf; import mc.protocol.io.NetByteBuf;
@@ -12,9 +13,16 @@ import mc.protocol.packets.ServerSidePacket;
* *
* <p>Структура пакета</p> * <p>Структура пакета</p>
* <pre> * <pre>
* | FIELD | TYPE | NOTES | * | FIELD | TYPE | NOTES |
* |--------|------|----------------------------------| * |-------------|--------|----------------------------------|
* | Reason | Text | Причина отключения. Опционально. | * | JSON Reason | String | Причина отключения. Опционально. |
* </pre>
*
* <p>Пример JSON Reason</p>
* <pre>
* {
* "text": "foo"
* }
* </pre> * </pre>
* *
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Disconnect_2" target="_top">Disconnect</a> * @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; private String reason;
@Override @Override
public void writeSelf(NetByteBuf netByteBuf) { 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 lombok.extern.slf4j.Slf4j;
import mc.protocol.NettyServer; import mc.protocol.NettyServer;
import mc.protocol.ProtocolConstant; import mc.protocol.ProtocolConstant;
import mc.protocol.model.ServerInfo;
import mc.protocol.packets.PingPacket; import mc.protocol.packets.PingPacket;
import mc.protocol.packets.client.HandshakePacket; import mc.protocol.packets.client.HandshakePacket;
import mc.protocol.packets.client.LoginStartPacket; import mc.protocol.packets.client.LoginStartPacket;
import mc.protocol.packets.client.StatusServerRequestPacket; import mc.protocol.packets.client.StatusServerRequestPacket;
import mc.protocol.packets.server.DisconnectPacket; 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.config.Config;
import mc.server.di.ConfigModule; import mc.server.di.ConfigModule;
import mc.server.di.DaggerServerComponent; import mc.server.di.DaggerServerComponent;
import mc.server.di.ServerComponent; import mc.server.di.ServerComponent;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Collections;
@Slf4j @Slf4j
public class Main { public class Main {
@@ -48,21 +50,16 @@ public class Main {
server.packetFlux(StatusServerRequestPacket.class) server.packetFlux(StatusServerRequestPacket.class)
.doOnNext(channel -> log.info("{}", channel.getPacket())) .doOnNext(channel -> log.info("{}", channel.getPacket()))
.subscribe(channel -> { .subscribe(channel -> {
StatusServerResponsePacket response = new StatusServerResponsePacket(); ServerInfo serverInfo = new ServerInfo();
response.setInfo("{\n" + serverInfo.version().name(ProtocolConstant.PROTOCOL_NAME);
" \"version\": {\n" + serverInfo.version().protocol(ProtocolConstant.PROTOCOL_NUMBER);
" \"name\": \"" + ProtocolConstant.PROTOCOL_NAME + "\",\n" + serverInfo.players().max(config.players().maxOnlile());
" \"protocol\": " + ProtocolConstant.PROTOCOL_NUMBER + "\n" + serverInfo.players().online(config.players().onlile());
" },\n" + serverInfo.players().sample(Collections.emptyList());
" \"players\": {\n" + serverInfo.description(config.motd());
" \"max\": " + config.players().maxOnlile() + ",\n" +
" \"online\": " + config.players().onlile() + ",\n" + StatusServerResponse response = new StatusServerResponse();
" \"sample\": []\n" + response.setInfo(serverInfo);
" },\n" +
" \"description\": {\n" +
" \"text\": \"" + config.motd() + "\"\n" +
" }\n" +
"}");
channel.getCtx().writeAndFlush(response); channel.getCtx().writeAndFlush(response);
}); });
@@ -71,9 +68,7 @@ public class Main {
.doOnNext(channel -> log.info("{}", channel.getPacket())) .doOnNext(channel -> log.info("{}", channel.getPacket()))
.subscribe(channel -> { .subscribe(channel -> {
DisconnectPacket disconnectPacket = new DisconnectPacket(); DisconnectPacket disconnectPacket = new DisconnectPacket();
disconnectPacket.setReason("{\n" + disconnectPacket.setReason("Server is not available.");
" \"text\": \"Server is not available.\"\n" +
"}");
channel.getCtx().writeAndFlush(disconnectPacket).channel().disconnect(); channel.getCtx().writeAndFlush(disconnectPacket).channel().disconnect();
}); });