mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Merge branch 'profile-restrictions' into 'master'
Social restrictions until you've played some games See merge request KartKrew/Kart!1194
This commit is contained in:
commit
3344ddc659
11 changed files with 256 additions and 163 deletions
145
src/d_clisrv.c
145
src/d_clisrv.c
|
|
@ -223,6 +223,10 @@ consvar_t cv_httpsource = CVAR_INIT ("http_source", "", CV_SAVE, NULL, NULL);
|
|||
|
||||
consvar_t cv_kicktime = CVAR_INIT ("kicktime", "20", CV_SAVE, CV_Unsigned, NULL);
|
||||
|
||||
consvar_t cv_gamestochat = CVAR_INIT ("gamestochat", "0", CV_SAVE, CV_Unsigned, NULL);
|
||||
|
||||
static tic_t stop_spamming[MAXPLAYERS];
|
||||
|
||||
// Generate a message for an authenticating client to sign, with some guarantees about who we are.
|
||||
void GenerateChallenge(uint8_t *buf)
|
||||
{
|
||||
|
|
@ -2986,6 +2990,8 @@ static void Command_Nodes(void)
|
|||
CONS_Printf(" [%.4d PWR]", clientpowerlevels[i][K_UsingPowerLevels()]);
|
||||
}
|
||||
|
||||
CONS_Printf(" [%d games]", SV_GetStatsByPlayerIndex(i)->finishedrounds);
|
||||
|
||||
|
||||
CONS_Printf(" [RRID-%s]", GetPrettyRRID(players[i].public_key, true));
|
||||
|
||||
|
|
@ -4225,10 +4231,10 @@ boolean SV_SpawnServer(void)
|
|||
SINT8 node = 0;
|
||||
for (; node < MAXNETNODES; node++)
|
||||
result |= SV_AddWaitingPlayers(node, availabilitiesbuffer,
|
||||
cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(0)->public_key)->powerlevels,
|
||||
cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(1)->public_key)->powerlevels,
|
||||
cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(2)->public_key)->powerlevels,
|
||||
cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key, SV_RetrieveStats(PR_GetLocalPlayerProfile(3)->public_key)->powerlevels);
|
||||
cv_playername[0].zstring, PR_GetLocalPlayerProfile(0)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(0)->public_key)->powerlevels,
|
||||
cv_playername[1].zstring, PR_GetLocalPlayerProfile(1)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(1)->public_key)->powerlevels,
|
||||
cv_playername[2].zstring, PR_GetLocalPlayerProfile(2)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(2)->public_key)->powerlevels,
|
||||
cv_playername[3].zstring, PR_GetLocalPlayerProfile(3)->public_key, SV_GetStatsByKey(PR_GetLocalPlayerProfile(3)->public_key)->powerlevels);
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
|
|
@ -4547,10 +4553,10 @@ static void HandleConnect(SINT8 node)
|
|||
}
|
||||
|
||||
SV_AddWaitingPlayers(node, availabilitiesbuffer,
|
||||
names[0], lastReceivedKey[node][0], SV_RetrieveStats(lastReceivedKey[node][0])->powerlevels,
|
||||
names[1], lastReceivedKey[node][1], SV_RetrieveStats(lastReceivedKey[node][1])->powerlevels,
|
||||
names[2], lastReceivedKey[node][2], SV_RetrieveStats(lastReceivedKey[node][2])->powerlevels,
|
||||
names[3], lastReceivedKey[node][3], SV_RetrieveStats(lastReceivedKey[node][3])->powerlevels);
|
||||
names[0], lastReceivedKey[node][0], SV_GetStatsByKey(lastReceivedKey[node][0])->powerlevels,
|
||||
names[1], lastReceivedKey[node][1], SV_GetStatsByKey(lastReceivedKey[node][1])->powerlevels,
|
||||
names[2], lastReceivedKey[node][2], SV_GetStatsByKey(lastReceivedKey[node][2])->powerlevels,
|
||||
names[3], lastReceivedKey[node][3], SV_GetStatsByKey(lastReceivedKey[node][3])->powerlevels);
|
||||
joindelay += cv_joindelay.value * TICRATE;
|
||||
player_joining = true;
|
||||
}
|
||||
|
|
@ -4968,6 +4974,70 @@ static boolean CheckForSpeedHacks(UINT8 p)
|
|||
return false;
|
||||
}
|
||||
|
||||
static void PT_Say(int node)
|
||||
{
|
||||
if (client)
|
||||
return; // Only sent to servers, why are we receiving this?
|
||||
|
||||
say_pak say = netbuffer->u.say;
|
||||
|
||||
if (playernode[say.source] != node)
|
||||
return; // Spoofed source!
|
||||
|
||||
if ((cv_mute.value || say.flags & (HU_CSAY|HU_SHOUT)) && say.source != serverplayer && !(IsPlayerAdmin(say.source)))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s), but cv_mute is on.\n", say.source+1, player_names[say.source]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((say.flags & HU_PRIVNOTICE) && !(IsPlayerAdmin(say.source)))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s) with an illegal HU_PRIVNOTICE flag.\n", say.source+1, player_names[say.source]);
|
||||
SendKick(say.source, KICK_MSG_CON_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
size_t i;
|
||||
const size_t j = strlen(say.message);
|
||||
for (i = 0; i < j; i++)
|
||||
{
|
||||
if (say.message[i] & 0x80)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal say command received from %s containing invalid characters\n"), player_names[say.source]);
|
||||
SendKick(say.source, KICK_MSG_CON_FAIL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stop_spamming[say.source] != 0 && consoleplayer != say.source && cv_chatspamprotection.value && !(say.flags & (HU_CSAY|HU_SHOUT)))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", say.source+1, player_names[say.source]);
|
||||
stop_spamming[say.source] = 4;
|
||||
return;
|
||||
}
|
||||
|
||||
stop_spamming[say.source] = 4;
|
||||
|
||||
serverplayer_t *stats = SV_GetStatsByPlayerIndex(say.source);
|
||||
|
||||
if (stats->finishedrounds < (uint32_t)cv_gamestochat.value && !(consoleplayer == say.source || IsPlayerAdmin(say.source)))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s), but they aren't permitted to chat yet.\n", say.source+1, player_names[say.source]);
|
||||
|
||||
char rejectmsg[256];
|
||||
strlcpy(rejectmsg, va("Please finish in %d more games to use chat.", cv_gamestochat.value - stats->finishedrounds), 256);
|
||||
if (IsPlayerGuest(say.source))
|
||||
strlcpy(rejectmsg, va("GUESTs can't chat on this server. Rejoin with a profile to track your playtime."), 256);
|
||||
SendServerNotice(say.source, rejectmsg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DoSayCommand(say.message, say.target, say.flags, say.source);
|
||||
}
|
||||
|
||||
static char NodeToSplitPlayer(int node, int split)
|
||||
{
|
||||
if (split == 0)
|
||||
|
|
@ -5269,10 +5339,12 @@ static void HandlePacketFromPlayer(SINT8 node)
|
|||
textcmd[0] += (UINT8)netbuffer->u.textcmd[0];
|
||||
}
|
||||
break;
|
||||
case PT_SAY:
|
||||
PT_Say(node);
|
||||
break;
|
||||
case PT_LOGIN:
|
||||
if (client)
|
||||
break;
|
||||
|
||||
#ifndef NOMD5
|
||||
if (doomcom->datalength < 16)/* ignore partial sends */
|
||||
break;
|
||||
|
|
@ -6824,6 +6896,15 @@ void NetUpdate(void)
|
|||
}
|
||||
}
|
||||
|
||||
if (server)
|
||||
{
|
||||
for(i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (stop_spamming[i] > 0)
|
||||
stop_spamming[i]--;
|
||||
}
|
||||
}
|
||||
|
||||
Net_AckTicker();
|
||||
HandleNodeTimeouts();
|
||||
|
||||
|
|
@ -6972,3 +7053,49 @@ void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *
|
|||
md5_buffer(tmpbuf, 256, dest);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Want to say something? XD_SAY is server only, gotta request that they send one on our behalf
|
||||
void DoSayPacket(SINT8 target, UINT8 flags, UINT8 source, char *message)
|
||||
{
|
||||
say_pak *packet = (void*)&netbuffer->u.say;
|
||||
netbuffer->packettype = PT_SAY;
|
||||
|
||||
memset(packet->message, 0, sizeof(packet->message));
|
||||
strcpy(packet->message, message);
|
||||
|
||||
packet->source = source;
|
||||
packet->flags = flags;
|
||||
packet->target = target;
|
||||
|
||||
HSendPacket(servernode, false, 0, sizeof(say_pak));
|
||||
}
|
||||
|
||||
void DoSayPacketFromCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
||||
{
|
||||
char buf[2 + HU_MAXMSGLEN + 1];
|
||||
size_t numwords, ix;
|
||||
char *msg = &buf[3];
|
||||
const size_t msgspace = sizeof buf - 2;
|
||||
|
||||
numwords = COM_Argc() - usedargs;
|
||||
I_Assert(numwords > 0);
|
||||
|
||||
msg[0] = '\0';
|
||||
|
||||
for (ix = 0; ix < numwords; ix++)
|
||||
{
|
||||
if (ix > 0)
|
||||
strlcat(msg, " ", msgspace);
|
||||
strlcat(msg, COM_Argv(ix + usedargs), msgspace);
|
||||
}
|
||||
|
||||
DoSayPacket(target, flags, consoleplayer, msg);
|
||||
}
|
||||
|
||||
// This is meant to be targeted at player indices, not whatever the hell XD_SAY is doing with 1-indexed players.
|
||||
void SendServerNotice(SINT8 target, char *message)
|
||||
{
|
||||
if (client)
|
||||
return;
|
||||
DoSayCommand(message, target + 1, HU_PRIVNOTICE, servernode);
|
||||
}
|
||||
|
|
@ -41,6 +41,8 @@ applications may follow different packet versions.
|
|||
// one that defines the actual packets to
|
||||
// be transmitted.
|
||||
|
||||
#define HU_MAXMSGLEN 223
|
||||
|
||||
// Networking and tick handling related.
|
||||
#define BACKUPTICS 512 // more than enough for most timeouts....
|
||||
#define CLIENTBACKUPTICS 32
|
||||
|
|
@ -127,6 +129,8 @@ typedef enum
|
|||
PT_RESPONSEALL, // OK, here is my signature on that random bullshit
|
||||
PT_RESULTSALL, // Here's what everyone responded to PT_CHALLENGEALL with, if this is wrong or you don't receive it disconnect
|
||||
|
||||
PT_SAY, // "Hey server, please send this chat message to everyone via XD_SAY"
|
||||
|
||||
NUMPACKETTYPE
|
||||
} packettype_t;
|
||||
|
||||
|
|
@ -385,6 +389,14 @@ struct resultsall_pak
|
|||
uint8_t signature[MAXPLAYERS][SIGNATURELENGTH];
|
||||
} ATTRPACK;
|
||||
|
||||
struct say_pak
|
||||
{
|
||||
char message[HU_MAXMSGLEN + 1];
|
||||
UINT8 target;
|
||||
UINT8 flags;
|
||||
UINT8 source;
|
||||
} ATTRPACK;
|
||||
|
||||
//
|
||||
// Network packet data
|
||||
//
|
||||
|
|
@ -427,6 +439,7 @@ struct doomdata_t
|
|||
challengeall_pak challengeall; // 256 bytes
|
||||
responseall_pak responseall; // 256 bytes
|
||||
resultsall_pak resultsall; // 1024 bytes. Also, you really shouldn't trust anything here.
|
||||
say_pak say; // I don't care anymore.
|
||||
} u; // This is needed to pack diff packet types data together
|
||||
} ATTRPACK;
|
||||
|
||||
|
|
@ -534,6 +547,8 @@ extern consvar_t cv_discordinvites;
|
|||
|
||||
extern consvar_t cv_allowguests;
|
||||
|
||||
extern consvar_t cv_gamestochat;
|
||||
|
||||
#ifdef DEVELOP
|
||||
extern consvar_t cv_badjoin;
|
||||
extern consvar_t cv_badtraffic;
|
||||
|
|
@ -635,6 +650,10 @@ rewind_t *CL_RewindToTime(tic_t time);
|
|||
|
||||
void HandleSigfail(const char *string);
|
||||
|
||||
void DoSayPacket(SINT8 target, UINT8 flags, UINT8 source, char *message);
|
||||
void DoSayPacketFromCommand(SINT8 target, size_t usedargs, UINT8 flags);
|
||||
void SendServerNotice(SINT8 target, char *message);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1023,6 +1023,7 @@ static boolean ShouldDropPacket(void)
|
|||
case PT_LOGIN:
|
||||
case PT_ASKLUAFILE:
|
||||
case PT_SENDINGLUAFILE:
|
||||
case PT_SAY:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -970,6 +970,7 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_mindelay);
|
||||
|
||||
CV_RegisterVar(&cv_allowguests);
|
||||
CV_RegisterVar(&cv_gamestochat);
|
||||
|
||||
#ifdef DEVELOP
|
||||
CV_RegisterVar(&cv_badjoin);
|
||||
|
|
|
|||
181
src/hu_stuff.c
181
src/hu_stuff.c
|
|
@ -60,18 +60,13 @@
|
|||
#include "k_color.h"
|
||||
#include "k_hud.h"
|
||||
#include "r_fps.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "y_inter.h" // Y_PlayerStandingsDrawer
|
||||
|
||||
// coords are scaled
|
||||
#define HU_INPUTX 0
|
||||
#define HU_INPUTY 0
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HU_SHOUT = 1, // Shout message
|
||||
HU_CSAY = 1<<1, // Middle-of-screen server message
|
||||
} sayflags_t;
|
||||
|
||||
//-------------------------------------------
|
||||
// heads up font
|
||||
//-------------------------------------------
|
||||
|
|
@ -491,7 +486,6 @@ void HU_AddChatText(const char *text, boolean playsound)
|
|||
CON_LogMessage(va("%s\n", text));
|
||||
}
|
||||
|
||||
|
||||
/** Runs a say command, sending an ::XD_SAY message.
|
||||
* A say command consists of a signed 8-bit integer for the target, an
|
||||
* unsigned 8-bit flag variable, and then the message itself.
|
||||
|
|
@ -511,27 +505,10 @@ void HU_AddChatText(const char *text, boolean playsound)
|
|||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
|
||||
static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
||||
void DoSayCommand(char *message, SINT8 target, UINT8 flags, UINT8 source)
|
||||
{
|
||||
char buf[2 + HU_MAXMSGLEN + 1];
|
||||
size_t numwords, ix;
|
||||
char *msg = &buf[2];
|
||||
const size_t msgspace = sizeof buf - 2;
|
||||
|
||||
numwords = COM_Argc() - usedargs;
|
||||
I_Assert(numwords > 0);
|
||||
|
||||
if (CHAT_MUTE) // TODO: Per Player mute.
|
||||
{
|
||||
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only servers/admins can shout or CSAY.
|
||||
if (!server && !IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
flags &= ~(HU_SHOUT|HU_CSAY);
|
||||
}
|
||||
char *msg = &buf[3];
|
||||
|
||||
// Enforce shout for the dedicated server.
|
||||
if (dedicated && !(flags & HU_CSAY))
|
||||
|
|
@ -541,66 +518,16 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags)
|
|||
|
||||
buf[0] = target;
|
||||
buf[1] = flags;
|
||||
buf[2] = source;
|
||||
msg[0] = '\0';
|
||||
|
||||
for (ix = 0; ix < numwords; ix++)
|
||||
{
|
||||
if (ix > 0)
|
||||
strlcat(msg, " ", msgspace);
|
||||
strlcat(msg, COM_Argv(ix + usedargs), msgspace);
|
||||
}
|
||||
|
||||
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
|
||||
{
|
||||
// what we're gonna do now is check if the player exists
|
||||
// with that logic, characters 4 and 5 are our numbers:
|
||||
const char *newmsg;
|
||||
char playernum[3];
|
||||
INT32 spc = 1; // used if playernum[1] is a space.
|
||||
|
||||
strncpy(playernum, msg+3, 3);
|
||||
|
||||
// check for undesirable characters in our "number"
|
||||
if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9')))
|
||||
{
|
||||
// check if playernum[1] is a space
|
||||
if (playernum[1] == ' ')
|
||||
spc = 0;
|
||||
// let it slide
|
||||
else
|
||||
{
|
||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// I'm very bad at C, I swear I am, additional checks eww!
|
||||
if (spc != 0 && msg[5] != ' ')
|
||||
{
|
||||
HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm<playernum> \'.", false);
|
||||
return;
|
||||
}
|
||||
|
||||
target = atoi(playernum); // turn that into a number
|
||||
//CONS_Printf("%d\n", target);
|
||||
|
||||
// check for target player, if it doesn't exist then we can't send the message!
|
||||
if (target < MAXPLAYERS && playeringame[target]) // player exists
|
||||
target++; // even though playernums are from 0 to 31, target is 1 to 32, so up that by 1 to have it work!
|
||||
else
|
||||
{
|
||||
HU_AddChatText(va("\x82NOTICE: \x80Player %d does not exist.", target), false); // same
|
||||
return;
|
||||
}
|
||||
buf[0] = target;
|
||||
newmsg = msg+5+spc;
|
||||
strlcpy(msg, newmsg, HU_MAXMSGLEN + 1);
|
||||
}
|
||||
strcpy(msg, message);
|
||||
|
||||
SendNetXCmd(XD_SAY, buf, strlen(msg) + 1 + msg-buf);
|
||||
}
|
||||
|
||||
/** Send a message to everyone.
|
||||
* \sa DoSayCommand, Command_Sayteam_f, Command_Sayto_f
|
||||
* \sa DoSayPacket, Command_Sayteam_f, Command_Sayto_f
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void Command_Say_f(void)
|
||||
|
|
@ -613,11 +540,11 @@ static void Command_Say_f(void)
|
|||
|
||||
// Autoshout is handled by HU_queueChatChar.
|
||||
// If you're using the say command, you can use the shout command, lol.
|
||||
DoSayCommand(0, 1, 0);
|
||||
DoSayPacketFromCommand(0, 1, 0);
|
||||
}
|
||||
|
||||
/** Send a message to a particular person.
|
||||
* \sa DoSayCommand, Command_Sayteam_f, Command_Say_f
|
||||
* \sa DoSayPacket, Command_Sayteam_f, Command_Say_f
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void Command_Sayto_f(void)
|
||||
|
|
@ -638,11 +565,11 @@ static void Command_Sayto_f(void)
|
|||
}
|
||||
target++; // Internally we use 0 to 31, but say command uses 1 to 32.
|
||||
|
||||
DoSayCommand((SINT8)target, 2, 0);
|
||||
DoSayPacketFromCommand((SINT8)target, 2, 0);
|
||||
}
|
||||
|
||||
/** Send a message to members of the player's team.
|
||||
* \sa DoSayCommand, Command_Say_f, Command_Sayto_f
|
||||
* \sa DoSayPacket, Command_Say_f, Command_Sayto_f
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void Command_Sayteam_f(void)
|
||||
|
|
@ -660,9 +587,9 @@ static void Command_Sayteam_f(void)
|
|||
}
|
||||
|
||||
if (G_GametypeHasTeams()) // revert to normal say if we don't have teams in this gametype.
|
||||
DoSayCommand(-1, 1, 0);
|
||||
DoSayPacketFromCommand(-1, 1, 0);
|
||||
else
|
||||
DoSayCommand(0, 1, 0);
|
||||
DoSayPacketFromCommand(0, 1, 0);
|
||||
}
|
||||
|
||||
/** Send a message to everyone, to be displayed by CECHO. Only
|
||||
|
|
@ -682,7 +609,7 @@ static void Command_CSay_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
DoSayCommand(0, 1, HU_CSAY);
|
||||
DoSayPacketFromCommand(0, 1, HU_CSAY);
|
||||
}
|
||||
|
||||
static void Command_Shout(void)
|
||||
|
|
@ -699,13 +626,11 @@ static void Command_Shout(void)
|
|||
return;
|
||||
}
|
||||
|
||||
DoSayCommand(0, 1, HU_SHOUT);
|
||||
DoSayPacketFromCommand(0, 1, HU_SHOUT);
|
||||
}
|
||||
|
||||
static tic_t stop_spamming[MAXPLAYERS];
|
||||
|
||||
/** Receives a message, processing an ::XD_SAY command.
|
||||
* \sa DoSayCommand
|
||||
* \sa DoSayPacket
|
||||
* \author Graue <graue@oceanbase.org>
|
||||
*/
|
||||
static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
||||
|
|
@ -716,25 +641,19 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
char *msg;
|
||||
boolean action = false;
|
||||
char *ptr;
|
||||
INT32 spam_eatmsg = 0;
|
||||
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd from Player %d (%s)\n", playernum+1, player_names[playernum]);
|
||||
|
||||
// Only server can ever legitimately send this
|
||||
if (playernum != serverplayer)
|
||||
return;
|
||||
|
||||
target = READSINT8(*p);
|
||||
flags = READUINT8(*p);
|
||||
playernum = READUINT8(*p);
|
||||
msg = (char *)*p;
|
||||
SKIPSTRINGL(*p, HU_MAXMSGLEN + 1);
|
||||
|
||||
if ((cv_mute.value || flags & (HU_CSAY|HU_SHOUT)) && playernum != serverplayer && !(IsPlayerAdmin(playernum)))
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, cv_mute.value ?
|
||||
M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"),
|
||||
player_names[playernum]);
|
||||
if (server)
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
//check for invalid characters (0x80 or above)
|
||||
{
|
||||
size_t i;
|
||||
|
|
@ -751,26 +670,6 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
}
|
||||
}
|
||||
|
||||
// before we do anything, let's verify the guy isn't spamming, get this easier on us.
|
||||
|
||||
//if (stop_spamming[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY))
|
||||
if (stop_spamming[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & (HU_CSAY|HU_SHOUT)))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]);
|
||||
stop_spamming[playernum] = 4;
|
||||
spam_eatmsg = 1;
|
||||
}
|
||||
else
|
||||
stop_spamming[playernum] = 4; // you can hold off for 4 tics, can you?
|
||||
|
||||
// run the lua hook even if we were supposed to eat the msg, netgame consistency goes first.
|
||||
|
||||
if (LUA_HookPlayerMsg(playernum, target, flags, msg, spam_eatmsg))
|
||||
return;
|
||||
|
||||
if (spam_eatmsg)
|
||||
return; // don't proceed if we were supposed to eat the message.
|
||||
|
||||
// If it's a CSAY, just CECHO and be done with it.
|
||||
if (flags & HU_CSAY)
|
||||
{
|
||||
|
|
@ -900,6 +799,13 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
cstart = "\x82";
|
||||
textcolor = "\x82";
|
||||
fmt2 = "%s<%s%s>%s\x80 %s%s";
|
||||
|
||||
if (flags & HU_PRIVNOTICE)
|
||||
{
|
||||
dispname = "SERVER";
|
||||
prefix = "\x82";
|
||||
fmt2 = "%s[%s%s]%s %s%s";
|
||||
}
|
||||
}
|
||||
else if (target > 0) // By you, to another player
|
||||
{
|
||||
|
|
@ -909,6 +815,12 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
cstart = "\x82";
|
||||
fmt2 = "%s<%s%s>%s\x80 %s%s";
|
||||
|
||||
if (flags & HU_PRIVNOTICE)
|
||||
{
|
||||
if (tempchar)
|
||||
Z_Free(tempchar);
|
||||
return; // I pretend I do not see it
|
||||
}
|
||||
}
|
||||
else // To everyone or sayteam, it doesn't change anything.
|
||||
fmt2 = "%s<%s%s%s>\x80 %s%s";
|
||||
|
|
@ -1032,13 +944,6 @@ void HU_Ticker(void)
|
|||
{
|
||||
size_t i = 0;
|
||||
|
||||
// handle spam while we're at it:
|
||||
for(; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
if (stop_spamming[i] > 0)
|
||||
stop_spamming[i]--;
|
||||
}
|
||||
|
||||
// handle chat timers
|
||||
for (i=0; (i<chat_nummsg_min); i++)
|
||||
{
|
||||
|
|
@ -1107,29 +1012,12 @@ static void HU_sendChatMessage(void)
|
|||
memset(w_chat, '\0', sizeof(w_chat));
|
||||
c_input = 0;
|
||||
|
||||
// last minute mute check
|
||||
if (CHAT_MUTE)
|
||||
{
|
||||
HU_AddChatText(va("%s>ERROR: The chat is muted. You can't say anything.", "\x85"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm
|
||||
{
|
||||
INT32 spc = 1; // used if playernum[1] is a space.
|
||||
char playernum[3];
|
||||
const char *newmsg;
|
||||
|
||||
// what we're gonna do now is check if the player exists
|
||||
// with that logic, characters 4 and 5 are our numbers:
|
||||
|
||||
// teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko.
|
||||
if (teamtalk)
|
||||
{
|
||||
HU_AddChatText(va("%sCannot send sayto in Say-Team.", "\x85"), false);
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy(playernum, msg+3, 3);
|
||||
// check for undesirable characters in our "number"
|
||||
if (!(isdigit(playernum[0]) && isdigit(playernum[1])))
|
||||
|
|
@ -1174,7 +1062,8 @@ static void HU_sendChatMessage(void)
|
|||
buf[0] = target;
|
||||
|
||||
buf[1] = ((server || IsPlayerAdmin(consoleplayer)) && cv_autoshout.value) ? HU_SHOUT : 0; // flags
|
||||
SendNetXCmd(XD_SAY, buf, 2 + strlen(&buf[2]) + 1);
|
||||
|
||||
DoSayPacket(target, buf[1], consoleplayer, msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -98,7 +98,6 @@ extern char english_shiftxform[];
|
|||
//------------------------------------
|
||||
// chat stuff
|
||||
//------------------------------------
|
||||
#define HU_MAXMSGLEN 223
|
||||
#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand.
|
||||
#define NETSPLITSCREEN // why the hell WOULDN'T we want this?
|
||||
#ifdef NETSPLITSCREEN
|
||||
|
|
@ -109,6 +108,13 @@ extern char english_shiftxform[];
|
|||
#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot.
|
||||
#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
HU_SHOUT = 1, // Shout message
|
||||
HU_CSAY = 1<<1, // Middle-of-screen server message
|
||||
HU_PRIVNOTICE = 1<<2, // Special server sayto, we don't want to see it as the sender.
|
||||
} sayflags_t;
|
||||
|
||||
// some functions
|
||||
void HU_AddChatText(const char *text, boolean playsound);
|
||||
|
||||
|
|
@ -159,6 +165,8 @@ void HU_DoCEcho(const char *msg);
|
|||
void HU_DoTitlecardCEcho(const char *msg);
|
||||
void HU_ClearTitlecardCEcho(void);
|
||||
|
||||
void DoSayCommand(char *message, SINT8 target, UINT8 flags, UINT8 source);
|
||||
|
||||
// Demo playback info
|
||||
extern UINT32 hu_demotime;
|
||||
extern UINT32 hu_demolap;
|
||||
|
|
|
|||
|
|
@ -430,8 +430,6 @@ void K_CashInPowerLevels(void)
|
|||
|
||||
//CONS_Printf("%s: %d -> %d (%d)\n", player_names[i], clientpowerlevels[i][powerType] - inc, clientpowerlevels[i][powerType], inc);
|
||||
}
|
||||
|
||||
clientPowerAdd[i] = 0;
|
||||
}
|
||||
|
||||
SV_UpdateStats();
|
||||
|
|
|
|||
|
|
@ -112,6 +112,13 @@ void SV_LoadStats(void)
|
|||
{
|
||||
trackedList[i].powerlevels[j] = READUINT16(save.p);
|
||||
}
|
||||
|
||||
// Migration 1 -> 2: Add finishedrounds
|
||||
if (version < 2)
|
||||
trackedList[i].finishedrounds = 0;
|
||||
else
|
||||
trackedList[i].finishedrounds = READUINT32(save.p);
|
||||
|
||||
trackedList[i].hash = quickncasehash((char*)trackedList[i].public_key, PUBKEYLENGTH);
|
||||
}
|
||||
}
|
||||
|
|
@ -149,6 +156,7 @@ void SV_SaveStats(void)
|
|||
{
|
||||
WRITEUINT16(save.p, trackedList[i].powerlevels[j]);
|
||||
}
|
||||
WRITEUINT32(save.p, trackedList[i].finishedrounds);
|
||||
}
|
||||
|
||||
length = save.p - save.buffer;
|
||||
|
|
@ -162,7 +170,7 @@ void SV_SaveStats(void)
|
|||
}
|
||||
|
||||
// New player, grab their stats from trackedList or initialize new ones if they're new
|
||||
serverplayer_t *SV_RetrieveStats(uint8_t *key)
|
||||
serverplayer_t *SV_GetStatsByKey(uint8_t *key)
|
||||
{
|
||||
UINT32 j, hash;
|
||||
|
||||
|
|
@ -183,12 +191,16 @@ serverplayer_t *SV_RetrieveStats(uint8_t *key)
|
|||
SV_ExpandStats(numtracked+1);
|
||||
|
||||
// Default stats
|
||||
// (NB: This will make a GUEST record if someone tries to retrieve GUEST stats, because
|
||||
// at the very least we should try to provide other codepaths the right _data type_,
|
||||
// but it will not be written back.)
|
||||
trackedList[numtracked].lastseen = time(NULL);
|
||||
memcpy(&trackedList[numtracked].public_key, key, PUBKEYLENGTH);
|
||||
for(j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
{
|
||||
trackedList[numtracked].powerlevels[j] = PR_IsKeyGuest(key) ? 0 : PWRLVRECORD_START;
|
||||
}
|
||||
trackedList[numtracked].finishedrounds = 0;
|
||||
trackedList[numtracked].hash = quickncasehash((char*)key, PUBKEYLENGTH);
|
||||
|
||||
numtracked++;
|
||||
|
|
@ -196,7 +208,18 @@ serverplayer_t *SV_RetrieveStats(uint8_t *key)
|
|||
return &trackedList[numtracked - 1];
|
||||
}
|
||||
|
||||
// Write player stats to trackedList, then save to disk
|
||||
serverplayer_t *SV_GetStatsByPlayerIndex(UINT8 p)
|
||||
{
|
||||
return SV_GetStatsByKey(players[p].public_key);
|
||||
}
|
||||
|
||||
serverplayer_t *SV_GetStats(player_t *player)
|
||||
{
|
||||
return SV_GetStatsByKey(player->public_key);
|
||||
}
|
||||
|
||||
// Write clientpowerlevels and timestamps back to matching trackedList entries, then save trackedList to disk
|
||||
// (NB: Stats changes can be made directly to trackedList through other paths, but will only write to disk here)
|
||||
void SV_UpdateStats(void)
|
||||
{
|
||||
UINT32 i, j, hash;
|
||||
|
|
@ -234,3 +257,23 @@ void SV_UpdateStats(void)
|
|||
|
||||
SV_SaveStats();
|
||||
}
|
||||
|
||||
void SV_BumpMatchStats(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
if (players[i].spectator)
|
||||
continue;
|
||||
if (PR_IsKeyGuest(players[i].public_key))
|
||||
continue;
|
||||
|
||||
serverplayer_t *stat = SV_GetStatsByPlayerIndex(i);
|
||||
|
||||
if (!(players[i].pflags & PF_NOCONTEST))
|
||||
stat->finishedrounds++;
|
||||
}
|
||||
}
|
||||
|
|
@ -27,13 +27,14 @@ extern "C" {
|
|||
|
||||
#define SERVERSTATSFILE "srvstats.dat"
|
||||
#define SERVERSTATSHEADER "Doctor Robotnik's Ring Racers Server Stats"
|
||||
#define SERVERSTATSVER 1
|
||||
#define SERVERSTATSVER 2
|
||||
|
||||
struct serverplayer_t
|
||||
{
|
||||
uint8_t public_key[PUBKEYLENGTH];
|
||||
UINT32 lastseen;
|
||||
UINT16 powerlevels[PWRLV_NUMTYPES];
|
||||
UINT32 finishedrounds;
|
||||
|
||||
UINT32 hash; // Not persisted! Used for early outs during key comparisons
|
||||
};
|
||||
|
|
@ -42,10 +43,14 @@ void SV_SaveStats(void);
|
|||
|
||||
void SV_LoadStats(void);
|
||||
|
||||
serverplayer_t *SV_RetrieveStats(uint8_t *key);
|
||||
serverplayer_t *SV_GetStatsByKey(uint8_t *key);
|
||||
serverplayer_t *SV_GetStatsByPlayerIndex(UINT8 p);
|
||||
serverplayer_t *SV_GetStats(player_t *player);
|
||||
|
||||
void SV_UpdateStats(void);
|
||||
|
||||
void SV_BumpMatchStats(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ TYPEDEF (serverchallenge_pak);
|
|||
TYPEDEF (challengeall_pak);
|
||||
TYPEDEF (responseall_pak);
|
||||
TYPEDEF (resultsall_pak);
|
||||
TYPEDEF (say_pak);
|
||||
|
||||
// d_event.h
|
||||
TYPEDEF (event_t);
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
#include "k_boss.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_grandprix.h"
|
||||
#include "k_color.h"
|
||||
#include "k_serverstats.h" // SV_BumpMatchStats
|
||||
#include "m_easing.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
|
@ -1635,6 +1635,7 @@ void Y_StartIntermission(void)
|
|||
}
|
||||
|
||||
K_CashInPowerLevels();
|
||||
SV_BumpMatchStats();
|
||||
}
|
||||
|
||||
if (roundqueue.size > 0 && roundqueue.position == roundqueue.size)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue