From 4f5749b2a45313708f800e609abff971ba7e47b4 Mon Sep 17 00:00:00 2001 From: LaG1924 <12997935+LaG1924@users.noreply.github.com> Date: Mon, 27 Jul 2020 04:13:39 +0500 Subject: Improved ChatComponent support #13 --- src/Chat.cpp | 146 ++++++++++++++++++++++++++++++++++++++++++++++-------- src/Chat.hpp | 90 +++++++++++++++++++++++++++------ src/GameState.cpp | 2 +- src/Packet.hpp | 6 +-- src/Render.cpp | 2 +- 5 files changed, 206 insertions(+), 40 deletions(-) diff --git a/src/Chat.cpp b/src/Chat.cpp index 193c1fd..6870a83 100644 --- a/src/Chat.cpp +++ b/src/Chat.cpp @@ -4,29 +4,135 @@ using nlohmann::json; -void Recursive(const json::iterator &iter, bool isIterObj, std::string &str) { - if (isIterObj && iter.key() == "text") { - str.append(iter->get() + " "); - } - - if (iter->is_structured()) { - for (json::iterator it = iter->begin(); it != iter->end(); ++it) - Recursive(it, iter->is_object(), str); - } +Component RecurParseComponent(json j) { + Component component; + if (j.is_string()) { + component.type = Component::STRING; + component.text = j.get(); + return component; + } + + if (j.find("text") != j.end()) { + component.type = Component::STRING; + component.text = j["text"].get(); + } + else if (j.find("translate") != j.end()) { + component.type = Component::TRANSLATION; + component.translate = j["translate"].get(); + for (auto& it : j["with"]) { + component.with.push_back(RecurParseComponent(it)); + } + } + else if (j.find("keybind") != j.end()) { + + } + else if (j.find("score") != j.end()) { + + } + else if (j.find("selector") != j.end()) { + + } + + if (j.find("bold") != j.end()) + component.isBold = j["bold"].get(); + if (j.find("italic") != j.end()) + component.isItalic = j["italic"].get(); + if (j.find("underlined") != j.end()) + component.isUnderlined = j["underlined"].get(); + if (j.find("strikethrough") != j.end()) + component.isStrikethrough = j["strikethrough"].get(); + if (j.find("obfuscated") != j.end()) + component.isObfuscated = j["obfuscated"].get(); + if (j.find("color") != j.end()) + component.color = j["color"].get(); + if (j.find("insertion") != j.end()) + component.insertion = j["insertion"].get(); + + if (j.find("clickEvent") != j.end()) { + component.clickEvent.value = j["clickEvent"]["value"].get(); + + if (j["clickEvent"]["action"] == "open_url") + component.clickEvent.action = ClickEvent::OPEN_URL; + else if (j["clickEvent"]["action"] == "open_file") + component.clickEvent.action = ClickEvent::OPEN_FILE; + else if (j["clickEvent"]["action"] == "run_command") + component.clickEvent.action = ClickEvent::RUN_COMMAND; + else if (j["clickEvent"]["action"] == "suggest_command") + component.clickEvent.action = ClickEvent::SUGGEST_COMMAND; + else if (j["clickEvent"]["action"] == "change_page") + component.clickEvent.action = ClickEvent::CHANGE_PAGE; + } + + if (j.find("hoverEvent") != j.end()) { + if (j["hoverEvent"]["value"].is_string()) + component.hoverEvent.value = j["hoverEvent"]["value"].get(); + else + component.hoverEvent.value = j["hoverEvent"]["value"]["text"].get(); + + if (j["hoverEvent"]["action"] == "show_text") + component.hoverEvent.action = HoverEvent::SHOW_TEXT; + else if (j["hoverEvent"]["action"] == "show_item") + component.hoverEvent.action = HoverEvent::SHOW_ITEM; + else if (j["hoverEvent"]["action"] == "show_entity") + component.hoverEvent.action = HoverEvent::SHOW_ENTITY; + else if (j["hoverEvent"]["action"] == "show_achievement") + component.hoverEvent.action = HoverEvent::SHOW_ACHIEVEMENT; + } + + if (j.find("extra") != j.end()) { + for (auto& it : j["extra"]) { + component.extra.push_back(RecurParseComponent(it)); + } + } + + return component; +} + +Chat::Chat(const std::string &json) { + static const size_t s = sizeof(Component); + nlohmann::json j = nlohmann::json::parse(json); + volatile size_t f = s + 1; + component = RecurParseComponent(j); } -Chat::Chat(const std::string &str) { - json j = json::parse(str); +void RecurPlainTextAppend(const Component& component, std::string& str) { + switch (component.type) { + case Component::STRING: + str += component.text; + break; + case Component::TRANSLATION: + if (component.translate == "chat.type.text") { + str += "<"; + RecurPlainTextAppend(component.with[0], str); + str += "> "; + for (int i = 1; i < component.with.size(); i++) + RecurPlainTextAppend(component.with[i], str); + } else { + str += component.translate; + str += "{"; + for (auto& it : component.with) { + RecurPlainTextAppend(it, str); + str += ";"; + } + str += "}"; + } + break; + default: + break; + } + + for (auto& it : component.extra) { + RecurPlainTextAppend(it, str); + } +} - if (j["translate"] == "chat.type.text") { - text = j["with"][0]["text"].get() + ": " + j["with"][1].get(); - } else - for (json::iterator it = j.begin(); it != j.end(); ++it) { - Recursive(it, j.is_object(), text); - } +std::string Chat::ToPlainText() const +{ + std::string ret; + RecurPlainTextAppend(component, ret); + return ret; } std::string Chat::ToJson() const { - throw std::logic_error("Chat not deserealizable"); - return text; -} \ No newline at end of file + return ""; +} diff --git a/src/Chat.hpp b/src/Chat.hpp index 9ab5691..f9dde98 100644 --- a/src/Chat.hpp +++ b/src/Chat.hpp @@ -3,23 +3,83 @@ #include #include -struct TextModifier { - size_t offset; - size_t length; - enum { - Italic, - Bold, - Underline, - } type; + +struct ClickEvent { + enum ActionType { + NONE, + OPEN_URL, + OPEN_FILE, + RUN_COMMAND, + SUGGEST_COMMAND, + CHANGE_PAGE, + } action = NONE; + std::string value; +}; + +struct HoverEvent { + enum ActionType { + NONE, + SHOW_TEXT, + SHOW_ITEM, + SHOW_ENTITY, + SHOW_ACHIEVEMENT, + } action = NONE; + std::string value; }; -struct Chat { - std::vector modifiers; - std::string text; +struct Component { + enum ComponentType { + DEFAULT, + STRING, + TRANSLATION, + KEYBIND, + SCORE, + SELECTOR, + UNKNOWN, + } type = DEFAULT; + + bool isBold = false; + bool isItalic = false; + bool isUnderlined = false; + bool isStrikethrough = false; + bool isObfuscated = false; + std::string color; + std::string insertion; + ClickEvent clickEvent; + HoverEvent hoverEvent; + std::vector extra; + + //string component + std::string text; - Chat(const std::string &str); + //tranlation component + std::string translate; + std::vector with; - Chat() = default; + //keybind component + std::string keybind; + + //score component + struct { + std::string name; + std::string objective; + std::string value; + } score; + + //selector component + std::string selector; +}; - std::string ToJson() const; -}; \ No newline at end of file +class Chat { + Component component; + +public: + + Chat() = default; + + Chat(const std::string &json); + + std::string ToPlainText() const; + + std::string ToJson() const; +}; diff --git a/src/GameState.cpp b/src/GameState.cpp index 8e50ee6..fdb453f 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -150,7 +150,7 @@ void GameState::UpdatePacket(std::shared_ptr ptr) { case ChatMessageCB: { auto packet = std::static_pointer_cast(ptr); - LOG(INFO) << "Message (" << int(packet->Position) << "): " << packet->JsonData.text; + LOG(INFO) << "Message (" << int(packet->Position) << "): " << packet->JsonData.ToPlainText(); PUSH_EVENT("ChatMessageReceived", std::make_tuple(packet->JsonData, packet->Position)); break; } diff --git a/src/Packet.hpp b/src/Packet.hpp index 275de75..cca01ec 100644 --- a/src/Packet.hpp +++ b/src/Packet.hpp @@ -241,7 +241,7 @@ struct PacketDisconnectPlay : Packet { } void FromStream(StreamInput *stream) override { - Reason = stream->ReadChat().text; + Reason = stream->ReadChat().ToPlainText(); } int GetPacketId() override { @@ -861,7 +861,7 @@ struct PacketOpenWindow : Packet { void FromStream(StreamInput *stream) override { WindowId = stream->ReadUByte(); WindowType = stream->ReadString(); - WindowTitle = stream->ReadChat().text; + WindowTitle = stream->ReadChat().ToPlainText(); NumberOfSlots = stream->ReadUByte(); if (WindowType == "EntityHorse") @@ -1032,7 +1032,7 @@ struct PacketDisconnect : Packet { } void FromStream(StreamInput *stream) override { - Reason = stream->ReadChat().text; + Reason = stream->ReadChat().ToPlainText(); } int GetPacketId() override { diff --git a/src/Render.cpp b/src/Render.cpp index 128c877..d583205 100644 --- a/src/Render.cpp +++ b/src/Render.cpp @@ -713,7 +713,7 @@ void Render::InitEvents() { listener.RegisterHandler("ChatMessageReceived", [this](const Event& eventData) { auto data = eventData.get>(); - std::string msg = "(" + std::to_string((int)std::get<1>(data)) + ") " + std::get<0>(data).text; + std::string msg = "(" + std::to_string((int)std::get<1>(data)) + ") " + (std::get<0>(data).ToPlainText()); chatMessages.push_back(msg); }); -- cgit v1.2.3