Remote menus - serverside part

This commit is contained in:
zbyv 2026-03-26 23:14:50 +01:00
parent 29c8b575d9
commit d43ca2a45a
4 changed files with 206 additions and 0 deletions

View File

@ -148,6 +148,8 @@ set(SERVER_ONLY_SOURCES
"src/game/player_character.cpp" "src/game/player_character.cpp"
"src/game/player.hpp" "src/game/player.hpp"
"src/game/player.cpp" "src/game/player.cpp"
"src/game/remote_menu.hpp"
"src/game/remote_menu.cpp"
"src/game/simple_entity.hpp" "src/game/simple_entity.hpp"
"src/game/simple_entity.cpp" "src/game/simple_entity.cpp"
"src/game/usable.hpp" "src/game/usable.hpp"

105
src/game/remote_menu.cpp Normal file
View File

@ -0,0 +1,105 @@
#include "remote_menu.hpp"
#include "net/defs.hpp"
game::RemoteMenuItem::RemoteMenuItem(RemoteMenu& menu, RemoteMenuItemType type, std::string text) : menu_(menu), type_(type)
{
}
void game::RemoteMenuItem::SetText(std::string text)
{
if (text == text_)
return;
text_ = std::move(text);
text_synced_ = false;
menu_.items_synced_ = false;
}
void game::RemoteMenuItem::SetSelection(std::string selection)
{
if (selection == selection_)
return;
selection_ = std::move(selection);
selection_synced_ = false;
menu_.items_synced_ = false;
}
game::RemoteMenu::RemoteMenu(net::MenuId id) : id_(id)
{
}
game::RemoteMenuItem& game::RemoteMenu::AddItem(RemoteMenuItemType type, std::string text)
{
auto item = std::make_unique<RemoteMenuItem>(*this, type, std::move(text));
auto& item_ref = *item;
items_.push_back(std::move(item));
synced_ = false;
return item_ref;
}
void game::RemoteMenu::Update()
{
if (synced_ && items_synced_)
return;
// not synced at all, write full update
if (!synced_)
{
auto msg = BeginMenuMsg(net::MMSG_UPDATE);
msg.Write<net::MenuItemCount>(items_.size());
for (auto& item : items_)
{
msg.Write(item->type_);
msg.Write(net::MenuItemText(item->text_));
msg.Write(net::MenuItemSelection(item->selection_));
item->text_synced_ = true;
item->selection_synced_ = true;
}
synced_ = true;
items_synced_ = true;
return;
}
// some items want sync
if (!items_synced_)
{
for (size_t i = 0; i < items_.size(); ++i)
{
auto& item = *items_[i];
if (!item.text_synced_)
{
auto msg = BeginMenuMsg(net::MMSG_ITEM_UPDATE_TEXT);
msg.Write<net::MenuItemId>(i);
msg.Write(net::MenuItemText(item.text_));
item.text_synced_ = true;
}
if (!item.selection_synced_)
{
auto msg = BeginMenuMsg(net::MMSG_ITEM_UPDATE_SELECTION);
msg.Write<net::MenuItemId>(i);
msg.Write(net::MenuItemSelection(item.selection_));
item.selection_synced_ = true;
}
}
items_synced_ = true;
}
}
net::OutMessage game::RemoteMenu::BeginMenuMsg(net::MenuMessageType type)
{
auto msg = BeginMsg(net::MSG_REMOTEMENU);
msg.Write(id_);
msg.Write(type);
return msg;
}

76
src/game/remote_menu.hpp Normal file
View File

@ -0,0 +1,76 @@
#pragma once
#include <string>
#include <functional>
#include <memory>
#include "net/defs.hpp"
#include "net/msg_producer.hpp"
#include "net/outmessage.hpp"
namespace game
{
enum RemoteMenuItemType : uint8_t
{
RM_LABEL,
RM_BUTTON,
RM_SELECT,
};
class RemoteMenu;
class RemoteMenuItem;
using RemoteMenuClickCallback = std::function<void()>;
using RemoteMenuHoveredCallback = std::function<void()>;
using RemoteMenuSelectCallback = std::function<void(int)>;
class RemoteMenuItem
{
public:
RemoteMenuItem(RemoteMenu& menu, RemoteMenuItemType type, std::string text);
void SetText(std::string text);
void SetSelection(std::string selection);
void SetOnClick(RemoteMenuClickCallback on_click) { on_click_ = std::move(on_click); }
void SetOnSelect(RemoteMenuSelectCallback on_select) { on_select_ = std::move(on_select); }
void SetOnHovered(RemoteMenuHoveredCallback on_hovered) { on_hovered_ = std::move(on_hovered); }
private:
RemoteMenu& menu_;
RemoteMenuItemType type_ = RM_LABEL;
std::string text_;
bool text_synced_ = false;
std::string selection_;
bool selection_synced_ = false;
RemoteMenuClickCallback on_click_;
RemoteMenuSelectCallback on_select_;
RemoteMenuHoveredCallback on_hovered_;
friend class RemoteMenu;
};
class RemoteMenu : public net::MsgProducer
{
public:
RemoteMenu(net::MenuId id);
RemoteMenuItem& AddItem(RemoteMenuItemType type, std::string text);
void Update();
private:
net::OutMessage BeginMenuMsg(net::MenuMessageType type);
private:
net::MenuId id_;
bool synced_ = false;
bool items_synced_ = false;
std::vector<std::unique_ptr<RemoteMenuItem>> items_;
int hovered_ = -1;
friend class RemoteMenuItem;
};
}

View File

@ -37,6 +37,9 @@ enum MessageType : uint8_t
// USETARGET ... // USETARGET ...
MSG_USETARGET, MSG_USETARGET,
// REMOTEMENU ...
MSG_REMOTEMENU,
/*~~~~~~~~ Entity ~~~~~~~~*/ /*~~~~~~~~ Entity ~~~~~~~~*/
// ENTSPAWN <EntNum> <EntType> data... // ENTSPAWN <EntNum> <EntType> data...
MSG_ENTSPAWN, MSG_ENTSPAWN,
@ -144,4 +147,24 @@ using TuningPartIdx = uint8_t;
using UseTargetName = FixedStr<128>; using UseTargetName = FixedStr<128>;
using UseDelayQ = Quantized<uint8_t, 0, 10>; using UseDelayQ = Quantized<uint8_t, 0, 10>;
// remote menu
enum MenuMessageType
{
MMSG_CREATE,
MMSG_UPDATE,
MMSG_ITEM_UPDATE_TEXT,
MMSG_ITEM_UPDATE_SELECTION,
MMSG_CLOSE,
};
using MenuId = uint8_t;
using MenuItemId = uint8_t;
using MenuItemCount = MenuItemId;
using MenuItemText = FixedStr<64>;
using MenuItemSelection = FixedStr<64>;
} // namespace net } // namespace net