mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-03-11 21:56:43 +00:00
Scheduling commands
- `schedule_add <seconds> <command>` to add a command that runs on a recurring timer. - `schedule_list` to print out all of the scheduled tasks. - NEW: `schedule_clear` to revert the schedule to a blank slate. - `schedule` cvar determines whenever or not to run the scheduled tasks. Unlike HOSTMOD, turning this off will reset the timers of the tasks, instead of freezing them. - I did not implement HOSTMOD's ability to pick from several random command per scheduled task. Would drastically increase the code complexity when you can just use a choose command in your schedule_add for the exact same effect.
This commit is contained in:
parent
d2a0bdb044
commit
0308ab6bd4
5 changed files with 364 additions and 21 deletions
|
|
@ -2001,7 +2001,9 @@ static void CL_ConnectToServer(void)
|
|||
wipegamestate = GS_WAITINGPLAYERS;
|
||||
|
||||
ClearAdminPlayers();
|
||||
Schedule_Clear();
|
||||
K_ClearClientPowerLevels();
|
||||
|
||||
pnumnodes = 1;
|
||||
oldtic = 0;
|
||||
#ifndef NONET
|
||||
|
|
@ -3135,14 +3137,17 @@ void SV_ResetServer(void)
|
|||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
LUA_InvalidatePlayer(&players[i]);
|
||||
playeringame[i] = false;
|
||||
playernode[i] = UINT8_MAX;
|
||||
sprintf(player_names[i], "Player %c", 'A' + i);
|
||||
adminplayers[i] = -1; // Populate the entire adminplayers array with -1.
|
||||
K_ClearClientPowerLevels();
|
||||
splitscreen_invitations[i] = -1;
|
||||
}
|
||||
|
||||
memset(playeringame, false, sizeof playeringame);
|
||||
memset(playernode, UINT8_MAX, sizeof playernode);
|
||||
|
||||
ClearAdminPlayers();
|
||||
Schedule_Clear();
|
||||
K_ClearClientPowerLevels();
|
||||
|
||||
memset(splitscreen_invitations, -1, sizeof splitscreen_invitations);
|
||||
memset(splitscreen_partied, 0, sizeof splitscreen_partied);
|
||||
memset(player_name_changes, 0, sizeof player_name_changes);
|
||||
|
||||
|
|
@ -3227,6 +3232,7 @@ void D_QuitNetGame(void)
|
|||
|
||||
D_CloseConnection();
|
||||
ClearAdminPlayers();
|
||||
Schedule_Clear();
|
||||
K_ClearClientPowerLevels();
|
||||
|
||||
DEBFILE("===========================================================================\n"
|
||||
|
|
@ -5230,7 +5236,13 @@ boolean TryRunTics(tic_t realtics)
|
|||
ps_tictime = I_GetPreciseTime();
|
||||
|
||||
G_Ticker((gametic % NEWTICRATERATIO) == 0);
|
||||
if (gametic % TICRATE == 0)
|
||||
{
|
||||
Schedule_Run();
|
||||
}
|
||||
|
||||
ExtraDataTicker();
|
||||
|
||||
gametic++;
|
||||
consistancy[gametic%BACKUPTICS] = Consistancy();
|
||||
|
||||
|
|
|
|||
297
src/d_netcmd.c
297
src/d_netcmd.c
|
|
@ -98,6 +98,8 @@ static void Got_RunSOCcmd(UINT8 **cp, INT32 playernum);
|
|||
static void Got_Teamchange(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Clearscores(UINT8 **cp, INT32 playernum);
|
||||
static void Got_DiscordInfo(UINT8 **cp, INT32 playernum);
|
||||
static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum);
|
||||
|
||||
static void PointLimit_OnChange(void);
|
||||
static void TimeLimit_OnChange(void);
|
||||
|
|
@ -146,6 +148,8 @@ static void KartEncore_OnChange(void);
|
|||
static void KartComeback_OnChange(void);
|
||||
static void KartEliminateLast_OnChange(void);
|
||||
|
||||
static void Schedule_OnChange(void);
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
static void Fishcake_OnChange(void);
|
||||
#endif
|
||||
|
|
@ -221,6 +225,10 @@ static void Command_Archivetest_f(void);
|
|||
|
||||
static void Command_KartGiveItem_f(void);
|
||||
|
||||
static void Command_Schedule_Add(void);
|
||||
static void Command_Schedule_Clear(void);
|
||||
static void Command_Schedule_List(void);
|
||||
|
||||
// =========================================================================
|
||||
// CLIENT VARIABLES
|
||||
// =========================================================================
|
||||
|
|
@ -521,6 +529,8 @@ consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", 0, perfstats_cons_t, NUL
|
|||
|
||||
consvar_t cv_director = CVAR_INIT ("director", "Off", 0, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_schedule = CVAR_INIT ("schedule", "On", CV_NETVAR|CV_CALL, CV_OnOff, Schedule_OnChange);
|
||||
|
||||
char timedemo_name[256];
|
||||
boolean timedemo_csv;
|
||||
char timedemo_csv_id[256];
|
||||
|
|
@ -536,6 +546,11 @@ UINT8 splitscreen = 0;
|
|||
boolean circuitmap = false;
|
||||
INT32 adminplayers[MAXPLAYERS];
|
||||
|
||||
// Scheduled cvars.
|
||||
scheduleTask_t **schedule = NULL;
|
||||
size_t schedule_size = 0;
|
||||
size_t schedule_len = 0;
|
||||
|
||||
/// \warning Keep this up-to-date if you add/remove/rename net text commands
|
||||
const char *netxcmdnames[MAXNETXCMD - 1] =
|
||||
{
|
||||
|
|
@ -575,7 +590,9 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
"GIVEITEM", // XD_GIVEITEM
|
||||
"ADDBOT", // XD_ADDBOT
|
||||
"DISCORD", // XD_DISCORD
|
||||
"PLAYSOUND" // XD_PLAYSOUND
|
||||
"PLAYSOUND", // XD_PLAYSOUND
|
||||
"SCHEDULETASK", // XD_SCHEDULETASK
|
||||
"SCHEDULECLEAR" // XD_SCHEDULECLEAR
|
||||
};
|
||||
|
||||
// =========================================================================
|
||||
|
|
@ -630,6 +647,9 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
RegisterNetXCmd(XD_GIVEITEM, Got_GiveItemcmd);
|
||||
|
||||
RegisterNetXCmd(XD_SCHEDULETASK, Got_ScheduleTaskcmd);
|
||||
RegisterNetXCmd(XD_SCHEDULECLEAR, Got_ScheduleClearcmd);
|
||||
|
||||
// Remote Administration
|
||||
COM_AddCommand("password", Command_Changepassword_f);
|
||||
COM_AddCommand("login", Command_Login_f); // useful in dedicated to kick off remote admin
|
||||
|
|
@ -687,6 +707,10 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
COM_AddCommand("kartgiveitem", Command_KartGiveItem_f);
|
||||
|
||||
COM_AddCommand("schedule_add", Command_Schedule_Add);
|
||||
COM_AddCommand("schedule_clear", Command_Schedule_Clear);
|
||||
COM_AddCommand("schedule_list", Command_Schedule_List);
|
||||
|
||||
// for master server connection
|
||||
AddMServCommands();
|
||||
|
||||
|
|
@ -758,6 +782,8 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_director);
|
||||
|
||||
CV_RegisterVar(&cv_schedule);
|
||||
|
||||
CV_RegisterVar(&cv_dummyconsvar);
|
||||
|
||||
#ifdef USE_STUN
|
||||
|
|
@ -3731,9 +3757,7 @@ void SetAdminPlayer(INT32 playernum)
|
|||
|
||||
void ClearAdminPlayers(void)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
adminplayers[i] = -1;
|
||||
memset(adminplayers, -1, sizeof(adminplayers));
|
||||
}
|
||||
|
||||
void RemoveAdminPlayer(INT32 playernum)
|
||||
|
|
@ -3850,6 +3874,117 @@ static void Got_Removal(UINT8 **cp, INT32 playernum)
|
|||
CONS_Printf(M_GetText("You are no longer a server administrator.\n"));
|
||||
}
|
||||
|
||||
void Schedule_Run(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (schedule_len == 0)
|
||||
{
|
||||
// No scheduled tasks to run.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cv_schedule.value)
|
||||
{
|
||||
// We don't WANT to run tasks.
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < schedule_len; i++)
|
||||
{
|
||||
scheduleTask_t *task = schedule[i];
|
||||
|
||||
if (task == NULL)
|
||||
{
|
||||
// Shouldn't happen.
|
||||
break;
|
||||
}
|
||||
|
||||
if (task->timer > 0)
|
||||
{
|
||||
task->timer--;
|
||||
}
|
||||
|
||||
if (task->timer == 0)
|
||||
{
|
||||
// Reset timer
|
||||
task->timer = task->basetime;
|
||||
|
||||
// Run command for server
|
||||
if (server)
|
||||
{
|
||||
CONS_Printf(
|
||||
"%d seconds elapsed, running \"" "\x82" "%s" "\x80" "\".\n",
|
||||
task->basetime,
|
||||
task->command
|
||||
);
|
||||
|
||||
COM_BufAddText(task->command);
|
||||
COM_BufAddText("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Schedule_Insert(scheduleTask_t *addTask)
|
||||
{
|
||||
if (schedule_len >= schedule_size)
|
||||
{
|
||||
if (schedule_size == 0)
|
||||
{
|
||||
schedule_size = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
schedule_size *= 2;
|
||||
}
|
||||
|
||||
schedule = Z_ReallocAlign(
|
||||
(void*) schedule,
|
||||
sizeof(scheduleTask_t*) * schedule_size,
|
||||
PU_STATIC,
|
||||
NULL,
|
||||
sizeof(scheduleTask_t*) * 8
|
||||
);
|
||||
}
|
||||
|
||||
schedule[schedule_len] = addTask;
|
||||
schedule_len++;
|
||||
}
|
||||
|
||||
void Schedule_Add(INT16 basetime, INT16 timeleft, const char *command)
|
||||
{
|
||||
scheduleTask_t *task = (scheduleTask_t*) Z_CallocAlign(
|
||||
sizeof(scheduleTask_t),
|
||||
PU_STATIC,
|
||||
NULL,
|
||||
sizeof(scheduleTask_t) * 8
|
||||
);
|
||||
|
||||
task->basetime = basetime;
|
||||
task->timer = timeleft;
|
||||
task->command = Z_StrDup(command);
|
||||
|
||||
Schedule_Insert(task);
|
||||
}
|
||||
|
||||
void Schedule_Clear(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < schedule_len; i++)
|
||||
{
|
||||
scheduleTask_t *task = schedule[i];
|
||||
|
||||
if (task->command)
|
||||
Z_Free(task->command);
|
||||
}
|
||||
|
||||
schedule_len = 0;
|
||||
schedule_size = 0;
|
||||
schedule = NULL;
|
||||
}
|
||||
|
||||
static void Command_MotD_f(void)
|
||||
{
|
||||
size_t i, j;
|
||||
|
|
@ -5023,6 +5158,58 @@ static void Got_GiveItemcmd(UINT8 **cp, INT32 playernum)
|
|||
players[playernum].itemamount = amt;
|
||||
}
|
||||
|
||||
static void Got_ScheduleTaskcmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char command[MAXTEXTCMD];
|
||||
INT16 seconds;
|
||||
|
||||
seconds = READINT16(*cp);
|
||||
READSTRING(*cp, command);
|
||||
|
||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
M_GetText ("Illegal schedule task received from %s\n"),
|
||||
player_names[playernum]);
|
||||
if (server)
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
Schedule_Add(seconds, seconds, (const char *)command);
|
||||
|
||||
if (server || consoleplayer == playernum)
|
||||
{
|
||||
CONS_Printf(
|
||||
"OK! Running \"" "\x82" "%s" "\x80" "\" every " "\x82" "%d" "\x80" " seconds.\n",
|
||||
command,
|
||||
seconds
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static void Got_ScheduleClearcmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
(void)cp;
|
||||
|
||||
if (playernum != serverplayer && !IsPlayerAdmin(playernum))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
M_GetText ("Illegal schedule clear received from %s\n"),
|
||||
player_names[playernum]);
|
||||
if (server)
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
Schedule_Clear();
|
||||
|
||||
if (server || consoleplayer == playernum)
|
||||
{
|
||||
CONS_Printf("All scheduled tasks have been cleared.\n");
|
||||
}
|
||||
}
|
||||
|
||||
/** Prints the number of displayplayers[0].
|
||||
*
|
||||
* \todo Possibly remove this; it was useful for debugging at one point.
|
||||
|
|
@ -5287,6 +5474,86 @@ static void Command_KartGiveItem_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void Command_Schedule_Add(void)
|
||||
{
|
||||
UINT8 buf[MAXTEXTCMD];
|
||||
UINT8 *buf_p = buf;
|
||||
|
||||
size_t ac;
|
||||
INT16 seconds;
|
||||
const char *command;
|
||||
|
||||
if (!(server || IsPlayerAdmin(consoleplayer)))
|
||||
{
|
||||
CONS_Printf("Only the server or a remote admin can use this.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ac = COM_Argc();
|
||||
if (ac < 3)
|
||||
{
|
||||
CONS_Printf("schedule <seconds> <...>: runs the specified commands on a recurring timer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
seconds = atoi(COM_Argv(1));
|
||||
|
||||
if (seconds <= 0)
|
||||
{
|
||||
CONS_Printf("Timer must be at least 1 second.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
command = COM_Argv(2);
|
||||
|
||||
WRITEINT16(buf_p, seconds);
|
||||
WRITESTRING(buf_p, command);
|
||||
|
||||
SendNetXCmd(XD_SCHEDULETASK, buf, buf_p - buf);
|
||||
}
|
||||
|
||||
static void Command_Schedule_Clear(void)
|
||||
{
|
||||
if (!(server || IsPlayerAdmin(consoleplayer)))
|
||||
{
|
||||
CONS_Printf("Only the server or a remote admin can use this.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SendNetXCmd(XD_SCHEDULECLEAR, NULL, 0);
|
||||
}
|
||||
|
||||
static void Command_Schedule_List(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!(server || IsPlayerAdmin(consoleplayer)))
|
||||
{
|
||||
// I set it up in a way that this information could be available
|
||||
// to everyone, but HOSTMOD has it server/admin-only too, so eh?
|
||||
CONS_Printf("Only the server or a remote admin can use this.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (schedule_len == 0)
|
||||
{
|
||||
CONS_Printf("No tasks are scheduled.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < schedule_len; i++)
|
||||
{
|
||||
scheduleTask_t *task = schedule[i];
|
||||
|
||||
CONS_Printf(
|
||||
"In " "\x82" "%d" "\x80" " second%s: " "\x82" "%s" "\x80" "\n",
|
||||
task->timer,
|
||||
(task->timer > 1) ? "s" : "",
|
||||
task->command
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** Makes a change to ::cv_forceskin take effect immediately.
|
||||
*
|
||||
* \sa Command_SetForcedSkin_f, cv_forceskin, forcedskin
|
||||
|
|
@ -5912,6 +6179,28 @@ static void KartEliminateLast_OnChange(void)
|
|||
P_CheckRacers();
|
||||
}
|
||||
|
||||
static void Schedule_OnChange(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (cv_schedule.value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (schedule_len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Reset timers when turning off.
|
||||
for (i = 0; i < schedule_len; i++)
|
||||
{
|
||||
scheduleTask_t *task = schedule[i];
|
||||
task->timer = task->basetime;
|
||||
}
|
||||
}
|
||||
|
||||
void Got_DiscordInfo(UINT8 **p, INT32 playernum)
|
||||
{
|
||||
if (playernum != serverplayer /*&& !IsPlayerAdmin(playernum)*/)
|
||||
|
|
|
|||
|
|
@ -115,6 +115,8 @@ extern consvar_t cv_perfstats;
|
|||
|
||||
extern consvar_t cv_director;
|
||||
|
||||
extern consvar_t cv_schedule;
|
||||
|
||||
extern char timedemo_name[256];
|
||||
extern boolean timedemo_csv;
|
||||
extern char timedemo_csv_id[256];
|
||||
|
|
@ -159,6 +161,8 @@ typedef enum
|
|||
XD_ADDBOT, // 33
|
||||
XD_DISCORD, // 34
|
||||
XD_PLAYSOUND, // 35
|
||||
XD_SCHEDULETASK, // 36
|
||||
XD_SCHEDULECLEAR, // 37
|
||||
|
||||
MAXNETXCMD
|
||||
} netxcmd_t;
|
||||
|
|
@ -227,6 +231,22 @@ void RemoveAdminPlayer(INT32 playernum);
|
|||
void ItemFinder_OnChange(void);
|
||||
void D_SetPassword(const char *pw);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT16 basetime;
|
||||
UINT16 timer;
|
||||
char *command;
|
||||
} scheduleTask_t;
|
||||
|
||||
extern scheduleTask_t **schedule;
|
||||
extern size_t schedule_size;
|
||||
extern size_t schedule_len;
|
||||
|
||||
void Schedule_Run(void);
|
||||
void Schedule_Insert(scheduleTask_t *addTask);
|
||||
void Schedule_Add(INT16 basetime, INT16 timeleft, const char *command);
|
||||
void Schedule_Clear(void);
|
||||
|
||||
// used for the player setup menu
|
||||
UINT8 CanChangeSkin(INT32 playernum);
|
||||
|
||||
|
|
|
|||
|
|
@ -60,16 +60,8 @@ SINT8 K_UsingPowerLevels(void)
|
|||
|
||||
void K_ClearClientPowerLevels(void)
|
||||
{
|
||||
UINT8 i, j;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
clientPowerAdd[i] = 0;
|
||||
|
||||
for (j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
{
|
||||
clientpowerlevels[i][j] = 0;
|
||||
}
|
||||
}
|
||||
memset(clientpowerlevels, 0, sizeof clientpowerlevels);
|
||||
memset(clientPowerAdd, 0, sizeof clientPowerAdd);
|
||||
}
|
||||
|
||||
// Adapted from this: http://wiki.tockdom.com/wiki/Player_Rating
|
||||
|
|
|
|||
|
|
@ -4407,7 +4407,7 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride)
|
|||
|
||||
static void P_NetArchiveMisc(boolean resending)
|
||||
{
|
||||
INT32 i;
|
||||
size_t i;
|
||||
|
||||
WRITEUINT32(save_p, ARCHIVEBLOCK_MISC);
|
||||
|
||||
|
|
@ -4536,11 +4536,23 @@ static void P_NetArchiveMisc(boolean resending)
|
|||
WRITEUINT8(save_p, 0x2f);
|
||||
else
|
||||
WRITEUINT8(save_p, 0x2e);
|
||||
|
||||
// Only the server uses this, but it
|
||||
// needs synched for remote admins anyway.
|
||||
WRITEUINT32(save_p, schedule_len);
|
||||
for (i = 0; i < schedule_len; i++)
|
||||
{
|
||||
scheduleTask_t *task = schedule[i];
|
||||
WRITEINT16(save_p, task->basetime);
|
||||
WRITEINT16(save_p, task->timer);
|
||||
WRITESTRING(save_p, task->command);
|
||||
}
|
||||
}
|
||||
|
||||
static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
||||
{
|
||||
INT32 i;
|
||||
size_t i;
|
||||
size_t numTasks;
|
||||
|
||||
if (READUINT32(save_p) != ARCHIVEBLOCK_MISC)
|
||||
I_Error("Bad $$$.sav at archive block Misc");
|
||||
|
|
@ -4684,6 +4696,24 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
if (READUINT8(save_p) == 0x2f)
|
||||
paused = true;
|
||||
|
||||
// Only the server uses this, but it
|
||||
// needs synched for remote admins anyway.
|
||||
Schedule_Clear();
|
||||
|
||||
numTasks = READUINT32(save_p);
|
||||
for (i = 0; i < numTasks; i++)
|
||||
{
|
||||
INT16 basetime;
|
||||
INT16 timer;
|
||||
char command[MAXTEXTCMD];
|
||||
|
||||
basetime = READINT16(save_p);
|
||||
timer = READINT16(save_p);
|
||||
READSTRING(save_p, command);
|
||||
|
||||
Schedule_Add(basetime, timer, command);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue