1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 19:13:07 +01:00

Refactor events into EventList class

This commit is contained in:
Ted John
2020-08-17 12:19:19 +01:00
parent dce547af99
commit 7a5cb8a5b6

View File

@@ -16,8 +16,59 @@
# include "Duktape.hpp"
# include "ScriptEngine.h"
# include <algorithm>
# include <vector>
namespace OpenRCT2::Scripting
{
class EventList
{
private:
std::vector<std::vector<DukValue>> _listeners;
std::vector<DukValue>& GetListenerList(uint32_t id)
{
if (_listeners.size() <= id)
{
_listeners.resize(static_cast<size_t>(id) + 1);
}
return _listeners[id];
}
public:
void Raise(
uint32_t id, const std::shared_ptr<Plugin>& plugin, const std::vector<DukValue>& args, bool isGameStateMutable)
{
auto& scriptEngine = GetContext()->GetScriptEngine();
// Use simple for i loop in case listeners is modified during the loop
auto listeners = GetListenerList(id);
for (size_t i = 0; i < listeners.size(); i++)
{
scriptEngine.ExecutePluginCall(plugin, listeners[i], args, isGameStateMutable);
// Safety, listeners might get reallocated
listeners = GetListenerList(id);
}
}
void AddListener(uint32_t id, const DukValue& listener)
{
auto& listeners = GetListenerList(id);
listeners.push_back(listener);
}
void RemoveListener(uint32_t id, const DukValue& value)
{
auto& listeners = GetListenerList(id);
auto it = std::find(listeners.begin(), listeners.end(), value);
if (it != listeners.end())
{
listeners.erase(it);
}
}
};
class ScSocketBase
{
private:
@@ -51,12 +102,14 @@ namespace OpenRCT2::Scripting
class ScSocket : public ScSocketBase
{
private:
static constexpr uint32_t EVENT_NONE = std::numeric_limits<uint32_t>::max();
static constexpr uint32_t EVENT_CLOSE = 0;
static constexpr uint32_t EVENT_DATA = 1;
EventList _eventList;
std::unique_ptr<ITcpSocket> _socket;
bool _disposed{};
DukValue _onClose;
DukValue _onData;
public:
ScSocket(const std::shared_ptr<Plugin>& plugin)
: ScSocketBase(plugin)
@@ -115,13 +168,20 @@ namespace OpenRCT2::Scripting
ScSocket* on(const std::string& eventType, const DukValue& callback)
{
if (eventType == "close")
auto eventId = GetEventType(eventType);
if (eventId != EVENT_NONE)
{
_onClose = callback;
_eventList.AddListener(eventId, callback);
}
else if (eventType == "data")
return this;
}
ScSocket* off(const std::string& eventType, const DukValue& callback)
{
auto eventId = GetEventType(eventType);
if (eventId != EVENT_NONE)
{
_onData = callback;
_eventList.RemoveListener(eventId, callback);
}
return this;
}
@@ -138,16 +198,24 @@ namespace OpenRCT2::Scripting
void RaiseOnClose(bool hadError)
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto ctx = scriptEngine.GetContext();
scriptEngine.ExecutePluginCall(GetPlugin(), _onClose, { ToDuk(ctx, hadError) }, false);
auto ctx = GetContext()->GetScriptEngine().GetContext();
_eventList.Raise(EVENT_CLOSE, GetPlugin(), { ToDuk(ctx, hadError) }, false);
}
void RaiseOnData(const std::string& data)
{
auto& scriptEngine = GetContext()->GetScriptEngine();
auto ctx = scriptEngine.GetContext();
scriptEngine.ExecutePluginCall(GetPlugin(), _onData, { ToDuk(ctx, data) }, false);
_eventList.Raise(EVENT_DATA, GetPlugin(), { ToDuk(ctx, data) }, false);
}
uint32_t GetEventType(const std::string_view& name)
{
if (name == "close")
return EVENT_CLOSE;
if (name == "data")
return EVENT_DATA;
return EVENT_NONE;
}
public:
@@ -203,14 +271,18 @@ namespace OpenRCT2::Scripting
dukglue_register_method(ctx, &ScSocket::end, "end");
dukglue_register_method(ctx, &ScSocket::write, "write");
dukglue_register_method(ctx, &ScSocket::on, "on");
dukglue_register_method(ctx, &ScSocket::off, "off");
}
};
class ScSocketServer : public ScSocketBase
{
private:
static constexpr uint32_t EVENT_NONE = std::numeric_limits<uint32_t>::max();
static constexpr uint32_t EVENT_CONNECTION = 0;
EventList _eventList;
std::unique_ptr<ITcpSocket> _socket;
DukValue _onConnection;
std::vector<std::shared_ptr<ScSocket>> _scClientSockets;
bool _disposed{};
@@ -249,13 +321,31 @@ namespace OpenRCT2::Scripting
ScSocketServer* on(const std::string& eventType, const DukValue& callback)
{
if (eventType == "connection")
auto eventId = GetEventType(eventType);
if (eventId != EVENT_NONE)
{
_onConnection = callback;
_eventList.AddListener(eventId, callback);
}
return this;
}
ScSocketServer* off(const std::string& eventType, const DukValue& callback)
{
auto eventId = GetEventType(eventType);
if (eventId != EVENT_NONE)
{
_eventList.RemoveListener(eventId, callback);
}
return this;
}
uint32_t GetEventType(const std::string_view& name)
{
if (name == "connection")
return EVENT_CONNECTION;
return EVENT_NONE;
}
public:
ScSocketServer(const std::shared_ptr<Plugin>& plugin)
: ScSocketBase(plugin)
@@ -281,7 +371,7 @@ namespace OpenRCT2::Scripting
auto ctx = scriptEngine.GetContext();
auto dukClientSocket = GetObjectAsDukValue(ctx, clientSocket);
scriptEngine.ExecutePluginCall(GetPlugin(), _onConnection, { dukClientSocket }, false);
_eventList.Raise(EVENT_CONNECTION, GetPlugin(), { dukClientSocket }, false);
}
}
}
@@ -306,6 +396,7 @@ namespace OpenRCT2::Scripting
dukglue_register_method(ctx, &ScSocketServer::close, "close");
dukglue_register_method(ctx, &ScSocketServer::listen, "listen");
dukglue_register_method(ctx, &ScSocketServer::on, "on");
dukglue_register_method(ctx, &ScSocketServer::off, "off");
}
};
} // namespace OpenRCT2::Scripting