Чат и список игроков
- Протокол: Chat (что сказал сервер), ChatSend (что сказал клиент) и PlayerList (весь список игроков с их режимами). - Сервер: сообщения уходят всем, а имя отправителя ставит сервер, поэтому подделать его нельзя. Список игроков уходит всем целиком, когда он меняется. Команды сервера: /help и /players. - Клиент: перевод наших пакетов в игровые (SPacketChat и SPacketPlayerListItem), уходящий чат перехватывается патчем, список игроков обновляется по разнице (ушедших убираем, пришедших добавляем). - Тесты: два игрока, один пишет - второй слышит с правильным именем; список игроков приходит обоим и меняется, когда кто-то выходит. Попутно: run-server.ps1 теперь знает про rsx-plugin-api, иначе сервер не запускался (нет класса Hitboxes в classpath). Тесты: протокол 34, сервер 87. Форк собирается чисто.
This commit is contained in:
@@ -161,6 +161,15 @@ public final class Packets {
|
||||
/** The client hits something. */
|
||||
public static final int ATTACK = 0x2D;
|
||||
|
||||
/** What somebody said. */
|
||||
public static final int CHAT = 0x2E;
|
||||
|
||||
/** The client says something. */
|
||||
public static final int CHAT_SEND = 0x2F;
|
||||
|
||||
/** Who is in the world. */
|
||||
public static final int PLAYER_LIST = 0x30;
|
||||
|
||||
/**
|
||||
* One slot of the inventory and what is in it now.
|
||||
*
|
||||
@@ -1604,6 +1613,100 @@ public final class Packets {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What somebody said.
|
||||
*
|
||||
* The name of the sender is here, because the server is the one who
|
||||
* decides who said what: a client cannot claim to be somebody else.
|
||||
*/
|
||||
public static final class Chat implements Packet {
|
||||
|
||||
/** The name of the sender, or empty when the server speaks. */
|
||||
public final String from;
|
||||
|
||||
public final String text;
|
||||
|
||||
public Chat(String from, String text) {
|
||||
this.from = from == null ? "" : from;
|
||||
this.text = text == null ? "" : text;
|
||||
}
|
||||
|
||||
public Buf write() {
|
||||
Buf buf = new Buf(64 + this.text.length());
|
||||
buf.writeString(this.from);
|
||||
buf.writeString(this.text);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static Chat read(Buf in) {
|
||||
return new Chat(in.readString(MAX_TEXT), in.readString(MAX_TEXT));
|
||||
}
|
||||
}
|
||||
|
||||
/** The client says something. */
|
||||
public static final class ChatSend implements Packet {
|
||||
|
||||
public final String text;
|
||||
|
||||
public ChatSend(String text) {
|
||||
this.text = text == null ? "" : text;
|
||||
}
|
||||
|
||||
public Buf write() {
|
||||
Buf buf = new Buf(64 + this.text.length());
|
||||
buf.writeString(this.text);
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static ChatSend read(Buf in) {
|
||||
return new ChatSend(in.readString(MAX_TEXT));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Who is in the world.
|
||||
*
|
||||
* The whole list, every time it changes: the list of a server with a
|
||||
* handful of players is small, and a full list cannot get out of step
|
||||
* with itself the way a difference can.
|
||||
*/
|
||||
public static final class PlayerList implements Packet {
|
||||
|
||||
public final String[] names;
|
||||
|
||||
/** The game mode of each player, in the same order. */
|
||||
public final int[] gameModes;
|
||||
|
||||
public PlayerList(String[] names, int[] gameModes) {
|
||||
this.names = names;
|
||||
this.gameModes = gameModes;
|
||||
}
|
||||
|
||||
public Buf write() {
|
||||
Buf buf = new Buf(32 + this.names.length * 24);
|
||||
buf.writeVarInt(this.names.length);
|
||||
for (int i = 0; i < this.names.length; i++) {
|
||||
buf.writeString(this.names[i]);
|
||||
buf.writeVarInt(i < this.gameModes.length ? this.gameModes[i] : 0);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
public static PlayerList read(Buf in) {
|
||||
int count = in.readVarInt();
|
||||
if (count < 0 || count > 4096) {
|
||||
throw new ProtocolException("that many players is not real");
|
||||
}
|
||||
String[] names = new String[count];
|
||||
int[] gameModes = new int[count];
|
||||
for (int i = 0; i < count; i++) {
|
||||
names[i] = in.readString(MAX_TEXT);
|
||||
gameModes[i] = in.readVarInt();
|
||||
}
|
||||
return new PlayerList(names, gameModes);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Every packet id this build knows, and what it decodes into.
|
||||
*
|
||||
@@ -1648,6 +1751,9 @@ public final class Packets {
|
||||
map.put(Integer.valueOf(HITBOX_INSTANCES), "HitboxInstances");
|
||||
map.put(Integer.valueOf(HITBOXES_RELOAD), "HitboxesReload");
|
||||
map.put(Integer.valueOf(ATTACK), "Attack");
|
||||
map.put(Integer.valueOf(CHAT), "Chat");
|
||||
map.put(Integer.valueOf(CHAT_SEND), "ChatSend");
|
||||
map.put(Integer.valueOf(PLAYER_LIST), "PlayerList");
|
||||
map.put(Integer.valueOf(DISCONNECT), "Disconnect");
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -326,6 +326,23 @@ public final class ItemTest {
|
||||
near("the place of the hit survives", 2.5, attackBack.y);
|
||||
eq("the hand survives", Integer.valueOf(Packets.Attack.HAND_MAIN),
|
||||
Integer.valueOf(attackBack.hand));
|
||||
|
||||
Packets.Chat chat = new Packets.Chat("Player", "hello there");
|
||||
Packets.Chat chatBack = Packets.Chat.read(new Buf(chat.write().toByteArray()));
|
||||
eq("the sender survives", "Player", chatBack.from);
|
||||
eq("the line survives", "hello there", chatBack.text);
|
||||
|
||||
Packets.ChatSend send = new Packets.ChatSend("hi");
|
||||
Packets.ChatSend sendBack = Packets.ChatSend.read(new Buf(send.write().toByteArray()));
|
||||
eq("the sent line survives", "hi", sendBack.text);
|
||||
|
||||
Packets.PlayerList list = new Packets.PlayerList(
|
||||
new String[]{"One", "Two"}, new int[]{0, 1});
|
||||
Packets.PlayerList listBack =
|
||||
Packets.PlayerList.read(new Buf(list.write().toByteArray()));
|
||||
eq("two names", Integer.valueOf(2), Integer.valueOf(listBack.names.length));
|
||||
eq("the first name", "One", listBack.names[0]);
|
||||
eq("the second mode", Integer.valueOf(1), Integer.valueOf(listBack.gameModes[1]));
|
||||
}
|
||||
|
||||
private static void near(Object what, double expected, double actual) {
|
||||
|
||||
@@ -552,7 +552,7 @@ public final class ProtocolTest {
|
||||
Packets.CONTAINER_OPEN, Packets.CONTAINER_TAKE,
|
||||
Packets.LEARN_BLUEPRINT,
|
||||
Packets.HITBOXES, Packets.HITBOX_INSTANCES, Packets.HITBOXES_RELOAD,
|
||||
Packets.ATTACK,
|
||||
Packets.ATTACK, Packets.CHAT, Packets.CHAT_SEND, Packets.PLAYER_LIST,
|
||||
Packets.DISCONNECT,
|
||||
};
|
||||
for (int i = 0; i < ids.length; i++) {
|
||||
|
||||
Reference in New Issue
Block a user