diff --git a/src/events.cpp b/src/events.cpp index 73f440947..4535f98f5 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -5,6 +5,7 @@ #include "gi.h" #include "v_text.h" #include "actor.h" +#include "c_dispatch.h" DStaticEventHandler* E_FirstEventHandler = nullptr; DStaticEventHandler* E_LastEventHandler = nullptr; @@ -394,6 +395,12 @@ bool E_Responder(event_t* ev) return false; } +void E_Console(int player, FString name, int arg1, int arg2, int arg3) +{ + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) + handler->ConsoleProcess(player, name, arg1, arg2, arg3); +} + bool E_CheckUiProcessors() { for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) @@ -427,6 +434,7 @@ IMPLEMENT_CLASS(DWorldEvent, false, false) IMPLEMENT_CLASS(DPlayerEvent, false, false) IMPLEMENT_CLASS(DUiEvent, false, false) IMPLEMENT_CLASS(DInputEvent, false, false) +IMPLEMENT_CLASS(DConsoleEvent, false, false) DEFINE_FIELD_X(StaticEventHandler, DStaticEventHandler, Order); DEFINE_FIELD_X(StaticEventHandler, DStaticEventHandler, IsUiProcessor); @@ -468,6 +476,10 @@ DEFINE_FIELD_X(InputEvent, DInputEvent, KeyChar); DEFINE_FIELD_X(InputEvent, DInputEvent, MouseX); DEFINE_FIELD_X(InputEvent, DInputEvent, MouseY); +DEFINE_FIELD_X(ConsoleEvent, DConsoleEvent, Player) +DEFINE_FIELD_X(ConsoleEvent, DConsoleEvent, Name) +DEFINE_FIELD_X(ConsoleEvent, DConsoleEvent, Args) + DEFINE_ACTION_FUNCTION(DStaticEventHandler, SetOrder) { PARAM_SELF_PROLOGUE(DStaticEventHandler); @@ -616,6 +628,8 @@ DEFINE_EMPTY_HANDLER(DStaticEventHandler, PlayerDisconnected) DEFINE_EMPTY_HANDLER(DStaticEventHandler, UiProcess); DEFINE_EMPTY_HANDLER(DStaticEventHandler, InputProcess); +DEFINE_EMPTY_HANDLER(DStaticEventHandler, ConsoleProcess); + // =========================================== // // Event handlers @@ -1012,9 +1026,67 @@ bool DStaticEventHandler::InputProcess(event_t* ev) return false; } +static DConsoleEvent* E_SetupConsoleEvent() +{ + static DConsoleEvent* e = nullptr; + if (!e) e = (DConsoleEvent*)RUNTIME_CLASS(DConsoleEvent)->CreateNew(); + e->Player = -1; + e->Name = ""; + for (int i = 0; i < countof(e->Args); i++) + e->Args[i] = 0; + return e; +} + +void DStaticEventHandler::ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3) +{ + IFVIRTUAL(DStaticEventHandler, ConsoleProcess) + { + // don't create excessive DObjects if not going to be processed anyway + if (func == DStaticEventHandler_ConsoleProcess_VMPtr) + return; + DConsoleEvent* e = E_SetupConsoleEvent(); + + // + e->Player = player; + e->Name = name; + e->Args[0] = arg1; + e->Args[1] = arg2; + e->Args[2] = arg3; + + VMValue params[2] = { (DStaticEventHandler*)this, e }; + GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); + } +} + // void DStaticEventHandler::OnDestroy() { E_UnregisterHandler(this); Super::OnDestroy(); } + +// console stuff +// this is kinda like puke, except it distinguishes between local events and playsim events. +CCMD(event) +{ + int argc = argv.argc(); + + if (argc < 2 || argc > 5) + { + Printf("Usage: event [arg1] [arg2] [arg3]\n"); + } + else + { + int arg[3] = { 0, 0, 0 }; + int argn = MIN(argc - 2, countof(arg)); + for (int i = 0; i < argn; i++) + arg[i] = atoi(argv[2 + i]); + // call locally + E_Console(-1, argv[1], arg[0], arg[1], arg[2]); + } +} + +CCMD(netevent) +{ + +} \ No newline at end of file diff --git a/src/events.h b/src/events.h index 1ec6d068a..71c8a27f6 100755 --- a/src/events.h +++ b/src/events.h @@ -57,6 +57,8 @@ void E_PlayerDied(int num); void E_PlayerDisconnected(int num); // this executes on events. bool E_Responder(event_t* ev); // splits events into InputProcess and UiProcess +// this executes on console/net events. +void E_Console(int player, FString name, int arg1, int arg2, int arg3); // check if there is anything that should receive GUI events bool E_CheckUiProcessors(); @@ -139,10 +141,12 @@ public: void PlayerDied(int num); void PlayerDisconnected(int num); - // // return true if handled. - virtual bool InputProcess(event_t* ev); - virtual bool UiProcess(event_t* ev); + bool InputProcess(event_t* ev); + bool UiProcess(event_t* ev); + + // + void ConsoleProcess(int player, FString name, int arg1, int arg2, int arg3); }; class DEventHandler : public DStaticEventHandler { @@ -280,4 +284,20 @@ public: } }; +class DConsoleEvent : public DBaseEvent +{ + DECLARE_CLASS(DConsoleEvent, DBaseEvent) +public: + // player that activated this event. note that it's always -1 for non-playsim events (i.e. these not called with netevent) + int Player; + // + FString Name; + int Args[3]; + + DConsoleEvent() + { + Player = -1; + } +}; + #endif \ No newline at end of file diff --git a/wadsrc/static/zscript/events.txt b/wadsrc/static/zscript/events.txt index fe0d45e7d..24707055f 100755 --- a/wadsrc/static/zscript/events.txt +++ b/wadsrc/static/zscript/events.txt @@ -270,6 +270,15 @@ class InputEvent : BaseEvent native native readonly int MouseY; } +class ConsoleEvent : BaseEvent native +{ + // for net events, this will be the activator. + // for UI events, this is always -1, and you need to check if level is loaded and use players[consoleplayer]. + native readonly int Player; + native readonly String Name; + native readonly int Args[3]; +} + class StaticEventHandler : Object native { // static event handlers CAN register other static event handlers. @@ -311,6 +320,9 @@ class StaticEventHandler : Object native virtual native bool UiProcess(UiEvent e); virtual native bool InputProcess(InputEvent e); + // + virtual native void ConsoleProcess(ConsoleEvent e); + // this value will be queried on Register() to decide the relative order of this handler to every other. // this is most useful in UI systems. // default is 0.