void VM::VMHandleSyscall(uint32_t id, Util::Reader reader) { int major = id >> 16; int minor = id & 0xffff; if (major == VM::QVM) { switch (minor) { case GAME_STATIC_INIT: IPC::HandleMsg<GameStaticInitMsg>(VM::rootChannel, std::move(reader), [] (int milliseconds) { VM::InitializeProxies(milliseconds); FS::Initialize(); VM::VMInit(); }); break; case GAME_INIT: IPC::HandleMsg<GameInitMsg>(VM::rootChannel, std::move(reader), [](int levelTime, int randomSeed, bool cheats, bool inClient) { g_cheats.integer = cheats; G_InitGame(levelTime, randomSeed, inClient); }); break; case GAME_SHUTDOWN: IPC::HandleMsg<GameShutdownMsg>(VM::rootChannel, std::move(reader), [](bool restart) { G_ShutdownGame(restart); }); break; case GAME_CLIENT_CONNECT: IPC::HandleMsg<GameClientConnectMsg>(VM::rootChannel, std::move(reader), [](int clientNum, bool firstTime, int isBot, bool& denied, std::string& reason) { const char* deniedStr = isBot ? ClientBotConnect(clientNum, firstTime, TEAM_NONE) : ClientConnect(clientNum, firstTime); denied = deniedStr != nullptr; if (denied) reason = deniedStr; }); break; case GAME_CLIENT_THINK: IPC::HandleMsg<GameClientThinkMsg>(VM::rootChannel, std::move(reader), [](int clientNum) { ClientThink(clientNum); }); break; case GAME_CLIENT_USERINFO_CHANGED: IPC::HandleMsg<GameClientUserinfoChangedMsg>(VM::rootChannel, std::move(reader), [](int clientNum) { ClientUserinfoChanged(clientNum, false); }); break; case GAME_CLIENT_DISCONNECT: IPC::HandleMsg<GameClientDisconnectMsg>(VM::rootChannel, std::move(reader), [](int clientNum) { ClientDisconnect(clientNum); }); break; case GAME_CLIENT_BEGIN: IPC::HandleMsg<GameClientBeginMsg>(VM::rootChannel, std::move(reader), [](int clientNum) { ClientBegin(clientNum); }); break; case GAME_CLIENT_COMMAND: IPC::HandleMsg<GameClientCommandMsg>(VM::rootChannel, std::move(reader), [](int clientNum, std::string command) { Cmd::PushArgs(command); ClientCommand(clientNum); Cmd::PopArgs(); }); break; case GAME_RUN_FRAME: IPC::HandleMsg<GameRunFrameMsg>(VM::rootChannel, std::move(reader), [](int levelTime) { G_RunFrame(levelTime); }); break; case GAME_SNAPSHOT_CALLBACK: G_Error("GAME_SNAPSHOT_CALLBACK not implemented"); break; case BOTAI_START_FRAME: G_Error("BOTAI_START_FRAME not implemented"); break; case GAME_MESSAGERECEIVED: G_Error("GAME_MESSAGERECEIVED not implemented"); break; default: G_Error("VMMain(): unknown game command %i", minor); } } else if (major < VM::LAST_COMMON_SYSCALL) { VM::HandleCommonSyscall(major, minor, std::move(reader), VM::rootChannel); } else { G_Error("unhandled VM major syscall number %i", major); } }
bool G_BotAdd( const char *name, team_t team, int skill, const char *behavior, bool filler ) { int clientNum; char userinfo[MAX_INFO_STRING]; const char* s = 0; gentity_t *bot; bool autoname = false; bool okay; if ( !navMeshLoaded ) { Log::Warn( "No Navigation Mesh file is available for this map" ); return false; } // find what clientNum to use for bot clientNum = trap_BotAllocateClient(); if ( clientNum < 0 ) { Log::Warn( "no more slots for bot" ); return false; } bot = &g_entities[ clientNum ]; bot->r.svFlags |= SVF_BOT; bot->inuse = true; if ( !Q_stricmp( name, BOT_NAME_FROM_LIST ) ) { name = G_BotSelectName( team ); autoname = name != nullptr; } //default bot data okay = G_BotSetDefaults( clientNum, team, skill, behavior ); // register user information userinfo[0] = '\0'; Info_SetValueForKey( userinfo, "name", name ? name : "", false ); // allow defaulting Info_SetValueForKey( userinfo, "rate", "25000", false ); Info_SetValueForKey( userinfo, "snaps", "20", false ); if ( autoname ) { Info_SetValueForKey( userinfo, "autoname", name, false ); } //so we can connect if server is password protected if ( g_needpass.integer == 1 ) { Info_SetValueForKey( userinfo, "password", g_password.string, false ); } trap_SetUserinfo( clientNum, userinfo ); // have it connect to the game as a normal client if ( ( s = ClientBotConnect( clientNum, true, team ) ) ) { // won't let us join Log::Warn( s ); okay = false; } if ( !okay ) { G_BotDel( clientNum ); return false; } if ( autoname ) { G_BotNameUsed( team, name, true ); } ClientBegin( clientNum ); bot->pain = BotPain; // ClientBegin resets the pain function level.clients[clientNum].pers.isFillerBot = filler; G_ChangeTeam( bot, team ); return true; }
// Module RPC entry point static void VMMain(int index, RPC::Reader& inputs, RPC::Writer& outputs) { switch (index) { case GAME_INIT: { int levelTime = inputs.ReadInt(); int randomSeed = inputs.ReadInt(); qboolean restart = inputs.ReadInt(); G_InitGame(levelTime, randomSeed, restart); break; } case GAME_SHUTDOWN: G_ShutdownGame(inputs.ReadInt()); break; case GAME_CLIENT_CONNECT: { int clientNum = inputs.ReadInt(); qboolean firstTime = inputs.ReadInt(); qboolean isBot = inputs.ReadInt(); const char* denied = isBot ? ClientBotConnect(clientNum, firstTime, TEAM_NONE) : ClientConnect(clientNum, firstTime); outputs.WriteInt(denied ? qtrue : qfalse); if (denied) outputs.WriteString(denied); break; } case GAME_CLIENT_THINK: ClientThink(inputs.ReadInt()); break; case GAME_CLIENT_USERINFO_CHANGED: ClientUserinfoChanged(inputs.ReadInt(), qfalse); break; case GAME_CLIENT_DISCONNECT: ClientDisconnect(inputs.ReadInt()); break; case GAME_CLIENT_BEGIN: ClientBegin(inputs.ReadInt()); break; case GAME_CLIENT_COMMAND: ClientCommand(inputs.ReadInt()); break; case GAME_RUN_FRAME: G_RunFrame(inputs.ReadInt()); break; case GAME_CONSOLE_COMMAND: outputs.WriteInt(ConsoleCommand()); break; case GAME_SNAPSHOT_CALLBACK: G_Error("GAME_SNAPSHOT_CALLBACK not implemented"); break; case BOTAI_START_FRAME: G_Error("BOTAI_START_FRAME not implemented"); break; case GAME_MESSAGERECEIVED: G_Error("GAME_MESSAGERECEIVED not implemented"); break; default: G_Error("VMMain(): unknown game command %i", index); } }