JSON вместо String
This commit is contained in:
@@ -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 = [
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|||||||
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;
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 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();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user