JSON вместо String
This commit is contained in:
@@ -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 = [
|
||||
|
||||
@@ -4,6 +4,7 @@ dependencies {
|
||||
implementation libs.netty
|
||||
implementation libs.reactor
|
||||
implementation libs.guava
|
||||
implementation libs.json
|
||||
|
||||
testImplementation libs.lang3
|
||||
}
|
||||
|
||||
@@ -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
|
||||
)
|
||||
),
|
||||
|
||||
47
protocol/src/main/java/mc/protocol/model/ServerInfo.java
Normal file
47
protocol/src/main/java/mc/protocol/model/ServerInfo.java
Normal 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;
|
||||
}
|
||||
}
|
||||
1
protocol/src/main/java/mc/protocol/model/lombok.config
Normal file
1
protocol/src/main/java/mc/protocol/model/lombok.config
Normal file
@@ -0,0 +1 @@
|
||||
lombok.accessors.fluent=true
|
||||
@@ -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;
|
||||
@@ -13,8 +14,15 @@ import mc.protocol.packets.ServerSidePacket;
|
||||
* <p>Структура пакета</p>
|
||||
* <pre>
|
||||
* | FIELD | TYPE | NOTES |
|
||||
* |--------|------|----------------------------------|
|
||||
* | Reason | Text | Причина отключения. Опционально. |
|
||||
* |-------------|--------|----------------------------------|
|
||||
* | 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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,<data>"
|
||||
* }
|
||||
* </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;
|
||||
}
|
||||
}
|
||||
@@ -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,<data>"
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
private String info;
|
||||
|
||||
@Override
|
||||
public void writeSelf(NetByteBuf netByteBuf) {
|
||||
netByteBuf.writeString(info);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user