OpenTTD Source: src/social_integration.cpp Source File

OpenTTD Source 14.0-RC3

social_integration.cpp
Go to the documentation of this file.
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <http://www.gnu.org/licenses/>.
6 */
7
10 #include "stdafx.h"
11
12 #include "social_integration.h"
13 #include "3rdparty/openttd_social_integration_api/openttd_social_integration_api.h"
14
15 #include "debug.h"
16 #include "fileio_func.h"
17 #include "library_loader.h"
18 #include "rev.h"
19 #include "string_func.h"
20 #include "signature.h"
21
22 #include "safeguards.h"
23
27 class InternalSocialIntegrationPlugin {
28 public:
29 InternalSocialIntegrationPlugin(const std::string &filename, const std::string &basepath) : library(nullptr), external(basepath)
30 {
31 openttd_info.openttd_version = _openttd_revision;
32
33 if (!ValidateSignatureFile(fmt::format("{}.sig", filename))) {
34 external.state = SocialIntegrationPlugin::INVALID_SIGNATURE;
35 return;
36 }
37
38 this->library = std::make_unique<LibraryLoader>(filename);
39 }
40
41 OpenTTD_SocialIntegration_v1_PluginInfo plugin_info = {};
42 OpenTTD_SocialIntegration_v1_PluginApi plugin_api = {};
43 OpenTTD_SocialIntegration_v1_OpenTTDInfo openttd_info = {};
44
45 std::unique_ptr<LibraryLoader> library = nullptr;
46
47 SocialIntegrationPlugin external;
48 };
49
50 static std::vector<std::unique_ptr<InternalSocialIntegrationPlugin>> _plugins;
51 static std::set<std::string> _loaded_social_platform;
52
54 class SocialIntegrationFileScanner : FileScanner {
55 public:
56 void Scan()
57 {
58 #ifdef _WIN32
59 std::string extension = "-social.dll";
60 #elif defined(__APPLE__)
61 std::string extension = "-social.dylib";
62 #else
63 std::string extension = "-social.so";
64 #endif
65
66 this->FileScanner::Scan(extension.c_str(), SOCIAL_INTEGRATION_DIR, false);
67 }
68
69 bool AddFile(const std::string &filename, size_t basepath_length, const std::string &) override
70 {
71 std::string basepath = filename.substr(basepath_length);
72 Debug(misc, 1, "[Social Integration: {}] Loading ...", basepath);
73
74 auto &plugin = _plugins.emplace_back(std::make_unique<InternalSocialIntegrationPlugin>(filename, basepath));
75
76 /* Validation failed, so no library was loaded. */
77 if (plugin->library == nullptr) {
78 return false;
79 }
80
81 if (plugin->library->HasError()) {
82 plugin->external.state = SocialIntegrationPlugin::FAILED;
83
84 Debug(misc, 0, "[Social Integration: {}] Failed to load library: {}", basepath, plugin->library->GetLastError());
85 return false;
86 }
87
88 OpenTTD_SocialIntegration_v1_GetInfo getinfo_func = plugin->library->GetFunction("SocialIntegration_v1_GetInfo");
89 if (plugin->library->HasError()) {
90 plugin->external.state = SocialIntegrationPlugin::UNSUPPORTED_API;
91
92 Debug(misc, 0, "[Social Integration: {}] Failed to find symbol SocialPlugin_v1_GetInfo: {}", basepath, plugin->library->GetLastError());
93 return false;
94 }
95
96 OpenTTD_SocialIntegration_v1_Init init_func = plugin->library->GetFunction("SocialIntegration_v1_Init");
97 if (plugin->library->HasError()) {
98 plugin->external.state = SocialIntegrationPlugin::UNSUPPORTED_API;
99
100 Debug(misc, 0, "[Social Integration: {}] Failed to find symbol SocialPlugin_v1_Init: {}", basepath, plugin->library->GetLastError());
101 return false;
102 }
103
104 getinfo_func(&plugin->plugin_info);
105 /* Setup the information for the outside world to see. */
106 plugin->external.social_platform = plugin->plugin_info.social_platform;
107 plugin->external.name = plugin->plugin_info.name;
108 plugin->external.version = plugin->plugin_info.version;
109
110 /* Lowercase the string for comparison. */
111 std::string lc_social_platform = plugin->plugin_info.social_platform;
112 strtolower(lc_social_platform);
113
114 /* Prevent more than one plugin for a certain Social Platform to be loaded, as that never ends well. */
115 if (_loaded_social_platform.find(lc_social_platform) != _loaded_social_platform.end()) {
116 plugin->external.state = SocialIntegrationPlugin::DUPLICATE;
117
118 Debug(misc, 0, "[Social Integration: {}] Another plugin for {} is already loaded", basepath, plugin->plugin_info.social_platform);
119 return false;
120 }
121 _loaded_social_platform.insert(lc_social_platform);
122
123 auto state = init_func(&plugin->plugin_api, &plugin->openttd_info);
124 switch (state) {
125 case OTTD_SOCIAL_INTEGRATION_V1_INIT_SUCCESS:
126 plugin->external.state = SocialIntegrationPlugin::RUNNING;
127
128 Debug(misc, 1, "[Social Integration: {}] Loaded for {}: {} ({})", basepath, plugin->plugin_info.social_platform, plugin->plugin_info.name, plugin->plugin_info.version);
129 return true;
130
131 case OTTD_SOCIAL_INTEGRATION_V1_INIT_FAILED:
132 plugin->external.state = SocialIntegrationPlugin::FAILED;
133
134 Debug(misc, 0, "[Social Integration: {}] Failed to initialize", basepath);
135 return false;
136
137 case OTTD_SOCIAL_INTEGRATION_V1_INIT_PLATFORM_NOT_RUNNING:
138 plugin->external.state = SocialIntegrationPlugin::PLATFORM_NOT_RUNNING;
139
140 Debug(misc, 1, "[Social Integration: {}] Failed to initialize: {} is not running", basepath, plugin->plugin_info.social_platform);
141 return false;
142
143 default:
144 NOT_REACHED();
145 }
146 }
147 };
148
149 std::vector<SocialIntegrationPlugin *> SocialIntegration::GetPlugins()
150 {
151 std::vector<SocialIntegrationPlugin *> plugins;
152
153 for (auto &plugin : _plugins) {
154 plugins.push_back(&plugin->external);
155 }
156
157 return plugins;
158 }
159
160 void SocialIntegration::Initialize()
161 {
162 SocialIntegrationFileScanner fs;
163 fs.Scan();
164 }
165
172 template <typename T, typename... Ts>
173 static void PluginCall(std::unique_ptr<InternalSocialIntegrationPlugin> &plugin, T func, Ts... args)
174 {
175 if (plugin->external.state != SocialIntegrationPlugin::RUNNING) {
176 return;
177 }
178
179 if (func != nullptr) {
180 func(args...);
181 }
182 }
183
184 void SocialIntegration::Shutdown()
185 {
186 for (auto &plugin : _plugins) {
187 PluginCall(plugin, plugin->plugin_api.shutdown);
188 }
189
190 _plugins.clear();
191 _loaded_social_platform.clear();
192 }
193
194 void SocialIntegration::RunCallbacks()
195 {
196 for (auto &plugin : _plugins) {
197 if (plugin->external.state != SocialIntegrationPlugin::RUNNING) {
198 continue;
199 }
200
201 if (plugin->plugin_api.run_callbacks != nullptr) {
202 if (!plugin->plugin_api.run_callbacks()) {
203 Debug(misc, 1, "[Social Plugin: {}] Requested to be unloaded", plugin->external.basepath);
204
205 _loaded_social_platform.erase(plugin->plugin_info.social_platform);
206 plugin->external.state = SocialIntegrationPlugin::UNLOADED;
207 PluginCall(plugin, plugin->plugin_api.shutdown);
208 }
209 }
210 }
211 }
212
213 void SocialIntegration::EventEnterMainMenu()
214 {
215 for (auto &plugin : _plugins) {
216 PluginCall(plugin, plugin->plugin_api.event_enter_main_menu);
217 }
218 }
219
220 void SocialIntegration::EventEnterScenarioEditor(uint map_width, uint map_height)
221 {
222 for (auto &plugin : _plugins) {
223 PluginCall(plugin, plugin->plugin_api.event_enter_scenario_editor, map_width, map_height);
224 }
225 }
226
227 void SocialIntegration::EventEnterSingleplayer(uint map_width, uint map_height)
228 {
229 for (auto &plugin : _plugins) {
230 PluginCall(plugin, plugin->plugin_api.event_enter_singleplayer, map_width, map_height);
231 }
232 }
233
234 void SocialIntegration::EventEnterMultiplayer(uint map_width, uint map_height)
235 {
236 for (auto &plugin : _plugins) {
237 PluginCall(plugin, plugin->plugin_api.event_enter_multiplayer, map_width, map_height);
238 }
239 }
240
241 void SocialIntegration::EventJoiningMultiplayer()
242 {
243 for (auto &plugin : _plugins) {
244 PluginCall(plugin, plugin->plugin_api.event_joining_multiplayer);
245 }
246 }
social_integration.h
SocialIntegrationPlugin::FAILED
@ FAILED
The plugin failed to initialize.
Definition: social_integration.h:18
FileScanner::Scan
uint Scan(const char *extension, Subdirectory sd, bool tars=true, bool recursive=true)
Scan for files with the given extension in the given search path.
Definition: fileio.cpp:1213
fileio_func.h
SocialIntegration::EventEnterSingleplayer
static void EventEnterSingleplayer(uint map_width, uint map_height)
Event: user entered a singleplayer game.
Definition: social_integration.cpp:227
SocialIntegrationPlugin::state
State state
Result of the plugin's init function.
Definition: social_integration.h:32
Debug
#define Debug(category, level, format_string,...)
Ouptut a line of debugging information.
Definition: debug.h:37
SocialIntegrationPlugin::INVALID_SIGNATURE
@ INVALID_SIGNATURE
The signature of the plugin is invalid.
Definition: social_integration.h:23
SocialIntegrationFileScanner
Helper for scanning for files with SocialIntegration as extension.
Definition: social_integration.cpp:54
SocialIntegrationPlugin::UNLOADED
@ UNLOADED
The plugin is unloaded upon request.
Definition: social_integration.h:20
SocialIntegrationPlugin
Definition: social_integration.h:13
InternalSocialIntegrationPlugin::plugin_info
OpenTTD_SocialIntegration_v1_PluginInfo plugin_info
Information supplied by plugin.
Definition: social_integration.cpp:41
SocialIntegrationFileScanner::AddFile
bool AddFile(const std::string &filename, size_t basepath_length, const std::string &) override
Add a file with the given filename.
Definition: social_integration.cpp:69
signature.h
library_loader.h
SocialIntegrationPlugin::DUPLICATE
@ DUPLICATE
Another plugin of the same Social Platform is already loaded.
Definition: social_integration.h:21
safeguards.h
ValidateSignatureFile
bool ValidateSignatureFile(const std::string &filename)
Validate that the signatures mentioned in the signature file are matching the files in question.
Definition: signature.cpp:270
SocialIntegration::Shutdown
static void Shutdown()
Shutdown the social integration system, and all social integration plugins that are loaded.
Definition: social_integration.cpp:184
stdafx.h
SocialIntegration::EventEnterMultiplayer
static void EventEnterMultiplayer(uint map_width, uint map_height)
Event: user entered a multiplayer game.
Definition: social_integration.cpp:234
PluginCall
static void PluginCall(std::unique_ptr< InternalSocialIntegrationPlugin > &plugin, T func, Ts... args)
Wrapper to call a function pointer of a plugin if it isn't a nullptr.
Definition: social_integration.cpp:173
SocialIntegrationPlugin::RUNNING
@ RUNNING
The plugin is successfully loaded and running.
Definition: social_integration.h:16
string_func.h
SocialIntegration::EventEnterScenarioEditor
static void EventEnterScenarioEditor(uint map_width, uint map_height)
Event: user entered the Scenario Editor.
Definition: social_integration.cpp:220
rev.h
SocialIntegration::EventJoiningMultiplayer
static void EventJoiningMultiplayer()
Event: user is joining a multiplayer game.
Definition: social_integration.cpp:241
_plugins
static std::vector< std::unique_ptr< InternalSocialIntegrationPlugin > > _plugins
List of loaded plugins.
Definition: social_integration.cpp:50
InternalSocialIntegrationPlugin::external
SocialIntegrationPlugin external
Information of the plugin to be used by other parts of our codebase.
Definition: social_integration.cpp:47
SocialIntegration::EventEnterMainMenu
static void EventEnterMainMenu()
Event: user entered the main menu.
Definition: social_integration.cpp:213
SocialIntegration::RunCallbacks
static void RunCallbacks()
Allow any social integration library to handle their own events.
Definition: social_integration.cpp:194
SocialIntegrationPlugin::UNSUPPORTED_API
@ UNSUPPORTED_API
The plugin does not support the current API version.
Definition: social_integration.h:22
InternalSocialIntegrationPlugin::library
std::unique_ptr< LibraryLoader > library
Library handle.
Definition: social_integration.cpp:45
SocialIntegration::Initialize
static void Initialize()
Initialize the social integration system, loading any social integration plugins that are available.
Definition: social_integration.cpp:160
SocialIntegrationPlugin::PLATFORM_NOT_RUNNING
@ PLATFORM_NOT_RUNNING
The plugin failed to initialize because the Social Platform is not running.
Definition: social_integration.h:19
SOCIAL_INTEGRATION_DIR
@ SOCIAL_INTEGRATION_DIR
Subdirectory for all social integration plugins.
Definition: fileio_type.h:124
FileScanner
Helper for scanning for files with a given name.
Definition: fileio_func.h:37
InternalSocialIntegrationPlugin::plugin_api
OpenTTD_SocialIntegration_v1_PluginApi plugin_api
API supplied by plugin.
Definition: social_integration.cpp:42
InternalSocialIntegrationPlugin::openttd_info
OpenTTD_SocialIntegration_v1_OpenTTDInfo openttd_info
Information supplied by OpenTTD.
Definition: social_integration.cpp:43
_loaded_social_platform
static std::set< std::string > _loaded_social_platform
List of Social Platform plugins already loaded. Used to prevent loading a plugin for the same Social ...
Definition: social_integration.cpp:51
SocialIntegration::GetPlugins
static std::vector< SocialIntegrationPlugin * > GetPlugins()
Get the list of loaded social integration plugins.
Definition: social_integration.cpp:149
debug.h
InternalSocialIntegrationPlugin
Container to track information per plugin.
Definition: social_integration.cpp:27