/* ==================== COM_BlockSequenceCRCByte For proxy protecting ==================== */ byte COM_BlockSequenceCRCByte (byte *base, int length, int sequence) { int n, x; const byte *p; byte chkb[60 + 4]; uint16 crc; byte r; if (sequence < 0) Sys_Error("sequence < 0, this shouldn't happen\n"); p = chktbl + (sequence % (sizeof(chktbl) - 4)); if (length > 60) length = 60; memcpy (chkb, base, length); chkb[length] = p[0]; chkb[length+1] = p[1]; chkb[length+2] = p[2]; chkb[length+3] = p[3]; length += 4; crc = CRC_Block(chkb, length); for (x=0, n=0; n<length; n++) x += chkb[n]; r = (crc ^ x) & 0xff; return r; }
static cvar_t *Cvar_FindVarLink (const char *var_name, cvar_t **parent, cvar_t ***link, cvar_t **prev_alpha) { int hashindex; cvar_t *var; // use hash lookup to minimize search time hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name)); if(parent) *parent = NULL; if(prev_alpha) *prev_alpha = NULL; if(link) *link = &cvar_hashtable[hashindex]; for (var = cvar_hashtable[hashindex];var;var = var->nextonhashchain) { if (!strcmp (var_name, var->name)) { if(!prev_alpha || var == cvar_vars) return var; *prev_alpha = cvar_vars; // if prev_alpha happens to become NULL then there has been some inconsistency elsewhere // already - should I still insert '*prev_alpha &&' in the loop? while((*prev_alpha)->next != var) *prev_alpha = (*prev_alpha)->next; return var; } if(parent) *parent = var; } return NULL; }
static unsigned SV_CheckModel(char *mdl) { unsigned char *buf; unsigned short crc; int filesize; int mark; mark = Hunk_LowMark (); buf = (byte *) FS_LoadHunkFile (mdl, &filesize); if (!buf) { if (!strcmp (mdl, "progs/player.mdl")) return 33168; else if (!strcmp (mdl, "progs/newplayer.mdl")) return 62211; else if (!strcmp (mdl, "progs/eyes.mdl")) return 6967; else SV_Error ("SV_CheckModel: could not load %s\n", mdl); } crc = CRC_Block (buf, filesize); Hunk_FreeToLowMark (mark); return crc; }
/* ============ Cvar_FindVar ============ */ cvar_t *Cvar_FindVar (const char *var_name) { int hashindex; cvar_t *var; // use hash lookup to minimize search time hashindex = CRC_Block((const unsigned char *)var_name, strlen(var_name)) % CVAR_HASHSIZE; for (var = cvar_hashtable[hashindex];var;var = var->nextonhashchain) if (!strcmp (var_name, var->name)) return var; return NULL; }
unsigned SV_CheckModel(char *mdl) { byte stackbuf[1024]; // avoid dirtying the cache heap byte *buf; unsigned short crc; buf = (byte *)FS_LoadStackFile (mdl, stackbuf, sizeof(stackbuf)); if (!buf) Host_Error ("SV_CheckModel: could not load %s\n", mdl); crc = CRC_Block(buf, fs_filesize); return crc; }
void PR_LoadProgs (void) { int i; char num[32]; char name[MAX_OSPATH]; int filesize; // flush the non-C variable lookup cache for (i = 0; i < GEFV_CACHESIZE; i++) gefvCache[i].field[0] = 0; // clear pr_newstrtbl PF_clear_strtbl(); snprintf(name, sizeof(name), "%s.dat", sv_progsname.string); progs = (dprograms_t *)FS_LoadHunkFile (name, &filesize); if (!progs) progs = (dprograms_t *)FS_LoadHunkFile ("qwprogs.dat", &filesize); if (!progs) progs = (dprograms_t *)FS_LoadHunkFile ("spprogs.dat", &filesize); #ifdef WITH_NQPROGS pr_nqprogs = false; if (!progs || Cvar_Value("sv_forcenqprogs")) { progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat", &filesize); if (progs) pr_nqprogs = true; } #endif if (!progs) SV_Error ("PR_LoadProgs: couldn't load progs.dat"); Con_DPrintf ("Programs occupy %iK.\n", filesize/1024); // add prog crc to the serverinfo snprintf (num, sizeof(num), "%i", CRC_Block ((byte *)progs, filesize)); #ifdef USE_PR2 Info_SetStar( &_localinfo_, "*qvm", "DAT" ); // Info_SetValueForStarKey (svs.info, "*qvm", "DAT", MAX_SERVERINFO_STRING); #endif Info_SetValueForStarKey (svs.info, "*progs", num, MAX_SERVERINFO_STRING); // byte swap the header for (i = 0; i < (int) sizeof(*progs) / 4 ; i++) ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] ); if (progs->version != PROG_VERSION) SV_Error ("qwprogs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); if (progs->crc != (pr_nqprogs ? NQ_PROGHEADER_CRC : PROGHEADER_CRC)) SV_Error ("You must have the qwprogs.dat from QuakeWorld installed"); pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); pr_strings = (char *)progs + progs->ofs_strings; pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); num_prstr = 0; pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); pr_globals = (float *)pr_global_struct; pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); // byte swap the lumps for (i = 0; i < progs->numstatements; i++) { pr_statements[i].op = LittleShort(pr_statements[i].op); pr_statements[i].a = LittleShort(pr_statements[i].a); pr_statements[i].b = LittleShort(pr_statements[i].b); pr_statements[i].c = LittleShort(pr_statements[i].c); } for (i = 0; i < progs->numfunctions; i++) { pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement); pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start); pr_functions[i].s_name = LittleLong (pr_functions[i].s_name); pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); pr_functions[i].locals = LittleLong (pr_functions[i].locals); } for (i = 0; i < progs->numglobaldefs; i++) { pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type); pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs); pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); } for (i = 0; i < progs->numfielddefs; i++) { pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) SV_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); } for (i = 0; i < progs->numglobals; i++) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); #ifdef WITH_NQPROGS PR_InitPatchTables(); #endif // find optional QC-exported functions SpectatorConnect = ED_FindFunctionOffset ("SpectatorConnect"); SpectatorThink = ED_FindFunctionOffset ("SpectatorThink"); SpectatorDisconnect = ED_FindFunctionOffset ("SpectatorDisconnect"); ChatMessage = ED_FindFunctionOffset ("ChatMessage"); UserInfo_Changed = ED_FindFunctionOffset ("UserInfo_Changed"); mod_ConsoleCmd = ED_FindFunctionOffset ("ConsoleCmd"); mod_UserCmd = ED_FindFunctionOffset ("UserCmd"); localinfoChanged = ED_FindFunctionOffset ("localinfoChanged"); GE_ClientCommand = ED_FindFunctionOffset ("GE_ClientCommand"); GE_PausedTic = ED_FindFunctionOffset ("GE_PausedTic"); GE_ShouldPause = ED_FindFunctionOffset ("GE_ShouldPause"); CheckKTPro (); }
static uintptr_t blend_get_hash (const void *e, void *unused) { iqmblend_t *b = (iqmblend_t *) e; return CRC_Block ((byte *) b, sizeof (iqmblend_t)); }
/* =============== PR_LoadProgs =============== */ void PR_LoadProgs (void) { int i; char num[32]; static int lumpsize[6] = { sizeof(dstatement_t), sizeof(ddef_t), sizeof(ddef_t), sizeof(dfunction_t), 4, 4 }; int filesize = 0; const char *progsname; progs = NULL; // decide whether to load qwprogs.dat, progs.dat or spprogs.dat #ifdef WITH_NQPROGS if (Cvar_Value("sv_forcenqprogs")) goto use_progs; #endif if (!deathmatch.value) { if (Q_stricmp(com_gamedirfile, "qw") && strcmp(com_gamedirfile, "")) { // if we're using a custom mod, anything // in gamedir is preferred to stock *progs.dat qbool check; check = FS_FindFile ("spprogs.dat"); if (check && file_from_gamedir) goto use_spprogs; #ifdef WITH_NQPROGS check = FS_FindFile ("progs.dat"); if (check && file_from_gamedir) goto use_progs; #endif check = FS_FindFile ("qwprogs.dat"); if (check && file_from_gamedir) goto use_qwprogs; } use_spprogs: progs = (dprograms_t *) FS_LoadHunkFile ("spprogs.dat"); progsname = "spprogs.dat"; pr_nqprogs = false; if (!progs) { #ifdef WITH_NQPROGS use_progs: progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat"); progsname = "progs.dat"; pr_nqprogs = true; } #endif if (!progs) { use_qwprogs: progs = (dprograms_t *)FS_LoadHunkFile ("qwprogs.dat"); progsname = "qwprogs.dat"; pr_nqprogs = false; } } else // deathmatch { if (Q_stricmp(com_gamedirfile, "qw") && strcmp(com_gamedirfile, "")) { qbool check; check = FS_FindFile ("qwprogs.dat"); if (check && file_from_gamedir) goto dm_use_qwprogs; #ifdef WITH_NQPROGS check = FS_FindFile ("progs.dat"); if (check && file_from_gamedir) goto dm_use_progs; #endif } dm_use_qwprogs: progs = (dprograms_t *) FS_LoadHunkFile ("qwprogs.dat"); progsname = "qwprogs.dat"; pr_nqprogs = false; if (!progs) { #ifdef WITH_NQPROGS dm_use_progs: progs = (dprograms_t *)FS_LoadHunkFile ("progs.dat"); progsname = "progs.dat"; pr_nqprogs = true; } #endif } if (!progs) Host_Error ("PR_LoadProgs: couldn't load progs.dat"); filesize = fs_filesize; if (filesize < (int)sizeof(*progs)) Host_Error("%s is corrupt", progsname); Com_DPrintf ("Using %s (%i bytes).\n", progsname, filesize); // add prog crc to the serverinfo sprintf (num, "%i", CRC_Block ((byte *)progs, filesize)); svs.info.set("*progs", num); // byte swap the header for (i = 0; i < sizeof(*progs)/4; i++) ((int *)progs)[i] = LittleLong ( ((int *)progs)[i] ); if (progs->version != PROG_VERSION) Host_Error ("progs.dat has wrong version number (%i should be %i)", progs->version, PROG_VERSION); if (progs->crc != (pr_nqprogs ? NQ_PROGHEADER_CRC : PROGHEADER_CRC)) Host_Error ("You must have the qwprogs.dat from QuakeWorld installed"); // check lump offsets and sizes for (i = 0; i < 6; i ++) { if (((int *)progs)[i*2 + 2] < sizeof(*progs) || ((int *)progs)[i*2 + 2] + ((int *)progs)[i*2 + 3]*lumpsize[i] > filesize) Host_Error("progs.dat is corrupt"); } pr_functions = (dfunction_t *)((byte *)progs + progs->ofs_functions); pr_strings = (char *)progs + progs->ofs_strings; pr_globaldefs = (ddef_t *)((byte *)progs + progs->ofs_globaldefs); pr_fielddefs = (ddef_t *)((byte *)progs + progs->ofs_fielddefs); pr_statements = (dstatement_t *)((byte *)progs + progs->ofs_statements); pr_global_struct = (globalvars_t *)((byte *)progs + progs->ofs_globals); pr_globals = (float *)pr_global_struct; PR_InitStrings (); pr_edict_size = progs->entityfields * 4 + sizeof (edict_t) - sizeof(entvars_t); // byte swap the lumps for (i=0 ; i<progs->numstatements ; i++) { pr_statements[i].op = LittleShort(pr_statements[i].op); pr_statements[i].a = LittleShort(pr_statements[i].a); pr_statements[i].b = LittleShort(pr_statements[i].b); pr_statements[i].c = LittleShort(pr_statements[i].c); } for (i=0 ; i<progs->numfunctions; i++) { pr_functions[i].first_statement = LittleLong (pr_functions[i].first_statement); pr_functions[i].parm_start = LittleLong (pr_functions[i].parm_start); pr_functions[i].s_name = LittleLong (pr_functions[i].s_name); pr_functions[i].s_file = LittleLong (pr_functions[i].s_file); pr_functions[i].numparms = LittleLong (pr_functions[i].numparms); pr_functions[i].locals = LittleLong (pr_functions[i].locals); } for (i=0 ; i<progs->numglobaldefs ; i++) { pr_globaldefs[i].type = LittleShort (pr_globaldefs[i].type); pr_globaldefs[i].ofs = LittleShort (pr_globaldefs[i].ofs); pr_globaldefs[i].s_name = LittleLong (pr_globaldefs[i].s_name); } for (i=0 ; i<progs->numfielddefs ; i++) { pr_fielddefs[i].type = LittleShort (pr_fielddefs[i].type); if (pr_fielddefs[i].type & DEF_SAVEGLOBAL) Host_Error ("PR_LoadProgs: pr_fielddefs[i].type & DEF_SAVEGLOBAL"); pr_fielddefs[i].ofs = LittleShort (pr_fielddefs[i].ofs); pr_fielddefs[i].s_name = LittleLong (pr_fielddefs[i].s_name); } for (i=0 ; i<progs->numglobals ; i++) ((int *)pr_globals)[i] = LittleLong (((int *)pr_globals)[i]); #ifdef WITH_NQPROGS if (pr_nqprogs) { memcpy (pr_globaloffsetpatch, pr_globaloffsetpatch_nq, sizeof(pr_globaloffsetpatch)); for (i = 0; i < 106; i++) { pr_fieldoffsetpatch[i] = (i < 8) ? i : (i < 25) ? i + 1 : (i < 28) ? i + (102 - 25) : (i < 73) ? i - 2 : (i < 74) ? i + (105 - 73) : (i < 105) ? i - 3 : /* (i == 105) */ 8; } for (i=0 ; i<progs->numfielddefs ; i++) pr_fielddefs[i].ofs = PR_FIELDOFS(pr_fielddefs[i].ofs); } else { memset (pr_globaloffsetpatch, 0, sizeof(pr_globaloffsetpatch)); for (i = 0; i < 106; i++) pr_fieldoffsetpatch[i] = i; } #endif // find optional QC-exported functions SpectatorConnect = ED_FindFunctionOffset ("SpectatorConnect"); SpectatorThink = ED_FindFunctionOffset ("SpectatorThink"); SpectatorDisconnect = ED_FindFunctionOffset ("SpectatorDisconnect"); GE_ClientCommand = ED_FindFunctionOffset ("GE_ClientCommand"); GE_ConsoleCommand = ED_FindFunctionOffset ("GE_ConsoleCommand"); GE_PausedTic = ED_FindFunctionOffset ("GE_PausedTic"); GE_ShouldPause = ED_FindFunctionOffset ("GE_ShouldPause"); // find optional QC-exported fields fofs_maxspeed = ED_FindFieldOffset ("maxspeed"); fofs_gravity = ED_FindFieldOffset ("gravity"); fofs_items2 = ED_FindFieldOffset ("items2"); fofs_movement = ED_FindFieldOffset ("movement"); fofs_vw_index = ED_FindFieldOffset ("vw_index"); for (i = 3; i < 8; i++) fofs_buttonX[i-3] = ED_FindFieldOffset(va("button%i", i)); // reset stuff like ZQ_CLIENTCOMMAND, progs must enable it explicitly memset (&pr_ext_enabled, sizeof(pr_ext_enabled), 0); PR_Exec_Init (); }
// Generate a chat message from a specified message type, and return // the pointer of the generated message char *CChatManager::GenerateChat(CBaseBot *pClient, const char *type) { static char msg[256]; // for the chat message msg[0] = '\0'; // initialize the string unsigned short usCrc = CRC_Block((unsigned char *)type, strlen(type)); // find if we already have this section int found; for (found = 0; found < m_ChatItem.size(); found++) { if (m_ChatItem[found].type == usCrc) break; } if (found < m_ChatItem.size()) { char sz[256]; strncpy(sz, m_ChatItem[found].PickMessage(), 256); int length = strlen(sz); char *p = sz; while (p != NULL && *p) { if (*p == '%') { char type = *(++p); // skip to next character to get the type int hiscore = -9999, j, count; CClient *pPickedClient = NULL; char buffer[32]; switch (type) { case '%': strncat(msg, "%", 256); break; case 'n': // bot name strncpy(buffer, pClient->GetNetName(), 32); HumanizeName(buffer); strncat(msg, buffer, 256); // append it to the message break; case 'r': // random opponent j = RandomLong(0, g_pServer->GetMaxClients()); for (count = 0; count < g_pServer->GetMaxClients(); count++, j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p != pClient && p->IsValid()) { strncpy(buffer, p->GetNetName(), 32); HumanizeName(buffer); strncat(msg, buffer, 256); // append it to the message break; } } if (count >= g_pServer->GetMaxClients()) return NULL; // can't find any player, don't say anything break; case 'f': // opponent in first place for (j = 0; j < g_pServer->GetMaxClients(); j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p == pClient || !p->IsValid()) continue; if (p->GetFrags() >= hiscore) { hiscore = p->GetFrags(); pPickedClient = p; } } if (pPickedClient) { strncpy(buffer, pPickedClient->GetNetName(), 32); HumanizeName(buffer); // humanize the name strncat(msg, buffer, 256); // append it to the message } else { return NULL; // can't find such a player, don't say anything } break; case 'l': // opponent in last place hiscore = 9999; for (j = 0; j < g_pServer->GetMaxClients(); j++) { CClient *p = g_pServer->m_rgpClients[j]; if (p == pClient || !p->IsValid()) continue; if (p->GetFrags() <= hiscore) { hiscore = p->GetFrags(); pPickedClient = p; } } if (pPickedClient) { strncpy(buffer, pPickedClient->GetNetName(), 32); HumanizeName(buffer); // humanize the name strncat(msg, buffer, 256); // append it to the message } else { return NULL; // can't find such a player, don't say anything } break; case 'm': // map title strncat(msg, g_pServer->GetMapName(), 256); // get the map name break; case 'v': // last victim of this bot if (pClient->Chat()->m_strLastVictim.length() <= 0) return NULL; // we don't have a victim yet, don't say anything strncat(msg, pClient->Chat()->m_strLastVictim.c_str(), 256); break; case 'k': // last player killed this bot if (pClient->Chat()->m_strLastKiller.length() <= 0) return NULL; // this bot hasn't been killed yet, don't say anything strncat(msg, pClient->Chat()->m_strLastKiller.c_str(), 256); break; } p++; // skip to the next character continue; } char *prev = p; p = strchr(p, '%'); // search for the next "%" sign if (p) { *p = '\0'; // if found, terminate the string } strncat(msg, prev, 256); // append the remaining text if (p) { *p = '%'; // restore the '%' } } HumanizeChat(msg); // 'Humanize' the chat message return msg; } return NULL; // not found }
// load the bot chat data file void CChatManager::LoadBotChat() { char str[256]; FILE *fp = fopen(g_General.BuildFileName("botchat.txt"), "r"); if (!fp) { printf("BOT: cannot load file botchat.txt !\n"); return; } bool fIsReply = false, fLoadingKeywords = false; while (fgets(str, 256, fp)) { trim(str); // trim all the blanks or linefeeds // skip all comment lines or empty lines if (!str[0] || str[0] == ';' || str[0] == '/' || str[0] == '#') continue; // check if this is a section line (e.g., [SECTION]) int length = strlen(str); if (str[0] == '[' && str[length - 1] == ']') { int i; char section[256]; section[0] = '\0'; strcpy(section, &str[1]); section[length - 2] = 0; // remove the ] trim(section); // convert the key name to upper case for (i = 0; i < length - 2; i++) { section[i] = toupper(section[i]); } if (strcmpi(section, "REPLIES") == 0) { fIsReply = true; } else { fIsReply = false; unsigned short usCrc = CRC_Block((unsigned char *)section, length - 2); // CRC the section name // add a session m_ChatItem.push_back(CChatItem(usCrc)); } } else if (fIsReply) { if (strncmp(str, "@KEY ", 5) == 0) { // This is a keyword line. Add the keyword to our list if (!fLoadingKeywords) { m_ChatReply.push_back(CChatReply()); fLoadingKeywords = true; } m_ChatReply[m_ChatReply.size() - 1].AddKeyword(&str[5]); } else if (m_ChatReply.size() > 0) { // This is a reply message line. Add it to our list m_ChatReply[m_ChatReply.size() - 1].AddMessage(str); fLoadingKeywords = false; } } else if (m_ChatItem.size() > 0) { // This is a chat message line. Add it to our list m_ChatItem[m_ChatItem.size() - 1].AddMessage(str); } } fclose(fp); // close the file }
qbool VM_LoadBytecode( vm_t * vm, sys_callex_t syscall1 ) { char name[MAX_OSPATH]; byte *buff; vmHeader_t *header; qvm_t *qvm; char num[32]; int filesize; snprintf( name, sizeof( name ), "%s.qvm", vm->name ); Con_DPrintf( "VM_LoadBytecode: load %s\n", name ); buff = FS_LoadTempFile( name , &filesize ); if ( !buff ) return false; // add qvm crc to the serverinfo snprintf( num, sizeof(num), "%i", CRC_Block( ( byte * ) buff, filesize ) ); Info_SetValueForStarKey( svs.info, "*progs", num, MAX_SERVERINFO_STRING ); header = ( vmHeader_t * ) buff; header->vmMagic = LittleLong( header->vmMagic ); header->instructionCount = LittleLong( header->instructionCount ); header->codeOffset = LittleLong( header->codeOffset ); header->codeLength = LittleLong( header->codeLength ); header->dataOffset = LittleLong( header->dataOffset ); header->dataLength = LittleLong( header->dataLength ); header->litLength = LittleLong( header->litLength ); header->bssLength = LittleLong( header->bssLength ); // check file if ( header->vmMagic != VM_MAGIC || header->instructionCount <= 0 || header->codeLength <= 0 ) { return false; } // create vitrual machine if(vm->hInst) qvm = (qvm_t *)vm->hInst; else qvm = (qvm_t *) Q_malloc (sizeof (qvm_t)); qvm->len_cs = header->instructionCount + 1; //bad opcode padding. qvm->len_ds = header->dataOffset + header->litLength + header->bssLength; //align ds qvm->ds_mask = 1; while( qvm->ds_mask < qvm->len_ds) qvm->ds_mask<<=1; qvm->len_ds = qvm->ds_mask; qvm->ds_mask--; qvm->len_ss = 0x10000; // default by q3asm if ( qvm->len_ds < qvm->len_ss ) Sys_Error( "VM_LoadBytecode: stacksize greater than data segment" ); qvm->cs = ( qvm_instruction_t * ) Hunk_AllocName( qvm->len_cs * sizeof( qvm_instruction_t ), "qvmcode" ); qvm->ds = (byte *) Hunk_AllocName( qvm->len_ds, "qvmdata" ); qvm->ss = qvm->ds + qvm->len_ds - qvm->len_ss; // setup registers qvm->PC = 0; qvm->SP = 0; qvm->LP = qvm->len_ds - sizeof(int); qvm->cycles = 0; qvm->reenter = 0; qvm->syscall = syscall1; // load instructions { byte *src = buff + header->codeOffset; qvm_instruction_t *dst = qvm->cs; opcode_t op; int i; for ( i = 0; i < header->instructionCount; i++, dst++ ) { op = (opcode_t) *src++; dst->opcode = op; switch ( op ) { case OP_ARG: dst->parm._int = ( int ) *src++; break; case OP_ENTER: case OP_LEAVE: case OP_CONST: case OP_LOCAL: case OP_EQ: case OP_NE: case OP_LTI: case OP_LEI: case OP_GTI: case OP_GEI: case OP_LTU: case OP_LEU: case OP_GTU: case OP_GEU: case OP_EQF: case OP_NEF: case OP_LTF: case OP_LEF: case OP_GTF: case OP_GEF: case OP_BLOCK_COPY: dst->parm._int = LittleLong( *( int * ) src ); src += 4; break; default: dst->parm._int = 0; break; } } dst->opcode = OP_BREAK; dst->parm._int = 0; } // load data segment { int *src = ( int * ) ( buff + header->dataOffset ); int *dst = ( int * ) qvm->ds; int i; for ( i = 0; i < header->dataLength / 4; i++ ) *dst++ = LittleLong( *src++ ); memcpy( dst, src, header->litLength ); } LoadMapFile( qvm, vm->name ); vm->type = VM_BYTECODE; vm->hInst = qvm; return true; }
/* ================= Mod_LoadAliasModel ================= */ void Mod_LoadAliasModel(const model_loader_t *loader, model_t *mod, void *buffer, const model_t *loadmodel, const char *loadname) { byte *container; int i, j, pad; mdl_t *pinmodel; stvert_t *pinstverts; dtriangle_t *pintriangles; int version, numframes; int size; daliasframetype_t *pframetype; daliasframe_t *frame; daliasgroup_t *group; daliasskintype_t *pskintype; int start, end, total; float *intervals; #ifdef QW_HACK const char *crcmodel = NULL; if (!strcmp(loadmodel->name, "progs/player.mdl")) crcmodel = "pmodel"; if (!strcmp(loadmodel->name, "progs/eyes.mdl")) crcmodel = "emodel"; if (crcmodel) { uint16_t crc = CRC_Block(buffer, com_filesize); Info_SetValueForKey(cls.userinfo, crcmodel, va("%d", (int)crc), MAX_INFO_STRING); if (cls.state >= ca_connected) { MSG_WriteByte(&cls.netchan.message, clc_stringcmd); MSG_WriteStringf(&cls.netchan.message, "setinfo %s %d", crcmodel, (int)crc); } } #endif start = Hunk_LowMark(); pinmodel = (mdl_t *)buffer; #ifdef MSB_FIRST version = LittleLong(pinmodel->version); #else version = (pinmodel->version); #endif if (version != ALIAS_VERSION) Sys_Error("%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_VERSION); // allocate space for a working header, plus all the data except the frames, // skin and group info pad = loader->Aliashdr_Padding(); #ifdef MSB_FIRST size = pad + sizeof(aliashdr_t) + LittleLong(pinmodel->numframes) * sizeof(pheader->frames[0]); #else size = pad + sizeof(aliashdr_t) + (pinmodel->numframes) * sizeof(pheader->frames[0]); #endif container = (byte*)Hunk_AllocName(size, loadname); pheader = (aliashdr_t *)(container + pad); #ifdef MSB_FIRST mod->flags = LittleLong(pinmodel->flags); // endian-adjust and copy the data, starting with the alias model header pheader->numskins = LittleLong(pinmodel->numskins); pheader->skinwidth = LittleLong(pinmodel->skinwidth); pheader->skinheight = LittleLong(pinmodel->skinheight); #else mod->flags = (pinmodel->flags); pheader->numskins = (pinmodel->numskins); pheader->skinwidth = (pinmodel->skinwidth); pheader->skinheight = (pinmodel->skinheight); #endif if (pheader->skinheight > MAX_LBM_HEIGHT) Sys_Error("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); #ifdef MSB_FIRST pheader->numverts = LittleLong(pinmodel->numverts); #else pheader->numverts = (pinmodel->numverts); #endif if (pheader->numverts <= 0) Sys_Error("model %s has no vertices", mod->name); if (pheader->numverts > MAXALIASVERTS) Sys_Error("model %s has too many vertices", mod->name); #ifdef MSB_FIRST pheader->numtris = LittleLong(pinmodel->numtris); #else pheader->numtris = (pinmodel->numtris); #endif if (pheader->numtris <= 0) Sys_Error("model %s has no triangles", mod->name); #ifdef MSB_FIRST pheader->numframes = LittleLong(pinmodel->numframes); pheader->size = LittleFloat(pinmodel->size) * ALIAS_BASE_SIZE_RATIO; mod->synctype = (synctype_t)LittleLong(pinmodel->synctype); #else pheader->numframes = (pinmodel->numframes); pheader->size = (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; mod->synctype = (synctype_t)(pinmodel->synctype); #endif mod->numframes = pheader->numframes; for (i = 0; i < 3; i++) { #ifdef MSB_FIRST pheader->scale[i] = LittleFloat(pinmodel->scale[i]); pheader->scale_origin[i] = LittleFloat(pinmodel->scale_origin[i]); #else pheader->scale[i] = (pinmodel->scale[i]); pheader->scale_origin[i] = (pinmodel->scale_origin[i]); #endif } // load the skins pskintype = (daliasskintype_t *)&pinmodel[1]; pskintype = (daliasskintype_t *)Mod_LoadAllSkins(loader, loadmodel, pheader->numskins, pskintype, loadname); // set base s and t vertices pinstverts = (stvert_t *)pskintype; for (i = 0; i < pheader->numverts; i++) { #ifdef MSB_FIRST stverts[i].onseam = LittleLong(pinstverts[i].onseam); stverts[i].s = LittleLong(pinstverts[i].s); stverts[i].t = LittleLong(pinstverts[i].t); #else stverts[i].onseam = (pinstverts[i].onseam); stverts[i].s = (pinstverts[i].s); stverts[i].t = (pinstverts[i].t); #endif } // set up the triangles pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts]; for (i = 0; i < pheader->numtris; i++) { #ifdef MSB_FIRST triangles[i].facesfront = LittleLong(pintriangles[i].facesfront); #else triangles[i].facesfront = (pintriangles[i].facesfront); #endif for (j = 0; j < 3; j++) { #ifdef MSB_FIRST triangles[i].vertindex[j] = LittleLong(pintriangles[i].vertindex[j]); #else triangles[i].vertindex[j] = (pintriangles[i].vertindex[j]); #endif if (triangles[i].vertindex[j] < 0 || triangles[i].vertindex[j] >= pheader->numverts) Sys_Error("%s: invalid vertex index (%d of %d) in %s\n", __func__, triangles[i].vertindex[j], pheader->numverts, mod->name); } } /* load the frames */ numframes = pheader->numframes; if (numframes < 1) Sys_Error("%s: Invalid # of frames: %d", __func__, numframes); posenum = 0; pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris]; for (i = 0; i < numframes; i++) { #ifdef MSB_FIRST if (LittleLong(pframetype->type) == ALIAS_SINGLE) #else if ((pframetype->type) == ALIAS_SINGLE) #endif { frame = (daliasframe_t *)(pframetype + 1); Mod_LoadAliasFrame(frame, &pheader->frames[i]); pframetype = (daliasframetype_t *)&frame->verts[pheader->numverts]; } else { group = (daliasgroup_t *)(pframetype + 1); pframetype = Mod_LoadAliasGroup(group, &pheader->frames[i], loadname); } } pheader->numposes = posenum; mod->type = mod_alias; // FIXME: do this right mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; /* Save the frame intervals */ intervals = (float*)Hunk_Alloc(pheader->numposes * sizeof(float)); pheader->poseintervals = (byte *)intervals - (byte *)pheader; for (i = 0; i < pheader->numposes; i++) intervals[i] = poseintervals[i]; /* Save the mesh data (verts, stverts, triangles) */ loader->LoadMeshData(loadmodel, pheader, triangles, stverts, poseverts); // move the complete, relocatable alias model to the cache end = Hunk_LowMark(); total = end - start; Cache_AllocPadded(&mod->cache, pad, total - pad, loadname); if (!mod->cache.data) return; memcpy((byte *)mod->cache.data - pad, container, total); Hunk_FreeToLowMark(start); }
/* ================= Mod_LoadAliasModel ================= */ void Mod_LoadAliasModel (model_t *mod, void *buffer) { int i; mdl_t *pmodel, *pinmodel; stvert_t *pstverts, *pinstverts; aliashdr_t *pheader; mtriangle_t *ptri; dtriangle_t *pintriangles; int version, numframes, numskins; int size; daliasframetype_t *pframetype; daliasskintype_t *pskintype; maliasskindesc_t *pskindesc; int skinsize; int start, end, total; // some models are special if(!strcmp(mod->name, "progs/player.mdl")) mod->modhint = MOD_PLAYER; else if(!strcmp(mod->name, "progs/eyes.mdl")) mod->modhint = MOD_EYES; else if (!strcmp(mod->name, "progs/flame.mdl") || !strcmp(mod->name, "progs/flame2.mdl")) mod->modhint = MOD_FLAME; /* else if (!strcmp(mod->name, "progs/bolt.mdl") || !strcmp(mod->name, "progs/bolt2.mdl") || !strcmp(mod->name, "progs/bolt3.mdl")) mod->modhint = MOD_THUNDERBOLT; */ if (mod->modhint == MOD_PLAYER || mod->modhint == MOD_EYES) mod->crc = CRC_Block (buffer, fs_filesize); start = Hunk_LowMark (); pinmodel = (mdl_t *)buffer; version = LittleLong (pinmodel->version); if (version != ALIAS_VERSION) Host_Error ("%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_VERSION); // // allocate space for a working header, plus all the data except the frames, // skin and group info // size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * sizeof (pheader->frames[0]) + sizeof (mdl_t) + LittleLong (pinmodel->numverts) * sizeof (stvert_t) + LittleLong (pinmodel->numtris) * sizeof (mtriangle_t); pheader = Hunk_AllocName (size, loadname); pmodel = (mdl_t *) ((byte *)&pheader[1] + (LittleLong (pinmodel->numframes) - 1) * sizeof (pheader->frames[0])); // mod->cache.data = pheader; mod->flags = LittleLong (pinmodel->flags); // // endian-adjust and copy the data, starting with the alias model header // pmodel->boundingradius = LittleFloat (pinmodel->boundingradius); pmodel->numskins = LittleLong (pinmodel->numskins); pmodel->skinwidth = LittleLong (pinmodel->skinwidth); pmodel->skinheight = LittleLong (pinmodel->skinheight); if (pmodel->skinheight > MAX_LBM_HEIGHT) Host_Error ("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); pmodel->numverts = LittleLong (pinmodel->numverts); if (pmodel->numverts <= 0) Host_Error ("model %s has no vertices", mod->name); if (pmodel->numverts > MAXALIASVERTS) Host_Error ("model %s has too many vertices", mod->name); pmodel->numtris = LittleLong (pinmodel->numtris); if (pmodel->numtris <= 0) Host_Error ("model %s has no triangles", mod->name); pmodel->numframes = LittleLong (pinmodel->numframes); pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; mod->synctype = LittleLong (pinmodel->synctype); mod->numframes = pmodel->numframes; for (i=0 ; i<3 ; i++) { pmodel->scale[i] = LittleFloat (pinmodel->scale[i]); pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); } numskins = pmodel->numskins; numframes = pmodel->numframes; if (pmodel->skinwidth & 0x03) Host_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4"); pheader->model = (byte *)pmodel - (byte *)pheader; // // load the skins // skinsize = pmodel->skinheight * pmodel->skinwidth; if (numskins < 1) Host_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); pskintype = (daliasskintype_t *)&pinmodel[1]; pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), loadname); pheader->skindesc = (byte *)pskindesc - (byte *)pheader; for (i=0 ; i<numskins ; i++) { aliasskintype_t skintype; skintype = LittleLong (pskintype->type); pskindesc[i].type = skintype; if (skintype == ALIAS_SKIN_SINGLE) { pskintype = (daliasskintype_t *) Mod_LoadAliasSkin (pskintype + 1, &pskindesc[i].skin, skinsize, pheader); } else { pskintype = (daliasskintype_t *) Mod_LoadAliasSkinGroup (pskintype + 1, &pskindesc[i].skin, skinsize, pheader); } } // // set base s and t vertices // pstverts = (stvert_t *)&pmodel[1]; pinstverts = (stvert_t *)pskintype; pheader->stverts = (byte *)pstverts - (byte *)pheader; for (i=0 ; i<pmodel->numverts ; i++) { pstverts[i].onseam = LittleLong (pinstverts[i].onseam); // put s and t in 16.16 format pstverts[i].s = LittleLong (pinstverts[i].s) << 16; pstverts[i].t = LittleLong (pinstverts[i].t) << 16; } // // set up the triangles // ptri = (mtriangle_t *)&pstverts[pmodel->numverts]; pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts]; pheader->triangles = (byte *)ptri - (byte *)pheader; for (i=0 ; i<pmodel->numtris ; i++) { int j; ptri[i].facesfront = LittleLong (pintriangles[i].facesfront); for (j=0 ; j<3 ; j++) { ptri[i].vertindex[j] = LittleLong (pintriangles[i].vertindex[j]); } } // // load the frames // if (numframes < 1) Host_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris]; for (i=0 ; i<numframes ; i++) { aliasframetype_t frametype; frametype = LittleLong (pframetype->type); pheader->frames[i].type = frametype; if (frametype == ALIAS_SINGLE) { pframetype = (daliasframetype_t *) Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i].frame, pmodel->numverts, &pheader->frames[i].bboxmin, &pheader->frames[i].bboxmax, pheader, pheader->frames[i].name); } else { pframetype = (daliasframetype_t *) Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i].frame, pmodel->numverts, &pheader->frames[i].bboxmin, &pheader->frames[i].bboxmax, pheader, pheader->frames[i].name); } } mod->type = mod_alias; // FIXME: do this right mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; // // move the complete, relocatable alias model to the cache // end = Hunk_LowMark (); total = end - start; Cache_Alloc (&mod->cache, total, loadname); if (!mod->cache.data) return; memcpy (mod->cache.data, pheader, total); Hunk_FreeToLowMark (start); }
/* ================= Mod_LoadTextures ================= */ void Mod_LoadTextures (lump_t *l) { int i, j, num, max, altmax, texture_flag, brighten_flag; miptex_t *mt; texture_t *tx, *tx2, *txblock, *anims[10], *altanims[10]; dmiptexlump_t *m; #ifndef RQM_SV_ONLY byte *data; #endif if (!l->filelen) { loadmodel->textures = NULL; return; } m = (dmiptexlump_t *)(mod_base + l->fileofs); m->nummiptex = LittleLong (m->nummiptex); loadmodel->numtextures = m->nummiptex; loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures), mod_loadname); txblock = Hunk_AllocName (m->nummiptex * sizeof(**loadmodel->textures), mod_loadname); #ifndef RQM_SV_ONLY #ifdef HEXEN2_SUPPORT if (hexen2) brighten_flag = 0; else #endif // brighten_flag = (gl_lightmode.value == 1) ? TEX_BRIGHTEN : 0; brighten_flag = 0; texture_flag = (gl_picmip_all.value || loadmodel->isworldmodel) ? TEX_MIPMAP : 0; #else brighten_flag = texture_flag = 0; #endif for (i = 0 ; i < m->nummiptex ; i++) { m->dataofs[i] = LittleLong (m->dataofs[i]); if (m->dataofs[i] == -1) continue; mt = (miptex_t *)((byte *)m + m->dataofs[i]); loadmodel->textures[i] = tx = txblock + i; memcpy (tx->name, mt->name, sizeof(tx->name)); if (!tx->name[0]) { Q_snprintfz (tx->name, sizeof(tx->name), "unnamed%d", i); Con_DPrintf ("Warning: unnamed texture in %s, renaming to %s\n", loadmodel->name, tx->name); } tx->width = mt->width = LittleLong (mt->width); tx->height = mt->height = LittleLong (mt->height); // if ((mt->width & 15) || (mt->height & 15)) // Host_Error ("Mod_LoadTextures: Texture %s is not 16 aligned", mt->name); // was Sys_Error for (j=0 ; j<MIPLEVELS ; j++) mt->offsets[j] = LittleLong (mt->offsets[j]); // HACK HACK HACK if (!strcmp(mt->name, "shot1sid") && mt->width == 32 && mt->height == 32 && CRC_Block((byte*)(mt+1), mt->width*mt->height) == 65393) { // This texture in b_shell1.bsp has some of the first 32 pixels painted white. // They are invisible in software, but look really ugly in GL. So we just copy // 32 pixels from the bottom to make it look nice. memcpy (mt+1, (byte *)(mt+1) + 32*31, 32); } #ifndef RQM_SV_ONLY if (loadmodel->isworldmodel && ISSKYTEX(tx->name)) { R_InitSky (mt); continue; } if (Mod_LoadBrushModelTexture(tx, texture_flag)) continue; if (mt->offsets[0]) { data = (byte *)mt + mt->offsets[0]; tx2 = tx; } else { data = (byte *)tx2 + tx2->offsets[0]; // JDH: what is tx2 equal to at this point ??? tx2 = r_notexture_mip; } #ifdef _DEBUG // for (j = tx2->width*tx2->height; j >= 0; j--) // if (data[j] == 255) // break; #endif // tx->gl_texturenum = GL_LoadTexture (tx2->name, tx2->width, tx2->height, data, texture_flag | brighten_flag, 1); tx->gl_texturenum = GL_LoadTexture (tx2->name, tx2->width, tx2->height, data, texture_flag | TEX_BMODEL, 1); if (!ISTURBTEX(tx->name) && Img_HasFullbrights(data, tx2->width * tx2->height)) tx->fb_texturenum = GL_LoadTexture (va("@fb_%s", tx2->name), tx2->width, tx2->height, data, texture_flag | TEX_FULLBRIGHT, 1); /************** JDH ***************/ else tx->fb_texturenum = 0; /************** JDH ***************/ #endif } // sequence the animations for (i=0 ; i<m->nummiptex ; i++) { tx = loadmodel->textures[i]; if (!tx || tx->name[0] != '+') continue; if (tx->anim_next) continue; // already sequenced // find the number of frames in the animation memset (anims, 0, sizeof(anims)); memset (altanims, 0, sizeof(altanims)); max = tx->name[1]; altmax = 0; if (max >= 'a' && max <= 'z') max -= 'a' - 'A'; if (max >= '0' && max <= '9') { max -= '0'; altmax = 0; anims[max] = tx; max++; } else if (max >= 'A' && max <= 'J') { altmax = max - 'A'; max = 0; altanims[altmax] = tx; altmax++; } else { Host_Error ("Bad animating texture %s", tx->name); // was Sys_Error } for (j=i+1 ; j<m->nummiptex ; j++) { tx2 = loadmodel->textures[j]; if (!tx2 || tx2->name[0] != '+') continue; if (strcmp(tx2->name+2, tx->name+2)) continue; num = tx2->name[1]; if (num >= 'a' && num <= 'z') num -= 'a' - 'A'; if (num >= '0' && num <= '9') { num -= '0'; anims[num] = tx2; if (num+1 > max) max = num + 1; } else if (num >= 'A' && num <= 'J') { num = num - 'A'; altanims[num] = tx2; if (num+1 > altmax) altmax = num+1; } else { Host_Error ("Bad animating texture %s", tx->name); // was Sys_Error } } #define ANIM_CYCLE 2 // link them all together for (j=0 ; j<max ; j++) { tx2 = anims[j]; if (!tx2) Host_Error ("Mod_LoadTextures: Missing frame %i of %s", j, tx->name); // was Sys_Error tx2->anim_total = max * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = anims[(j+1)%max]; if (altmax) tx2->alternate_anims = altanims[0]; } for (j=0 ; j<altmax ; j++) { tx2 = altanims[j]; if (!tx2) Host_Error ("Mod_LoadTextures: Missing frame %i of %s", j, tx->name); // was Sys_Error tx2->anim_total = altmax * ANIM_CYCLE; tx2->anim_min = j * ANIM_CYCLE; tx2->anim_max = (j+1) * ANIM_CYCLE; tx2->anim_next = altanims[(j+1)%altmax]; if (max) tx2->alternate_anims = anims[0]; } } }
/* ================ SV_SpawnServer Change the server to a new map, taking all connected clients along with it. This is only called from the SV_Map_f() function. ================ */ void SV_SpawnServer (char *mapname, qbool devmap) { char *entitystring; edict_t *ent; int i; extern qbool sv_allow_cheats; extern cvar_t sv_cheats; Com_DPrintf ("SpawnServer: %s\n", mapname); NET_InitServer(); SV_SaveSpawnparms (); svs.spawncount++; // any partially connected client will be restarted sv.state = ss_dead; com_serveractive = false; Cvar_ForceSet (&sv_paused, "0"); Host_ClearMemory(); if (deathmatch.value) Cvar_Set (&coop, "0"); current_skill = (int)(skill.value + 0.5); if (current_skill < 0) current_skill = 0; if (current_skill > 3) current_skill = 3; Cvar_Set (&skill, va("%d", (int)current_skill)); if ((sv_cheats.value || devmap) && !sv_allow_cheats) { sv_allow_cheats = true; Info_SetValueForStarKey (svs.info, "*cheats", "ON", MAX_SERVERINFO_STRING); } else if ((!sv_cheats.value && !devmap) && sv_allow_cheats) { sv_allow_cheats = false; Info_SetValueForStarKey (svs.info, "*cheats", "", MAX_SERVERINFO_STRING); } // wipe the entire per-level structure memset (&sv, 0, sizeof(sv)); SZ_Init (&sv.datagram, sv.datagram_buf, sizeof(sv.datagram_buf)); sv.datagram.allowoverflow = true; SZ_Init (&sv.reliable_datagram, sv.reliable_datagram_buf, sizeof(sv.reliable_datagram_buf)); SZ_Init (&sv.multicast, sv.multicast_buf, sizeof(sv.multicast_buf)); SZ_Init (&sv.signon, sv.signon_buffers[0], sizeof(sv.signon_buffers[0])); sv.num_signon_buffers = 1; // load progs to get entity field count // which determines how big each edict is PR_LoadProgs (); // allocate edicts sv.edicts = (edict_t *) Hunk_AllocName (SV_MAX_EDICTS*pr_edict_size, "edicts"); // leave slots at start for clients only sv.num_edicts = MAX_CLIENTS+1; for (i = 0; i < MAX_CLIENTS; i++) { ent = EDICT_NUM(i+1); svs.clients[i].edict = ent; svs.clients[i].old_frags = 0; //ZOID - make sure we update frags right } sv.time = 1.0; #ifndef SERVERONLY { void R_PreMapLoad (char *mapname); R_PreMapLoad (mapname); } #endif strlcpy (sv.mapname, mapname, sizeof(sv.mapname)); Cvar_ForceSet (&host_mapname, mapname); snprintf (sv.modelname, sizeof(sv.modelname), "maps/%s.bsp", mapname); sv.worldmodel = CM_LoadMap (sv.modelname, false, &sv.map_checksum, &sv.map_checksum2); // clear physics interaction links SV_ClearWorld (); sv.sound_precache[0] = pr_strings; sv.model_precache[0] = pr_strings; sv.model_precache[1] = sv.modelname; sv.models[1] = sv.worldmodel; for (i = 1; i < CM_NumInlineModels(); i++) { sv.model_precache[1+i] = localmodels[i]; sv.models[i + 1] = CM_InlineModel (localmodels[i]); } //check player/eyes models for hacks sv.model_player_checksum = SV_CheckModel("progs/player.mdl"); sv.eyes_player_checksum = SV_CheckModel("progs/eyes.mdl"); // spawn the rest of the entities on the map // precache and static commands can be issued during map initialization sv.state = ss_loading; com_serveractive = true; ent = EDICT_NUM(0); ent->free = false; ent->v.model = PR_SetString(sv.modelname); ent->v.modelindex = 1; // world model ent->v.solid = SOLID_BSP; ent->v.movetype = MOVETYPE_PUSH; pr_global_struct->mapname = PR_SetString(sv.mapname); // serverflags are for cross level information (sigils) pr_global_struct->serverflags = svs.serverflags; // run the frame start qc function to let progs check cvars SV_ProgStartFrame (); // load and spawn all other entities entitystring = NULL; if ((int) sv_loadentfiles.value) { int filesize; entitystring = (char *)FS_LoadHunkFile (va("maps/%s.ent", sv.mapname), &filesize); if (entitystring) { Com_DPrintf ("Using entfile maps/%s.ent\n", sv.mapname); Info_SetValueForStarKey (svs.info, "*entfile", va("%i", CRC_Block((byte *)entitystring, filesize)), MAX_SERVERINFO_STRING); } } if (!entitystring) { Info_SetValueForStarKey (svs.info, "*entfile", "", MAX_SERVERINFO_STRING); entitystring = CM_EntityString(); } ED_LoadFromFile (entitystring); // look up some model indexes for specialized message compression SV_FindModelNumbers (); // all spawning is completed, any further precache statements // or prog writes to the signon message are errors sv.state = ss_active; // run two frames to allow everything to settle SV_Physics (); sv.time += 0.1; SV_Physics (); sv.time += 0.1; sv.old_time = sv.time; // save movement vars SV_SetMoveVars(); // create a baseline for more efficient communications SV_CreateBaseline (); sv.signon_buffer_size[sv.num_signon_buffers - 1] = sv.signon.cursize; Info_SetValueForKey (svs.info, "map", sv.mapname, MAX_SERVERINFO_STRING); Com_DPrintf ("Server spawned.\n"); #ifndef SERVERONLY if (!dedicated) { void CL_ClearState (void); CL_ClearState (); } #endif }