...
 
Commits (4)
......@@ -320,6 +320,7 @@ set(CLIENTBASELIST
${ENGINE_DIR}/client/cl_cgame.cpp
${ENGINE_DIR}/client/cl_cin.cpp
${ENGINE_DIR}/client/cl_console.cpp
${ENGINE_DIR}/client/cl_download.cpp
${ENGINE_DIR}/client/cl_input.cpp
${ENGINE_DIR}/client/cl_main.cpp
${ENGINE_DIR}/client/cl_parse.cpp
......
......@@ -69,7 +69,7 @@ class ClientApplication : public Application {
}
void Initialize(Str::StringRef uri) override {
Com_Init((char*) "");
Com_Init();
if (!uri.empty()) {
Cmd::BufferCommandTextAfter(std::string("connect ") + Cmd::Escape(uri));
......
......@@ -204,8 +204,6 @@ void trap_SetMouseMode( MouseMode mode );
void trap_S_StopBackgroundTrack();
void trap_R_RemapShader( const char *oldShader, const char *newShader, const char *timeOffset );
bool trap_GetEntityToken( char *buffer, int bufferSize );
void trap_SendMessage(const std::vector<uint8_t>& message);
messageStatus_t trap_MessageStatus();
std::vector<std::vector<Keyboard::Key>> trap_Key_GetKeysForBinds(int team, const std::vector<std::string>& binds);
int trap_Parse_AddGlobalDefine( const char *define );
int trap_Parse_LoadSource( const char *filename );
......
......@@ -223,6 +223,7 @@ enum cgameImport_t
CG_LAN_SERVERSTATUS,
CG_LAN_RESETSERVERSTATUS,
// TODO(0.52) Remove these two.
CG_SEND_MESSAGE = 125,
CG_MESSAGE_STATUS,
};
......@@ -536,8 +537,6 @@ enum cgameExport_t
// void (*CG_FocusEvent)( bool focus);
CG_FOCUS_EVENT,
CG_RECV_MESSAGE,
};
using CGameStaticInitMsg = IPC::SyncMessage<
......@@ -571,9 +570,6 @@ using CGameCharacterInputMsg = IPC::SyncMessage <
using CGameFocusEventMsg = IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, CG_FOCUS_EVENT>, bool>
>;
using CGameRecvMessageMsg = IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, CG_RECV_MESSAGE>, IPC::SharedMemory, size_t, int>
>;
//TODO Check all rocket calls
using CGameRocketInitMsg = IPC::SyncMessage<
......
......@@ -978,44 +978,6 @@ void CL_SetCGameTime()
}
}
/*
====================
CL_SendBinaryMessage
====================
*/
static void CL_SendBinaryMessage(std::vector<uint8_t> message)
{
if (message.size() > MAX_BINARY_MESSAGE) {
Sys::Drop("CL_SendBinaryMessage: bad length %zi", message.size());
}
memcpy(clc.binaryMessage, message.data(), clc.binaryMessageLength = message.size());
}
/*
====================
CL_BinaryMessageStatus
====================
*/
static messageStatus_t CL_BinaryMessageStatus()
{
if (clc.binaryMessageLength == 0) {
return messageStatus_t::MESSAGE_EMPTY;
}
if (clc.binaryMessageOverflowed) {
return messageStatus_t::MESSAGE_WAITING_OVERFLOW;
}
return messageStatus_t::MESSAGE_WAITING;
}
void CL_CGameBinaryMessageReceived(const uint8_t *buf, size_t size, int serverTime)
{
static auto shm = IPC::SharedMemory::Create(MAX_BINARY_MESSAGE);
memcpy(shm.GetBase(), buf, size);
cgvm.SendMsg<CGameRecvMessageMsg>(shm, size, serverTime);
}
/**
* is notified by teamchanges.
* while most notifications will come from the cgame, due to game semantics,
......@@ -1563,17 +1525,20 @@ void CGameVM::QVMSyscall(int index, Util::Reader& reader, IPC::Channel& channel)
break;
case CG_SEND_MESSAGE:
IPC::HandleMsg<SendMessageMsg>(channel, std::move(reader), [this](std::vector<uint8_t> message) {
CL_SendBinaryMessage(std::move(message));
IPC::HandleMsg<SendMessageMsg>(channel, std::move(reader), [this](std::vector<uint8_t>) {
Log::Warn("unsupported SendMessageMsg");
});
break;
case CG_MESSAGE_STATUS:
IPC::HandleMsg<MessageStatusMsg>(channel, std::move(reader), [this](messageStatus_t& status) {
status = CL_BinaryMessageStatus();
Log::Warn("unsupported MessageStatusMsg");
status = {};
});
break;
default:
Sys::Drop("Bad CGame QVM syscall minor number: %d", index);
}
......
This diff is collapsed.
......@@ -858,31 +858,6 @@ bool CL_ReadyToSendPacket()
return true;
}
/*
================
CL_WriteBinaryMessage
================
*/
static void CL_WriteBinaryMessage( msg_t *msg )
{
if ( !clc.binaryMessageLength )
{
return;
}
MSG_Uncompressed( msg );
if ( ( msg->cursize + clc.binaryMessageLength ) >= msg->maxsize )
{
clc.binaryMessageOverflowed = true;
return;
}
MSG_WriteData( msg, clc.binaryMessage, clc.binaryMessageLength );
clc.binaryMessageLength = 0;
clc.binaryMessageOverflowed = false;
}
/*
===================
CL_WritePacket
......@@ -1015,7 +990,6 @@ void CL_WritePacket()
}
MSG_WriteByte( &buf, clc_EOF );
CL_WriteBinaryMessage( &buf );
Netchan_Transmit( &clc.netchan, buf.cursize, buf.data );
// clients never really should have messages large enough
......
......@@ -167,8 +167,6 @@ clientConnection_t clc;
clientStatic_t cls;
CGameVM cgvm;
Log::Logger downloadLogger("client.pakDownload");
// Structure containing functions exported from refresh DLL
refexport_t re;
......@@ -829,22 +827,6 @@ void CL_ClearState()
new(&cl) clientActive_t{}; // Using {} instead of () to work around MSVC bug
}
/*
=====================
CL_ClearStaticDownload
Clear download information that we keep in cls (disconnected download support)
=====================
*/
void CL_ClearStaticDownload()
{
downloadLogger.Debug("Clearing the download info");
ASSERT(!cls.bWWWDlDisconnected); // reset before calling
cls.downloadRestart = false;
cls.downloadTempName[ 0 ] = '\0';
cls.downloadName[ 0 ] = '\0';
cls.originalDownloadName[ 0 ] = '\0';
}
/*
=====================
CL_Disconnect
......@@ -1741,200 +1723,6 @@ public:
static DemoStopVideoCmd DemoStopVideoCmdRegistration;
/*
=================
CL_DownloadsComplete
Called when all downloading has been completed
=================
*/
void CL_DownloadsComplete()
{
// if we downloaded files we need to restart the file system
if ( cls.downloadRestart )
{
cls.downloadRestart = false;
downloadLogger.Debug("Downloaded something, reload the paks");
downloadLogger.Debug(" The paks to load are '%s'", Cvar_VariableString("sv_paks"));
FS::PakPath::ClearPaks();
FS_LoadServerPaks(Cvar_VariableString("sv_paks"), clc.demoplaying); // We possibly downloaded a pak, restart the file system to load it
if ( !cls.bWWWDlDisconnected )
{
// inform the server so we get new gamestate info
CL_AddReliableCommand( "donedl" );
}
// we can reset that now
cls.bWWWDlDisconnected = false;
CL_ClearStaticDownload();
// by sending the donedl command we request a new gamestate
// so we don't want to load stuff yet
return;
}
if ( cls.bWWWDlDisconnected )
{
cls.bWWWDlDisconnected = false;
CL_ClearStaticDownload();
return;
}
// let the client game init and load data
cls.state = connstate_t::CA_LOADING;
// Pump the loop, this may change gamestate!
Com_EventLoop();
// if the gamestate was changed by calling Com_EventLoop
// then we loaded everything already and we don't want to do it again.
if ( cls.state != connstate_t::CA_LOADING )
{
return;
}
// flush client memory and start loading stuff
// this will also (re)load the UI
CL_FlushMemory();
// initialize the CGame
cls.cgameStarted = true;
CL_InitCGame();
CL_WritePacket();
CL_WritePacket();
CL_WritePacket();
}
/*
=================
CL_BeginDownload
Requests a file to download from the server. Stores it in the current
game directory.
=================
*/
void CL_BeginDownload( const char *localName, const char *remoteName )
{
downloadLogger.Debug("Requesting the download of '%s', with remote name '%s'", localName, remoteName);
Q_strncpyz( cls.downloadName, localName, sizeof( cls.downloadName ) );
Com_sprintf( cls.downloadTempName, sizeof( cls.downloadTempName ), "%s.tmp", localName );
// Set so UI gets access to it
Cvar_Set( "cl_downloadName", remoteName );
Cvar_Set( "cl_downloadSize", "0" );
Cvar_Set( "cl_downloadCount", "0" );
Cvar_SetValue( "cl_downloadTime", cls.realtime );
clc.downloadBlock = 0; // Starting new file
clc.downloadCount = 0;
CL_AddReliableCommand( va( "download %s", Cmd_QuoteString( remoteName ) ) );
}
/*
=================
CL_NextDownload
A download completed or failed
=================
*/
void CL_NextDownload()
{
char *s;
char *remoteName, *localName;
// We are looking to start a download here
if ( *clc.downloadList )
{
downloadLogger.Debug("CL_NextDownload downloadList is '%s'", clc.downloadList);
s = clc.downloadList;
// format is:
// @remotename@localname@remotename@localname, etc.
if ( *s == '@' )
{
s++;
}
remoteName = s;
if ( ( s = strchr( s, '@' ) ) == nullptr )
{
CL_DownloadsComplete();
return;
}
*s++ = 0;
localName = s;
if ( ( s = strchr( s, '@' ) ) != nullptr )
{
*s++ = 0;
}
else
{
s = localName + strlen( localName ); // point at the nul byte
}
CL_BeginDownload( localName, remoteName );
cls.downloadRestart = true;
// move over the rest
memmove( clc.downloadList, s, strlen( s ) + 1 );
return;
}
CL_DownloadsComplete();
}
/*
=================
CL_InitDownloads
After receiving a valid game state, we valid the cgame and local zip files here
and determine if we need to download them
=================
*/
void CL_InitDownloads()
{
// TTimo
// init some of the www dl data
clc.bWWWDl = false;
clc.bWWWDlAborting = false;
cls.bWWWDlDisconnected = false;
CL_ClearStaticDownload();
if ( cl_allowDownload->integer )
FS_DeletePaksWithBadChecksum();
// reset the redirect checksum tracking
clc.redirectedList[ 0 ] = '\0';
if ( cl_allowDownload->integer && FS_ComparePaks( clc.downloadList, sizeof( clc.downloadList ) ) )
{
downloadLogger.Debug("Need paks: '%s'", clc.downloadList);
if ( *clc.downloadList )
{
// if autodownloading is not enabled on the server
cls.state = connstate_t::CA_DOWNLOADING;
CL_NextDownload();
return;
}
}
CL_DownloadsComplete();
}
/*
=================
CL_CheckForResend
......@@ -2793,128 +2581,6 @@ void CL_CheckUserinfo()
}
}
/*
==================
CL_WWWDownload
==================
*/
void CL_WWWDownload()
{
dlStatus_t ret;
static bool bAbort = false;
if ( clc.bWWWDlAborting )
{
if ( !bAbort )
{
Log::Debug( "CL_WWWDownload: WWWDlAborting" );
bAbort = true;
}
return;
}
if ( bAbort )
{
Log::Debug( "CL_WWWDownload: WWWDlAborting done" );
bAbort = false;
}
ret = DL_DownloadLoop();
if ( ret == dlStatus_t::DL_CONTINUE )
{
return;
}
if ( ret == dlStatus_t::DL_DONE )
{
downloadLogger.Debug("Finished WWW download of '%s', moving it to '%s'", cls.downloadTempName, cls.originalDownloadName);
// taken from CL_ParseDownload
clc.download = 0;
FS_SV_Rename( cls.downloadTempName, cls.originalDownloadName );
*cls.downloadTempName = *cls.downloadName = 0;
Cvar_Set( "cl_downloadName", "" );
if ( !cls.bWWWDlDisconnected )
{
CL_AddReliableCommand( "wwwdl done" );
// tracking potential web redirects leading us to wrong checksum - only works in connected mode
if ( strlen( clc.redirectedList ) + strlen( cls.originalDownloadName ) + 1 >= sizeof( clc.redirectedList ) )
{
// just to be safe
Log::Warn( "redirectedList overflow (%s)\n", clc.redirectedList );
}
else
{
strcat( clc.redirectedList, "@" );
strcat( clc.redirectedList, cls.originalDownloadName );
}
}
}
else
{
if ( cls.bWWWDlDisconnected )
{
// in a connected download, we'd tell the server about failure and wait for a reply
// but in this case we can't get anything from server
// if we just reconnect it's likely we'll get the same disconnected download message, and error out again
// this may happen for a regular dl or an auto update
const char *error = va( "Download failure while getting '%s'\n", cls.downloadName ); // get the msg before clearing structs
cls.bWWWDlDisconnected = false; // need clearing structs before ERR_DROP, or it goes into endless reload
CL_ClearStaticDownload();
Sys::Drop( "%s", error );
}
else
{
// see CL_ParseDownload, same abort strategy
Log::Notice( "Download failure while getting '%s'\n", cls.downloadName );
CL_AddReliableCommand( "wwwdl fail" );
clc.bWWWDlAborting = true;
}
return;
}
clc.bWWWDl = false;
CL_NextDownload();
}
/*
==================
CL_WWWBadChecksum
FS code calls this when doing FS_ComparePaks
we can detect files that we got from a www dl redirect with a wrong checksum
this indicates that the redirect setup is broken, and next dl attempt should NOT redirect
==================
*/
bool CL_WWWBadChecksum( const char *pakname )
{
if ( strstr( clc.redirectedList, va( "@%s@", pakname ) ) )
{
Log::Warn("file %s obtained through download redirect has wrong checksum\n"
"\tthis likely means the server configuration is broken", pakname );
if ( strlen( clc.badChecksumList ) + strlen( pakname ) + 1 >= sizeof( clc.badChecksumList ) )
{
Log::Warn("badChecksumList overflowed (%s)", clc.badChecksumList );
return false;
}
strcat( clc.badChecksumList, "@" );
strcat( clc.badChecksumList, pakname );
Log::Debug( "bad checksums: %s", clc.badChecksumList );
return true;
}
return false;
}
/*
==================
CL_Frame
......
......@@ -470,192 +470,6 @@ void CL_ParseGamestate( msg_t *msg )
//=====================================================================
/*
=====================
CL_ParseDownload
A download message has been received from the server
=====================
*/
void CL_ParseDownload( msg_t *msg )
{
int size;
unsigned char data[ MAX_MSGLEN ];
int block;
if ( !*cls.downloadTempName )
{
Log::Notice( "Server sending download, but no download was requested\n" );
// Eat the packet anyway
block = MSG_ReadShort( msg );
if (block == -1) {
MSG_ReadString( msg );
MSG_ReadLong( msg );
MSG_ReadLong( msg );
} else if (block != 0) {
size = MSG_ReadShort( msg );
if ( size < 0 || size > (int) sizeof( data ) )
{
Sys::Drop( "CL_ParseDownload: Invalid size %d for download chunk.", size );
}
MSG_ReadData( msg, data, size );
}
CL_AddReliableCommand( "stopdl" );
return;
}
// read the data
block = MSG_ReadShort( msg );
// TTimo - www dl
// if we haven't acked the download redirect yet
if ( block == -1 )
{
if ( !clc.bWWWDl )
{
// server is sending us a www download
Q_strncpyz( cls.originalDownloadName, cls.downloadName, sizeof( cls.originalDownloadName ) );
Q_strncpyz( cls.downloadName, MSG_ReadString( msg ), sizeof( cls.downloadName ) );
clc.downloadSize = MSG_ReadLong( msg );
clc.downloadFlags = MSG_ReadLong( msg );
downloadLogger.Debug("Server sent us a new WWW DL '%s', size %i, flags %i",
cls.downloadName, clc.downloadSize, clc.downloadFlags);
Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
clc.bWWWDl = true; // activate wwwdl client loop
CL_AddReliableCommand( "wwwdl ack" );
cls.state = connstate_t::CA_DOWNLOADING;
// make sure the server is not trying to redirect us again on a bad checksum
if ( strstr( clc.badChecksumList, va( "@%s", cls.originalDownloadName ) ) )
{
Log::Notice( "refusing redirect to %s by server (bad checksum)\n", cls.downloadName );
CL_AddReliableCommand( "wwwdl fail" );
clc.bWWWDlAborting = true;
return;
}
if ( !DL_BeginDownload( cls.downloadTempName, cls.downloadName ) )
{
// setting bWWWDl to false after sending the wwwdl fail doesn't work
// not sure why, but I suspect we have to eat all remaining block -1 that the server has sent us
// still leave a flag so that CL_WWWDownload is inactive
// we count on server sending us a gamestate to start up clean again
CL_AddReliableCommand( "wwwdl fail" );
clc.bWWWDlAborting = true;
Log::Notice( "Failed to initialize download for '%s'\n", cls.downloadName );
}
// Check for a disconnected download
// we'll let the server disconnect us when it gets the bbl8r message
if ( clc.downloadFlags & DL_FLAG_DISCON )
{
CL_AddReliableCommand( "wwwdl bbl8r" );
cls.bWWWDlDisconnected = true;
}
return;
}
else
{
// server keeps sending that message till we ack it, eat and ignore
//MSG_ReadLong( msg );
MSG_ReadString( msg );
MSG_ReadLong( msg );
MSG_ReadLong( msg );
return;
}
}
if ( !block )
{
// block zero is special, contains file size
clc.downloadSize = MSG_ReadLong( msg );
downloadLogger.Debug("Starting new direct download of size %i for '%s'", clc.downloadSize, cls.downloadTempName);
Cvar_SetValue( "cl_downloadSize", clc.downloadSize );
if ( clc.downloadSize < 0 )
{
Sys::Drop( "%s", MSG_ReadString( msg ) );
}
}
size = MSG_ReadShort( msg );
if ( size < 0 || size > (int) sizeof( data ) )
{
Sys::Drop( "CL_ParseDownload: Invalid size %d for download chunk.", size );
}
downloadLogger.Debug("Received block of size %i", size);
MSG_ReadData( msg, data, size );
if ( clc.downloadBlock != block )
{
downloadLogger.Debug( "CL_ParseDownload: Expected block %i, got %i", clc.downloadBlock, block );
return;
}
// open the file if not opened yet
if ( !clc.download )
{
clc.download = FS_SV_FOpenFileWrite( cls.downloadTempName );
if ( !clc.download )
{
Log::Notice( "Could not create %s\n", cls.downloadTempName );
CL_AddReliableCommand( "stopdl" );
CL_NextDownload();
return;
}
}
if ( size )
{
FS_Write( data, size, clc.download );
}
CL_AddReliableCommand( va( "nextdl %d", clc.downloadBlock ) );
clc.downloadBlock++;
clc.downloadCount += size;
// So UI gets access to it
Cvar_SetValue( "cl_downloadCount", clc.downloadCount );
if ( !size )
{
downloadLogger.Debug("Received EOF, closing '%s'", cls.downloadTempName);
// A zero length block means EOF
if ( clc.download )
{
FS_FCloseFile( clc.download );
clc.download = 0;
// rename the file
FS_SV_Rename( cls.downloadTempName, cls.downloadName );
}
*cls.downloadTempName = *cls.downloadName = 0;
Cvar_Set( "cl_downloadName", "" );
// send intentions now
// We need this because without it, we would hold the last nextdl and then start
// loading right away. If we take a while to load, the server is happily trying
// to send us that last block over and over.
// Write it twice to help make sure we acknowledge the download
CL_WritePacket();
CL_WritePacket();
// get another file if needed
CL_NextDownload();
}
}
/*
=====================
CL_ParseCommandString
......@@ -685,21 +499,6 @@ void CL_ParseCommandString( msg_t *msg )
Q_strncpyz( clc.serverCommands[ index ], s, sizeof( clc.serverCommands[ index ] ) );
}
/*
=====================
CL_ParseBinaryMessage
=====================
*/
void CL_ParseBinaryMessage(msg_t *msg)
{
MSG_BeginReadingUncompressed(msg);
int ssize = msg->cursize - msg->readcount;
if (ssize <= 0 || ssize > MAX_BINARY_MESSAGE) {
return;
}
CL_CGameBinaryMessageReceived(msg->data + msg->readcount, size_t(ssize), cl.snap.serverTime);
}
/*
=====================
CL_ParseServerMessage
......@@ -788,5 +587,4 @@ void CL_ParseServerMessage( msg_t *msg )
break;
}
}
CL_ParseBinaryMessage( msg );
}
......@@ -189,11 +189,6 @@ struct clientConnection_t
// TTimo - NOTE: incidentally, reliableCommands[0] is never used (always start at reliableAcknowledge+1)
char reliableCommands[ MAX_RELIABLE_COMMANDS ][ MAX_TOKEN_CHARS ];
// unreliable binary data to send to server
size_t binaryMessageLength;
uint8_t binaryMessage[MAX_BINARY_MESSAGE];
bool binaryMessageOverflowed;
// server message (unreliable) and command (reliable) sequence
// numbers are NOT cleared at level changes, but continue to
// increase as long as the connection is valid
......@@ -484,8 +479,6 @@ extern cvar_t *cl_aviMotionJpeg;
extern cvar_t *cl_useMumble;
extern cvar_t *cl_mumbleScale;
extern Log::Logger downloadLogger;
//=================================================
//
......@@ -508,9 +501,6 @@ void CL_Snd_Restart_f();
void CL_NextDemo();
void CL_ReadDemoMessage();
void CL_InitDownloads();
void CL_NextDownload();
void CL_GetPing( int n, char *buf, int buflen, int *pingtime );
void CL_ClearPing( int n );
int CL_GetPingQueueCount();
......@@ -528,6 +518,14 @@ void CL_Record(std::string demo_name);
Keyboard::Key Key_GetKeyNumber();
unsigned int Key_GetKeyTime();
//
// cl_download.cpp
//
void CL_ClearStaticDownload();
void CL_InitDownloads();
void CL_WWWDownload();
void CL_ParseDownload( msg_t *msg );
//
// cl_input
//
......@@ -729,7 +727,6 @@ void CL_ShutdownCGame();
void CL_CGameRendering();
void CL_SetCGameTime();
void CL_FirstSnapshot();
void CL_CGameBinaryMessageReceived(const uint8_t *buf, size_t size, int serverTime);
void CL_OnTeamChanged( int newTeam );
//
......
......@@ -665,7 +665,6 @@ namespace Cvar {
//Print the matches, keeping the flags and descriptions aligned
for (size_t i = 0; i < matches.size(); i++) {
const std::string& name = matchesNames[i];
const std::string& value = matchesValues[i];
cvarRecord_t* var = matches[i];
std::string flags = "";
......
......@@ -50,7 +50,7 @@ qhandle_t RE_RegisterShader( const char *, RegisterShaderFlags_t )
{
return 1;
}
fontInfo_t* RE_RegisterFont( const char *, const char *, int pointSize )
fontInfo_t* RE_RegisterFont( const char *, const char *, int )
{
return nullptr;
}
......
......@@ -69,8 +69,6 @@ Maryland 20850 USA.
static fileHandle_t logfile;
cvar_t *com_crashed = nullptr; // ydnar: set in case of a crash, prevents CVAR_UNSAFE variables from being set from a cfg
cvar_t *com_pid; // bani - process id
cvar_t *com_speeds;
......@@ -125,104 +123,6 @@ void CIN_CloseAllVideos();
//bani - moved
void CL_ShutdownCGame();
// *INDENT-ON*
/*
============================================================================
COMMAND LINE FUNCTIONS
+ characters separate the commandLine string into multiple console
command lines.
All of these are valid:
quake3 +set test blah +map test
quake3 set test blah+map test
quake3 set test blah + map test
============================================================================
*/
static const int MAX_CONSOLE_LINES = 32;
int com_numConsoleLines;
char *com_consoleLines[ MAX_CONSOLE_LINES ];
/*
==================
Com_ParseCommandLine
Break it up into multiple console lines
==================
*/
void Com_ParseCommandLine( char *commandLine )
{
com_consoleLines[ 0 ] = commandLine;
com_numConsoleLines = 1;
while ( *commandLine )
{
// look for a + separating character
// if commandLine came from a file, we might have real line separators
if ( *commandLine == '+' || *commandLine == '\n' || *commandLine == '\r' )
{
if ( com_numConsoleLines == MAX_CONSOLE_LINES )
{
return;
}
com_consoleLines[ com_numConsoleLines ] = commandLine + 1;
com_numConsoleLines++;
*commandLine = 0;
}
commandLine++;
}
}
/*
===============
Com_StartupVariable
Searches for command-line arguments that are set commands.
If match is not nullptr, only that cvar will be looked for.
That is necessary because the fs_* cvars need to be set
before the filesystem is started, but all other sets should
be after execing the config and default.
===============
*/
void Com_StartupVariable( const char *match )
{
int i;
const char *s;
cvar_t *cv;
for ( i = 0; i < com_numConsoleLines; i++ )
{
if (com_consoleLines[i] == nullptr) {
continue;
}
Cmd::Args line(com_consoleLines[i]);
if ( line.size() < 3 || strcmp( line[0].c_str(), "set" ))
{
continue;
}
s = line[1].c_str();
if ( !match || !strcmp( s, match ) )
{
Cvar_Set( s, line[2].c_str() );
cv = Cvar_Get( s, "", CVAR_USER_CREATED );
if (cv->flags & CVAR_ROM) {
com_consoleLines[i] = nullptr;
}
}
}
}
//============================================================================
void Info_Print( const char *s )
......@@ -1118,24 +1018,11 @@ void Com_In_Restart_f()
Com_Init
=================
*/
void Com_Init( char *commandLine )
void Com_Init()
{
char *s;
int qport;
// prepare enough of the subsystems to handle
// cvar and command buffer management
Com_ParseCommandLine( commandLine );
// override anything from the config files with command line args
Com_StartupVariable( nullptr );
// get the developer cvar set as early as possible
Com_StartupVariable( "developer" );
// ydnar: init crashed variable as early as possible
com_crashed = Cvar_Get( "com_crashed", "0", CVAR_TEMP );
Trans_Init();
#ifndef BUILD_SERVER
......
......@@ -206,8 +206,7 @@ using clipHandle_t = int;
#define MAX_SAY_TEXT 400
#define MAX_BINARY_MESSAGE 32768 // max length of binary message
// TODO(0.52): remove
enum class messageStatus_t : uint8_t
{
MESSAGE_EMPTY,
......
......@@ -546,7 +546,6 @@ unsigned Com_BlockChecksum( const void *buffer, int length );
char *Com_MD5File( const char *filename, int length );
void Com_MD5Buffer( const char *pubkey, int size, char *buffer, int bufsize );
void Com_StartupVariable( const char *match );
void Com_SetRecommended();
bool Com_AreCheatsAllowed();
bool Com_IsClient();
......@@ -557,8 +556,6 @@ bool Com_ServerRunning();
// if match is nullptr, all set commands will be executed, otherwise
// only a set with the exact name. Only used during startup.
extern cvar_t *com_crashed;
extern cvar_t *com_developer;
extern cvar_t *com_speeds;
extern cvar_t *com_timescale;
......@@ -653,7 +650,7 @@ void Hunk_FreeTempMemory( void *buf );
#endif
// commandLine should not include the executable name (argv[0])
void Com_Init( char *commandLine );
void Com_Init();
void Com_Frame();
void Com_Shutdown();
......@@ -674,7 +671,6 @@ void CL_InitKeyCommands();
// config files, but the rest of client startup will happen later
void CL_Init();
void CL_ClearStaticDownload();
void CL_Disconnect( bool showMainMenu );
void CL_SendDisconnect();
void CL_Shutdown();
......
......@@ -56,7 +56,7 @@ class ServerApplication : public Application {
}
void Initialize(Str::StringRef) override {
Com_Init((char*) "");
Com_Init();
}
void Frame() override {
......
......@@ -154,10 +154,6 @@ struct client_t
int reliableSent; // last sent reliable message, not necessarily acknowledged yet
int messageAcknowledge;
size_t binaryMessageLength;
uint8_t binaryMessage[MAX_BINARY_MESSAGE];
bool binaryMessageOverflowed;
int gamestateMessageNum; // netchan->outgoingSequence of gamestate
usercmd_t lastUsercmd;
......@@ -284,7 +280,6 @@ public:
void GameRunFrame(int levelTime);
bool GameSnapshotCallback(int entityNum, int clientNum);
void BotAIStartFrame(int levelTime);
void GameMessageRecieved(int clientNum, const uint8_t *buf, size_t size, int commandTime);
private:
virtual void Syscall(uint32_t id, Util::Reader reader, IPC::Channel& channel) override final;
......@@ -424,7 +419,6 @@ svEntity_t *SV_SvEntityForGentity( sharedEntity_t *gEnt );
void SV_InitGameProgs();
void SV_ShutdownGameProgs();
void SV_RestartGameProgs();
void SV_GameBinaryMessageReceived(int cno, const byte *buf, size_t buflen, int commandTime);
//
// sv_bot.c
......
......@@ -42,7 +42,7 @@ enum gameImport_t
G_GET_SERVERINFO,
G_GET_USERCMD,
G_GET_ENTITY_TOKEN,
G_SEND_MESSAGE,
G_SEND_MESSAGE, // TODO(0.52): Remove these two
G_MESSAGE_STATUS,
G_RSA_GENMSG, // ( const char *public_key, char *cleartext, char *encrypted )
G_GEN_FINGERPRINT,
......@@ -208,7 +208,7 @@ enum gameExport_t
BOT_CHECKATTACKATPOS, // bool ()( int entityNum, int enemyNum, vec3_t position,
// bool ducking, bool allowWorldHit );
GAME_MESSAGERECEIVED, // void ()( int clientNum, const char *buffer, int bufferSize, int commandTime );
GAME_MESSAGERECEIVED, // TODO(0.52) remove
};
using GameStaticInitMsg = IPC::SyncMessage<
......@@ -242,6 +242,3 @@ using GameClientThinkMsg = IPC::SyncMessage<
using GameRunFrameMsg = IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, GAME_RUN_FRAME>, int>
>;
using GameRecvMessageMsg = IPC::SyncMessage<
IPC::Message<IPC::Id<VM::QVM, GAME_MESSAGERECEIVED>, int, IPC::SharedMemory, size_t, int>
>;
......@@ -1388,22 +1388,6 @@ static void SV_UserMove( client_t *cl, msg_t *msg, bool delta )
}
}
/*
=====================
SV_ParseBinaryMessage
=====================
*/
static void SV_ParseBinaryMessage(client_t *cl, msg_t *msg)
{
MSG_BeginReadingUncompressed(msg);
int ssize = msg->cursize - msg->readcount;
if (ssize <= 0 || ssize > MAX_BINARY_MESSAGE) {
return;
}
const auto client = int(cl - svs.clients);
SV_GameBinaryMessageReceived(client, msg->data + msg->readcount, size_t(ssize), cl->lastUsercmd.serverTime);
}
/*
===========================================================================
......@@ -1548,7 +1532,6 @@ void SV_ExecuteClientMessage( client_t *cl, msg_t *msg )
Log::Warn("missing clc_EOF byte for client %i\n", (int) (cl - svs.clients));
}
SV_ParseBinaryMessage( cl, msg );
// TODO: track bytes read
// if (msg->readcount != msg->cursize) {
// Log::Warn("Junk at end of packet for client %i (%i bytes), read %i of %i bytes", cl - svs.clients, msg->cursize - msg->readcount, msg->readcount, msg->cursize);
......
......@@ -87,31 +87,6 @@ void SV_Netchan_TransmitNextFragment( client_t *client )
}
}
/*
===============
SV_WriteBinaryMessage
===============
*/
static void SV_WriteBinaryMessage( msg_t *msg, client_t *cl )
{
if ( !cl->binaryMessageLength )
{
return;
}
MSG_Uncompressed( msg );
if ( ( msg->cursize + cl->binaryMessageLength ) >= msg->maxsize )
{
cl->binaryMessageOverflowed = true;
return;
}
MSG_WriteData( msg, cl->binaryMessage, cl->binaryMessageLength );
cl->binaryMessageLength = 0;
cl->binaryMessageOverflowed = false;
}
/*
===============
SV_Netchan_Transmit
......@@ -127,7 +102,6 @@ void SV_Netchan_Transmit( client_t *client, msg_t *msg )
{
//int length, const byte *data ) {
MSG_WriteByte( msg, svc_EOF );
SV_WriteBinaryMessage( msg, client );
if ( client->netchan.unsentFragments )
{
......
......@@ -221,57 +221,6 @@ void SV_GetUsercmd( int clientNum, usercmd_t *cmd )
*cmd = svs.clients[ clientNum ].lastUsercmd;
}
/*
====================
SV_SendBinaryMessage
====================
*/
static void SV_SendBinaryMessage(int cno, std::vector<uint8_t> message)
{
if (cno < 0 || cno >= sv_maxclients->integer) {
Sys::Drop("SV_SendBinaryMessage: bad client %i", cno);
}
if (message.size() > MAX_BINARY_MESSAGE) {
Sys::Drop("SV_SendBinaryMessage: bad length %zi", message.size());
}
auto &cl = svs.clients[cno];
memcpy(cl.binaryMessage, message.data(), cl.binaryMessageLength = message.size());
}
/*
====================
SV_BinaryMessageStatus
====================
*/
static messageStatus_t SV_BinaryMessageStatus(int cno)
{
if (cno < 0 || cno >= sv_maxclients->integer) {
return messageStatus_t::MESSAGE_EMPTY;
}
const auto &cl = svs.clients[cno];
if (cl.binaryMessageLength == 0) {
return messageStatus_t::MESSAGE_EMPTY;
}
if (cl.binaryMessageOverflowed) {
return messageStatus_t::MESSAGE_WAITING_OVERFLOW;
}
return messageStatus_t::MESSAGE_WAITING;
}
/*
====================
SV_GameBinaryMessageReceived
====================
*/
void SV_GameBinaryMessageReceived(int cno, const byte *buf, size_t buflen, int commandTime)
{
gvm.GameMessageRecieved( cno, buf, buflen, commandTime );
}
//==============================================
/*
====================
SV_GetTimeString
......@@ -477,13 +426,6 @@ void GameVM::BotAIStartFrame(int)
Sys::Drop("GameVM::BotAIStartFrame not implemented");
}
void GameVM::GameMessageRecieved(int clientNum, const uint8_t *buf, size_t size, int commandTime)
{
static auto shm = IPC::SharedMemory::Create(MAX_BINARY_MESSAGE);
memcpy(shm.GetBase(), buf, size);
gvm.SendMsg<GameRecvMessageMsg>(clientNum, shm, size, commandTime);
}
void GameVM::Syscall(uint32_t id, Util::Reader reader, IPC::Channel& channel)
{
int major = id >> 16;
......@@ -593,14 +535,15 @@ void GameVM::QVMSyscall(int index, Util::Reader& reader, IPC::Channel& channel)
break;
case G_SEND_MESSAGE:
IPC::HandleMsg<SendMessageMsg>(channel, std::move(reader), [this](int clientNum, std::vector<uint8_t> message) {
SV_SendBinaryMessage(clientNum, std::move(message));
IPC::HandleMsg<SendMessageMsg>(channel, std::move(reader), [this](int, std::vector<uint8_t>) {
Log::Warn("SendMessageMsg unsupported");
});
break;
case G_MESSAGE_STATUS:
IPC::HandleMsg<MessageStatusMsg>(channel, std::move(reader), [this](int index, messageStatus_t& status) {
status = SV_BinaryMessageStatus(index);
IPC::HandleMsg<MessageStatusMsg>(channel, std::move(reader), [this](int, messageStatus_t& status) {
Log::Warn("MessageStatusMsg unsupported");
status = {};
});
break;
......
......@@ -104,18 +104,6 @@ bool trap_GetEntityToken( char *buffer, int bufferSize )
return res;
}
void trap_SendMessage(const std::vector<uint8_t>& message)
{
VM::SendMsg<SendMessageMsg>(message);
}
messageStatus_t trap_MessageStatus()
{
messageStatus_t res;
VM::SendMsg<MessageStatusMsg>(res);
return res;
}
void trap_RegisterButtonCommands( const char *cmds )
{
VM::SendMsg<RegisterButtonCommandsMsg>(cmds);
......
......@@ -112,18 +112,6 @@ bool trap_GetEntityToken(char *buffer, int bufferSize)
return res;
}
void trap_SendMessage(int clientNum, const std::vector<uint8_t>& message)
{
VM::SendMsg<SendMessageMsg>(clientNum, message);
}
messageStatus_t trap_MessageStatus(int clientNum)
{
messageStatus_t res;
VM::SendMsg<MessageStatusMsg>(clientNum, res);
return res;
}
int trap_RSA_GenerateMessage(const char *public_key, char *cleartext, char *encrypted)
{
std::string cleartext2, encrypted2;
......
......@@ -35,6 +35,4 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
extern IPC::SharedMemory shmRegion;
void trap_SendMessage(int clientNum, const std::vector<uint8_t>& message);
#endif