From: lordhavoc Date: Tue, 19 Feb 2002 10:56:54 +0000 (+0000) Subject: added viewzoom extension to QC and client (smooth sniper zooming, with sensitivity... X-Git-Tag: RELEASE_0_2_0_RC1~634 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=c65b6faa99d227bcd00107311acfb66a95be02c6;p=xonotic%2Fdarkplaces.git added viewzoom extension to QC and client (smooth sniper zooming, with sensitivity scaling) protocol should be able to masq now (not a perfect fix like net_chan, but a fix for most people - I hope) - server waits to send serverinfo until first reply from client (any clc_ message will do), client spams clc_nop every 3 seconds until it gets serverinfo (FIXME: maybe only once would do?) upgraded aiming angles sent from client to floats in DPPROTOCOL_VERSION2 mode updated cl_shownet 2 svc name list in cl_parse.c (it was quite outdated) git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@1539 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/cl_input.c b/cl_input.c index 11975ce4..0943007d 100644 --- a/cl_input.c +++ b/cl_input.c @@ -372,7 +372,7 @@ void CL_SendMove (usercmd_t *cmd) buf.maxsize = 128; buf.cursize = 0; buf.data = data; - + cl.cmd = *cmd; // @@ -382,7 +382,12 @@ void CL_SendMove (usercmd_t *cmd) MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times - if (dpprotocol) + if (dpprotocol == DPPROTOCOL_VERSION2) + { + for (i = 0;i < 3;i++) + MSG_WriteFloat (&buf, cl.viewangles[i]); + } + else if (dpprotocol == DPPROTOCOL_VERSION1) { for (i=0 ; i<3 ; i++) MSG_WritePreciseAngle (&buf, cl.viewangles[i]); diff --git a/cl_main.c b/cl_main.c index 8eab4358..122111e2 100644 --- a/cl_main.c +++ b/cl_main.c @@ -226,6 +226,13 @@ Host should be either "local" or a net address to be passed on */ void CL_EstablishConnection (char *host) { + sizebuf_t buf; + byte data[128]; + + buf.maxsize = 128; + buf.cursize = 0; + buf.data = data; + if (cls.state == ca_dedicated) return; @@ -242,6 +249,8 @@ void CL_EstablishConnection (char *host) cls.demonum = -1; // not in the demo loop now cls.state = ca_connected; cls.signon = 0; // need all the signon messages before playing + + CL_ClearState (); } /* @@ -626,8 +635,11 @@ static void CL_RelinkNetworkEntities() } } -void CL_LerpPlayerEye(float frac) +void CL_LerpPlayer(float frac) { + int i; + float d; + if (cl.entitydatabase.numframes) { cl.viewentorigin[0] = cl.viewentoriginold[0] + frac * (cl.viewentoriginnew[0] - cl.viewentoriginold[0]); @@ -636,12 +648,8 @@ void CL_LerpPlayerEye(float frac) } else VectorCopy (cl_entities[cl.viewentity].render.origin, cl.viewentorigin); -} -static void CL_LerpPlayerVelocity (float frac) -{ - int i; - float d; + cl.viewzoom = cl.viewzoomold + frac * (cl.viewzoomnew - cl.viewzoomold); for (i = 0;i < 3;i++) cl.velocity[i] = cl.mvelocity[1][i] + frac * (cl.mvelocity[0][i] - cl.mvelocity[1][i]); @@ -751,8 +759,7 @@ void CL_RelinkEntities (void) CL_MoveParticles(); CL_UpdateTEnts(); - CL_LerpPlayerEye(frac); - CL_LerpPlayerVelocity(frac); + CL_LerpPlayer(frac); } @@ -829,6 +836,19 @@ void CL_SendCmd (void) // send the unreliable message CL_SendMove (&cmd); } + else + { + // LordHavoc: fix for NAT routing of netquake: + // bounce back a clc_nop message to the newly allocated server port, + // to establish a routing connection for incoming frames, + // the server waits for this before sending anything + if (realtime > cl.sendnoptime) + { + Con_DPrintf("sending clc_nop to get server's attention\n"); + cl.sendnoptime = realtime + 3; + MSG_WriteByte(&cls.message, clc_nop); + } + } if (cls.demoplayback) { diff --git a/cl_parse.c b/cl_parse.c index aac1a732..a76646ae 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -52,7 +52,7 @@ char *svc_strings[128] = "svc_spawnstatic", "OBSOLETE svc_spawnbinary", "svc_spawnbaseline", - + "svc_temp_entity", // "svc_setpause", "svc_signonnum", @@ -80,10 +80,16 @@ char *svc_strings[128] = "", // 47 "", // 48 "", // 49 - "", // 50 - "svc_fog", // 51 - "svc_effect", // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate - "svc_effect2", // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate + "svc_cgame", // 50 // [short] length [bytes] data + "svc_fog", // 51 // unfinished and obsolete + "svc_effect", // 52 // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate + "svc_effect2", // 53 // [vector] org [short] modelindex [short] startframe [byte] framecount [byte] framerate + "svc_sound2", // 54 // short soundindex instead of byte + "svc_spawnbaseline2", // 55 // short modelindex instead of byte + "svc_spawnstatic2", // 56 // short modelindex instead of byte + "svc_entities", // 57 // [int] deltaframe [int] thisframe [float vector] eye [variable length] entitydata + "svc_unusedlh3", // 58 + "svc_spawnstaticsound2", // 59 // [coord3] [short] samp [byte] vol [byte] aten }; //============================================================================= @@ -804,7 +810,7 @@ void CL_ParseClientdata (int bits) cl.idealpitch = MSG_ReadChar (); else cl.idealpitch = 0; - + VectorCopy (cl.mvelocity[0], cl.mvelocity[1]); for (i=0 ; i<3 ; i++) { @@ -835,7 +841,7 @@ void CL_ParseClientdata (int bits) cl.item_gettime[j] = cl.time; cl.items = i; } - + cl.onground = (bits & SU_ONGROUND) != 0; cl.inwater = (bits & SU_INWATER) != 0; @@ -856,6 +862,18 @@ void CL_ParseClientdata (int bits) cl.stats[STAT_ACTIVEWEAPON] = (1<= cl.maxclients) - Host_Error ("CL_ParseServerMessage: svc_updatename >= MAX_SCOREBOARD"); + Host_Error ("CL_ParseServerMessage: svc_updatename >= cl.maxclients"); strcpy (cl.scores[i].name, MSG_ReadString ()); break; case svc_updatefrags: i = MSG_ReadByte (); if (i >= cl.maxclients) - Host_Error ("CL_ParseServerMessage: svc_updatefrags >= MAX_SCOREBOARD"); + Host_Error ("CL_ParseServerMessage: svc_updatefrags >= cl.maxclients"); cl.scores[i].frags = MSG_ReadShort (); break; case svc_updatecolors: i = MSG_ReadByte (); if (i >= cl.maxclients) - Host_Error ("CL_ParseServerMessage: svc_updatecolors >= MAX_SCOREBOARD"); + Host_Error ("CL_ParseServerMessage: svc_updatecolors >= cl.maxclients"); cl.scores[i].colors = MSG_ReadByte (); break; diff --git a/cl_screen.c b/cl_screen.c index 0586a676..8f2f269d 100644 --- a/cl_screen.c +++ b/cl_screen.c @@ -736,7 +736,8 @@ static void SCR_CalcRefdef (void) r_refdef.x = bound(0, r_refdef.x, vid.realwidth - r_refdef.width) + vid.realx; r_refdef.y = bound(0, r_refdef.y, vid.realheight - r_refdef.height) + vid.realy; - r_refdef.fov_x = scr_fov.value; + // LordHavoc: viewzoom (zoom in for sniper rifles, etc) + r_refdef.fov_x = scr_fov.value * cl.viewzoom; r_refdef.fov_y = CalcFov (r_refdef.fov_x, r_refdef.width, r_refdef.height); if (cl.worldmodel) diff --git a/client.h b/client.h index afc49452..3513a3f7 100644 --- a/client.h +++ b/client.h @@ -198,6 +198,7 @@ typedef struct // throw out the first couple, so the player // doesn't accidentally do something the // first frame + float sendnoptime; // send a clc_nop periodically until connected usercmd_t cmd; // last command sent to the server // information for local display @@ -276,6 +277,8 @@ typedef struct scoreboard_t *scores; // [cl.maxclients] vec3_t viewentorigin; + float viewzoom; // LordHavoc: sniping zoom, QC controlled + float viewzoomold, viewzoomnew; // for interpolation // entity database stuff vec3_t viewentoriginold, viewentoriginnew; diff --git a/in_svgalib.c b/in_svgalib.c index 971d497f..c84c6d65 100644 --- a/in_svgalib.c +++ b/in_svgalib.c @@ -353,8 +353,9 @@ void IN_Move(usercmd_t *cmd) /* Clear for next update */ mx = my = 0; - mouse_x *= sensitivity.value; - mouse_y *= sensitivity.value; + // LordHavoc: viewzoom affects mouse sensitivity for sniping + mouse_x *= sensitivity.value * cl.viewzoom; + mouse_y *= sensitivity.value * cl.viewzoom; /* Add mouse X/Y movement to cmd */ if ( (in_strafe.state & 1) || (lookstrafe.integer && mouselook)) diff --git a/in_win.c b/in_win.c index c6ce7aaa..4d5ddbe9 100644 --- a/in_win.c +++ b/in_win.c @@ -650,8 +650,9 @@ void IN_MouseMove (usercmd_t *cmd) old_mouse_x = mx; old_mouse_y = my; - mouse_x *= sensitivity.value; - mouse_y *= sensitivity.value; + // LordHavoc: viewzoom affects mouse sensitivity for sniping + mouse_x *= sensitivity.value * cl.viewzoom; + mouse_y *= sensitivity.value * cl.viewzoom; // add mouse X/Y movement to cmd if ( (in_strafe.state & 1) || (lookstrafe.integer && mouselook)) @@ -1050,7 +1051,8 @@ void IN_JoyMove (usercmd_t *cmd) speed = cl_movespeedkey.value; else speed = 1; - aspeed = speed * host_realframetime; + // LordHavoc: viewzoom affects sensitivity for sniping + aspeed = speed * host_realframetime * cl.viewzoom; // loop through the axes for (i = 0; i < JOY_MAX_AXES; i++) diff --git a/net_dgrm.c b/net_dgrm.c index 513c2561..dd4ed8a0 100644 --- a/net_dgrm.c +++ b/net_dgrm.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -55,6 +55,8 @@ unsigned long inet_addr(const char *cp); #include "quakedef.h" #include "net_dgrm.h" +cvar_t cl_port = {CVAR_SAVE, "cl_port", "0"}; + // these two macros are to make the code more readable #define sfunc net_landrivers[sock->landriver] #define dfunc net_landrivers[net_landriverlevel] @@ -767,6 +769,7 @@ int Datagram_Init (void) myDriverLevel = net_driverlevel; Cmd_AddCommand ("net_stats", NET_Stats_f); + Cvar_RegisterVariable (&cl_port); if (COM_CheckParm("-nolan")) return -1; @@ -887,7 +890,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void) int activeNumber; int clientNumber; client_t *client; - + playerNumber = MSG_ReadByte(); activeNumber = -1; for (clientNumber = 0, client = svs.clients; clientNumber < svs.maxclients; clientNumber++, client++) @@ -1064,7 +1067,7 @@ static qsocket_t *_Datagram_CheckNewConnections (void) return NULL; } - // everything is allocated, just fill in the details + // everything is allocated, just fill in the details sock->socket = newsock; sock->landriver = net_landriverlevel; sock->addr = clientaddr; @@ -1224,7 +1227,7 @@ static qsocket_t *_Datagram_Connect (char *host) if (dfunc.GetAddrFromName(host, &sendaddr) == -1) return NULL; - newsock = dfunc.OpenSocket (0); + newsock = dfunc.OpenSocket (cl_port.integer); if (newsock == -1) return NULL; @@ -1347,7 +1350,7 @@ static qsocket_t *_Datagram_Connect (char *host) dfunc.GetNameFromAddr (&sendaddr, sock->address); - Con_Printf ("Connection accepted\n"); + Con_Printf ("Connection accepted to %s\n", sock->address); sock->lastMessageTime = SetNetTime(); // switch the connection to the specified address diff --git a/net_loop.c b/net_loop.c index 133766aa..1ad3fee9 100644 --- a/net_loop.c +++ b/net_loop.c @@ -195,7 +195,8 @@ int Loop_SendUnreliableMessage (qsocket_t *sock, sizebuf_t *data) bufferLength = &((qsocket_t *)sock->driverdata)->receiveMessageLength; - if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short)) > NET_MAXMESSAGE) + // LordHavoc: added an extra sizeof(byte) to account for alignment + if ((*bufferLength + data->cursize + sizeof(byte) + sizeof(short) + sizeof(byte)) > NET_MAXMESSAGE) return 0; buffer = ((qsocket_t *)sock->driverdata)->receiveMessage + *bufferLength; diff --git a/pr_edict.c b/pr_edict.c index dc4166ad..6d14b12f 100644 --- a/pr_edict.c +++ b/pr_edict.c @@ -116,6 +116,7 @@ int eval_ping; int eval_movement; int eval_pmodel; int eval_punchvector; +int eval_viewzoom; dfunction_t *SV_PlayerPhysicsQC; dfunction_t *EndFrameQC; @@ -164,6 +165,7 @@ void FindEdictFieldOffsets(void) eval_movement = FindFieldOffset("movement"); eval_pmodel = FindFieldOffset("pmodel"); eval_punchvector = FindFieldOffset("punchvector"); + eval_viewzoom = FindFieldOffset("viewzoom"); // LordHavoc: allowing QuakeC to override the player movement code SV_PlayerPhysicsQC = ED_FindFunction ("SV_PlayerPhysics"); diff --git a/progs.h b/progs.h index bf960584..289f4214 100644 --- a/progs.h +++ b/progs.h @@ -89,6 +89,7 @@ extern int eval_ping; extern int eval_movement; extern int eval_pmodel; extern int eval_punchvector; +extern int eval_viewzoom; #define GETEDICTFIELDVALUE(ed, fieldoffset) (fieldoffset ? (eval_t*)((char*)&ed->v + fieldoffset) : NULL) diff --git a/protocol.h b/protocol.h index f07830f9..ad839c2b 100644 --- a/protocol.h +++ b/protocol.h @@ -111,7 +111,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define SU_PUNCHVEC1 (1<<16) #define SU_PUNCHVEC2 (1<<17) #define SU_PUNCHVEC3 (1<<18) -#define SU_UNUSED19 (1<<19) +#define SU_VIEWZOOM (1<<19) // byte factor (0 = 0.0 (not valid), 255 = 1.0) #define SU_UNUSED20 (1<<20) #define SU_UNUSED21 (1<<21) #define SU_UNUSED22 (1<<22) diff --git a/server.h b/server.h index 273b3de9..175cd41f 100644 --- a/server.h +++ b/server.h @@ -81,6 +81,10 @@ typedef struct client_s qboolean dropasap; // has been told to go to another level qboolean sendsignon; // only valid before spawned + // LordHavoc: to make netquake protocol get through NAT routers, have to wait for client to ack + qboolean waitingforconnect; // waiting for connect from client (stage 1) + qboolean sendserverinfo; // send server info in next datagram (stage 2) + double last_message; // reliable messages must be sent // periodically diff --git a/sv_main.c b/sv_main.c index 1ea395fa..ba3d483b 100644 --- a/sv_main.c +++ b/sv_main.c @@ -333,7 +333,10 @@ void SV_ConnectClient (int clientnum) client->spawn_parms[i] = (&pr_global_struct->parm1)[i]; } - SV_SendServerinfo (client); + // send serverinfo on first nop + client->waitingforconnect = true; + client->sendsignon = true; + client->spawned = false; // need prespawn, spawn, etc } @@ -1144,6 +1147,7 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) int items; eval_t *val; vec3_t punchvector; + byte viewzoom; // // send a damage message @@ -1205,6 +1209,20 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) if ((val = GETEDICTFIELDVALUE(ent, eval_punchvector))) VectorCopy(val->vector, punchvector); + i = 255; + if ((val = GETEDICTFIELDVALUE(ent, eval_viewzoom))) + { + i = val->_float * 255.0f; + if (i == 0) + i = 255; + else + i = bound(0, i, 255); + } + viewzoom = i; + + if (viewzoom != 255) + bits |= SU_VIEWZOOM; + for (i=0 ; i<3 ; i++) { if (ent->v.punchangle[i]) @@ -1287,6 +1305,9 @@ void SV_WriteClientdataToMessage (edict_t *ent, sizebuf_t *msg) { MSG_WriteByte (msg, ent->v.weapon); } + + if (bits & SU_VIEWZOOM) + MSG_WriteByte (msg, viewzoom); } /* @@ -1306,14 +1327,17 @@ qboolean SV_SendClientDatagram (client_t *client) MSG_WriteByte (&msg, svc_time); MSG_WriteFloat (&msg, sv.time); -// add the client specific data to the datagram - SV_WriteClientdataToMessage (client->edict, &msg); + if (!client->waitingforconnect) + { + // add the client specific data to the datagram + SV_WriteClientdataToMessage (client->edict, &msg); - SV_WriteEntitiesToClient (client, client->edict, &msg); + SV_WriteEntitiesToClient (client, client->edict, &msg); -// copy the server datagram if there is space - if (msg.cursize + sv.datagram.cursize < msg.maxsize) - SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize); + // copy the server datagram if there is space + if (msg.cursize + sv.datagram.cursize < msg.maxsize) + SZ_Write (&msg, sv.datagram.data, sv.datagram.cursize); + } // send the datagram if (NET_SendUnreliableMessage (client->netconnection, &msg) == -1) @@ -1342,7 +1366,7 @@ void SV_UpdateToReliableMessages (void) { for (j=0, client = svs.clients ; jactive) + if (!client->active || !client->spawned) continue; MSG_WriteByte (&client->message, svc_updatefrags); MSG_WriteByte (&client->message, i); @@ -1406,6 +1430,12 @@ void SV_SendClientMessages (void) if (!host_client->active) continue; + if (host_client->sendserverinfo) + { + host_client->sendserverinfo = false; + SV_SendServerinfo (host_client); + } + if (host_client->spawned) { if (!SV_SendClientDatagram (host_client)) diff --git a/sv_user.c b/sv_user.c index 1fc07731..27c8ec9f 100644 --- a/sv_user.c +++ b/sv_user.c @@ -447,7 +447,7 @@ void SV_ClientThink (void) return; } - SV_AirMove (); + SV_AirMove (); } @@ -463,7 +463,7 @@ void SV_ReadClientMove (usercmd_t *move) int bits; eval_t *val; float total; - + // read ping time host_client->ping_times[host_client->num_pings % NUM_PING_TIMES] = sv.time - MSG_ReadFloat (); host_client->num_pings++; @@ -477,12 +477,12 @@ void SV_ReadClientMove (usercmd_t *move) val->_float = host_client->ping * 1000.0; // read current angles - // dpprotocol - for (i=0 ; i<3 ; i++) - angle[i] = MSG_ReadPreciseAngle (); + // dpprotocol version 2 + for (i = 0;i < 3;i++) + angle[i] = MSG_ReadFloat (); VectorCopy (angle, host_client->edict->v.v_angle); - + // read movement move->forwardmove = MSG_ReadShort (); move->sidemove = MSG_ReadShort (); @@ -493,7 +493,7 @@ void SV_ReadClientMove (usercmd_t *move) val->vector[1] = move->sidemove; val->vector[2] = move->upmove; } - + // read buttons bits = MSG_ReadByte (); host_client->edict->v.button0 = bits & 1; @@ -518,6 +518,7 @@ SV_ReadClientMessage Returns false if the client should be killed =================== */ +void SV_SendServerinfo (client_t *client); qboolean SV_ReadClientMessage (void) { int ret; @@ -547,24 +548,30 @@ nextmsg: { Sys_Printf ("SV_ReadClientMessage: badread\n"); return false; - } - + } + cmd = MSG_ReadChar (); - + + if (cmd != -1 && host_client->waitingforconnect) + { + host_client->waitingforconnect = false; + host_client->sendserverinfo = true; + } + switch (cmd) { case -1: goto nextmsg; // end of message - + default: Sys_Printf ("SV_ReadClientMessage: unknown command char %i\n", cmd); return false; - + case clc_nop: // Sys_Printf ("clc_nop\n"); break; - - case clc_stringcmd: + + case clc_stringcmd: s = MSG_ReadString (); ret = 0; if (Q_strncasecmp(s, "status", 6) == 0 diff --git a/vid_glx.c b/vid_glx.c index 3fc5efb1..8124ed71 100644 --- a/vid_glx.c +++ b/vid_glx.c @@ -849,8 +849,9 @@ void IN_MouseMove (usercmd_t *cmd) old_mouse_y = mouse_y; } - mouse_x *= sensitivity.value; - mouse_y *= sensitivity.value; + // LordHavoc: viewzoom affects mouse sensitivity for sniping + mouse_x *= sensitivity.value * cl.viewzoom; + mouse_y *= sensitivity.value * cl.viewzoom; if (in_strafe.state & 1) cmd->sidemove += m_side.value * mouse_x;