Add RequestFrame() native (#412)

* Add RequestFrame() native

* Change underlying container from CQueue to ke::Deque

* CFrameAction: Fix PackageScript and MSVC project, wrap CFrameAction in AutoPtr
This commit is contained in:
KliPPy 2017-02-23 12:55:53 +01:00 committed by Vincent Herbet
parent 3a73e12550
commit 828e74e6c3
9 changed files with 169 additions and 0 deletions

61
amxmodx/CFrameAction.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef FRAMEACTION_H
#define FRAMEACTION_H
#include "amxmodx.h"
#include <amtl/am-deque.h>
#include <amtl/am-autoptr.h>
class CFrameActionMngr
{
public:
class CFrameAction
{
public:
CFrameAction(int callbackForward, cell callbackData) :
m_callbackForward(callbackForward),
m_callbackData(callbackData)
{
}
~CFrameAction()
{
unregisterSPForward(m_callbackForward);
}
void Execute()
{
executeForwards(m_callbackForward, m_callbackData);
}
public:
int m_callbackForward;
cell m_callbackData;
};
public:
void AddFrameAction(int callbackForward, cell callbackData)
{
m_requestedFrames.append(new CFrameAction(callbackForward, callbackData));
}
void ExecuteFrameCallbacks()
{
// In case a frame callback requests another frame, newly added frames won't be executed this way
int callbacksToRun = m_requestedFrames.length();
while (callbacksToRun--)
{
ke::AutoPtr<CFrameAction> action = ke::Move(m_requestedFrames.front());
m_requestedFrames.popFront();
action->Execute();
}
}
private:
ke::Deque<ke::AutoPtr<CFrameAction>> m_requestedFrames;
};
#endif // FRAMEACTION_H

View File

@ -4636,6 +4636,24 @@ static cell AMX_NATIVE_CALL AutoExecConfig(AMX *amx, cell *params)
return 1; return 1;
} }
//native RequestFrame(const callback[], any:data);
static cell AMX_NATIVE_CALL RequestFrame(AMX *amx, cell *params)
{
int len;
const char *funcName = get_amxstring(amx, params[1], 0, len);
int func = registerSPForwardByName(amx, funcName, FP_CELL, FP_DONE);
if (func < 0)
{
LogError(amx, AMX_ERR_NATIVE, "Function \"%s\" was not found", funcName);
return 0;
}
g_frameActionMngr.AddFrameAction(func, params[2]);
return 1;
}
static cell AMX_NATIVE_CALL is_rukia_a_hag(AMX *amx, cell *params) static cell AMX_NATIVE_CALL is_rukia_a_hag(AMX *amx, cell *params)
{ {
return 1; return 1;
@ -4834,6 +4852,7 @@ AMX_NATIVE_INFO amxmodx_Natives[] =
{"PrepareArray", PrepareArray}, {"PrepareArray", PrepareArray},
{"ShowSyncHudMsg", ShowSyncHudMsg}, {"ShowSyncHudMsg", ShowSyncHudMsg},
{"AutoExecConfig", AutoExecConfig}, {"AutoExecConfig", AutoExecConfig},
{"RequestFrame", RequestFrame},
{"is_rukia_a_hag", is_rukia_a_hag}, {"is_rukia_a_hag", is_rukia_a_hag},
{NULL, NULL} {NULL, NULL}
}; };

View File

@ -51,6 +51,7 @@
#include "amxxlog.h" #include "amxxlog.h"
#include "CvarManager.h" #include "CvarManager.h"
#include "CoreConfig.h" #include "CoreConfig.h"
#include "CFrameAction.h"
#include <amxmodx_version.h> #include <amxmodx_version.h>
#include <HLTypeConversion.h> #include <HLTypeConversion.h>
@ -166,6 +167,7 @@ struct fakecmd_t
extern CLog g_log; extern CLog g_log;
extern CPluginMngr g_plugins; extern CPluginMngr g_plugins;
extern CTaskMngr g_tasksMngr; extern CTaskMngr g_tasksMngr;
extern CFrameActionMngr g_frameActionMngr;
extern CPlayer g_players[33]; extern CPlayer g_players[33];
extern CPlayer* mPlayer; extern CPlayer* mPlayer;
extern CmdMngr g_commands; extern CmdMngr g_commands;

View File

@ -71,6 +71,7 @@ CPlayer g_players[33];
CPlayer* mPlayer; CPlayer* mPlayer;
CPluginMngr g_plugins; CPluginMngr g_plugins;
CTaskMngr g_tasksMngr; CTaskMngr g_tasksMngr;
CFrameActionMngr g_frameActionMngr;
CmdMngr g_commands; CmdMngr g_commands;
CFlagManager FlagMan; CFlagManager FlagMan;
EventsMngr g_events; EventsMngr g_events;
@ -1217,6 +1218,8 @@ void C_StartFrame_Post(void)
} }
#endif // MEMORY_TEST #endif // MEMORY_TEST
g_frameActionMngr.ExecuteFrameCallbacks();
if (g_task_time > gpGlobals->time) if (g_task_time > gpGlobals->time)
RETURN_META(MRES_IGNORED); RETURN_META(MRES_IGNORED);

View File

@ -376,6 +376,7 @@
<ClInclude Include="..\trie_natives.h" /> <ClInclude Include="..\trie_natives.h" />
<ClInclude Include="..\..\public\sdk\amxxmodule.h" /> <ClInclude Include="..\..\public\sdk\amxxmodule.h" />
<ClInclude Include="..\..\public\sdk\moduleconfig.h" /> <ClInclude Include="..\..\public\sdk\moduleconfig.h" />
<ClInclude Include="..\CFrameAction.h">
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\version.rc" /> <ResourceCompile Include="..\version.rc" />

View File

@ -500,6 +500,9 @@
<ClInclude Include="..\CoreConfig.h"> <ClInclude Include="..\CoreConfig.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\CFrameAction.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\version.rc"> <ResourceCompile Include="..\version.rc">

View File

@ -3290,5 +3290,18 @@ forward OnAutoConfigsBuffered();
*/ */
native AutoExecConfig(bool:autoCreate = true, const name[] = "", const folder[] = ""); native AutoExecConfig(bool:autoCreate = true, const name[] = "", const folder[] = "");
/**
* Creates a single use hook for the next frame.
*
* @param callback Function to be executed on the next frame.
* @param data Optional data to be passed to the callback function.
*
* @note Callback function prototype:
* public function(data)
*
* @noreturn
*/
native RequestFrame(const callback[], any:data = 0);
// Always keep this at the bottom of this file // Always keep this at the bottom of this file
#include <message_stocks> #include <message_stocks>

View File

@ -0,0 +1,66 @@
#include <amxmodx>
#include <fakemeta>
/*
Expected console output:
Command_Test - Frame: X
FrameCallback1 - Frame: X + 1 Data: 100
FrameCallback2 - Frame: X + 2 Data: 200
FrameCallback3 - Frame: X + 2 Data: 300
FrameCallback4 - Frame: X + 3 Data: 400
FrameCallback4 - Frame: X + 3 Data: 500
*/
new g_frameNumber = 0;
public plugin_precache()
{
register_forward(FM_StartFrame, "OnStartFrame", false);
}
public plugin_init()
{
register_plugin("RequestFrame() Test", "1.0.0", "KliPPy");
register_concmd("request_frame_test", "Command_Test");
}
public OnStartFrame()
{
g_frameNumber++;
}
public Command_Test()
{
console_print(0, "Command_Test - Frame: %d", g_frameNumber);
RequestFrame("FrameCallback1", 100);
}
public FrameCallback1(data)
{
console_print(0, "FrameCallback1 - Frame: %d Data: %d", g_frameNumber, data);
RequestFrame("FrameCallback2", 200);
RequestFrame("FrameCallback3", 300);
}
public FrameCallback2(data)
{
console_print(0, "FrameCallback2 - Frame: %d Data: %d", g_frameNumber, data);
RequestFrame("FrameCallback4", 400);
}
public FrameCallback3(data)
{
console_print(0, "FrameCallback3 - Frame: %d Data: %d", g_frameNumber, data);
RequestFrame("FrameCallback4", 500);
}
public FrameCallback4(data)
{
console_print(0, "FrameCallback4 - Frame: %d Data: %d", g_frameNumber, data);
}

View File

@ -267,6 +267,7 @@ scripting_files = [
'testsuite/textparse_test.sma', 'testsuite/textparse_test.sma',
'testsuite/textparse_test.cfg', 'testsuite/textparse_test.cfg',
'testsuite/textparse_test.ini', 'testsuite/textparse_test.ini',
'testsuite/request_frame_test.sma',
'include/amxconst.inc', 'include/amxconst.inc',
'include/amxmisc.inc', 'include/amxmisc.inc',
'include/amxmodx.inc', 'include/amxmodx.inc',