diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index abd0470e76..3702817b74 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -846,7 +846,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet SetLocalCompany(_network_join.company); } - JoinData data = { + OTTD_Social_Event_Server_Joined_Data data = { "Unknown", // TODO: fix this this->connection_string.c_str() }; diff --git a/src/network/network_coordinator.cpp b/src/network/network_coordinator.cpp index 2c7d9353fb..1ca1fb3b71 100644 --- a/src/network/network_coordinator.cpp +++ b/src/network/network_coordinator.cpp @@ -195,7 +195,7 @@ bool ClientNetworkCoordinatorSocketHandler::Receive_GC_REGISTER_ACK(Packet *p) * attempt to re-use when registering again. */ _network_server_invite_code = _settings_client.network.server_invite_code; - JoinData data = { + OTTD_Social_Event_Server_Joined_Data data = { _settings_client.network.server_name.c_str(), _network_server_invite_code.c_str() }; diff --git a/src/network/social/loader.cpp b/src/network/social/loader.cpp index 31ceab9536..31e9954a4e 100644 --- a/src/network/social/loader.cpp +++ b/src/network/social/loader.cpp @@ -16,7 +16,9 @@ void callback(const char* serverName) { } SocialPlatformLoader::SocialPlatformLoader() { +#if !defined(__EMSCRIPTEN__) LoadSocialPlatforms(this->plugins); +#endif for (SocialPlatformPlugin plugin : plugins) { plugin.initialize(callback, &plugin.userdata); @@ -35,7 +37,7 @@ void SocialPlatformLoader::RunDispatch() { } } -void SocialPlatformLoader::NewState(eventCode event, void* parameter) { +void SocialPlatformLoader::NewState(OTTD_Social_Event event, void* parameter) { for (SocialPlatformPlugin plugin : plugins) { plugin.newState(event, parameter, plugin.userdata); } diff --git a/src/network/social/loader.h b/src/network/social/loader.h index 65a3e0d1dc..dadffa836e 100644 --- a/src/network/social/loader.h +++ b/src/network/social/loader.h @@ -27,7 +27,7 @@ class SocialPlatformLoader { public: void Shutdown(); void RunDispatch(); - void NewState(eventCode event, void* parameter); + void NewState(OTTD_Social_Event event, void* parameter); static SocialPlatformLoader* GetInstance(); @@ -37,7 +37,9 @@ private: std::vector plugins; }; +#if !defined(__EMSCRIPTEN__) /* Defined in os//social_.cpp. */ void LoadSocialPlatforms(std::vector& plugins); +#endif #endif diff --git a/src/network/social/social_api.h b/src/network/social/social_api.h index 714e2b27a0..73e5e355ac 100644 --- a/src/network/social/social_api.h +++ b/src/network/social/social_api.h @@ -14,7 +14,7 @@ extern "C" { #endif -struct JoinData { +struct OTTD_Social_Event_Server_Joined_Data { // Name of the server as shown to players. const char* server_name; @@ -22,7 +22,7 @@ struct JoinData { const char* connection_string; }; -enum eventCode { +enum OTTD_Social_Event { // Called when the player has entered the main menu. // Parameter: N/A OTTD_SOCIAL_EVENT_MENU, @@ -46,7 +46,9 @@ typedef void (* OTTD_Social_JoinCallback)(const char* serverName); // Initializes the plugin. // The plugin is free to initialize the memory pointed to at the given address with any structure it needs to keep data around. -// The plugin loader will keep track of this memory for the plugin. +// The plugin loader will keep track of this memory for the plugin. It remains valid until the shutdown function is called. +// +// The callback function is a static reference to a function, however, the plugin should leverage its user data to keep track of it. typedef bool (* OTTD_Social_Initialize)(OTTD_Social_JoinCallback callback, void **userdata); // Called by the plugin loader to indicate that OpenTTD is currently shutting down. @@ -57,7 +59,9 @@ typedef void (* OTTD_Social_Shutdown)(void *userdata); typedef void (* OTTD_Social_Dispatch)(void *userdata); // Called when the game's state changes. -typedef void (* OTTD_Social_NewState)(eventCode event, void* parameter, void *userdata); +// +// The data pointed to by parameter is only valid during the duration of this function. +typedef void (* OTTD_Social_NewState)(OTTD_Social_Event event, void* parameter, void *userdata); #ifdef __cplusplus } diff --git a/src/os/unix/CMakeLists.txt b/src/os/unix/CMakeLists.txt index 1e8bb5d63d..195d8977c6 100644 --- a/src/os/unix/CMakeLists.txt +++ b/src/os/unix/CMakeLists.txt @@ -6,6 +6,7 @@ add_files( add_files( unix.cpp + social_unix.cpp CONDITION UNIX ) diff --git a/src/os/unix/social_unix.cpp b/src/os/unix/social_unix.cpp new file mode 100644 index 0000000000..e3f4f84be4 --- /dev/null +++ b/src/os/unix/social_unix.cpp @@ -0,0 +1,65 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file social_unix.cpp Unix like backing implementation for social plugin loading. */ + +#include "../../stdafx.h" +#include "../../fileio_func.h" +#include "../../string_func.h" +#include "../../network/social/loader.h" + +#include +#include +#include + +#include "../../safeguards.h" + +void LoadSocialPlatforms(std::vector& plugins) { + std::string search_dir = FioGetDirectory(SP_BINARY_DIR, BASE_DIR); + + DIR* directory = opendir(OTTD2FS(search_dir).c_str()); + if (directory == nullptr) { + return; + } + + while (true) { + struct dirent* entry = readdir(directory); + if (entry == nullptr) { + break; + } + + if (!StrEndsWith(FS2OTTD(entry->d_name), ".ots")) { + continue; + } + + std::string library_path = search_dir + FS2OTTD(entry->d_name); + void* library = dlopen(library_path.c_str(), 0); + if (library == nullptr) { + continue; + } + + SocialPlatformPlugin plugin = { + library, + + (OTTD_Social_Initialize)dlsym(library, "OTTD_Social_Initialize"), + (OTTD_Social_Shutdown)dlsym(library, "OTTD_Social_Shutdown"), + (OTTD_Social_Dispatch)dlsym(library, "OTTD_Social_Dispatch"), + (OTTD_Social_NewState)dlsym(library, "OTTD_Social_NewState"), + + nullptr + }; + + if (plugin.initialize == nullptr || plugin.shutdown == nullptr || plugin.dispatch == nullptr || plugin.newState == nullptr) { + dlclose(library); + continue; + } + + plugins.push_back(plugin); + } + + closedir(directory); +} diff --git a/src/os/windows/social_win.cpp b/src/os/windows/social_win.cpp index 4cc09cd4ca..09e934ae98 100644 --- a/src/os/windows/social_win.cpp +++ b/src/os/windows/social_win.cpp @@ -8,11 +8,9 @@ /** @file social_win.cpp Win32 backing implementation for social plugin loading. */ #include "../../stdafx.h" - -#include "../../network/social/loader.h" #include "../../fileio_func.h" +#include "../../network/social/loader.h" -#include #include #include "../../safeguards.h" @@ -20,35 +18,38 @@ void LoadSocialPlatforms(std::vector& plugins) { std::string search_dir = FioGetDirectory(SP_BINARY_DIR, BASE_DIR); - WIN32_FIND_DATAW find_data = {}; + WIN32_FIND_DATAW find_data = { }; HANDLE find_handle = FindFirstFileW(OTTD2FS(search_dir + "*.ots").c_str(), &find_data); - if (find_handle != INVALID_HANDLE_VALUE) { - do { - std::string library_path = search_dir + FS2OTTD(find_data.cFileName); - HMODULE library = LoadLibraryW(OTTD2FS(library_path).c_str()); - if (library == nullptr) { - continue; - } - - SocialPlatformPlugin plugin = { - library, - - (OTTD_Social_Initialize)GetProcAddress(library, "OTTD_Social_Initialize"), - (OTTD_Social_Shutdown)GetProcAddress(library, "OTTD_Social_Shutdown"), - (OTTD_Social_Dispatch)GetProcAddress(library, "OTTD_Social_Dispatch"), - (OTTD_Social_NewState)GetProcAddress(library, "OTTD_Social_NewState"), - - nullptr - }; - - if (plugin.initialize == nullptr || plugin.shutdown == nullptr || plugin.dispatch == nullptr || plugin.newState == nullptr) { - FreeLibrary(library); - continue; - } - - plugins.push_back(plugin); - } while (FindNextFileW(find_handle, &find_data)); - - FindClose(find_handle); + if (find_handle == INVALID_HANDLE_VALUE) { + return; } + + do { + std::string library_path = search_dir + FS2OTTD(find_data.cFileName); + HMODULE library = LoadLibraryW(OTTD2FS(library_path).c_str()); + if (library == nullptr) { + continue; + } + + SocialPlatformPlugin plugin = { + library, + + (OTTD_Social_Initialize)GetProcAddress(library, "OTTD_Social_Initialize"), + (OTTD_Social_Shutdown)GetProcAddress(library, "OTTD_Social_Shutdown"), + (OTTD_Social_Dispatch)GetProcAddress(library, "OTTD_Social_Dispatch"), + (OTTD_Social_NewState)GetProcAddress(library, "OTTD_Social_NewState"), + + nullptr + }; + + if (plugin.initialize == nullptr || plugin.shutdown == nullptr || plugin.dispatch == nullptr || plugin.newState == nullptr) { + FreeLibrary(library); + continue; + } + + plugins.push_back(plugin); + } while (FindNextFileW(find_handle, &find_data) == TRUE); + + FindClose(find_handle); + }