Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 77 additions & 63 deletions Server/Components/Pawn/timers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ Pair<size_t, PawnTimerHandler*> PawnTimerImpl::newTimer(const char* callback, Mi
ITimersComponent* timers = PawnManager::Get()->timers;
if (timers && amx)
{

int callbackId;

// Also checking the callbackId value because SAMPGDK's FindPublic hook returns AMX_ERR_NONE.
Expand Down Expand Up @@ -44,82 +43,97 @@ int PawnTimerImpl::setTimer(const char* callback, Milliseconds interval, bool re
return newTimer(callback, interval, repeating, amx).first;
}

#define RETURN_WITH_ERROR(message) \
amx_RaiseError(amx, err); \
PawnManager::Get()->core->logLn(LogLevel::Error, "SetTimerEx: There was a problem creating the timer %s (fmt: %s). Error: %s (amx: %s)", callback, fmt, message, aux_StrError(err)); \
timer->kill(); \
return 0

int PawnTimerImpl::setTimerEx(const char* callback, Milliseconds interval, bool repeating, const char* fmt, AMX* amx, const cell* params)
{
auto res = newTimer(callback, interval, repeating, amx);
PawnTimerHandler* handler = res.second;
if (res.second)
auto [id, handler] = newTimer(callback, interval, repeating, amx);

if (!handler)
{
int err = AMX_ERR_NONE;
handler->fmt = fmt;
return id;
}

auto* timer = this->getTimer(handler->poolID);

cell* data;
cell* len1;
int len2;
int err = AMX_ERR_NONE;
handler->fmt = fmt;

// Collect data and parameters
for (size_t i = 0; fmt[i]; ++i)
cell* data;
cell* len1;
int len2;

// Collect data and parameters
for (size_t i = 0; fmt[i]; ++i)
{
switch (fmt[i])
{
case 'a':
{
switch (fmt[i])
++i;

if (fmt[i] != 'i' && fmt[i] != 'd')
{
case 'a':
++i;
if (fmt[i] != 'i' && fmt[i] != 'd')
err = AMX_ERR_PARAMS;
RETURN_WITH_ERROR("Error in pushing parameters; Array not followed by size");
}
if ((err = amx_GetAddr(amx, params[i - 1], &data)) != AMX_ERR_NONE || (err = amx_GetAddr(amx, params[i], &len1)) != AMX_ERR_NONE || *len1 < 1)
{
if (err == AMX_ERR_NONE)
{
err = AMX_ERR_PARAMS;
return newTimerExError(handler, amx, err, "Error in pushing parameters; Array not followed by size");
}
if (
(err = amx_GetAddr(amx, params[i - 1], &data)) != AMX_ERR_NONE || (err = amx_GetAddr(amx, params[i], &len1)) != AMX_ERR_NONE || *len1 < 1)
{
if (err == AMX_ERR_NONE)
{
err = AMX_ERR_PARAMS;
}
return newTimerExError(handler, amx, err, "Error in pushing parameters");
}
// Store the offset in to the new heap data, then the size, then copy the data.
handler->params.push_back(handler->data.size() * sizeof(cell));
handler->params.push_back(*len1);
handler->data.insert(handler->data.end(), data, data + *len1);
break;
case 's':
if ((err = amx_GetAddr(amx, params[i], &data)) != AMX_ERR_NONE || (err = amx_StrSize(data, &len2)) != AMX_ERR_NONE)
{
return newTimerExError(handler, amx, err, "Error in pushing parameters");
}
// Store the offset in to the new heap data, then copy the data.
handler->params.push_back(handler->data.size() * sizeof(cell));
handler->data.insert(handler->data.end(), data, data + len2);
break;
case 'v':
if ((err = amx_GetAddr(amx, params[i], &data)) != AMX_ERR_NONE)
{
return newTimerExError(handler, amx, err, "Error in pushing parameters");
}
// Store the offset in to the new heap data, then copy the data.
handler->params.push_back(handler->data.size() * sizeof(cell));
handler->data.push_back(*data);
break;
default:
if ((err = amx_GetAddr(amx, params[i], &data)) != AMX_ERR_NONE)
{
return newTimerExError(handler, amx, err, "Error in pushing parameters");
}
handler->params.push_back(*data);
break;
RETURN_WITH_ERROR("Error in pushing parameters");
}

// Store the offset in to the new heap data, then the size, then copy the data.
handler->params.push_back(handler->data.size() * sizeof(cell));
handler->params.push_back(*len1);
handler->data.insert(handler->data.end(), data, data + *len1);
break;
}
case 's':
{
if ((err = amx_GetAddr(amx, params[i], &data)) != AMX_ERR_NONE || (err = amx_StrSize(data, &len2)) != AMX_ERR_NONE)
{
RETURN_WITH_ERROR("Error in pushing parameters");
}

// Store the offset in to the new heap data, then copy the data.
handler->params.push_back(handler->data.size() * sizeof(cell));
handler->data.insert(handler->data.end(), data, data + len2);
break;
}
case 'v':
{
if ((err = amx_GetAddr(amx, params[i], &data)) != AMX_ERR_NONE)
{
RETURN_WITH_ERROR("Error in pushing parameters");
}

// Store the offset in to the new heap data, then copy the data.
handler->params.push_back(handler->data.size() * sizeof(cell));
handler->data.push_back(*data);
break;
}
default:
{
if ((err = amx_GetAddr(amx, params[i], &data)) != AMX_ERR_NONE)
{
RETURN_WITH_ERROR("Error in pushing parameters");
}

handler->params.push_back(*data);
break;
}
}
}
return res.first;
}

int PawnTimerImpl::newTimerExError(PawnTimerHandler* handler, AMX* amx, int err, StringView message)
{
amx_RaiseError(amx, err);
PawnManager::Get()->core->logLn(LogLevel::Error, "SetTimerEx: %.*s: %s", PRINT_VIEW(message), aux_StrError(err));
delete handler;
return 0;
return id;
}

void PawnTimerImpl::killTimers(AMX* amx)
Expand Down
1 change: 0 additions & 1 deletion Server/Components/Pawn/timers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ struct PawnTimerImpl : public Singleton<PawnTimerImpl>

private:
Pair<size_t, PawnTimerHandler*> newTimer(const char* callback, Milliseconds interval, bool repeating, AMX* amx);
int newTimerExError(PawnTimerHandler* handler, AMX* amx, int err, StringView message);

size_t insert(ITimer* timer)
{
Expand Down
Loading