1 /*****************************************************************************
2  * Copyright (c) 2014-2020 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 
10 #ifdef ENABLE_SCRIPTING
11 
12 #    include "ScNetwork.hpp"
13 
14 #    include "../../../Context.h"
15 #    include "../../../actions/NetworkModifyGroupAction.h"
16 #    include "../../../actions/PlayerKickAction.h"
17 #    include "../../../network/NetworkAction.h"
18 #    include "../../../network/network.h"
19 
20 namespace OpenRCT2::Scripting
21 {
ScNetwork(duk_context * ctx)22     ScNetwork::ScNetwork(duk_context* ctx)
23         : _context(ctx)
24     {
25     }
26 
mode_get() const27     std::string ScNetwork::mode_get() const
28     {
29 #    ifndef DISABLE_NETWORK
30         switch (network_get_mode())
31         {
32             case NETWORK_MODE_SERVER:
33                 return "server";
34             case NETWORK_MODE_CLIENT:
35                 return "client";
36         }
37 #    endif
38         return "none";
39     }
40 
numPlayers_get() const41     int32_t ScNetwork::numPlayers_get() const
42     {
43 #    ifndef DISABLE_NETWORK
44         return network_get_num_players();
45 #    else
46         return 0;
47 #    endif
48     }
49 
numGroups_get() const50     int32_t ScNetwork::numGroups_get() const
51     {
52 #    ifndef DISABLE_NETWORK
53         return network_get_num_groups();
54 #    else
55         return 0;
56 #    endif
57     }
58 
defaultGroup_get() const59     int32_t ScNetwork::defaultGroup_get() const
60     {
61 #    ifndef DISABLE_NETWORK
62         return network_get_default_group();
63 #    else
64         return 0;
65 #    endif
66     }
67 
defaultGroup_set(int32_t value)68     void ScNetwork::defaultGroup_set(int32_t value)
69     {
70 #    ifndef DISABLE_NETWORK
71         auto action = NetworkModifyGroupAction(ModifyGroupType::SetDefault, value);
72         GameActions::Execute(&action);
73 #    endif
74     }
75 
groups_get() const76     std::vector<std::shared_ptr<ScPlayerGroup>> ScNetwork::groups_get() const
77     {
78         std::vector<std::shared_ptr<ScPlayerGroup>> groups;
79 #    ifndef DISABLE_NETWORK
80         auto numGroups = network_get_num_groups();
81         for (int32_t i = 0; i < numGroups; i++)
82         {
83             auto groupId = network_get_group_id(i);
84             groups.push_back(std::make_shared<ScPlayerGroup>(groupId));
85         }
86 #    endif
87         return groups;
88     }
89 
players_get() const90     std::vector<std::shared_ptr<ScPlayer>> ScNetwork::players_get() const
91     {
92         std::vector<std::shared_ptr<ScPlayer>> players;
93 #    ifndef DISABLE_NETWORK
94         auto numPlayers = network_get_num_players();
95         for (int32_t i = 0; i < numPlayers; i++)
96         {
97             auto playerId = network_get_player_id(i);
98             players.push_back(std::make_shared<ScPlayer>(playerId));
99         }
100 #    endif
101         return players;
102     }
103 
currentPlayer_get() const104     std::shared_ptr<ScPlayer> ScNetwork::currentPlayer_get() const
105     {
106         std::shared_ptr<ScPlayer> player;
107 #    ifndef DISABLE_NETWORK
108         auto playerId = network_get_current_player_id();
109         player = std::make_shared<ScPlayer>(playerId);
110 #    endif
111         return player;
112     }
113 
getPlayer(int32_t index) const114     std::shared_ptr<ScPlayer> ScNetwork::getPlayer(int32_t index) const
115     {
116 #    ifndef DISABLE_NETWORK
117         auto numPlayers = network_get_num_players();
118         if (index < numPlayers)
119         {
120             auto playerId = network_get_player_id(index);
121             return std::make_shared<ScPlayer>(playerId);
122         }
123 #    endif
124         return nullptr;
125     }
126 
stats_get() const127     DukValue ScNetwork::stats_get() const
128     {
129 #    ifndef DISABLE_NETWORK
130         auto obj = OpenRCT2::Scripting::DukObject(_context);
131         auto networkStats = network_get_stats();
132         {
133             duk_push_array(_context);
134             duk_uarridx_t index = 0;
135             for (auto v : networkStats.bytesReceived)
136             {
137                 duk_push_number(_context, v);
138                 duk_put_prop_index(_context, -2, index);
139                 index++;
140             }
141             obj.Set("bytesReceived", DukValue::take_from_stack(_context));
142         }
143         {
144             duk_push_array(_context);
145             duk_uarridx_t index = 0;
146             for (auto v : networkStats.bytesSent)
147             {
148                 duk_push_number(_context, v);
149                 duk_put_prop_index(_context, -2, index);
150                 index++;
151             }
152             obj.Set("bytesSent", DukValue::take_from_stack(_context));
153         }
154         return obj.Take();
155 #    else
156         return ToDuk(_context, nullptr);
157 #    endif
158     }
159 
getGroup(int32_t index) const160     std::shared_ptr<ScPlayerGroup> ScNetwork::getGroup(int32_t index) const
161     {
162 #    ifndef DISABLE_NETWORK
163         auto numGroups = network_get_num_groups();
164         if (index < numGroups)
165         {
166             auto groupId = network_get_group_id(index);
167             return std::make_shared<ScPlayerGroup>(groupId);
168         }
169 #    endif
170         return nullptr;
171     }
172 
addGroup()173     void ScNetwork::addGroup()
174     {
175 #    ifndef DISABLE_NETWORK
176         auto networkModifyGroup = NetworkModifyGroupAction(ModifyGroupType::AddGroup);
177         GameActions::Execute(&networkModifyGroup);
178 #    endif
179     }
180 
removeGroup(int32_t index)181     void ScNetwork::removeGroup(int32_t index)
182     {
183 #    ifndef DISABLE_NETWORK
184         auto numGroups = network_get_num_groups();
185         if (index < numGroups)
186         {
187             auto groupId = network_get_group_id(index);
188             auto networkAction = NetworkModifyGroupAction(ModifyGroupType::RemoveGroup, groupId);
189             GameActions::Execute(&networkAction);
190         }
191 #    endif
192     }
193 
kickPlayer(int32_t index)194     void ScNetwork::kickPlayer(int32_t index)
195     {
196 #    ifndef DISABLE_NETWORK
197         auto numPlayers = network_get_num_players();
198         if (index < numPlayers)
199         {
200             auto playerId = network_get_player_id(index);
201             auto kickPlayerAction = PlayerKickAction(playerId);
202             GameActions::Execute(&kickPlayerAction);
203         }
204 #    endif
205     }
206 
sendMessage(std::string message,DukValue players)207     void ScNetwork::sendMessage(std::string message, DukValue players)
208     {
209 #    ifndef DISABLE_NETWORK
210         if (players.is_array())
211         {
212             if (network_get_mode() == NETWORK_MODE_SERVER)
213             {
214                 std::vector<uint8_t> playerIds;
215                 auto playerArray = players.as_array();
216                 for (const auto& item : playerArray)
217                 {
218                     if (item.type() == DukValue::Type::NUMBER)
219                     {
220                         playerIds.push_back(static_cast<uint8_t>(item.as_int()));
221                     }
222                 }
223                 if (!playerArray.empty())
224                 {
225                     network_send_chat(message.c_str(), playerIds);
226                 }
227             }
228             else
229             {
230                 duk_error(players.context(), DUK_ERR_ERROR, "Only servers can send private messages.");
231             }
232         }
233         else
234         {
235             network_send_chat(message.c_str());
236         }
237 #    endif
238     }
239 
240 #    ifndef DISABLE_NETWORK
createListener()241     std::shared_ptr<ScListener> ScNetwork::createListener()
242     {
243         auto& scriptEngine = GetContext()->GetScriptEngine();
244         auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
245         auto socket = std::make_shared<ScListener>(plugin);
246         scriptEngine.AddSocket(socket);
247         return socket;
248     }
249 #    else
createListener()250     void ScNetwork::createListener()
251     {
252         duk_error(_context, DUK_ERR_ERROR, "Networking has been disabled.");
253     }
254 #    endif
255 
256 #    ifndef DISABLE_NETWORK
createSocket()257     std::shared_ptr<ScSocket> ScNetwork::createSocket()
258     {
259         auto& scriptEngine = GetContext()->GetScriptEngine();
260         auto plugin = scriptEngine.GetExecInfo().GetCurrentPlugin();
261         auto socket = std::make_shared<ScSocket>(plugin);
262         scriptEngine.AddSocket(socket);
263         return socket;
264     }
265 #    else
createSocket()266     void ScNetwork::createSocket()
267     {
268         duk_error(_context, DUK_ERR_ERROR, "Networking has been disabled.");
269     }
270 #    endif
271 
Register(duk_context * ctx)272     void ScNetwork::Register(duk_context* ctx)
273     {
274         dukglue_register_property(ctx, &ScNetwork::mode_get, nullptr, "mode");
275         dukglue_register_property(ctx, &ScNetwork::numGroups_get, nullptr, "numGroups");
276         dukglue_register_property(ctx, &ScNetwork::numPlayers_get, nullptr, "numPlayers");
277         dukglue_register_property(ctx, &ScNetwork::groups_get, nullptr, "groups");
278         dukglue_register_property(ctx, &ScNetwork::players_get, nullptr, "players");
279         dukglue_register_property(ctx, &ScNetwork::currentPlayer_get, nullptr, "currentPlayer");
280         dukglue_register_property(ctx, &ScNetwork::defaultGroup_get, &ScNetwork::defaultGroup_set, "defaultGroup");
281         dukglue_register_property(ctx, &ScNetwork::stats_get, nullptr, "stats");
282         dukglue_register_method(ctx, &ScNetwork::addGroup, "addGroup");
283         dukglue_register_method(ctx, &ScNetwork::getGroup, "getGroup");
284         dukglue_register_method(ctx, &ScNetwork::removeGroup, "removeGroup");
285         dukglue_register_method(ctx, &ScNetwork::getPlayer, "getPlayer");
286         dukglue_register_method(ctx, &ScNetwork::kickPlayer, "kickPlayer");
287         dukglue_register_method(ctx, &ScNetwork::sendMessage, "sendMessage");
288 
289         dukglue_register_method(ctx, &ScNetwork::createListener, "createListener");
290         dukglue_register_method(ctx, &ScNetwork::createSocket, "createSocket");
291     }
292 
293 } // namespace OpenRCT2::Scripting
294 
295 #endif
296