Add readJson and writeJson for some packets

This commit is contained in:
Kae 2024-03-22 20:59:02 +11:00
parent e318098f0b
commit c1592b079d
6 changed files with 289 additions and 27 deletions

View File

@ -0,0 +1,80 @@
local commands = {}
local logHelp = "Available OpenStarbound server commands:\n"
local userHelp = logHelp .. "^cyan;"
local adminHelp = userHelp
local function cmd(name, description, permission, func)
local first = next(commands) == nil
logHelp = logHelp .. (first and name or ", " .. name)
userHelp = userHelp .. (first and name or ", ^cyan;" .. name)
adminHelp = adminHelp .. (first and name or ", ^cyan;" .. name)
local keyName = name:lower()
if permission == "tell" then
commands[keyName] = function(connectionId, ...)
return func(universe.isAdmin(connectionId), connectionId, ...)
end
elseif permission == "admin" then
commands[keyName] = function(connectionId, ...)
local error = CommandProcessor.adminCheck(connectionId, description:sub(1, 1):lower() .. description:sub(2))
if error then
return error
else
return func(connectionId, ...)
end
end
elseif permission == "user" then
commands[keyName] = func
else
error(string.format("Command '%s' has invalid permission", name))
end
end
cmd("openhelp", "Get help", "tell", function(isAdmin, connectionId)
return isAdmin and adminHelp or userHelp
end)
do
local objects = nil
cmd("packetTest", "Do science", "admin", function(connectionId)
if not objects then
objects = {}
local paths = root.assetsByExtension("object")
for i, v in pairs(paths) do
local json = root.assetJson(v)
objects[i] = {json.objectName, json.shortdescription or json.objectName}
end
end
local item = objects[math.random(#objects)]
universe.sendPacket(connectionId, "GiveItem", {
item = {name = item[1], count = 1}
})
return "Can I interest you in a ^cyan;" .. item[2] .. "^reset;?"
end)
end
local _init = type(init) == "function" and init
function init(...)
sb.logInfo("%s", logHelp)
if _init then return _init(...) end
end
local _command = type(command) == "function" and command
function command(commandName, connectionId, args)
local ret = _command and _command(commandName, connectionId, args)
if ret then return ret end
local command = commands[commandName:lower()]
if command then
local success, ret = pcall(command, connectionId, table.unpack(args))
if not success then
sb.logError("Error in OpenStarbound server command /%s: %s", commandName, ret)
return "command error: " .. ret
else
return ret
end
end
end

View File

@ -0,0 +1,7 @@
[
{
"op" : "add",
"path" : "/commandProcessorScripts/-",
"value" : "/scripts/opensb/servercommands/servercommands.lua"
}
]

View File

@ -46,6 +46,32 @@ ChatReceivedMessage::ChatReceivedMessage(MessageContext context, ConnectionId fr
ChatReceivedMessage::ChatReceivedMessage(MessageContext context, ConnectionId fromConnection, String const& fromNick, String const& text, String const& portrait)
: context(context), fromConnection(fromConnection), fromNick(fromNick), portrait(portrait), text(text) {}
ChatReceivedMessage::ChatReceivedMessage(Json const& json) : ChatReceivedMessage() {
auto jContext = json.get("context");
context = MessageContext(
MessageContextModeNames.getLeft(jContext.getString("mode")),
jContext.getString("channelName", "")
);
fromConnection = json.getUInt("fromConnection", 0);
fromNick = json.getString("fromNick", "");
portrait = json.getString("portrait", "");
text = json.getString("text");
}
Json ChatReceivedMessage::toJson() const {
return JsonObject{
{"context", JsonObject{
{"mode", MessageContextModeNames.getRight(context.mode)},
{"channelName", context.channelName.empty() ? Json() : Json(context.channelName)}
}},
{"fromConnection", fromConnection},
{"fromNick", fromNick.empty() ? Json() : fromNick},
{"portrait", portrait.empty() ? Json() : portrait},
{"text", text}
};
}
DataStream& operator>>(DataStream& ds, ChatReceivedMessage& receivedMessage) {
ds.read(receivedMessage.context);
ds.read(receivedMessage.fromConnection);

View File

@ -2,6 +2,7 @@
#include "StarDataStream.hpp"
#include "StarGameTypes.hpp"
#include "StarJson.hpp"
namespace Star {
@ -43,6 +44,9 @@ struct ChatReceivedMessage {
ChatReceivedMessage();
ChatReceivedMessage(MessageContext context, ConnectionId fromConnection, String const& fromNick, String const& text);
ChatReceivedMessage(MessageContext context, ConnectionId fromConnection, String const& fromNick, String const& text, String const& portrait);
ChatReceivedMessage(Json const& json);
Json toJson() const;
MessageContext context;

View File

@ -1,5 +1,6 @@
#include "StarNetPackets.hpp"
#include "StarDataStreamExtra.hpp"
#include "StarJsonExtra.hpp"
namespace Star {
@ -79,17 +80,13 @@ EnumMap<PacketType> const PacketTypeNames{
Packet::~Packet() {}
void Packet::readLegacy(DataStream& ds) {
read(ds);
}
void Packet::writeLegacy(DataStream& ds) const {
write(ds);
}
void Packet::readLegacy(DataStream& ds) { read(ds); }
void Packet::writeLegacy(DataStream& ds) const { write(ds); }
void Packet::readJson(Json const& json) {}
Json Packet::writeJson() const { return JsonObject{}; }
PacketCompressionMode Packet::compressionMode() const
{ return m_compressionMode; }
void Packet::setCompressionMode(PacketCompressionMode compressionMode)
{ m_compressionMode = compressionMode; }
PacketCompressionMode Packet::compressionMode() const { return m_compressionMode; }
void Packet::setCompressionMode(PacketCompressionMode compressionMode) { m_compressionMode = compressionMode; }
PacketPtr createPacket(PacketType type) {
switch (type) {
@ -168,22 +165,12 @@ PacketPtr createPacket(PacketType type) {
}
PacketPtr createPacket(PacketType type, Maybe<Json> const& args) {
if (!args)
return createPacket(type);
auto packet = createPacket(type);
switch (type) {
case PacketType::Pause: return make_shared<PausePacket>(args->getBool("pause"), args->getFloat("timescale", 1.0f));
case PacketType::ServerInfo: return make_shared<ServerInfoPacket>(args->getUInt("players"), args->getUInt("maxPlayers"));
case PacketType::GiveItem: return make_shared<GiveItemPacket>(ItemDescriptor(args->getObject("ItemDescriptor")));
case PacketType::UpdateTileProtection: return make_shared<UpdateTileProtectionPacket>(args->getUInt("dungeonId"), args->getBool("protected"));
case PacketType::SetDungeonGravity: return make_shared<SetDungeonGravityPacket>(args->getUInt("dungeonId"), args->getFloat("gravity"));
case PacketType::SetDungeonBreathable: return make_shared<SetDungeonBreathablePacket>(args->getUInt("dungeonId"), args->getBool("breathable"));
case PacketType::SetPlayerStart: return make_shared<SetPlayerStartPacket>(Vec2F{args->getArray("position")[0].toFloat(), args->getArray("position")[1].toFloat()}, args->getBool("respawnInWorld"));
case PacketType::EntityMessage: return make_shared<EntityMessagePacket>(EntityId(args->getInt("entityId")), args->getString("message"), args->get("JsonArray").toArray(), Uuid(args->getString("Uuid")));
case PacketType::UpdateWorldProperties: return make_shared<UpdateWorldPropertiesPacket>(args->getObject("updatedProperties"));
default:
throw StarPacketException(strf("Unrecognized packet type {}", (unsigned int)type));
}
if (args && !args->isNull())
packet->readJson(*args);
return packet;
}
ProtocolRequestPacket::ProtocolRequestPacket()
@ -265,6 +252,16 @@ void ChatReceivePacket::write(DataStream& ds) const {
ds.write(receivedMessage);
}
void ChatReceivePacket::readJson(Json const& json) {
receivedMessage = ChatReceivedMessage(json.get("receivedMessage"));
}
Json ChatReceivePacket::writeJson() const {
return JsonObject{
{"receivedMessage", receivedMessage.toJson()}
};
}
UniverseTimeUpdatePacket::UniverseTimeUpdatePacket() {
universeTime = 0;
}
@ -344,6 +341,18 @@ void PausePacket::write(DataStream& ds) const {
ds.write(timescale);
}
void PausePacket::readJson(Json const& json) {
pause = json.getBool("pause");
timescale = json.getFloat("timescale", 1.0f);
}
Json PausePacket::writeJson() const {
return JsonObject{
{"pause", pause},
{"timescale", timescale}
};
}
ServerInfoPacket::ServerInfoPacket() {}
ServerInfoPacket::ServerInfoPacket(uint16_t players, uint16_t maxPlayers) :
@ -362,6 +371,18 @@ void ServerInfoPacket::write(DataStream& ds) const
ds.write(maxPlayers);
}
void ServerInfoPacket::readJson(Json const& json) {
players = json.getUInt("players");
maxPlayers = json.getUInt("maxPlayers");
}
Json ServerInfoPacket::writeJson() const {
return JsonObject{
{"players", players},
{"maxPlayers", maxPlayers}
};
}
ClientConnectPacket::ClientConnectPacket() {}
ClientConnectPacket::ClientConnectPacket(ByteArray assetsDigest, bool allowAssetsMismatch, Uuid playerUuid,
@ -676,6 +697,16 @@ void GiveItemPacket::write(DataStream& ds) const {
ds.write(item);
}
void GiveItemPacket::readJson(Json const& json) {
item = ItemDescriptor(json.get("item"));
}
Json GiveItemPacket::writeJson() const {
return JsonObject{
{"item", item.toJson()}
};
}
EnvironmentUpdatePacket::EnvironmentUpdatePacket() {}
EnvironmentUpdatePacket::EnvironmentUpdatePacket(ByteArray skyDelta, ByteArray weatherDelta)
@ -1019,6 +1050,28 @@ void EntityMessagePacket::write(DataStream& ds) const {
ds.write(fromConnection);
}
void EntityMessagePacket::readJson(Json const& json) {
auto jEntityId = json.get("entityId");
if (jEntityId.canConvert(Json::Type::Int))
entityId = (EntityId)jEntityId.toInt();
else
entityId = jEntityId.toString();
message = json.getString("message");
args = json.getArray("args");
uuid = Uuid(json.getString("uuid"));
fromConnection = json.getUInt("fromConnection");
}
Json EntityMessagePacket::writeJson() const {
return JsonObject{
{"entityId", entityId.is<EntityId>() ? Json(entityId.get<EntityId>()) : Json(entityId.get<String>())},
{"message", message},
{"args", args},
{"uuid", uuid.hex()},
{"fromConnection", fromConnection}
};
}
EntityMessageResponsePacket::EntityMessageResponsePacket() {}
EntityMessageResponsePacket::EntityMessageResponsePacket(Either<String, Json> response, Uuid uuid)
@ -1047,6 +1100,17 @@ void UpdateWorldPropertiesPacket::write(DataStream& ds) const {
ds.writeMapContainer(updatedProperties);
}
void UpdateWorldPropertiesPacket::readJson(Json const& json) {
updatedProperties = json.getObject("updatedProperties");
}
Json UpdateWorldPropertiesPacket::writeJson() const {
return JsonObject{
{"updatedProperties", updatedProperties},
};
}
UpdateTileProtectionPacket::UpdateTileProtectionPacket() {}
UpdateTileProtectionPacket::UpdateTileProtectionPacket(DungeonId dungeonId, bool isProtected)
@ -1062,6 +1126,18 @@ void UpdateTileProtectionPacket::write(DataStream& ds) const {
ds.write(isProtected);
}
void UpdateTileProtectionPacket::readJson(Json const& json) {
dungeonId = json.getUInt("dungeonId");
isProtected = json.getBool("isProtected");
}
Json UpdateTileProtectionPacket::writeJson() const {
return JsonObject{
{"dungeonId", dungeonId},
{"isProtected", isProtected}
};
}
SetDungeonGravityPacket::SetDungeonGravityPacket() {}
SetDungeonGravityPacket::SetDungeonGravityPacket(DungeonId dungeonId, Maybe<float> gravity)
@ -1077,6 +1153,18 @@ void SetDungeonGravityPacket::write(DataStream& ds) const {
ds.write(gravity);
}
void SetDungeonGravityPacket::readJson(Json const& json) {
dungeonId = json.getUInt("dungeonId");
gravity = json.optFloat("gravity");
}
Json SetDungeonGravityPacket::writeJson() const {
return JsonObject{
{"dungeonId", dungeonId},
{"gravity", jsonFromMaybe<float>(gravity)}
};
}
SetDungeonBreathablePacket::SetDungeonBreathablePacket() {}
SetDungeonBreathablePacket::SetDungeonBreathablePacket(DungeonId dungeonId, Maybe<bool> breathable)
@ -1092,6 +1180,18 @@ void SetDungeonBreathablePacket::write(DataStream& ds) const {
ds.write(breathable);
}
void SetDungeonBreathablePacket::readJson(Json const& json) {
dungeonId = json.getUInt("dungeonId");
breathable = json.optBool("breathable");
}
Json SetDungeonBreathablePacket::writeJson() const {
return JsonObject{
{"dungeonId", dungeonId},
{"breathable", jsonFromMaybe<bool>(breathable)}
};
}
SetPlayerStartPacket::SetPlayerStartPacket() {}
SetPlayerStartPacket::SetPlayerStartPacket(Vec2F playerStart, bool respawnInWorld) : playerStart(playerStart), respawnInWorld(respawnInWorld) {}
@ -1106,6 +1206,18 @@ void SetPlayerStartPacket::write(DataStream& ds) const {
ds.write(respawnInWorld);
}
void SetPlayerStartPacket::readJson(Json const& json) {
playerStart = jsonToVec2F(json.get("playerStart"));
respawnInWorld = json.getBool("respawnInWorld");
}
Json SetPlayerStartPacket::writeJson() const {
return JsonObject{
{"playerStart", jsonFromVec2F(playerStart)},
{"respawnInWorld", respawnInWorld}
};
}
FindUniqueEntityResponsePacket::FindUniqueEntityResponsePacket() {}
FindUniqueEntityResponsePacket::FindUniqueEntityResponsePacket(String uniqueEntityId, Maybe<Vec2F> entityPosition)

View File

@ -132,6 +132,9 @@ struct Packet {
virtual void writeLegacy(DataStream& ds) const;
virtual void write(DataStream& ds) const = 0;
virtual void readJson(Json const& json);
virtual Json writeJson() const;
PacketCompressionMode compressionMode() const;
void setCompressionMode(PacketCompressionMode compressionMode);
@ -216,6 +219,9 @@ struct ChatReceivePacket : PacketBase<PacketType::ChatReceive> {
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
ChatReceivedMessage receivedMessage;
};
@ -271,8 +277,11 @@ struct PausePacket : PacketBase<PacketType::Pause> {
void writeLegacy(DataStream& ds) const override;
void write(DataStream& ds) const override;
bool pause;
float timescale;
void readJson(Json const& json) override;
Json writeJson() const override;
bool pause = false;
float timescale = 1.0f;
};
struct ServerInfoPacket : PacketBase<PacketType::ServerInfo> {
@ -282,6 +291,9 @@ struct ServerInfoPacket : PacketBase<PacketType::ServerInfo> {
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
uint16_t players;
uint16_t maxPlayers;
};
@ -505,6 +517,9 @@ struct GiveItemPacket : PacketBase<PacketType::GiveItem> {
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
ItemDescriptor item;
};
@ -526,6 +541,9 @@ struct UpdateTileProtectionPacket : PacketBase<PacketType::UpdateTileProtection>
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
DungeonId dungeonId;
bool isProtected;
};
@ -537,6 +555,9 @@ struct SetDungeonGravityPacket : PacketBase<PacketType::SetDungeonGravity> {
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
DungeonId dungeonId;
Maybe<float> gravity;
};
@ -548,6 +569,9 @@ struct SetDungeonBreathablePacket : PacketBase<PacketType::SetDungeonBreathable>
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
DungeonId dungeonId;
Maybe<bool> breathable;
};
@ -559,6 +583,9 @@ struct SetPlayerStartPacket : PacketBase<PacketType::SetPlayerStart> {
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
Vec2F playerStart;
bool respawnInWorld;
};
@ -795,6 +822,9 @@ struct EntityMessagePacket : PacketBase<PacketType::EntityMessage> {
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
Variant<EntityId, String> entityId;
String message;
JsonArray args;
@ -820,6 +850,9 @@ struct UpdateWorldPropertiesPacket : PacketBase<PacketType::UpdateWorldPropertie
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
void readJson(Json const& json) override;
Json writeJson() const override;
JsonObject updatedProperties;
};