From a2bb038ed07bf712934aa052ba2b99c266ffcf71 Mon Sep 17 00:00:00 2001 From: danij Date: Wed, 5 Sep 2012 12:29:02 +0100 Subject: [PATCH] libcommon: Experimenting with a console command EventSequence handler Presently the cheat console commands use a somewhat awkward mechanic where the arguments are converted to integers, packed into an array and then fed to the relevant cheat code handler. This not only makes them difficult to extend but also results in code duplication. G_AddEventSequenceCommand() works identically to G_AddEventSequence() except that the native function callback is replaced with a console command execution. With a little reqwiring work, most if not all the cheat code handlers could be replaced with templated console command event sequences. Presently unused. --- .../plugins/common/include/g_eventsequence.h | 8 +++ .../plugins/common/src/g_eventsequence.cpp | 70 +++++++++++++++++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/doomsday/plugins/common/include/g_eventsequence.h b/doomsday/plugins/common/include/g_eventsequence.h index 26f4297b99..e6576a7651 100644 --- a/doomsday/plugins/common/include/g_eventsequence.h +++ b/doomsday/plugins/common/include/g_eventsequence.h @@ -67,6 +67,14 @@ int G_EventSequenceResponder(event_t* ev); */ void G_AddEventSequence(const char* sequence, eventsequencehandler_t callback); +/** + * Add a new event sequence. + * + * @param sequence Text description of the sequence. + * @param cmdTemplate Templated console command to be executed upon sequence completion. + */ +void G_AddEventSequenceCommand(const char* sequence, const char* commandTemplate); + #if __cplusplus } // extern "C" #endif diff --git a/doomsday/plugins/common/src/g_eventsequence.cpp b/doomsday/plugins/common/src/g_eventsequence.cpp index baad19fa2c..03546262ba 100644 --- a/doomsday/plugins/common/src/g_eventsequence.cpp +++ b/doomsday/plugins/common/src/g_eventsequence.cpp @@ -28,10 +28,55 @@ #include "common.h" #include "g_eventsequence.h" +/// Base class for all sequence complete handlers. +class ISequenceCompleteHandler +{ +public: + virtual ~ISequenceCompleteHandler() {} + virtual void invoke(int player, EventSequenceArg* args, int numArgs) = 0; +}; + +/// Sequence complete Callback handler. +class SequenceCompleteHandler : public ISequenceCompleteHandler +{ +public: + SequenceCompleteHandler(eventsequencehandler_t _callback) : callback(_callback) {} + virtual void invoke(int player, EventSequenceArg* args, int numArgs) + { + callback(player, args, numArgs); + } +private: + eventsequencehandler_t callback; +}; + +/// Sequence complete Command handler. +class SequenceCompleteCommandHandler : public ISequenceCompleteHandler +{ +public: + SequenceCompleteCommandHandler(const char* _commandTemplate) + { + Str_Set(Str_InitStd(&commandTemplate), _commandTemplate); + } + virtual ~SequenceCompleteCommandHandler() + { + Str_Free(&commandTemplate); + } + virtual void invoke(int player, EventSequenceArg* args, int numArgs) + { + DENG_UNUSED(player); + DENG_UNUSED(args); + DENG_UNUSED(numArgs); + /// @todo Compose the real command substituting arguments in the template. + DD_Execute(true/*silent*/, Str_Text(&commandTemplate)); + } +private: + Str commandTemplate; +}; + class EventSequence { public: - EventSequence(const char* _sequence, eventsequencehandler_t _handler) + EventSequence(const char* _sequence, ISequenceCompleteHandler& _handler) : sequence(), handler(_handler), pos(0), numArgs(0), args(0) { int len = strlen(_sequence); @@ -47,7 +92,7 @@ class EventSequence int arg = ch[1] - '0'; if(arg < 1 || arg > 9) { - Con_Message("Warning: EventSequence: Bad suffix %c in sequence %s, sequence truncated.", *ch, _sequence); + Con_Message("Warning: EventSequence: Bad suffix %c in sequence %s, sequence truncated.", ch[1], _sequence); len = ch - _sequence; break; } @@ -76,6 +121,7 @@ class EventSequence { Str_Free(&sequence); if(args) delete[] args; + delete &handler; } /** @@ -121,7 +167,7 @@ class EventSequence if(pos < Str_Length(&sequence)) return false; // Sequence completed. - handler(player, args, numArgs); + handler.invoke(player, args, numArgs); rewind(); return true; @@ -129,7 +175,7 @@ class EventSequence private: Str sequence; - eventsequencehandler_t handler; + ISequenceCompleteHandler& handler; int pos; int numArgs; EventSequenceArg* args; @@ -185,10 +231,20 @@ int G_EventSequenceResponder(event_t* ev) return eventWasEaten; } -void G_AddEventSequence(const char* sequence, eventsequencehandler_t handler) +void G_AddEventSequence(const char* sequence, eventsequencehandler_t callback) { if(!inited) Con_Error("G_AddEventSequence: Subsystem not presently initialized."); - if(!sequence || !sequence[0] || !handler) Con_Error("G_AddEventSequence: Invalid argument(s)."); + if(!sequence || !sequence[0] || !callback) Con_Error("G_AddEventSequence: Invalid argument(s)."); + + SequenceCompleteHandler* handler = new SequenceCompleteHandler(callback); + sequences.push_back(new EventSequence(sequence, *handler)); +} + +void G_AddEventSequenceCommand(const char* sequence, const char* commandTemplate) +{ + if(!inited) Con_Error("G_AddEventSequenceCommand: Subsystem not presently initialized."); + if(!sequence || !sequence[0] || !commandTemplate || !commandTemplate[0]) Con_Error("G_AddEventSequenceCommand: Invalid argument(s)."); - sequences.push_back(new EventSequence(sequence, handler)); + SequenceCompleteCommandHandler* handler = new SequenceCompleteCommandHandler(commandTemplate); + sequences.push_back(new EventSequence(sequence, *handler)); }