Skip to content

Commit

Permalink
Implement session websocket
Browse files Browse the repository at this point in the history
Most packets are now correctly sent, except for the case
when changing rooms which leaves the user in singleplayer mode still.
  • Loading branch information
Desdaemon committed Dec 16, 2024
1 parent 026cdb5 commit 3937a03
Show file tree
Hide file tree
Showing 12 changed files with 402 additions and 193 deletions.
17 changes: 13 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -927,11 +927,11 @@ else()
find_package(Libwebsockets CONFIG REQUIRED)
require_lws_config(LWS_ROLE_H1 1 requirements)
require_lws_config(LWS_WITHOUT_CLIENT 0 requirements)
require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements)
# require_lws_config(LWS_WITH_SECURE_STREAMS 1 requirements)
# require_lws_config(LWS_WITH_SECURE_STREAMS_CPP 1 requirements)
require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements)
# require_lws_config(LWS_WITH_SECURE_STREAMS_STATIC_POLICY_ONLY 0 requirements)
require_lws_config(LWS_WITH_TLS 1 requirements)
require_lws_config(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4 0 requirements)
# require_lws_config(LWS_WITH_SECURE_STREAMS_AUTH_SIGV4 0 requirements)

# uses system trust store
require_lws_config(LWS_WITH_MBEDTLS 0 requirements)
Expand All @@ -947,6 +947,13 @@ else()
else()
target_link_libraries(${PROJECT_NAME} websockets ${LIBWEBSOCKETS_DEP_LIBS})
endif()

#find_package(websocketpp REQUIRED)
#add_dependencies(${PROJECT_NAME} websocketpp::websocketpp)
#find_package(httplib CONFIG REQUIRED)
#target_link_libraries(${PROJECT_NAME} httplib::httplib)
find_package(cpr CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} cpr::cpr)
endif()

# Sound system to use
Expand Down Expand Up @@ -1162,7 +1169,8 @@ if(${PLAYER_BUILD_EXECUTABLE} AND ${PLAYER_TARGET_PLATFORM} MATCHES "^SDL[12]$"

if(WIN32)
# Open console for Debug builds
set_target_properties(${EXE_NAME} PROPERTIES WIN32_EXECUTABLE $<$<NOT:$<CONFIG:Debug>>:TRUE>)
#set_target_properties(${EXE_NAME} PROPERTIES WIN32_EXECUTABLE $<$<NOT:$<CONFIG:Debug>>:TRUE>)
set_target_properties(${EXE_NAME} PROPERTIES WIN32_EXECUTABLE FALSE)

# Add resources
string(REPLACE "." "," RC_VERSION ${PROJECT_VERSION})
Expand All @@ -1177,6 +1185,7 @@ if(${PLAYER_BUILD_EXECUTABLE} AND ${PLAYER_TARGET_PLATFORM} MATCHES "^SDL[12]$"

# Change executable name
set_target_properties(${EXE_NAME} PROPERTIES OUTPUT_NAME "Player")
target_link_libraries(${EXE_NAME} dbghelp)
endif()

target_link_libraries(${EXE_NAME} ${PROJECT_NAME})
Expand Down
2 changes: 1 addition & 1 deletion src/game_actor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,7 @@ void Game_Actor::ChangeClass(int new_class_id,
}
}

StringView Game_Actor::GetClassName() const {
StringView Game_Actor::ClassName() const {
if (!GetClass()) {
return {};
}
Expand Down
2 changes: 1 addition & 1 deletion src/game_actor.h
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ class Game_Actor final : public Game_Battler {
*
* @return Rpg2k3 hero class name
*/
StringView GetClassName() const;
StringView ClassName() const;

/**
* Gets battle commands.
Expand Down
2 changes: 1 addition & 1 deletion src/game_pictures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ std::vector<lcf::rpg::SavePicture> Game_Pictures::GetSaveData() const {
auto data_size = GetDefaultNumberOfPictures();
save.reserve(data_size);

int idx;
int idx{ 0 };
for (auto& pic: pictures) {
if (++idx > data_size) break;
save.push_back(pic.data);
Expand Down
85 changes: 62 additions & 23 deletions src/multiplayer/game_multiplayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@
#include "yno_connection.h"
#include "messages.h"

#ifndef EMSCRIPTEN
# include <cpr/cpr.h>
#endif

static Game_Multiplayer _instance;

Game_Multiplayer& Game_Multiplayer::Instance() {
Expand Down Expand Up @@ -125,10 +129,7 @@ static std::string get_room_url(int room_id, std::string_view session_token) {
return room_url;
}

void Game_Multiplayer::InitConnection() {
/*
conn.RegisterSystemHandler(YNOConnection::SystemMessage::OPEN, [] (Multiplayer::Connection& c) {
});*/
void Game_Multiplayer::InitConnection() {
using YSM = YNOConnection::SystemMessage;
using MCo = Multiplayer::Connection;
connection.RegisterSystemHandler(YSM::CLOSE, [this] (MCo& c) {
Expand All @@ -150,6 +151,7 @@ void Game_Multiplayer::InitConnection() {
connection.RegisterHandler<SyncPlayerDataPacket>("s", [this] (SyncPlayerDataPacket& p) {
host_id = p.host_id;
auto key_num = std::stoul(p.key);
Output::Debug("[{}] syncplayerdata key={}", room_id, key_num);
//if (key_num > std::numeric_limits<uint32_t>::max()) {
// std::terminate();
//}
Expand Down Expand Up @@ -473,9 +475,20 @@ void Game_Multiplayer::InitConnection() {
cu_temperature = p.temperature;
cu_precipitation = p.precipitation;
});
#ifndef EMSCRIPTEN
sessionConn.RegisterSystemHandler(YSM::OPEN, [this](MCo&) {
session_active = true;
});
sessionConn.RegisterSystemHandler(YSM::CLOSE, [this](MCo&) {
Output::Error("[session] exited");
});
sessionConn.RegisterHandler<SessionGSay>("gsay", [](SessionGSay& p) {
Output::Debug("{}: {}", p.uuid, p.msg);
});
#endif
}

using namespace Messages::C2S;
namespace C2S = Messages::C2S;

void Game_Multiplayer::Connect(int map_id, bool room_switch) {
Output::Debug("MP: connecting to id={}", map_id);
Expand Down Expand Up @@ -515,6 +528,28 @@ void Game_Multiplayer::Initialize() {
}
}

void Game_Multiplayer::InitSession() {
#ifndef EMSCRIPTEN
std::string formdata = "user=&password=";
std::string sessionEndpoint = Web_API::GetSocketURL() + "session";
cpr::Header header;
header["Content-Type"] = "application/x-www-form-urlencoded";

auto resp = cpr::Post(
cpr::Url{ "https://connect.ynoproject.net/yume/api/login" },
cpr::Body{ formdata },
header);
if (resp.status_code >= 200 && resp.status_code < 300) {
session_token = resp.text;
sessionEndpoint += "?token=" + session_token;
}
else {
Output::Debug("login: {} {}", resp.status_code, resp.text);
}
sessionConn.Open(sessionEndpoint);
#endif
}

void Game_Multiplayer::Quit() {
Web_API::UpdateConnectionStatus(0); // disconnected
connection.Close();
Expand All @@ -539,52 +574,52 @@ void Game_Multiplayer::SendBasicData() {

void Game_Multiplayer::MainPlayerMoved(int dir) {
auto& p = Main_Data::game_player;
connection.SendPacketAsync<MainPlayerPosPacket>(p->GetX(), p->GetY());
connection.SendPacketAsync<C2S::MainPlayerPosPacket>(p->GetX(), p->GetY());
}

void Game_Multiplayer::MainPlayerFacingChanged(int dir) {
connection.SendPacketAsync<FacingPacket>(dir);
connection.SendPacketAsync<C2S::FacingPacket>(dir);
}

void Game_Multiplayer::MainPlayerChangedMoveSpeed(int spd) {
connection.SendPacketAsync<SpeedPacket>(spd);
connection.SendPacketAsync<C2S::SpeedPacket>(spd);
}

void Game_Multiplayer::MainPlayerChangedSpriteGraphic(std::string name, int index) {
connection.SendPacketAsync<SpritePacket>(name, index);
connection.SendPacketAsync<C2S::SpritePacket>(name, index);
Web_API::OnPlayerSpriteUpdated(name, index);
}

void Game_Multiplayer::MainPlayerJumped(int x, int y) {
auto& p = Main_Data::game_player;
connection.SendPacketAsync<JumpPacket>(x, y);
connection.SendPacketAsync<C2S::JumpPacket>(x, y);
}

void Game_Multiplayer::MainPlayerFlashed(int r, int g, int b, int p, int f) {
std::array<int, 5> flash_array = std::array<int, 5>{ r, g, b, p, f };
if (last_flash_frame_index == frame_index - 1 && (last_frame_flash.get() == nullptr || *last_frame_flash == flash_array)) {
if (last_frame_flash.get() == nullptr) {
last_frame_flash = std::make_unique<std::array<int, 5>>(flash_array);
connection.SendPacketAsync<RepeatingFlashPacket>(r, g, b, p, f);
connection.SendPacketAsync<C2S::RepeatingFlashPacket>(r, g, b, p, f);
}
} else {
connection.SendPacketAsync<FlashPacket>(r, g, b, p, f);
connection.SendPacketAsync<C2S::FlashPacket>(r, g, b, p, f);
last_frame_flash.reset();
}
last_flash_frame_index = frame_index;
}

void Game_Multiplayer::MainPlayerChangedTransparency(int transparency) {
connection.SendPacketAsync<TransparencyPacket>(transparency);
connection.SendPacketAsync<C2S::TransparencyPacket>(transparency);
}

void Game_Multiplayer::MainPlayerChangedSpriteHidden(bool hidden) {
int hidden_bin = hidden ? 1 : 0;
connection.SendPacketAsync<HiddenPacket>(hidden_bin);
connection.SendPacketAsync<C2S::HiddenPacket>(hidden_bin);
}

void Game_Multiplayer::MainPlayerTeleported(int map_id, int x, int y) {
connection.SendPacketAsync<TeleportPacket>(x, y);
connection.SendPacketAsync<C2S::TeleportPacket>(x, y);
Web_API::OnPlayerTeleported(map_id, x, y);
}

Expand All @@ -604,13 +639,13 @@ void Game_Multiplayer::MainPlayerTriggeredEvent(int event_id, bool action) {
}

void Game_Multiplayer::SystemGraphicChanged(StringView sys) {
connection.SendPacketAsync<SysNamePacket>(ToString(sys));
connection.SendPacketAsync<C2S::SysNamePacket>(ToString(sys));
Web_API::OnUpdateSystemGraphic(ToString(sys));
}

void Game_Multiplayer::SePlayed(const lcf::rpg::Sound& sound) {
if (!Main_Data::game_player->IsMenuCalling()) {
connection.SendPacketAsync<SEPacket>(sound);
connection.SendPacketAsync<C2S::SEPacket>(sound);
}
}

Expand Down Expand Up @@ -652,7 +687,7 @@ bool Game_Multiplayer::IsPictureSynced(int pic_id, Game_Pictures::ShowParams& pa
void Game_Multiplayer::PictureShown(int pic_id, Game_Pictures::ShowParams& params) {
if (IsPictureSynced(pic_id, params)) {
auto& p = Main_Data::game_player;
connection.SendPacketAsync<ShowPicturePacket>(pic_id, params,
connection.SendPacketAsync<C2S::ShowPicturePacket>(pic_id, params,
Game_Map::GetPositionX(), Game_Map::GetPositionY(),
p->GetPanX(), p->GetPanY());
}
Expand All @@ -661,7 +696,7 @@ void Game_Multiplayer::PictureShown(int pic_id, Game_Pictures::ShowParams& param
void Game_Multiplayer::PictureMoved(int pic_id, Game_Pictures::MoveParams& params) {
if (sync_picture_cache.count(pic_id) && sync_picture_cache[pic_id]) {
auto& p = Main_Data::game_player;
connection.SendPacketAsync<MovePicturePacket>(pic_id, params,
connection.SendPacketAsync<C2S::MovePicturePacket>(pic_id, params,
Game_Map::GetPositionX(), Game_Map::GetPositionY(),
p->GetPanX(), p->GetPanY());
}
Expand All @@ -670,7 +705,7 @@ void Game_Multiplayer::PictureMoved(int pic_id, Game_Pictures::MoveParams& param
void Game_Multiplayer::PictureErased(int pic_id) {
if (sync_picture_cache.count(pic_id) && sync_picture_cache[pic_id]) {
sync_picture_cache.erase(pic_id);
connection.SendPacketAsync<ErasePicturePacket>(pic_id);
connection.SendPacketAsync<C2S::ErasePicturePacket>(pic_id);
}
}

Expand All @@ -689,7 +724,7 @@ bool Game_Multiplayer::IsBattleAnimSynced(int anim_id) {

void Game_Multiplayer::PlayerBattleAnimShown(int anim_id) {
if (IsBattleAnimSynced(anim_id)) {
connection.SendPacketAsync<ShowPlayerBattleAnimPacket>(anim_id);
connection.SendPacketAsync<C2S::ShowPlayerBattleAnimPacket>(anim_id);
}
}

Expand Down Expand Up @@ -774,7 +809,7 @@ void Game_Multiplayer::UpdateGlobalVariables() {
void Game_Multiplayer::Update() {
if (session_active) {
if (last_flash_frame_index > -1 && frame_index > last_flash_frame_index) {
connection.SendPacketAsync<RemoveRepeatingFlashPacket>();
connection.SendPacketAsync<C2S::RemoveRepeatingFlashPacket>();
last_flash_frame_index = -1;
last_frame_flash.reset();
}
Expand Down Expand Up @@ -892,6 +927,10 @@ void Game_Multiplayer::Update() {
DrawableMgr::SetLocalList(old_list);
}

if (session_connected)
if (session_connected) {
connection.FlushQueue();
#ifndef EMSCRIPTEN
sessionConn.FlushQueue();
#endif
}
}
4 changes: 4 additions & 0 deletions src/multiplayer/game_multiplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Game_Multiplayer {

void Connect(int map_id, bool room_switch = false);
void Initialize();
void InitSession();
void Quit();
void Update();
void SendBasicData();
Expand Down Expand Up @@ -60,6 +61,9 @@ class Game_Multiplayer {
} settings;

YNOConnection connection;
#ifndef EMSCRIPTEN
YNOConnection sessionConn;
#endif
bool session_active{ false }; // if true, it will automatically reconnect when disconnected
bool session_connected{ false };
bool switching_room{ true }; // when client enters new room, but not synced to server
Expand Down
32 changes: 31 additions & 1 deletion src/multiplayer/messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,27 @@ namespace S2C {
int temperature;
int precipitation;
};
#ifndef EMSCRIPTEN
class SessionGSay : public S2CPacket {
public:
SessionGSay(const PL& v)
: uuid(v.at(0)),
mapid(v.at(1)),
prevmapid(v.at(2)),
prevlocsstr(v.at(3)),
x(stoi((std::string)v.at(4))),
y(stoi((std::string)v.at(5))),
msg(v.at(6)),
msgid(v.at(7)) {}
int x, y;
std::string uuid;
std::string mapid;
std::string prevmapid;
std::string prevlocsstr;
std::string msg;
std::string msgid;
};
#endif
}
namespace C2S {
using C2SPacket = Multiplayer::C2SPacket;
Expand Down Expand Up @@ -606,7 +627,16 @@ namespace C2S {
int event_id;
int action_bin;
};

#ifndef EMSCRIPTEN
class SessionPlayerName : public C2SPacket {
public:
SessionPlayerName(std::string name_) : C2SPacket("name"),
name(name_) {}
std::string ToBytes() const override { return Build(name); }
protected:
std::string name;
};
#endif
}
}

Expand Down
Loading

0 comments on commit 3937a03

Please sign in to comment.