From 7c011b0ba78b522ca850b198cad7097ba873d263 Mon Sep 17 00:00:00 2001
From: RD42 <42702181+dashr9230@users.noreply.github.com>
Date: Sun, 4 Feb 2024 19:15:17 +0800
Subject: [PATCH] [server/bot] Add and match `amxtime.c` functions
---
bot/bot.vcproj | 3 +
server/amx/amxtime.c | 297 +++++++++++++++++++++++++++++++++++++++++++
server/server.vcproj | 3 +
3 files changed, 303 insertions(+)
create mode 100644 server/amx/amxtime.c
diff --git a/bot/bot.vcproj b/bot/bot.vcproj
index 910c5c1..a027512 100644
--- a/bot/bot.vcproj
+++ b/bot/bot.vcproj
@@ -259,6 +259,9 @@
+
+
diff --git a/server/amx/amxtime.c b/server/amx/amxtime.c
new file mode 100644
index 0000000..2de5811
--- /dev/null
+++ b/server/amx/amxtime.c
@@ -0,0 +1,297 @@
+/* Date/time module for the Pawn Abstract Machine
+ *
+ * Copyright (c) ITB CompuPhase, 2001-2005
+ *
+ * This software is provided "as-is", without any express or implied warranty.
+ * In no event will the authors be held liable for any damages arising from
+ * the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software in
+ * a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ * Version: $Id: amxtime.c 3363 2005-07-23 09:03:29Z thiadmer $
+ */
+#include
+#include
+#include "amx.h"
+#if defined __WIN32__ || defined _WIN32
+ #include
+ #include
+#endif
+
+#if !defined CLOCKS_PER_SEC
+ #define CLOCKS_PER_SEC CLK_TCK
+#endif
+#if defined __WIN32__ || defined _WIN32 || defined WIN32
+ static int timerset = 0;
+ /* timeGetTime() is more accurate on WindowsNT if timeBeginPeriod(1) is set */
+ #define INIT_TIMER() \
+ if (!timerset) { \
+ timeBeginPeriod(1); \
+ timerset=1; \
+ }
+#else
+ #define INIT_TIMER()
+#endif
+static unsigned long timestamp;
+static unsigned long timelimit;
+static int timerepeat;
+
+static unsigned long gettimestamp(void)
+{
+ unsigned long value;
+
+ #if defined __WIN32__ || defined _WIN32 || defined WIN32
+ value=timeGetTime(); /* this value is already in milliseconds */
+ #else
+ value=(cell)clock();
+ #if CLOCKS_PER_SEC!=1000
+ /* convert to milliseconds */
+ value=(cell)((1000L * (value+CLOCKS_PER_SEC/2)) / CLOCKS_PER_SEC);
+ #endif
+ #endif
+ return value;
+}
+
+/* settime(hour, minute, second)
+ * Always returns 0
+ */
+static cell AMX_NATIVE_CALL n_settime(AMX *amx, cell *params)
+{
+ #if defined __WIN32__ || defined _WIN32 || defined WIN32
+ SYSTEMTIME systim;
+
+ GetLocalTime(&systim);
+ if (params[1]>=0)
+ systim.wHour=(WORD)params[1];
+ if (params[2]>=0)
+ systim.wMinute=(WORD)params[2];
+ if (params[3]>=0)
+ systim.wSecond=(WORD)params[3];
+ SetLocalTime(&systim);
+ #else
+ /* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
+ * must have "root" permission to call stime()
+ */
+ time_t sec1970;
+ struct tm gtm;
+
+ (void)amx;
+ time(&sec1970);
+ gtm=*localtime(&sec1970);
+ if (params[1]>=0)
+ gtm.tm_hour=params[1];
+ if (params[2]>=0)
+ gtm.tm_min=params[2];
+ if (params[3]>=0)
+ gtm.tm_sec=params[3];
+ sec1970=mktime(>m);
+ stime(&sec1970);
+ #endif
+ (void)amx;
+ return 0;
+}
+
+/* gettime(&hour, &minute, &second)
+ * The return value is the number of seconds since 1 January 1970 (Unix system
+ * time).
+ */
+static cell AMX_NATIVE_CALL n_gettime(AMX *amx, cell *params)
+{
+ time_t sec1970;
+ struct tm gtm;
+ cell *cptr;
+
+ assert(params[0]==(int)(3*sizeof(cell)));
+
+ time(&sec1970);
+
+ /* on DOS/Windows, the timezone is usually not set for the C run-time
+ * library; in that case gmtime() and localtime() return the same value
+ */
+ gtm=*localtime(&sec1970);
+ if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
+ *cptr=gtm.tm_hour;
+ if (amx_GetAddr(amx,params[2],&cptr)==AMX_ERR_NONE)
+ *cptr=gtm.tm_min;
+ if (amx_GetAddr(amx,params[3],&cptr)==AMX_ERR_NONE)
+ *cptr=gtm.tm_sec;
+
+ /* the time() function returns the number of seconds since January 1 1970
+ * in Universal Coordinated Time (the successor to Greenwich Mean Time)
+ */
+ return sec1970;
+}
+
+/* setdate(year, month, day)
+ * Always returns 0
+ */
+static cell AMX_NATIVE_CALL n_setdate(AMX *amx, cell *params)
+{
+ #if defined __WIN32__ || defined _WIN32 || defined WIN32
+ SYSTEMTIME systim;
+
+ GetLocalTime(&systim);
+ if (params[1]!=0)
+ systim.wYear=(WORD)params[1];
+ if (params[2]!=0)
+ systim.wMonth=(WORD)params[2];
+ if (params[3]!=0)
+ systim.wDay=(WORD)params[3];
+ SetLocalTime(&systim);
+ #else
+ /* Linux/Unix (and some DOS compilers) have stime(); on Linux/Unix, you
+ * must have "root" permission to call stime()
+ */
+ time_t sec1970;
+ struct tm gtm;
+
+ (void)amx;
+ time(&sec1970);
+ gtm=*localtime(&sec1970);
+ if (params[1]!=0)
+ gtm.tm_year=params[1]-1900;
+ if (params[2]!=0)
+ gtm.tm_mon=params[2]-1;
+ if (params[3]!=0)
+ gtm.tm_mday=params[3];
+ sec1970=mktime(>m);
+ stime(&sec1970);
+ #endif
+ (void)amx;
+ return 0;
+}
+
+/* getdate(&year, &month, &day)
+ * The return value is the number of days since the start of the year. January
+ * 1 is day 1 of the year.
+ */
+static cell AMX_NATIVE_CALL n_getdate(AMX *amx, cell *params)
+{
+ time_t sec1970;
+ struct tm gtm;
+ cell *cptr;
+
+ assert(params[0]==(int)(3*sizeof(cell)));
+
+ time(&sec1970);
+
+ gtm=*localtime(&sec1970);
+ if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
+ *cptr=gtm.tm_year+1900;
+ if (amx_GetAddr(amx,params[2],&cptr)==AMX_ERR_NONE)
+ *cptr=gtm.tm_mon+1;
+ if (amx_GetAddr(amx,params[3],&cptr)==AMX_ERR_NONE)
+ *cptr=gtm.tm_mday;
+
+ return gtm.tm_yday+1;
+}
+
+/* tickcount(&granularity)
+ * Returns the number of milliseconds since start-up. For a 32-bit cell, this
+ * count overflows after approximately 24 days of continuous operation.
+ */
+static cell AMX_NATIVE_CALL n_tickcount(AMX *amx, cell *params)
+{
+ cell *cptr;
+
+ assert(params[0]==(int)sizeof(cell));
+
+ INIT_TIMER();
+ #if defined __WIN32__ || defined _WIN32 || defined WIN32
+ if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
+ *cptr=1000; /* granularity = 1 ms */
+ #else
+ if (amx_GetAddr(amx,params[1],&cptr)==AMX_ERR_NONE)
+ *cptr=(cell)CLOCKS_PER_SEC; /* in Unix/Linux, this is often 100 */
+ #endif
+ return gettimestamp() & 0x7fffffff;
+}
+
+/* settimer(milliseconds, bool: singleshot = false)
+ * Sets the delay until the @timer() callback is called. The timer may either
+ * be single-shot or repetitive.
+ */
+static cell AMX_NATIVE_CALL n_settimer(AMX *amx, cell *params)
+{
+ (void)amx;
+ assert(params[0]==(int)(2*sizeof(cell)));
+ timestamp = gettimestamp();
+ timelimit = params[1];
+ timerepeat = (int)(params[2] == 0);
+ return 0;
+}
+
+
+#if !defined AMXTIME_NOIDLE
+static AMX_DEBUG PrevIdle = NULL;
+static int idxTimer = -1;
+
+static int AMXAPI amx_TimeIdle(AMX *amx)
+{
+ int err=0;
+
+ assert(idxTimer >= 0);
+
+ if (PrevIdle != NULL)
+ PrevIdle(amx);
+
+ if (timelimit>0 && (gettimestamp()-timestamp)>=timelimit) {
+ if (timerepeat)
+ timestamp+=timelimit;
+ else
+ timelimit=0; /* do not repeat single-shot timer */
+ err = amx_Exec(amx, NULL, idxTimer);
+ while (err == AMX_ERR_SLEEP)
+ err = amx_Exec(amx, NULL, AMX_EXEC_CONT);
+ } /* if */
+
+ return err;
+}
+#endif
+
+
+#if defined __cplusplus
+ extern "C"
+#endif
+const AMX_NATIVE_INFO time_Natives[] = {
+ { "gettime", n_gettime },
+ { "settime", n_settime },
+ { "getdate", n_getdate },
+ { "setdate", n_setdate },
+ { "tickcount", n_tickcount },
+ { "settimer", n_settimer },
+ { NULL, NULL } /* terminator */
+};
+
+int AMXEXPORT amx_TimeInit(AMX *amx)
+{
+ #if !defined AMXTIME_NOIDLE
+ /* see whether there is a @timer() function */
+ if (amx_FindPublic(amx,"@timer",&idxTimer) == AMX_ERR_NONE) {
+ if (amx_GetUserData(amx, AMX_USERTAG('I','d','l','e'), (void**)&PrevIdle) != AMX_ERR_NONE)
+ PrevIdle = NULL;
+ amx_SetUserData(amx, AMX_USERTAG('I','d','l','e'), amx_TimeIdle);
+ } /* if */
+ #endif
+
+ return amx_Register(amx, time_Natives, -1);
+}
+
+int AMXEXPORT amx_TimeCleanup(AMX *amx)
+{
+ (void)amx;
+ #if !defined AMXTIME_NOIDLE
+ PrevIdle = NULL;
+ #endif
+ return AMX_ERR_NONE;
+}
diff --git a/server/server.vcproj b/server/server.vcproj
index 4314bb7..58a1905 100644
--- a/server/server.vcproj
+++ b/server/server.vcproj
@@ -235,6 +235,9 @@
+
+