-=*Raz0r*=- Posted November 12, 2011 Share Posted November 12, 2011 There's an infinite loop in Cmd_FollowCycle_f (g_cmds.c) that can easily be used to attack an unpatched server. To reproduce the infinite loop: Join a server (Preferrably FFA?) where there are no in-game players (Spectators are fine) /team follow1 Click to cycle through clients Replace it with this version, also containing this fix void Cmd_FollowCycle_f( gentity_t *ent, int dir ) { int clientnum; int original; qboolean looped = qfalse; // if they are playing a tournement game, count as a loss if ( (g_gametype.integer == GT_DUEL || g_gametype.integer == GT_POWERDUEL) && ent->client->sess.sessionTeam == TEAM_FREE ) {\ //WTF??? ent->client->sess.losses++; } // first set them to spectator if ( ent->client->sess.spectatorState == SPECTATOR_NOT ) { SetTeam( ent, "spectator" ); } if ( dir != 1 && dir != -1 ) { G_Error( "Cmd_FollowCycle_f: bad dir %i", dir ); } clientnum = ent->client->sess.spectatorClient; original = clientnum; do { clientnum += dir; if ( clientnum >= level.maxclients ) { //Raz: Avoid /team follow1 crash if ( looped ) { clientnum = original; break; } else { clientnum = 0; looped = qtrue; } } if ( clientnum < 0 ) { if ( looped ) { clientnum = original; break; } else { clientnum = level.maxclients - 1; looped = qtrue; } } // can only follow connected clients if ( level.clients[ clientnum ].pers.connected != CON_CONNECTED ) { continue; } // can't follow another spectator if ( level.clients[ clientnum ].sess.sessionTeam == TEAM_SPECTATOR ) { continue; } //ensiform's fix // can't follow another spectator if ( level.clients[ clientnum ].tempSpectate >= level.time ) { return; } // this is good, we can use it ent->client->sess.spectatorClient = clientnum; ent->client->sess.spectatorState = SPECTATOR_FOLLOW; return; } while ( clientnum != original ); // leave it where it was } I'm sure the loop could be written more elegantly, but this will suffice. Link to comment Share on other sites More sharing options...
-=*Raz0r*=- Posted November 15, 2011 Share Posted November 15, 2011 Prediction error after spectating somebody who is on an ET_MOVER then switching to roaming mode. Modify the start of CG_AdjustPositionForMover (cg_ents.c) to match: void CG_AdjustPositionForMover( const vec3_t in, int moverNum, int fromTime, int toTime, vec3_t out ) { centity_t *cent; vec3_t oldOrigin, origin, deltaOrigin; vec3_t oldAngles, angles, deltaAngles; if ( cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_SPECTATOR ) {//Don't bother if we're a spectator VectorCopy( in, out ); return; } Link to comment Share on other sites More sharing options...
-=*Raz0r*=- Posted July 2, 2012 Share Posted July 2, 2012 Weird behaviour in UI code causes onOpen {} events to be triggered on the parent item of the item you're closing (via out-of-bounds click) Example: Ingame menu -> click "About" -> Click "Setup" -> the onOpen event of the "ingame" menu would be fired. This is only an issue if you have your own menus that use these events. Personally I'm using transitions in all my menus, which were being triggered at the wrong time. In ui_shared.c -> Menus_HandleOOBClick Comment out "Menus_Activate(&Menus);" in the for loop. for (i = 0; i < menuCount; i++) { if (Menu_OverActiveItem(&Menus[i], DC->cursorx, DC->cursory)) { Menu_RunCloseScript(menu); menu->window.flags &= ~(WINDOW_HASFOCUS | WINDOW_VISIBLE); // Menus_Activate(&Menus[i]); Menu_HandleMouseMove(&Menus[i], DC->cursorx, DC->cursory); Menu_HandleKey(&Menus[i], key, down); } } Link to comment Share on other sites More sharing options...
-=*Raz0r*=- Posted July 2, 2012 Share Posted July 2, 2012 JA's font width calculation is horrible broken, especially when using abnormal (anything but 1.0) scales. The issue is in the engine, RE_Font_StrLenPixels uses integer precision for the return value, causing visible data loss. The way I'm currently working around this is by replacing trap_R_Font_StrLenPixels with: float trap_R_Font_StrLenPixels(const char *text, const int iFontIndex, const float scale) { //Raz: HACK! RE_Font_StrLenPixels only works semi-correctly with 1.0f scale float width = (float)syscall( CG_R_FONT_STRLENPIXELS, text, iFontIndex, PASSFLOAT(1.0f)); return width * scale; } Note I'm using a float return value - you'll have to adjust function prototypes and usage all around the code to use floats for best results. I also use a large custom font to help with scaling. This is not a fix, but it does help tremendously when trying to center-align text in both cgame and ui Theoretically you could replace all text rendering with your own OpenGL code and use the bmfont library. If you wanted to D: Link to comment Share on other sites More sharing options...
ensiform Posted November 1, 2012 Author Share Posted November 1, 2012 There is a bug in jamp.exe where connecting to an invalid hostname or IP whilst ingame will shove you out to a black screen, unable to do anything (including open your console). A very ugly situation. The function in question is CL_Connect_f (0x41D990) The code in question is: //Taken from q3 if (!NET_StringToAdr( cls.servername, &clc.serverAddress) ) { Com_Printf ("Bad server address\n"); cls.state = CA_DISCONNECTED; return; } At the very least, it should be setting your connection state to CA_CONNECTING Ideally, you would rewrite this function to have a different code path if you attempt to connect to a bad hostname or IP whilst ingame. Another solution, is to patch the opcode setting cls.state to CA_DISCONNECTED You will have to unlock the code page with VirtualProtect or mprotect I suggest writing a wrapper. UnlockMemory( 0x41DACB, 1 ); *(unsigned char *)0x41DACB = (unsigned char)0x03; LockMemory( 0x41DACB, 1 ); At the moment this fix is only for Windows, but it is possible to fix on Mac with the right addresses. With this fix, you will be sent to the "Connecting to someinvalidhostname...1" screen and things will carry on as normal. Not ideal, but it works. This fix is actually wrong. The problem is raven fail coding in the UI: (Main menu is never actually loaded because you were in the server last which will tell UI_Init to be (qtrue) on ingameload so it will only load ingame related menus. (This is fine however) When it goes to try to revert back to main menu with setactivemenu UIMENU_MAIN: if (uiInfo.inGameLoad) { // UI_LoadNonIngame(); } because of this, it fails to actually "activate" main. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.