mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 05:11:35 +00:00
Reworked networking a little, separating out common code for separate server/master processes.
Reworked glsl bones, so they work based upon the shader's version instead of the driver's version (more robust). Fix te_teleport shader. Track angles for antilag. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5372 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
18280be6e9
commit
c6ed692871
56 changed files with 2026 additions and 964 deletions
|
@ -990,7 +990,7 @@ qboolean CL_GetMessage (void)
|
|||
if (cls.demoplayback != DPB_NONE)
|
||||
return CL_GetDemoMessage ();
|
||||
|
||||
if (NET_GetPacket (NS_CLIENT, 0) < 0)
|
||||
if (NET_GetPacket (cls.sockets, 0) < 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
|
|
@ -301,11 +301,6 @@ qbyte *host_basepal;
|
|||
qbyte *h2playertranslations;
|
||||
|
||||
cvar_t host_speeds = CVAR("host_speeds","0"); // set for running times
|
||||
#ifdef CRAZYDEBUGGING
|
||||
cvar_t developer = CVAR("developer","1");
|
||||
#else
|
||||
cvar_t developer = CVAR("developer","0");
|
||||
#endif
|
||||
|
||||
int fps_count;
|
||||
qboolean forcesaveprompt;
|
||||
|
@ -455,7 +450,7 @@ void CL_ConnectToDarkPlaces(char *challenge, netadr_t *adr)
|
|||
|
||||
Q_snprintfz(data, sizeof(data), "%c%c%c%cconnect\\protocol\\darkplaces 3\\protocols\\DP7 DP6 DP5 RMQ FITZ NEHAHRABJP2 NEHAHRABJP NEHAHRABJP3 QUAKE\\challenge\\%s\\name\\%s", 255, 255, 255, 255, challenge, name.string);
|
||||
|
||||
NET_SendPacket (NS_CLIENT, strlen(data), data, adr);
|
||||
NET_SendPacket (cls.sockets, strlen(data), data, adr);
|
||||
|
||||
cl.splitclients = 0;
|
||||
}
|
||||
|
@ -724,7 +719,7 @@ void CL_SendConnectPacket (netadr_t *to, int mtu,
|
|||
if (info)
|
||||
Q_strncatz(data, va("0x%x \"%s\"\n", PROTOCOL_INFO_GUID, info), sizeof(data));
|
||||
|
||||
NET_SendPacket (NS_CLIENT, strlen(data), data, to);
|
||||
NET_SendPacket (cls.sockets, strlen(data), data, to);
|
||||
}
|
||||
|
||||
char *CL_TryingToConnect(void)
|
||||
|
@ -752,7 +747,7 @@ void CL_CheckForResend (void)
|
|||
char *host;
|
||||
extern int r_blockvidrestart;
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
if (!cls.state && (!connectinfo.trying || sv.state != ss_clustermode) && sv.state)
|
||||
{
|
||||
const char *lbp;
|
||||
|
@ -951,7 +946,7 @@ void CL_CheckForResend (void)
|
|||
NET_AdrToString(data, sizeof(data), &connectinfo.adr);
|
||||
|
||||
/*eat up the server's packets, to clear any lingering loopback packets (like disconnect commands... yes this might cause packetloss for other clients)*/
|
||||
while(NET_GetPacket (NS_SERVER, 0) >= 0)
|
||||
while(NET_GetPacket (svs.sockets, 0) >= 0)
|
||||
{
|
||||
}
|
||||
net_message.packing = SZ_RAWBYTES;
|
||||
|
@ -1119,7 +1114,7 @@ void CL_CheckForResend (void)
|
|||
if (contype & 1)
|
||||
{
|
||||
Q_snprintfz (data, sizeof(data), "%c%c%c%cgetchallenge\n", 255, 255, 255, 255);
|
||||
switch(NET_SendPacket (NS_CLIENT, strlen(data), data, &connectinfo.adr))
|
||||
switch(NET_SendPacket (cls.sockets, strlen(data), data, &connectinfo.adr))
|
||||
{
|
||||
case NETERR_CLOGGED: //temporary failure
|
||||
case NETERR_SENT: //yay, works!
|
||||
|
@ -1159,7 +1154,7 @@ void CL_CheckForResend (void)
|
|||
MSG_WriteString(&sb, "getchallenge");
|
||||
|
||||
*(int*)sb.data = LongSwap(NETFLAG_CTL | sb.cursize);
|
||||
switch(NET_SendPacket (NS_CLIENT, sb.cursize, sb.data, &connectinfo.adr))
|
||||
switch(NET_SendPacket (cls.sockets, sb.cursize, sb.data, &connectinfo.adr))
|
||||
{
|
||||
case NETERR_CLOGGED: //temporary failure
|
||||
case NETERR_SENT: //yay, works!
|
||||
|
@ -1540,7 +1535,7 @@ void CL_Rcon_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
NET_SendPacket (NS_CLIENT, strlen(message)+1, message, &to);
|
||||
NET_SendPacket (cls.sockets, strlen(message)+1, message, &to);
|
||||
}
|
||||
|
||||
void CL_BlendFog(fogstate_t *result, fogstate_t *oldf, float time, fogstate_t *newf)
|
||||
|
@ -2659,7 +2654,7 @@ void CL_Packet_f (void)
|
|||
}
|
||||
*out = 0;
|
||||
|
||||
NET_SendPacket (NS_CLIENT, out-send, send, &adr);
|
||||
NET_SendPacket (cls.sockets, out-send, send, &adr);
|
||||
|
||||
if (Cmd_FromGamecode())
|
||||
{
|
||||
|
@ -2905,7 +2900,7 @@ void CL_ConnectionlessPacket (void)
|
|||
Q_snprintfz(data+6, sizeof(data)-6, "%i %i", atoi(MSG_ReadString()), cls.realip_ident);
|
||||
len = strlen(data);
|
||||
|
||||
NET_SendPacket (NS_CLIENT, len, &data, &net_from);
|
||||
NET_SendPacket (cls.sockets, len, &data, &net_from);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2954,7 +2949,7 @@ void CL_ConnectionlessPacket (void)
|
|||
{
|
||||
connectinfo.istransfer = true;
|
||||
connectinfo.adr = adr;
|
||||
NET_SendPacket (NS_CLIENT, strlen(data), data, &adr);
|
||||
NET_SendPacket (cls.sockets, strlen(data), data, &adr);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -3205,7 +3200,7 @@ void CL_ConnectionlessPacket (void)
|
|||
|
||||
//server says it can do tls.
|
||||
char *pkt = va("%c%c%c%cdtlsconnect %i", 255, 255, 255, 255, connectinfo.challenge);
|
||||
NET_SendPacket (NS_CLIENT, strlen(pkt), pkt, &net_from);
|
||||
NET_SendPacket (cls.sockets, strlen(pkt), pkt, &net_from);
|
||||
return;
|
||||
}
|
||||
if (connectinfo.dtlsupgrade == DTLS_REQUIRE)
|
||||
|
@ -3730,7 +3725,7 @@ void CL_ReadPackets (void)
|
|||
|
||||
if (cls.state == ca_disconnected)
|
||||
{ //connect to nq servers, but don't get confused with sequenced packets.
|
||||
if (NET_WasSpecialPacket(NS_CLIENT))
|
||||
if (NET_WasSpecialPacket(cls.sockets))
|
||||
continue;
|
||||
#ifdef NQPROT
|
||||
CLNQ_ConnectionlessPacket ();
|
||||
|
@ -3744,7 +3739,7 @@ void CL_ReadPackets (void)
|
|||
if (!cls.demoplayback &&
|
||||
!NET_CompareAdr (&net_from, &cls.netchan.remote_address))
|
||||
{
|
||||
if (NET_WasSpecialPacket(NS_CLIENT))
|
||||
if (NET_WasSpecialPacket(cls.sockets))
|
||||
continue;
|
||||
Con_DPrintf ("%s:sequenced packet from wrong server\n"
|
||||
,NET_AdrToString(adr, sizeof(adr), &net_from));
|
||||
|
@ -4188,7 +4183,7 @@ void CL_FTP_f(void)
|
|||
void CL_Fog_f(void)
|
||||
{
|
||||
int ftype = Q_strcasecmp(Cmd_Argv(0), "fog");
|
||||
if ((cl.fog_locked && !Cmd_FromGamecode()) || Cmd_Argc() <= 1)
|
||||
if ((cl.fog_locked && !Cmd_FromGamecode() && !cls.allow_cheats) || Cmd_Argc() <= 1)
|
||||
{
|
||||
if (Cmd_ExecLevel != RESTRICT_INSECURE)
|
||||
Con_Printf("Current fog %f (r:%f g:%f b:%f, a:%f bias:%f)\n", cl.fog[ftype].density, cl.fog[ftype].colour[0], cl.fog[ftype].colour[1], cl.fog[ftype].colour[2], cl.fog[ftype].alpha, cl.fog[ftype].depthbias);
|
||||
|
@ -4420,7 +4415,6 @@ void CL_Init (void)
|
|||
CSQC_RegisterCvarsAndThings();
|
||||
#endif
|
||||
Cvar_Register (&host_speeds, cl_controlgroup);
|
||||
Cvar_Register (&developer, cl_controlgroup);
|
||||
|
||||
Cvar_Register (&cfg_save_name, cl_controlgroup);
|
||||
|
||||
|
@ -5307,7 +5301,9 @@ done:
|
|||
// if (f->flags & HRF_DOWNLOADED)
|
||||
man->blockupdate = true;
|
||||
BZ_Free(fdata);
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
FS_ChangeGame(man, true, true);
|
||||
}
|
||||
else
|
||||
|
@ -6359,7 +6355,9 @@ Host_Init
|
|||
*/
|
||||
void Host_Init (quakeparms_t *parms)
|
||||
{
|
||||
#ifdef PACKAGEMANAGER
|
||||
char engineupdated[MAX_OSPATH];
|
||||
#endif
|
||||
int man;
|
||||
|
||||
com_parseutf8.ival = 1; //enable utf8 parsing even before cvars are registered.
|
||||
|
@ -6385,6 +6383,7 @@ void Host_Init (quakeparms_t *parms)
|
|||
Cmd_Init ();
|
||||
COM_Init ();
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
//we have enough of the filesystem inited now that we can read the package list and figure out which engine was last installed.
|
||||
if (PM_FindUpdatedEngine(engineupdated, sizeof(engineupdated)))
|
||||
{
|
||||
|
@ -6402,6 +6401,8 @@ void Host_Init (quakeparms_t *parms)
|
|||
}
|
||||
PM_Shutdown(); //will restart later as needed, but we need to be sure that no files are open or anything.
|
||||
}
|
||||
#endif
|
||||
|
||||
V_Init ();
|
||||
NET_Init ();
|
||||
|
||||
|
@ -6548,7 +6549,9 @@ void Host_Shutdown(void)
|
|||
Validation_FlushFileList();
|
||||
|
||||
Cmd_Shutdown();
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
Key_Unbindall_f();
|
||||
|
||||
#ifdef PLUGINS
|
||||
|
|
|
@ -17,7 +17,7 @@ enum masterprotocol_e
|
|||
MP_DPMASTER
|
||||
};
|
||||
|
||||
#if defined(CL_MASTER) && !defined(SERVERONLY)
|
||||
#if defined(CL_MASTER) && defined(HAVE_CLIENT)
|
||||
#define SS_PROTOCOLMASK 0xf
|
||||
#define SS_UNKNOWN 0
|
||||
#define SS_QUAKEWORLD 1
|
||||
|
@ -134,7 +134,10 @@ typedef struct serverinfo_s
|
|||
qbyte players;
|
||||
qbyte maxplayers;
|
||||
qbyte sends;
|
||||
qbyte status; //1=alive, 2=displayed
|
||||
qbyte status;
|
||||
#define SRVSTATUS_ALIVE 1u //server is responding to pings
|
||||
#define SRVSTATUS_DISPLAYED 2u //server passed all filters
|
||||
#define SRVSTATUS_GLOBAL 4u //server was reported by one of the master servers (ie: global and not local)
|
||||
|
||||
qbyte numspectators;
|
||||
qbyte numhumans;
|
||||
|
@ -247,8 +250,6 @@ serverinfo_t *Master_SortedServer(int idx);
|
|||
void Master_SetMaskString(qboolean or_, hostcachekey_t field, const char *param, slist_test_t testop);
|
||||
void Master_SetMaskInteger(qboolean or_, hostcachekey_t field, int param, slist_test_t testop);
|
||||
serverinfo_t *Master_FindRoute(netadr_t target);
|
||||
#else
|
||||
#define MasterInfo_WriteServers()
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -541,7 +541,6 @@ typedef struct
|
|||
#ifdef NQPROT
|
||||
int signon;
|
||||
#endif
|
||||
int language;
|
||||
|
||||
colourised_t *colourised;
|
||||
qboolean nqexpectingstatusresponse;
|
||||
|
|
|
@ -1028,7 +1028,7 @@ void CLQ3_SendAuthPacket(netadr_t *gameserver)
|
|||
}
|
||||
MSG_WriteByte(&msg, 0);
|
||||
|
||||
NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, &authaddr);
|
||||
NET_SendPacket (cls.sockets, msg.cursize, msg.data, &authaddr);
|
||||
}
|
||||
else
|
||||
Con_Printf(" failed\n");
|
||||
|
@ -1062,7 +1062,7 @@ void CLQ3_SendConnectPacket(netadr_t *to, int challenge, int qport)
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
NET_SendPacket (NS_CLIENT, msg.cursize, msg.data, to);
|
||||
NET_SendPacket (cls.sockets, msg.cursize, msg.data, to);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1061,7 +1061,7 @@ Handles cursor positioning, line wrapping, etc
|
|||
================
|
||||
*/
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
extern redirect_t sv_redirected;
|
||||
extern char sv_redirected_buf[8000];
|
||||
void SV_FlushRedirect (void);
|
||||
|
@ -1103,7 +1103,7 @@ void VARGS Con_Printf (const char *fmt, ...)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
|
@ -1147,7 +1147,7 @@ void VARGS Con_TPrintf (translation_t text, ...)
|
|||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
const char *fmt = langtext(text, cls.language);
|
||||
const char *fmt = langtext(text, com_language);
|
||||
|
||||
va_start (argptr,text);
|
||||
vsnprintf (msg,sizeof(msg), fmt,argptr);
|
||||
|
@ -1161,7 +1161,7 @@ void VARGS Con_SafeTPrintf (translation_t text, ...)
|
|||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
const char *fmt = langtext(text, cls.language);
|
||||
const char *fmt = langtext(text, com_language);
|
||||
|
||||
va_start (argptr,text);
|
||||
vsnprintf (msg,sizeof(msg), fmt,argptr);
|
||||
|
|
|
@ -2946,22 +2946,12 @@ qboolean PM_CanInstall(const char *packagename)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
void PM_Command_f (void)
|
||||
{
|
||||
Con_Printf("Package Manager is not implemented in this build\n");
|
||||
}
|
||||
void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const char *parent_logical, searchpath_t *search, unsigned int loadstuff, int minpri, int maxpri)
|
||||
{
|
||||
}
|
||||
void PM_EnumeratePlugins(void (*callback)(const char *name))
|
||||
{
|
||||
}
|
||||
void PM_ManifestPackage(const char *metaname, int security)
|
||||
{
|
||||
}
|
||||
void PM_Shutdown(void)
|
||||
{
|
||||
}
|
||||
int PM_IsApplying(qboolean listsonly)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -577,6 +577,7 @@ qboolean MultiBeginGame (union menuoption_s *option,struct menu_s *menu, int key
|
|||
if (cls.state)
|
||||
Cbuf_AddText("disconnect\n", RESTRICT_LOCAL);
|
||||
|
||||
Cbuf_AddText("sv_playerslots \"\"\n", RESTRICT_LOCAL); //just in case.
|
||||
Cbuf_AddText(va("maxclients \"%s\"\n", numplayeroptions[info->numplayers->selectedoption]), RESTRICT_LOCAL);
|
||||
if (info->rundedicated->value)
|
||||
Cbuf_AddText("setrenderer dedicated\n", RESTRICT_LOCAL);
|
||||
|
@ -711,7 +712,7 @@ void M_Menu_GameOptions_f (void)
|
|||
info->mapnameedit = MC_AddEdit (menu, 64, 160, y, "map", "start");
|
||||
y += 16;
|
||||
|
||||
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 54, 0, 32, NULL, false);
|
||||
menu->cursoritem = (menuoption_t*)MC_AddWhiteText(menu, 54, 0, menu->selecteditem->common.posy, NULL, false);
|
||||
|
||||
|
||||
info->lowercolour = bottomcolor.value;
|
||||
|
|
|
@ -75,7 +75,7 @@ enum
|
|||
ASPECT2D_CUSTOM,
|
||||
};
|
||||
|
||||
qboolean M_Vid_GetMode(int num, int *w, int *h)
|
||||
qboolean M_Vid_GetMode(qboolean forfullscreen, int num, int *w, int *h)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ static void SV_SetMaster_f (void);
|
|||
|
||||
extern cvar_t sv_public;
|
||||
extern cvar_t sv_reportheartbeats;
|
||||
extern cvar_t sv_heartbeat_interval;
|
||||
|
||||
extern cvar_t sv_listen_qw;
|
||||
extern cvar_t sv_listen_nq;
|
||||
|
@ -98,7 +99,7 @@ typedef struct {
|
|||
qboolean resolving; //set any time the cvar is modified
|
||||
netadr_t adr[MAX_MASTER_ADDRESSES];
|
||||
} net_masterlist_t;
|
||||
net_masterlist_t net_masterlist[] = {
|
||||
static net_masterlist_t net_masterlist[] = {
|
||||
#ifndef QUAKETC
|
||||
//user-specified master lists.
|
||||
{MP_QUAKEWORLD, CVARC("net_qwmaster1", "", Net_Masterlist_Callback)},
|
||||
|
@ -244,12 +245,14 @@ void SV_Master_SingleHeartbeat(net_masterlist_t *master)
|
|||
char adr[MAX_ADR_SIZE];
|
||||
netadr_t *na;
|
||||
int i;
|
||||
int e;
|
||||
|
||||
for (i = 0; i < MAX_MASTER_ADDRESSES; i++)
|
||||
{
|
||||
na = &master->adr[i];
|
||||
if (na->port)
|
||||
{
|
||||
e = -1;
|
||||
switch(master->protocol)
|
||||
{
|
||||
case MP_QUAKEWORLD:
|
||||
|
@ -272,32 +275,26 @@ void SV_Master_SingleHeartbeat(net_masterlist_t *master)
|
|||
madeqwstring = true;
|
||||
}
|
||||
|
||||
if (sv_reportheartbeats.value)
|
||||
{
|
||||
if (sv_reportheartbeats.ival != 2 || !master->announced)
|
||||
Con_TPrintf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), na), master->cv.string);
|
||||
master->announced = true;
|
||||
}
|
||||
|
||||
NET_SendPacket (NS_SERVER, strlen(string), string, na);
|
||||
e = NET_SendPacket (svs.sockets, strlen(string), string, na);
|
||||
}
|
||||
break;
|
||||
#ifdef Q2SERVER
|
||||
case MP_QUAKE2:
|
||||
if (svs.gametype == GT_QUAKE2 && sv_listen_qw.value) //set listen to 1 to allow qw connections, 2 to allow nq connections too.
|
||||
if (svs.gametype == GT_QUAKE2 && sv_listen_qw.value) //sv_listen==sv_listen_qw, yes, weird.
|
||||
{
|
||||
if (sv_reportheartbeats.value)
|
||||
char *str = "\377\377\377\377heartbeat\n%s\n%s";
|
||||
char info[8192];
|
||||
char q2users[8192];
|
||||
size_t i;
|
||||
const char *infos[] = {"hostname", "*version", "deathmatch", "fraglimit", "timelimit", "gamedir", "mapname", "maxclients", "dmflags", NULL};
|
||||
InfoBuf_ToString(&svs.info, info, sizeof(info), NULL, NULL, infos, NULL, NULL);
|
||||
q2users[0] = 0;
|
||||
for (i = 0; i < sv.allocated_client_slots; i++)
|
||||
{
|
||||
if (sv_reportheartbeats.ival != 2 || !master->announced)
|
||||
Con_TPrintf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), na), master->cv.string);
|
||||
master->announced = true;
|
||||
}
|
||||
|
||||
{
|
||||
char *str = "\377\377\377\377heartbeat\n%s";
|
||||
char *q2statusresp = "";
|
||||
NET_SendPacket (NS_SERVER, strlen(str), va(str, q2statusresp), na);
|
||||
if (svs.clients[i].state >= cs_connected)
|
||||
Q_strncatz(q2users, va("%i %i \"%s\"\n", svs.clients[i].old_frags, SV_CalcPing(&svs.clients[i], false), svs.clients[i].name), sizeof(q2users));
|
||||
}
|
||||
e = NET_SendPacket (svs.sockets, strlen(str), va(str, info, q2users), na);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -310,23 +307,56 @@ void SV_Master_SingleHeartbeat(net_masterlist_t *master)
|
|||
#if defined(NQPROT) && !defined(QUAKETC)
|
||||
if (sv_listen_dp.value || sv_listen_nq.value)
|
||||
#endif
|
||||
{
|
||||
if (sv_reportheartbeats.value)
|
||||
{
|
||||
if (sv_reportheartbeats.ival != 2 || !master->announced)
|
||||
Con_TPrintf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), na), master->cv.string);
|
||||
master->announced = true;
|
||||
}
|
||||
|
||||
{
|
||||
//darkplaces here refers to the master server protocol, rather than the game protocol
|
||||
//(specifies that the server responds to infoRequest packets from the master)
|
||||
char *str = "\377\377\377\377heartbeat DarkPlaces\x0A";
|
||||
NET_SendPacket (NS_SERVER, strlen(str), str, na);
|
||||
}
|
||||
e = NET_SendPacket (svs.sockets, strlen(str), str, na);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
e = -2;
|
||||
break;
|
||||
}
|
||||
switch(e)
|
||||
{
|
||||
case -1: //master not enabled for this game type
|
||||
break;
|
||||
case NETERR_SENT:
|
||||
if (sv_reportheartbeats.value)
|
||||
{
|
||||
if (sv_reportheartbeats.ival != 2 || !master->announced)
|
||||
{
|
||||
COM_Parse(master->cv.string);
|
||||
Con_TPrintf ("Sending heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), na), com_token);
|
||||
}
|
||||
master->announced = true;
|
||||
}
|
||||
break;
|
||||
case NETERR_NOROUTE:
|
||||
if (sv_reportheartbeats.value)
|
||||
{
|
||||
if (sv_reportheartbeats.ival != 2 || !master->announced)
|
||||
{
|
||||
COM_Parse(master->cv.string);
|
||||
Con_TPrintf (CON_WARNING"No route for heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), na), com_token);
|
||||
}
|
||||
master->announced = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
case NETERR_DISCONNECTED:
|
||||
case NETERR_MTU:
|
||||
case NETERR_CLOGGED:
|
||||
if (sv_reportheartbeats.value)
|
||||
{
|
||||
if (sv_reportheartbeats.ival != 2 || !master->announced)
|
||||
{
|
||||
COM_Parse(master->cv.string);
|
||||
Con_TPrintf (CON_ERROR"Failed to send heartbeat to %s (%s)\n", NET_AdrToString (adr, sizeof(adr), na), com_token);
|
||||
}
|
||||
master->announced = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -395,12 +425,12 @@ void SV_Master_Worker_Resolved(void *ctx, void *data, size_t a, size_t b)
|
|||
{
|
||||
#ifdef Q2SERVER
|
||||
case MP_QUAKE2:
|
||||
NET_SendPacket (NS_SERVER, 8, "\xff\xff\xff\xffping", na);
|
||||
NET_SendPacket (svs.sockets, 8, "\xff\xff\xff\xffping", na);
|
||||
break;
|
||||
#endif
|
||||
case MP_QUAKEWORLD:
|
||||
//qw does this for some reason, keep the behaviour even though its unreliable thus pointless
|
||||
NET_SendPacket (NS_SERVER, 2, "k\0", na);
|
||||
NET_SendPacket (svs.sockets, 2, "k\0", na);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -445,18 +475,18 @@ Send a message to the master every few minutes to
|
|||
let it know we are alive, and log information
|
||||
================
|
||||
*/
|
||||
#define HEARTBEAT_SECONDS 300
|
||||
void SV_Master_Heartbeat (void)
|
||||
{
|
||||
int i;
|
||||
int interval = bound(90, sv_heartbeat_interval.ival, 600);
|
||||
|
||||
if (sv_public.ival<=0 || SSV_IsSubServer())
|
||||
return;
|
||||
|
||||
if (realtime-HEARTBEAT_SECONDS - svs.last_heartbeat < HEARTBEAT_SECONDS)
|
||||
if (realtime-interval - svs.last_heartbeat < interval)
|
||||
return; // not time to send yet
|
||||
|
||||
svs.last_heartbeat = realtime-HEARTBEAT_SECONDS;
|
||||
svs.last_heartbeat = realtime-interval;
|
||||
|
||||
svs.heartbeat_sequence++;
|
||||
|
||||
|
@ -605,7 +635,7 @@ void SV_Master_Shutdown (void)
|
|||
if (sv_reportheartbeats.value)
|
||||
Con_TPrintf ("Sending shutdown to %s\n", NET_AdrToString (adr, sizeof(adr), na));
|
||||
|
||||
NET_SendPacket (NS_SERVER, strlen(string), string, na);
|
||||
NET_SendPacket (svs.sockets, strlen(string), string, na);
|
||||
break;
|
||||
//dp has no shutdown
|
||||
default:
|
||||
|
@ -736,7 +766,7 @@ void Master_HideServer(serverinfo_t *server)
|
|||
else
|
||||
i++;
|
||||
}
|
||||
server->status &= ~2u;
|
||||
server->status &= ~SRVSTATUS_DISPLAYED;
|
||||
}
|
||||
|
||||
void Master_InsertAt(serverinfo_t *server, int pos)
|
||||
|
@ -754,7 +784,7 @@ void Master_InsertAt(serverinfo_t *server, int pos)
|
|||
visibleservers[pos] = server;
|
||||
numvisibleservers++;
|
||||
|
||||
server->status |= 2u;
|
||||
server->status |= SRVSTATUS_DISPLAYED;
|
||||
}
|
||||
|
||||
qboolean Master_CompareInteger(int a, int b, slist_test_t rule)
|
||||
|
@ -907,8 +937,8 @@ qboolean Master_PassesMasks(serverinfo_t *a)
|
|||
qboolean val, res;
|
||||
// qboolean enabled;
|
||||
|
||||
//always filter out dead unresponsive servers.
|
||||
if (!(a->status & 1))
|
||||
//always filter out dead/unresponsive servers.
|
||||
if (!(a->status & SRVSTATUS_ALIVE))
|
||||
return false;
|
||||
|
||||
val = 1;
|
||||
|
@ -1066,7 +1096,7 @@ void Master_ShowServer(serverinfo_t *server)
|
|||
|
||||
void Master_ResortServer(serverinfo_t *server)
|
||||
{
|
||||
if (server->status&2u)
|
||||
if (server->status&SRVSTATUS_DISPLAYED)
|
||||
{
|
||||
if (!Master_PassesMasks(server))
|
||||
Master_HideServer(server);
|
||||
|
@ -1092,7 +1122,7 @@ int Master_SortServers(void)
|
|||
{
|
||||
numvisibleservers = 0;
|
||||
for (server = firstserver; server; server = server->next)
|
||||
server->status &= ~2u;
|
||||
server->status &= ~SRVSTATUS_DISPLAYED;
|
||||
}
|
||||
|
||||
for (server = firstserver; server; server = server->next)
|
||||
|
@ -2343,6 +2373,7 @@ void MasterInfo_ProcessHTTP(struct dl_download *dl)
|
|||
|
||||
Master_ResortServer(info);
|
||||
}
|
||||
info->status |= SRVSTATUS_GLOBAL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2450,6 +2481,7 @@ char *jsonnode(int level, char *node)
|
|||
|
||||
Master_ResortServer(info);
|
||||
}
|
||||
info->status |= SRVSTATUS_GLOBAL;
|
||||
}
|
||||
|
||||
return node;
|
||||
|
@ -2655,7 +2687,7 @@ void MasterInfo_Refresh(qboolean doreset)
|
|||
if (doreset)
|
||||
{
|
||||
for (info = firstserver; info; info = info->next)
|
||||
info->status &= ~1; //hide until we get a new response from it.
|
||||
info->status &= ~SRVSTATUS_ALIVE; //hide until we get a new response from it.
|
||||
}
|
||||
|
||||
loadedone = false;
|
||||
|
@ -2675,7 +2707,7 @@ void MasterInfo_Refresh(qboolean doreset)
|
|||
#ifndef QUAKETC
|
||||
Master_AddMaster("255.255.255.255:"STRINGIFY(PORT_QWSERVER), MT_BCAST, MP_QUAKEWORLD, "Nearby QuakeWorld UDP servers.");
|
||||
// Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quakeworld", MT_MASTERHTTP, MP_QUAKEWORLD, "gameaholic's QW master");
|
||||
Master_AddMasterHTTP("https://www.quakeservers.net/lists/servers/global.txt",MT_MASTERHTTP, MP_QUAKEWORLD, "QuakeServers.net (http)");
|
||||
// Master_AddMasterHTTP("https://www.quakeservers.net/lists/servers/global.txt",MT_MASTERHTTP, MP_QUAKEWORLD, "QuakeServers.net (http)");
|
||||
#endif
|
||||
#ifdef NQPROT
|
||||
// Master_AddMasterHTTP("http://www.gameaholic.com/servers/qspy-quake", MT_MASTERHTTP, MP_NETQUAKE, "gameaholic's NQ master");
|
||||
|
@ -2904,7 +2936,7 @@ unsigned int Master_NumAlive(void)
|
|||
|
||||
for (info = firstserver; info; info = info->next)
|
||||
{
|
||||
if (info->status&1u)
|
||||
if (info->status&SRVSTATUS_ALIVE)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
|
@ -3032,7 +3064,7 @@ int CL_ReadServerInfo(char *msg, enum masterprotocol_e prototype, qboolean favor
|
|||
info->refreshtime = 0;
|
||||
}
|
||||
|
||||
info->status |= 1u;
|
||||
info->status |= SRVSTATUS_ALIVE;
|
||||
|
||||
nl = strchr(msg, '\n');
|
||||
if (nl)
|
||||
|
@ -3484,6 +3516,7 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad)
|
|||
if ((old->special & (SS_PROTOCOLMASK)) != (type & (SS_PROTOCOLMASK)))
|
||||
old->special = type | (old->special & (SS_FAVORITE|SS_LOCAL));
|
||||
old->sends = 1; //reset.
|
||||
old->status |= SRVSTATUS_GLOBAL;
|
||||
Z_Free(info);
|
||||
}
|
||||
else
|
||||
|
@ -3492,6 +3525,7 @@ void CL_MasterListParse(netadrtype_t adrtype, int type, qboolean slashpad)
|
|||
|
||||
info->special = type;
|
||||
info->refreshtime = 0;
|
||||
info->status |= SRVSTATUS_GLOBAL;
|
||||
|
||||
Q_snprintfz(info->name, sizeof(info->name), "%s (via %s)", NET_AdrToString(adr, sizeof(adr), &info->adr), madr);
|
||||
|
||||
|
|
|
@ -707,14 +707,15 @@ void QCBUILTIN PF_soundlength (pubprogfuncs_t *prinst, struct globalvars_s *pr_g
|
|||
}
|
||||
}
|
||||
|
||||
qboolean M_Vid_GetMode(int num, int *w, int *h);
|
||||
qboolean M_Vid_GetMode(qboolean forfullscreen, int num, int *w, int *h);
|
||||
//a bit pointless really
|
||||
void QCBUILTIN PF_cl_getresolution (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
|
||||
{
|
||||
float mode = G_FLOAT(OFS_PARM0);
|
||||
// qboolean fixedmodes = (prinst->callargc >= 2)?!G_FLOAT(OFS_PARM1):false; //if true, we should return sane-sized modes suitable for a window... or the mod could make up its own, but whatever.
|
||||
qboolean forfullscreen = (prinst->callargc >= 2)?G_FLOAT(OFS_PARM1):true; //if true, we should return queried video modes... or the mod could make up its own, but whatever.
|
||||
float *ret = G_VECTOR(OFS_RETURN);
|
||||
int w, h;
|
||||
float pixelheight = 0;
|
||||
|
||||
w=h=0;
|
||||
if (mode == -1)
|
||||
|
@ -723,11 +724,11 @@ void QCBUILTIN PF_cl_getresolution (pubprogfuncs_t *prinst, struct globalvars_s
|
|||
Sys_GetDesktopParameters(&w, &h, &bpp, &rate);
|
||||
}
|
||||
else
|
||||
M_Vid_GetMode(mode, &w, &h);
|
||||
M_Vid_GetMode(forfullscreen, mode, &w, &h);
|
||||
|
||||
ret[0] = w;
|
||||
ret[1] = h;
|
||||
ret[2] = (w&&h)?1:0;
|
||||
ret[2] = pixelheight?pixelheight:((w&&h)?1:0); //pixelheight
|
||||
}
|
||||
|
||||
#ifdef CL_MASTER
|
||||
|
@ -988,7 +989,7 @@ static struct modlist_s
|
|||
static size_t nummods;
|
||||
static qboolean modsinited;
|
||||
|
||||
static qboolean Mods_AddManifest(void *usr, ftemanifest_t *man)
|
||||
/*static qboolean Mods_AddManifest(void *usr, ftemanifest_t *man)
|
||||
{
|
||||
int i = nummods;
|
||||
modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist));
|
||||
|
@ -997,7 +998,7 @@ static qboolean Mods_AddManifest(void *usr, ftemanifest_t *man)
|
|||
modlist[i].description = man->formalname;
|
||||
nummods = i+1;
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
static int QDECL Mods_AddGamedir(const char *fname, qofs_t fsize, time_t mtime, void *usr, searchpathfuncs_t *spath)
|
||||
{
|
||||
char *f;
|
||||
|
@ -1027,7 +1028,7 @@ static int QDECL Mods_AddGamedir(const char *fname, qofs_t fsize, time_t mtime,
|
|||
return true;
|
||||
}
|
||||
}
|
||||
f = FS_MallocFile(va("%s%s/modinfo.txt", usr, gamedir), FS_SYSTEM, NULL);
|
||||
f = FS_MallocFile(va("%s%s/modinfo.txt", (const char*)usr, gamedir), FS_SYSTEM, NULL);
|
||||
if (f)
|
||||
{
|
||||
modlist = BZ_Realloc(modlist, (i+1) * sizeof(*modlist));
|
||||
|
@ -1070,7 +1071,6 @@ void QCBUILTIN PF_cl_getgamedirinfo(pubprogfuncs_t *prinst, struct globalvars_s
|
|||
if (modlist[diridx].description)
|
||||
RETURN_TSTRING(modlist[diridx].description);
|
||||
break;
|
||||
//fallthrough
|
||||
case 0: //name
|
||||
RETURN_TSTRING(modlist[diridx].gamedir);
|
||||
break;
|
||||
|
@ -1091,8 +1091,8 @@ void QCBUILTIN PF_cl_SendPacket(pubprogfuncs_t *prinst, struct globalvars_s *pr_
|
|||
char *send = Z_Malloc(4+strlen(contents));
|
||||
send[0] = send[1] = send[2] = send[3] = 0xff;
|
||||
memcpy(send+4, contents, strlen(contents));
|
||||
//FIXME: NS_CLIENT is likely to change its port randomly...
|
||||
G_FLOAT(OFS_RETURN) = NET_SendPacket(NS_CLIENT, 4+strlen(contents), send, &to);
|
||||
//FIXME: this is likely to change its port randomly...
|
||||
G_FLOAT(OFS_RETURN) = NET_SendPacket(cls.sockets, 4+strlen(contents), send, &to);
|
||||
Z_Free(send);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,13 +99,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
#define QUAKEDEF_H__
|
||||
|
||||
#ifdef SERVERONLY
|
||||
#define isDedicated true
|
||||
#endif
|
||||
#ifdef CLIENTONLY
|
||||
#define isDedicated false
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#define PNG_SUCKS_WITH_SETJMP //cos it does.
|
||||
#endif
|
||||
|
@ -154,8 +147,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "translate.h"
|
||||
|
||||
#include "common.h"
|
||||
#include "bspfile.h"
|
||||
#include "vid.h"
|
||||
|
@ -163,6 +154,7 @@ extern "C" {
|
|||
#include "zone.h"
|
||||
#include "mathlib.h"
|
||||
#include "cvar.h"
|
||||
#include "translate.h"
|
||||
#include "net.h"
|
||||
#ifndef WEBSVONLY
|
||||
#include "protocol.h"
|
||||
|
@ -375,8 +367,11 @@ void COM_AssertMainThread(const char *msg);
|
|||
extern qboolean msg_suppress_1; // suppresses resolution and cache size console output
|
||||
// an fullscreen DIB focus gain/loss
|
||||
|
||||
|
||||
#if !defined(SERVERONLY) && !defined(CLIENTONLY)
|
||||
#ifndef HAVE_CLIENT
|
||||
#define isDedicated true
|
||||
#elif !defined(HAVE_SERVER)
|
||||
#define isDedicated false
|
||||
#else
|
||||
extern qboolean isDedicated;
|
||||
#endif
|
||||
extern qboolean wantquit; //flagged if we want to force a quit, safely breaking out of any modal stuff
|
||||
|
|
|
@ -1711,6 +1711,7 @@ char *particle_set_high =
|
|||
"surfaceparm nodlight\n"
|
||||
"glslprogram\n"
|
||||
"{\n"
|
||||
"!!samps screen=0\n"
|
||||
"varying vec2 tcoord;\n"
|
||||
"varying vec4 scoord;\n"
|
||||
"varying float alph;\n"
|
||||
|
@ -1738,7 +1739,7 @@ char *particle_set_high =
|
|||
// f = 1.0 - tcoord*tcoord;
|
||||
"if (f < 0.0) discard;\n"
|
||||
"f *= alph;\n"
|
||||
"gl_FragColor = texture2D(s_t0, nst - tcoord*f);\n"
|
||||
"gl_FragColor = texture2D(s_screen, nst - tcoord*f);\n"
|
||||
"}\n"
|
||||
"#endif\n"
|
||||
"}\n"
|
||||
|
|
|
@ -127,7 +127,7 @@ cvar_t r_refractreflect_scale = CVARD ("r_refractreflect_scale", "0.5", "Use
|
|||
cvar_t r_drawviewmodel = CVARF ("r_drawviewmodel", "1", CVAR_ARCHIVE);
|
||||
cvar_t r_drawviewmodelinvis = CVAR ("r_drawviewmodelinvis", "0");
|
||||
cvar_t r_dynamic = CVARFD ("r_dynamic", IFMINIMAL("0","1"),
|
||||
CVAR_ARCHIVE, "-1: the engine will bypass dlights completely, allowing for better batching.\n0: no standard dlights at all.\n1: coloured dlights will be used, they may show through walls. These are not realtime things.\n2: The dlights will be forced to monochrome (this does not affect coronas/flashblends/rtlights attached to the same light).");
|
||||
CVAR_ARCHIVE, "-1: the engine will use only pvs to determine which surfaces are visible. This can significantly reduce CPU time, but only if there are many surfaces with few textures visible from the camera.\n0: no standard dlights at all.\n1: coloured dlights will be used, they may show through walls. These are not realtime things.\n2: The dlights will be forced to monochrome (this does not affect coronas/flashblends/rtlights attached to the same light).");
|
||||
cvar_t r_fastturb = CVARF ("r_fastturb", "0",
|
||||
CVAR_SHADERSYSTEM);
|
||||
cvar_t r_fastsky = CVARF ("r_fastsky", "0",
|
||||
|
|
|
@ -104,7 +104,7 @@ cvar_t snd_khz = CVARAFD( "s_khz", DEFAULT_SND_KHZ,
|
|||
"snd_khz", CVAR_ARCHIVE, "Sound speed, in kilohertz. Common values are 11, 22, 44, 48. Values above 1000 are explicitly in hertz.");
|
||||
cvar_t snd_inactive = CVARAFD( "s_inactive", "1",
|
||||
"snd_inactive", CVAR_ARCHIVE,
|
||||
"Play sound while application is inactive (ex. tabbed out). Needs a snd_restart if changed."
|
||||
"Play sound while application is inactive (ie: tabbed out). Needs a snd_restart if changed."
|
||||
); //set if you want sound even when tabbed out.
|
||||
cvar_t _snd_mixahead = CVARAFD( "s_mixahead", "0.1",
|
||||
"_snd_mixahead", CVAR_ARCHIVE, "Specifies how many seconds to prebuffer audio. Lower values give less latency, but might result in crackling. Different hardware/drivers have different tolerances, and this setting may be ignored completely where drivers are expected to provide their own tolerances.");
|
||||
|
@ -152,7 +152,7 @@ cvar_t snd_voip_send = CVARFD("cl_voip_send", "0", CVAR_ARCHIVE, "Sends voice-
|
|||
cvar_t snd_voip_test = CVARD("cl_voip_test", "0", "If 1, enables you to hear your own voice directly, bypassing the server and thus without networking latency, but is fine for checking audio levels. Note that sv_voip_echo can be set if you want to include latency and packetloss considerations, but setting that cvar requires server admin access and is thus much harder to use.");
|
||||
cvar_t snd_voip_vad_threshhold = CVARFD("cl_voip_vad_threshhold", "15", CVAR_ARCHIVE, "This is the threshhold for voice-activation-detection when sending voip data");
|
||||
cvar_t snd_voip_vad_delay = CVARD("cl_voip_vad_delay", "0.3", "Keeps sending voice data for this many seconds after voice activation would normally stop");
|
||||
cvar_t snd_voip_capturingvol = CVARAFD("cl_voip_capturingvol", "0.5", NULL, CVAR_ARCHIVE, "Volume multiplier applied while capturing, to avoid your audio from being heard by others. Does not affect game volume when other speak (minimum of cl_voip_capturingvol and cl_voip_ducking is used).");
|
||||
cvar_t snd_voip_capturingvol = CVARAFD("cl_voip_capturingvol", "0.5", NULL, CVAR_ARCHIVE, "Volume multiplier applied while capturing, to avoid your audio from being heard by others. Does not affect game volume when others speak (minimum of cl_voip_capturingvol and cl_voip_ducking is used).");
|
||||
cvar_t snd_voip_showmeter = CVARAFD("cl_voip_showmeter", "1", NULL, CVAR_ARCHIVE, "Shows your speech volume above the standard hud. 0=hide, 1=show when transmitting, 2=ignore voice-activation disable");
|
||||
|
||||
cvar_t snd_voip_play = CVARAFCD("cl_voip_play", "1", NULL, CVAR_ARCHIVE, S_Voip_Play_Callback, "Enables voip playback. Value is a volume scaler.");
|
||||
|
@ -286,7 +286,11 @@ enum
|
|||
|
||||
VOIP_INVALID = 16 //not currently generating audio.
|
||||
};
|
||||
#ifdef NOLEGACY
|
||||
#define VOIP_DEFAULT_CODEC VOIP_OPUS
|
||||
#else
|
||||
#define VOIP_DEFAULT_CODEC (cls.protocol==CP_QUAKEWORLD?VOIP_SPEEX_OLD:VOIP_OPUS) //opus is preferred, but ezquake is still common and only supports my first attempt at voice compression so favour that for quakeworld.
|
||||
#endif
|
||||
static struct
|
||||
{
|
||||
struct
|
||||
|
|
|
@ -114,6 +114,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MASTERONLY
|
||||
#define SV_MASTER
|
||||
#undef SUBSERVERS
|
||||
#undef PLUGINS
|
||||
#undef HUFFNETWORK
|
||||
#undef SUPPORT_ICE
|
||||
#undef WEBCLIENT
|
||||
#undef LOADERTHREAD
|
||||
#undef PACKAGEMANAGER
|
||||
#undef PACKAGE_PK3
|
||||
#undef PACKAGE_Q1PAK
|
||||
#undef PACKAGE_DOOMWAD
|
||||
#undef PACKAGE_VPK
|
||||
#undef PACKAGE_DZIP
|
||||
#undef AVAIL_GZDEC
|
||||
#else
|
||||
#if defined(SERVERONLY) && defined(CLIENTONLY)
|
||||
#undef CLIENTONLY //impossible build. assume the config had CLIENTONLY and they tried building a dedicated server
|
||||
#endif
|
||||
|
@ -125,6 +141,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define HAVE_CLIENT
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SERVER
|
||||
#undef MVD_RECORDING
|
||||
|
|
|
@ -65,7 +65,9 @@ cvar_t cfg_save_buttons = CVARFD("cfg_save_buttons", "0", CVAR_ARCHIVE|CVAR_NOTF
|
|||
cvar_t cl_warncmd = CVARF("cl_warncmd", "1", CVAR_NOSAVE|CVAR_NORESET);
|
||||
cvar_t cl_aliasoverlap = CVARF("cl_aliasoverlap", "1", CVAR_NOTFROMSERVER);
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
cvar_t tp_disputablemacros = CVARF("tp_disputablemacros", "1", CVAR_SEMICHEAT);
|
||||
#endif
|
||||
|
||||
|
||||
//=============================================================================
|
||||
|
@ -120,9 +122,11 @@ static char *TP_MacroString (char *s, int *newaccesslevel, int *len)
|
|||
macro = ¯o_commands[i];
|
||||
if (!Q_strcasecmp(s, macro->name))
|
||||
{
|
||||
#ifdef HAVE_CLIENT
|
||||
if (macro->disputableintentions)
|
||||
if (!tp_disputablemacros.ival)
|
||||
*newaccesslevel = 0;
|
||||
#endif
|
||||
if (len)
|
||||
*len = strlen(macro->name);
|
||||
return macro->func();
|
||||
|
@ -187,7 +191,7 @@ static void Cmd_Wait_f (void)
|
|||
if (cmd_blockwait)
|
||||
return;
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
if (cmd_didwait && sv.state)
|
||||
Con_DPrintf("waits without server frames\n");
|
||||
#endif
|
||||
|
@ -531,7 +535,7 @@ void Cbuf_Execute (void)
|
|||
{
|
||||
int level;
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (cmd_text[RESTRICT_LOCAL].waitattime && cls.state == ca_active)
|
||||
{
|
||||
//keep binds blocked until after the next input frame was sent to the server (at which point it will be cleared
|
||||
|
@ -876,7 +880,7 @@ static void Cmd_Echo_f (void)
|
|||
//echo text is often quoted, so expand the text again now that we're no longer in quotes.
|
||||
t = Cmd_ExpandString(text, extext, sizeof(extext), &level, !Cmd_IsInsecure()?true:false, true);
|
||||
|
||||
#ifdef SERVERONLY
|
||||
#ifndef HAVE_CLIENT
|
||||
Con_Printf ("%s", t);
|
||||
#else
|
||||
t = TP_ParseFunChars(t);
|
||||
|
@ -1163,7 +1167,7 @@ static void Cmd_Alias_f (void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
static void Cmd_AliasEdit_f (void)
|
||||
{
|
||||
char *alias = Cmd_AliasExist(Cmd_Argv(1), RESTRICT_LOCAL);
|
||||
|
@ -2579,7 +2583,7 @@ static void Cmd_Apropos_f (void)
|
|||
//FIXME: add aliases.
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY // FIXME
|
||||
#ifdef HAVE_CLIENT // FIXME
|
||||
/*
|
||||
===================
|
||||
Cmd_ForwardToServer
|
||||
|
@ -2731,29 +2735,29 @@ void Cmd_ExecuteString (const char *text, int level)
|
|||
Con_TPrintf("cmd '%s' was restricted.\n", cmd_argv[0]);
|
||||
else if (!cmd->function)
|
||||
{
|
||||
#ifdef VM_CG
|
||||
#if defined(VM_CG) && defined(HAVE_CLIENT)
|
||||
if (CG_Command())
|
||||
return;
|
||||
#endif
|
||||
#ifdef Q3SERVER
|
||||
#if defined(Q3SERVER) && defined(HAVE_SERVER)
|
||||
if (SVQ3_Command())
|
||||
return;
|
||||
#endif
|
||||
#ifdef VM_UI
|
||||
#if defined(VM_UI) && defined(HAVE_CLIENT)
|
||||
if (UI_Command())
|
||||
return;
|
||||
#endif
|
||||
if (Cmd_AliasExist(cmd_argv[0], level))
|
||||
break; //server stuffed an alias for a command that it would already have received. use that instead.
|
||||
#if defined(CSQC_DAT) && !defined(SERVERONLY)
|
||||
#if defined(CSQC_DAT) && defined(HAVE_CLIENT)
|
||||
if (CSQC_ConsoleCommand(-1, text))
|
||||
return; //let the csqc handle it if it wants.
|
||||
#endif
|
||||
#if defined(MENU_DAT) && !defined(SERVERONLY)
|
||||
#if defined(MENU_DAT) && defined(HAVE_CLIENT)
|
||||
if (MP_ConsoleCommand(text))
|
||||
return; //let the csqc handle it if it wants.
|
||||
#endif
|
||||
#if defined(MENU_NATIVECODE) && !defined(SERVERONLY)
|
||||
#if defined(MENU_NATIVECODE) && defined(HAVE_CLIENT)
|
||||
if (mn_entry && mn_entry->ConsoleCommand(text, cmd_argc, (char const*const*)cmd_argv))
|
||||
return;
|
||||
#endif
|
||||
|
@ -2777,11 +2781,11 @@ void Cmd_ExecuteString (const char *text, int level)
|
|||
{
|
||||
int execlevel;
|
||||
|
||||
#ifndef SERVERONLY //an emergency escape mechansim, to avoid infinatly recursing aliases.
|
||||
#ifdef HAVE_CLIENT //an emergency escape mechansim, to avoid infinatly recursing aliases.
|
||||
extern qboolean keydown[];
|
||||
extern unsigned int con_splitmodifier;
|
||||
|
||||
if (keydown[K_SHIFT] && (keydown[K_LCTRL]||keydown[K_RCTRL]) && (keydown[K_LALT]||keydown[K_RALT]))
|
||||
if (keydown[K_SHIFT] && (keydown[K_LCTRL]||keydown[K_RCTRL]) && (keydown[K_LALT]||keydown[K_RALT]) && !isDedicated)
|
||||
return;
|
||||
#endif
|
||||
|
||||
|
@ -2837,7 +2841,7 @@ void Cmd_ExecuteString (const char *text, int level)
|
|||
Q_strncpyz(dest, a->value, sizeof(dest));
|
||||
Cbuf_InsertText (dest, execlevel, false);
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (con_splitmodifier > 0)
|
||||
{ //if the alias was execed via p1/p2 etc, make sure that propagates properly (at least for simple aliases like impulses)
|
||||
//fixme: should probably prefix each line. that may have different issues however.
|
||||
|
@ -2910,15 +2914,15 @@ void Cmd_ExecuteString (const char *text, int level)
|
|||
return;
|
||||
}
|
||||
|
||||
#if defined(CSQC_DAT) && !defined(SERVERONLY)
|
||||
#if defined(CSQC_DAT) && defined(HAVE_CLIENT)
|
||||
if (CSQC_ConsoleCommand(-1, text))
|
||||
return;
|
||||
#endif
|
||||
#if defined(MENU_DAT) && !defined(SERVERONLY)
|
||||
#if defined(MENU_DAT) && defined(HAVE_CLIENT)
|
||||
if (MP_ConsoleCommand(text))
|
||||
return; //let the csqc handle it if it wants.
|
||||
#endif
|
||||
#if defined(MENU_NATIVECODE) && !defined(SERVERONLY)
|
||||
#if defined(MENU_NATIVECODE) && defined(HAVE_CLIENT)
|
||||
if (mn_entry && mn_entry->ConsoleCommand(text, cmd_argc, (char const*const*)cmd_argv))
|
||||
return;
|
||||
#endif
|
||||
|
@ -2928,7 +2932,7 @@ void Cmd_ExecuteString (const char *text, int level)
|
|||
return;
|
||||
#endif
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
if (sv.state)
|
||||
{
|
||||
if (PR_ConsoleCmd(text))
|
||||
|
@ -2936,19 +2940,19 @@ void Cmd_ExecuteString (const char *text, int level)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef VM_CG
|
||||
#if defined(VM_CG) && defined(HAVE_CLIENT)
|
||||
if (CG_Command())
|
||||
return;
|
||||
#endif
|
||||
#ifdef Q3SERVER
|
||||
#if defined(Q3SERVER) && defined(HAVE_SERVER)
|
||||
if (SVQ3_Command())
|
||||
return;
|
||||
#endif
|
||||
#ifdef VM_UI
|
||||
#if defined(VM_UI) && defined(HAVE_CLIENT)
|
||||
if (UI_Command())
|
||||
return;
|
||||
#endif
|
||||
#ifdef Q2CLIENT
|
||||
#if defined(Q2CLIENT) && defined(HAVE_CLIENT)
|
||||
if (cls.protocol == CP_QUAKE2 || cls.protocol == CP_QUAKE3)
|
||||
{ //q2 servers convert unknown commands to text.
|
||||
Cmd_ForwardToServer();
|
||||
|
@ -3192,7 +3196,7 @@ static const char *If_Token_Term(const char *func, const char **end)
|
|||
else if (!strcmp(com_token, "vid")) //mostly for use with the menu system.
|
||||
{
|
||||
s = COM_ParseToken(s, IFPUNCT);
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (qrenderer == QR_NONE)
|
||||
s2 = "";
|
||||
else if (!strcmp(com_token, "width"))
|
||||
|
@ -3978,7 +3982,9 @@ static void Cmd_WriteConfig_f(void)
|
|||
snprintf(fname, sizeof(fname), "fte.cfg");
|
||||
#endif
|
||||
|
||||
#if defined(CL_MASTER) && defined(HAVE_CLIENT)
|
||||
MasterInfo_WriteServers();
|
||||
#endif
|
||||
|
||||
f = FS_OpenWithFriends(fname, sysname, sizeof(sysname), 3, "quake.rc", "hexen.rc", "*.cfg", "configs/*.cfg");
|
||||
|
||||
|
@ -4007,7 +4013,7 @@ static void Cmd_WriteConfig_f(void)
|
|||
}
|
||||
|
||||
VFS_PRINTF(f, "// %s config file\n\n", *fs_gamename.string?fs_gamename.string:FULLENGINENAME);
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (cfg_save_binds.ival)
|
||||
Key_WriteBindings (f);
|
||||
if (cfg_save_buttons.ival)
|
||||
|
@ -4022,11 +4028,11 @@ static void Cmd_WriteConfig_f(void)
|
|||
#else
|
||||
VFS_WRITE(f, "// Dedicated Server config\n\n", 28);
|
||||
#endif
|
||||
#ifdef CLIENTONLY
|
||||
VFS_WRITE(f, "// no local/server infos\n\n", 26);
|
||||
#else
|
||||
#ifdef HAVE_SERVER
|
||||
if (cfg_save_infos.ival)
|
||||
SV_SaveInfos(f);
|
||||
#else
|
||||
VFS_WRITE(f, "// no local/server infos\n\n", 26);
|
||||
#endif
|
||||
if (cfg_save_aliases.ival)
|
||||
Alias_WriteAliases (f);
|
||||
|
@ -4042,7 +4048,7 @@ static void Cmd_Reset_f(void)
|
|||
{
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
// dumps current console contents to a text file
|
||||
static void Cmd_Condump_f(void)
|
||||
{
|
||||
|
@ -4231,7 +4237,7 @@ void Cmd_Init (void)
|
|||
Cmd_AddCommand ("alias",Cmd_Alias_f);
|
||||
Cmd_AddCommand ("newalias",Cmd_Alias_f);
|
||||
Cmd_AddCommand ("wait", Cmd_Wait_f);
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
Cmd_AddCommand ("cmd", Cmd_ForwardToServer_f);
|
||||
Cmd_AddCommand ("condump", Cmd_Condump_f);
|
||||
Cmd_AddCommandAD ("aliasedit", Cmd_AliasEdit_f, Key_Alias_c, NULL);
|
||||
|
@ -4279,7 +4285,9 @@ void Cmd_Init (void)
|
|||
Cmd_AddMacro("qt", Macro_Quote, false);
|
||||
Cmd_AddMacro("dedicated", Macro_Dedicated, false);
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
Cvar_Register(&tp_disputablemacros, "Teamplay");
|
||||
#endif
|
||||
|
||||
Cvar_Register(&ruleset_allow_in, "Console");
|
||||
Cmd_AddCommandD ("in", Cmd_In_f, "Issues the given command after a time delay. Disabled if ruleset_allow_in is 0.");
|
||||
|
@ -4296,7 +4304,7 @@ void Cmd_Init (void)
|
|||
Cvar_Register (&cfg_save_binds, "client operation options");
|
||||
Cvar_Register (&cfg_save_buttons, "client operation options");
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
rcon_level.ival = atof(rcon_level.enginevalue); //client is restricted to not be allowed to change restrictions.
|
||||
#else
|
||||
Cvar_Register(&rcon_level, "Access controls"); //server gains versatility.
|
||||
|
|
|
@ -25,6 +25,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef HAVE_CLIENT
|
||||
double host_frametime;
|
||||
double realtime; // without any filtering or bounding
|
||||
qboolean host_initialized; // true if into command execution (compatability)
|
||||
quakeparms_t host_parms;
|
||||
int host_hunklevel;
|
||||
#endif
|
||||
|
||||
|
||||
//by adding 'extern' to one definition of a function in a translation unit, then the definition in that TU is NOT considered an inline definition. meaning non-inlined references in other TUs can link to it instead of their own if needed.
|
||||
fte_inlinebody conchar_t *Font_Decode(conchar_t *start, unsigned int *codeflags, unsigned int *codepoint);
|
||||
fte_inlinebody float M_SRGBToLinear(float x, float mag);
|
||||
|
@ -103,6 +112,12 @@ static char *safeargvs[] =
|
|||
static const char *largv[MAX_NUM_ARGVS + countof(safeargvs) + 1];
|
||||
static char *argvdummy = " ";
|
||||
|
||||
#ifdef CRAZYDEBUGGING
|
||||
cvar_t developer = CVAR("developer","1");
|
||||
#else
|
||||
cvar_t developer = CVARD("developer","0", "Enables the spewing of additional developer/debugging messages. 2 will give even more spam, much of it unwanted.");
|
||||
#endif
|
||||
|
||||
cvar_t registered = CVARD("registered","0","Set if quake's pak1.pak is available");
|
||||
cvar_t gameversion = CVARFD("gameversion","", CVAR_SERVERINFO, "gamecode version for server browsers");
|
||||
cvar_t gameversion_min = CVARD("gameversion_min","", "gamecode version for server browsers");
|
||||
|
@ -111,7 +126,7 @@ cvar_t fs_gamename = CVARAFD("com_fullgamename", NULL, "fs_gamename", CVAR_NOSET
|
|||
cvar_t com_protocolname = CVARAD("com_protocolname", NULL, "com_gamename", "The protocol game name used for dpmaster queries. For compatibility with DP, you can set this to 'DarkPlaces-Quake' in order to be listed in DP's master server, and to list DP servers.");
|
||||
cvar_t com_protocolversion = CVARAD("com_protocolversion", "3", NULL, "The protocol version used for dpmaster queries."); //3 by default, for compat with DP/NQ, even if our QW protocol uses different versions entirely. really it only matters for master servers.
|
||||
cvar_t com_parseutf8 = CVARD("com_parseutf8", "1", "Interpret console messages/playernames/etc as UTF-8. Requires special fonts. -1=iso 8859-1. 0=quakeascii(chat uses high chars). 1=utf8, revert to ascii on decode errors. 2=utf8 ignoring errors"); //1 parse. 2 parse, but stop parsing that string if a char was malformed.
|
||||
#ifndef NOLEGACY
|
||||
#if !defined(NOLEGACY) && defined(HAVE_CLIENT)
|
||||
cvar_t com_parseezquake = CVARD("com_parseezquake", "0", "Treat chevron chars from configs as a per-character flag. You should use this only for compat with nquake's configs.");
|
||||
#endif
|
||||
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
|
||||
|
@ -1131,7 +1146,7 @@ static unsigned int MSG_ReadEntity(void)
|
|||
return num;
|
||||
}
|
||||
//we use the high bit of the entity number to state that this is a large entity.
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
unsigned int MSGSV_ReadEntity(client_t *fromclient)
|
||||
{
|
||||
unsigned int num;
|
||||
|
@ -1148,7 +1163,7 @@ unsigned int MSGSV_ReadEntity(client_t *fromclient)
|
|||
return num;
|
||||
}
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
unsigned int MSGCL_ReadEntity(void)
|
||||
{
|
||||
unsigned int num;
|
||||
|
@ -1159,6 +1174,7 @@ unsigned int MSGCL_ReadEntity(void)
|
|||
return num;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_CLIENT) || defined(HAVE_SERVER)
|
||||
void MSG_WriteEntity(sizebuf_t *sb, unsigned int entnum)
|
||||
{
|
||||
if (entnum > MAX_EDICTS)
|
||||
|
@ -1172,6 +1188,7 @@ void MSG_WriteEntity(sizebuf_t *sb, unsigned int entnum)
|
|||
else
|
||||
MSG_WriteShort(sb, entnum);
|
||||
}
|
||||
#endif
|
||||
|
||||
void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
|
||||
{
|
||||
|
@ -1181,8 +1198,8 @@ void MSG_WriteDeltaUsercmd (sizebuf_t *buf, usercmd_t *from, usercmd_t *cmd)
|
|||
// send the movement message
|
||||
//
|
||||
bits = 0;
|
||||
#ifdef Q2CLIENT
|
||||
if (cls.protocol == CP_QUAKE2)
|
||||
#if defined(Q2CLIENT) && defined(HAVE_CLIENT)
|
||||
if (cls_state && cls.protocol == CP_QUAKE2)
|
||||
{
|
||||
unsigned char buttons = 0;
|
||||
if (cmd->angles[0] != from->angles[0])
|
||||
|
@ -1715,7 +1732,7 @@ vec3_t bytedirs[Q2NUMVERTEXNORMALS] =
|
|||
#include "../client/q2anorms.h"
|
||||
};
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
void MSG_ReadDir (vec3_t dir)
|
||||
{
|
||||
int b;
|
||||
|
@ -1774,7 +1791,7 @@ float MSG_ReadAngle (void)
|
|||
case 1:
|
||||
return MSG_ReadChar() * (360.0/256);
|
||||
default:
|
||||
Host_Error("Bad angle size\n");
|
||||
Sys_Error("Bad angle size\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -5720,7 +5737,9 @@ void COM_Init (void)
|
|||
COM_InitWorkerThread();
|
||||
#endif
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
Cmd_AddCommandD("pkg", PM_Command_f, "Provides a way to install / list / disable / purge packages via the console.");
|
||||
#endif
|
||||
Cmd_AddCommandD("version", COM_Version_f, "Reports engine revision and optional compile-time settings."); //prints the pak or whatever where this file can be found.
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
@ -5730,6 +5749,7 @@ void COM_Init (void)
|
|||
#endif
|
||||
COM_InitFilesystem ();
|
||||
|
||||
Cvar_Register (&developer, "Debugging");
|
||||
Cvar_Register (&sys_platform, "Gamecode");
|
||||
Cvar_Register (®istered, "Copy protection");
|
||||
Cvar_Register (&gameversion, "Gamecode");
|
||||
|
@ -5737,14 +5757,12 @@ void COM_Init (void)
|
|||
Cvar_Register (&gameversion_max, "Gamecode");
|
||||
Cvar_Register (&com_nogamedirnativecode, "Gamecode");
|
||||
Cvar_Register (&com_parseutf8, "Internationalisation");
|
||||
#ifndef NOLEGACY
|
||||
#if !defined(NOLEGACY) && defined(HAVE_CLIENT)
|
||||
Cvar_Register (&com_parseezquake, NULL);
|
||||
#endif
|
||||
Cvar_Register (&com_highlightcolor, "Internationalisation");
|
||||
com_parseutf8.ival = 1;
|
||||
|
||||
Cvar_Register (&r_meshpitch, "Gamecode");
|
||||
|
||||
TranslateInit();
|
||||
|
||||
COM_BiDi_Setup();
|
||||
|
@ -7115,7 +7133,7 @@ void Info_Print (const char *s, const char *lineprefix)
|
|||
}
|
||||
}*/
|
||||
|
||||
|
||||
#if defined(HAVE_CLIENT) || defined(HAVE_SERVER)
|
||||
static qbyte chktbl[1024 + 4] = {
|
||||
0x78,0xd2,0x94,0xe3,0x41,0xec,0xd6,0xd5,0xcb,0xfc,0xdb,0x8a,0x4b,0xcc,0x85,0x01,
|
||||
0x23,0xd2,0xe5,0xf2,0x29,0xa7,0x45,0x94,0x4a,0x62,0xe3,0xa5,0x6f,0x3f,0xe1,0x7a,
|
||||
|
@ -7350,6 +7368,7 @@ qbyte Q2COM_BlockSequenceCRCByte (qbyte *base, int length, int sequence)
|
|||
return crc;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -7465,3 +7484,220 @@ void COM_TimeOfDay(date_t *date)
|
|||
strftime( date->str, 128,
|
||||
"%a %b %d, %H:%M:%S %Y", newtime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_Printf
|
||||
|
||||
Handles cursor positioning, line wrapping, etc
|
||||
================
|
||||
*/
|
||||
#define MAXPRINTMSG 4096
|
||||
// FIXME: make a buffer size safe vsprintf?
|
||||
void SV_FlushRedirect (void);
|
||||
#ifndef HAVE_CLIENT
|
||||
|
||||
vfsfile_t *con_pipe;
|
||||
#ifdef HAVE_SERVER
|
||||
vfsfile_t *Con_POpen(char *conname)
|
||||
{
|
||||
if (!conname || !*conname)
|
||||
{
|
||||
if (con_pipe)
|
||||
VFS_CLOSE(con_pipe);
|
||||
con_pipe = VFSPIPE_Open(2, false);
|
||||
return con_pipe;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void Con_PrintFromThread (void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
Con_Printf("%s", (char*)data);
|
||||
BZ_Free(data);
|
||||
}
|
||||
void VARGS Con_Printf (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{
|
||||
COM_AddWork(WG_MAIN, Con_PrintFromThread, NULL, Z_StrDup(msg), 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
if (sv_redirected != -1)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
Con_Log(msg); // log to console
|
||||
|
||||
if (con_pipe)
|
||||
VFS_PUTS(con_pipe, msg);
|
||||
}
|
||||
void Con_TPrintf (translation_t stringnum, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
const char *fmt;
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{ //shouldn't be redirected anyway...
|
||||
fmt = langtext(stringnum,com_language);
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
COM_AddWork(WG_MAIN, Con_PrintFromThread, NULL, Z_StrDup(msg), 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
fmt = langtext(stringnum,sv_redirectedlang);
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
fmt = langtext(stringnum,com_language);
|
||||
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
Con_Log(msg); // log to console
|
||||
|
||||
if (con_pipe)
|
||||
VFS_PUTS(con_pipe, msg);
|
||||
}
|
||||
/*
|
||||
================
|
||||
Con_DPrintf
|
||||
|
||||
A Con_Printf that only shows up if the "developer" cvar is set
|
||||
================
|
||||
*/
|
||||
static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
Con_DLPrintf(a, "%s", (char*)data);
|
||||
BZ_Free(data);
|
||||
}
|
||||
void Con_DPrintf (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
extern cvar_t log_developer;
|
||||
|
||||
if (!developer.value && !log_developer.value)
|
||||
return;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{
|
||||
COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
if (sv_redirected != -1)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (developer.value)
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
|
||||
if (log_developer.value)
|
||||
Con_Log(msg); // log to console
|
||||
}
|
||||
void Con_DLPrintf (int level, const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
extern cvar_t log_developer;
|
||||
|
||||
if (developer.ival < level && !log_developer.value)
|
||||
return;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{
|
||||
COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), level, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SERVER
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
if (sv_redirected != -1)
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (developer.ival >= level)
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
|
||||
if (log_developer.value)
|
||||
Con_Log(msg); // log to console
|
||||
}
|
||||
|
||||
//for spammed warnings, so they don't spam prints with every single frame/call. the timer arg should be a static local.
|
||||
void VARGS Con_ThrottlePrintf (float *timer, int developerlevel, const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (developerlevel)
|
||||
Con_DLPrintf (developerlevel, "%s", msg);
|
||||
else
|
||||
Con_Printf("%s", msg);
|
||||
}
|
||||
#endif
|
|
@ -129,16 +129,16 @@ typedef enum {false, true} qboolean;
|
|||
#define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here.
|
||||
#define MAX_LOCALINFO_STRING 32768
|
||||
|
||||
#ifdef SERVERONLY
|
||||
#define cls_state 0
|
||||
#else
|
||||
#ifdef HAVE_CLIENT
|
||||
#define cls_state cls.state
|
||||
#else
|
||||
#define cls_state 0
|
||||
#endif
|
||||
|
||||
#ifdef CLIENTONLY
|
||||
#define sv_state 0
|
||||
#else
|
||||
#ifdef HAVE_SERVER
|
||||
#define sv_state sv.state
|
||||
#else
|
||||
#define sv_state 0
|
||||
#endif
|
||||
|
||||
struct netprim_s
|
||||
|
|
|
@ -746,13 +746,15 @@ static cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
|
|||
latch = "variable %s is latched and will be applied for the start of the next map\n";
|
||||
// else if (var->flags & CVAR_LATCHFLUSH)
|
||||
// latch = "variable %s is latched (type flush)\n";
|
||||
#ifdef HAVE_CLIENT
|
||||
else if (var->flags & CVAR_VIDEOLATCH && qrenderer != QR_NONE)
|
||||
latch = "variable %s will be changed after a vid_restart\n";
|
||||
else if (var->flags & CVAR_RENDERERLATCH && qrenderer != QR_NONE)
|
||||
latch = "variable %s will be changed after a vid_reload\n";
|
||||
#endif
|
||||
else if (var->flags & CVAR_RULESETLATCH)
|
||||
latch = "variable %s is latched due to current ruleset\n";
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
else if (var->flags & CVAR_CHEAT && !cls.allow_cheats && cls.state)
|
||||
latch = "variable %s is a cheat variable - latched\n";
|
||||
else if (var->flags & CVAR_SEMICHEAT && !cls.allow_semicheats && cls.state)
|
||||
|
@ -791,13 +793,13 @@ static cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
if (var->flags & CVAR_SERVERINFO)
|
||||
{
|
||||
InfoBuf_SetKey (&svs.info, var->name, value);
|
||||
}
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (var->flags & CVAR_SHADERSYSTEM)
|
||||
{
|
||||
if (var->string && value)
|
||||
|
@ -849,10 +851,10 @@ static cvar_t *Cvar_SetCore (cvar_t *var, const char *value, qboolean force)
|
|||
|
||||
if (var->flags & CVAR_TELLGAMECODE)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
SVQ1_CvarChanged(var);
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
#ifdef MENU_DAT
|
||||
MP_CvarChanged(var);
|
||||
#endif
|
||||
|
@ -1338,7 +1340,7 @@ qboolean Cvar_Command (int level)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (v->flags & CVAR_USERINFO)
|
||||
{
|
||||
int seat = CL_TargettedSplit(true);
|
||||
|
|
|
@ -12,6 +12,10 @@
|
|||
#include "winquake.h"
|
||||
#endif
|
||||
|
||||
#if (defined(HAVE_CLIENT) || defined(HAVE_SERVER)) && defined(WEBCLIENT)
|
||||
#define MANIFESTDOWNLOADS
|
||||
#endif
|
||||
|
||||
void FS_BeginManifestUpdates(void);
|
||||
static void QDECL fs_game_callback(cvar_t *var, char *oldvalue);
|
||||
static void COM_InitHomedir(ftemanifest_t *man);
|
||||
|
@ -2614,7 +2618,9 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
|
|||
BZ_Free(buffer);
|
||||
}
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_LoadPackages(oldpaths, purepath, logicalpaths, search, loadstuff, 0x80000000, -1);
|
||||
#endif
|
||||
|
||||
for (j = 0; j < sizeof(searchpathformats)/sizeof(searchpathformats[0]); j++)
|
||||
{
|
||||
|
@ -2661,7 +2667,9 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
|
|||
//now load ones from the manifest
|
||||
FS_AddManifestPackages(oldpaths, purepath, logicalpaths, search, loadstuff);
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_LoadPackages(oldpaths, purepath, logicalpaths, search, loadstuff, 0x0, 1000-1);
|
||||
#endif
|
||||
|
||||
//now load the random ones
|
||||
for (j = 0; j < sizeof(searchpathformats)/sizeof(searchpathformats[0]); j++)
|
||||
|
@ -2678,7 +2686,9 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_LoadPackages(oldpaths, purepath, logicalpaths, search, loadstuff, 1000, 0x7ffffffe);
|
||||
#endif
|
||||
}
|
||||
|
||||
static searchpath_t *FS_AddPathHandle(searchpath_t **oldpaths, const char *purepath, const char *logicalpath, searchpathfuncs_t *handle, const char *prefix, unsigned int flags, unsigned int loadstuff)
|
||||
|
@ -3057,7 +3067,7 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
|
|||
FS_ChangeGame(man, cfg_reload_on_gamedir.ival, false);
|
||||
}
|
||||
|
||||
#if defined(NOLEGACY) || defined(SERVERONLY)
|
||||
#if defined(NOLEGACY) || !defined(HAVE_CLIENT)
|
||||
#define ZFIXHACK
|
||||
#elif defined(ANDROID) //on android, these numbers seem to be generating major weirdness, so disable these.
|
||||
#define ZFIXHACK
|
||||
|
@ -3267,6 +3277,7 @@ qboolean FS_GenCachedPakName(const char *pname, const char *crc, char *local, in
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
#if 0
|
||||
qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags)
|
||||
{
|
||||
|
@ -3511,7 +3522,7 @@ void FS_PureMode(int puremode, char *purenamelist, char *purecrclist, char *refn
|
|||
{
|
||||
qboolean pureflush;
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
//if we're the server, we can't be impure.
|
||||
if (sv.state)
|
||||
return;
|
||||
|
@ -3543,7 +3554,7 @@ void FS_PureMode(int puremode, char *purenamelist, char *purecrclist, char *refn
|
|||
|
||||
if (pureflush)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
Shader_NeedReload(true);
|
||||
#endif
|
||||
Mod_ClearAll();
|
||||
|
@ -3551,7 +3562,6 @@ void FS_PureMode(int puremode, char *purenamelist, char *purecrclist, char *refn
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
int FS_PureOkay(void)
|
||||
{
|
||||
qboolean ret = true;
|
||||
|
@ -3629,6 +3639,7 @@ int FS_PureOkay(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q3CLIENT
|
||||
char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum)
|
||||
{ //this is for q3 compatibility.
|
||||
|
||||
|
@ -3667,6 +3678,7 @@ char *FSQ3_GenerateClientPacksList(char *buffer, int maxlen, int basechecksum)
|
|||
|
||||
return buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
================
|
||||
|
@ -4014,7 +4026,7 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
if (next || i != orderkey)//some path changed. make sure the fs cache is flushed.
|
||||
FS_FlushFSHashReally(false);
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
Shader_NeedReload(true);
|
||||
#endif
|
||||
// Mod_ClearAll();
|
||||
|
@ -4095,7 +4107,7 @@ static qboolean Sys_SteamHasFile(char *basepath, int basepathlen, char *steamdir
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
static INT CALLBACK StupidBrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lp, LPARAM pData)
|
||||
{ //'stolen' from microsoft's knowledge base.
|
||||
//required to work around microsoft being annoying.
|
||||
|
@ -4139,7 +4151,7 @@ int MessageBoxU(HWND hWnd, char *lpText, char *lpCaption, UINT uType);
|
|||
|
||||
qboolean Sys_DoDirectoryPrompt(char *basepath, size_t basepathsize, const char *poshname, const char *savedname)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
wchar_t resultpath[MAX_OSPATH];
|
||||
wchar_t title[MAX_OSPATH];
|
||||
BROWSEINFOW bi;
|
||||
|
@ -4305,7 +4317,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
|
|||
return true;
|
||||
}
|
||||
|
||||
#if !defined(NPFTE) && !defined(SERVERONLY) //this is *really* unfortunate, but doing this crashes the browser
|
||||
#if !defined(NPFTE) && defined(HAVE_CLIENT) //this is *really* unfortunate, but doing this crashes the browser
|
||||
if (allowprompts && poshname && *gamename && !COM_CheckParm("-manifest"))
|
||||
{
|
||||
if (Sys_DoDirectoryPrompt(basepath, basepathlen, poshname, gamename))
|
||||
|
@ -4411,7 +4423,7 @@ qboolean Sys_FindGameData(const char *poshname, const char *gamename, char *base
|
|||
}
|
||||
}
|
||||
|
||||
#if !defined(NPFTE) && !defined(SERVERONLY) //this is *really* unfortunate, but doing this crashes the browser
|
||||
#if !defined(NPFTE) && defined(HAVE_CLIENT) //this is *really* unfortunate, but doing this crashes the browser
|
||||
if (allowprompts && poshname && *gamename && !COM_CheckParm("-manifest"))
|
||||
{
|
||||
if (Sys_DoDirectoryPrompt(basepath, basepathlen, poshname, gamename))
|
||||
|
@ -4458,7 +4470,9 @@ void FS_Shutdown(void)
|
|||
if (!fs_thread_mutex)
|
||||
return;
|
||||
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_ManifestPackage(NULL, false);
|
||||
#endif
|
||||
FS_FreePaths();
|
||||
Sys_DestroyMutex(fs_thread_mutex);
|
||||
fs_thread_mutex = NULL;
|
||||
|
@ -4659,7 +4673,7 @@ static void FS_AppendManifestGameArguments(ftemanifest_t *man)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
#ifdef MANIFESTDOWNLOADS
|
||||
static char *FS_RelativeURL(char *base, char *file, char *buffer, int bufferlen)
|
||||
{
|
||||
//fixme: cope with windows paths
|
||||
|
@ -4841,7 +4855,11 @@ static void FS_PackageDownloaded(struct dl_download *dl)
|
|||
|
||||
if (fspdl_extracttype == X_UNZIP || fspdl_extracttype == X_MULTIUNZIP) //if zip...
|
||||
{ //archive
|
||||
#ifdef PACKAGE_PK3
|
||||
searchpathfuncs_t *archive = FSZIP_LoadArchive(VFSOS_Open(fspdl_temppath, "rb"), NULL, dl->url, dl->url, "");
|
||||
#else
|
||||
searchpathfuncs_t *archive = NULL;
|
||||
#endif
|
||||
if (archive)
|
||||
{
|
||||
flocation_t loc;
|
||||
|
@ -5416,17 +5434,20 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
qboolean reloadconfigs = false;
|
||||
qboolean builtingame = false;
|
||||
flocation_t loc;
|
||||
qboolean allowvidrestart = true;
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
qboolean allowvidrestart = true;
|
||||
char *vidfile[] = {"gfx.wad", "gfx/conback.lmp", //misc stuff
|
||||
"gfx/palette.lmp", "pics/colormap.pcx"}; //palettes
|
||||
searchpathfuncs_t *vidpath[countof(vidfile)];
|
||||
#endif
|
||||
|
||||
//if any of these files change location, the configs will be re-execed.
|
||||
//note that we reuse path handles if they're still valid, so we can just check the pointer to see if it got unloaded/replaced.
|
||||
char *conffile[] = {"quake.rc", "hexen.rc", "default.cfg", "server.cfg"};
|
||||
searchpathfuncs_t *confpath[countof(conffile)];
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
for (i = 0; i < countof(vidfile); i++)
|
||||
{
|
||||
if (allowvidrestart)
|
||||
|
@ -5437,6 +5458,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
else
|
||||
vidpath[i] = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (allowreloadconfigs && fs_noreexec.ival)
|
||||
allowreloadconfigs = false;
|
||||
|
@ -5600,7 +5622,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
{
|
||||
if (Sys_FindGameData(man->formalname, man->installation, realpath, sizeof(realpath), man->security != MANIFEST_SECURITY_INSTALLER) && FS_FixPath(realpath, sizeof(realpath)) && FS_DirHasAPackage(realpath, man))
|
||||
Q_strncpyz (newbasedir, realpath, sizeof(newbasedir));
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
else
|
||||
{
|
||||
Z_Free(man->updatefile);
|
||||
|
@ -5614,7 +5636,9 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
{
|
||||
if (strcmp(com_gamepath, newbasedir))
|
||||
{
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
Q_strncpyz (com_gamepath, newbasedir, sizeof(com_gamepath));
|
||||
}
|
||||
}
|
||||
|
@ -5664,7 +5688,9 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
|
||||
if (Sys_LockMutex(fs_thread_mutex))
|
||||
{
|
||||
#ifdef HAVE_CLIENT
|
||||
qboolean vidrestart = false;
|
||||
#endif
|
||||
|
||||
FS_ReloadPackFilesFlags(~0);
|
||||
|
||||
|
@ -5672,14 +5698,14 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
|
||||
FS_BeginManifestUpdates();
|
||||
|
||||
#ifdef WEBCLIENT
|
||||
#ifdef MANIFESTDOWNLOADS
|
||||
if (curpackagedownload && fs_loadedcommand)
|
||||
allowreloadconfigs = false;
|
||||
#endif
|
||||
|
||||
COM_CheckRegistered();
|
||||
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
if (qrenderer != QR_NONE && allowvidrestart)
|
||||
{
|
||||
for (i = 0; i < countof(vidfile); i++)
|
||||
|
@ -5692,6 +5718,7 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (allowreloadconfigs)
|
||||
{
|
||||
|
@ -5714,28 +5741,30 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
Cvar_ForceSet(&fs_gamename, fs_gamename.enginevalue);
|
||||
Cvar_ForceSet(&pm_downloads_url, pm_downloads_url.enginevalue);
|
||||
Cvar_ForceSet(&com_protocolname, com_protocolname.enginevalue);
|
||||
#ifdef HAVE_CLIENT
|
||||
vidrestart = false;
|
||||
#endif
|
||||
|
||||
if (isDedicated)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
SV_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
CL_ExecInitialConfigs(man->defaultexec?man->defaultexec:"");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_CLIENT
|
||||
else if (vidrestart)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
|
||||
#endif
|
||||
vidrestart = false;
|
||||
}
|
||||
#endif
|
||||
if (fs_loadedcommand)
|
||||
{
|
||||
Cbuf_AddText(fs_loadedcommand, RESTRICT_INSECURE);
|
||||
|
@ -5743,19 +5772,19 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
|
|||
fs_loadedcommand = NULL;
|
||||
}
|
||||
}
|
||||
#ifdef HAVE_CLIENT
|
||||
if (vidrestart)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
Cbuf_AddText ("vid_reload\n", RESTRICT_LOCAL);
|
||||
#endif
|
||||
vidrestart = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
//rebuild the cache now, should be safe to waste some cycles on it
|
||||
COM_FlushFSCache(false, true);
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
Validation_FlushFileList(); //prevent previous hacks from making a difference.
|
||||
#endif
|
||||
|
||||
|
@ -6051,13 +6080,15 @@ static void FS_ChangeGame_f(void)
|
|||
if (!Q_strcasecmp(gamemode_info[i].argname+1, arg))
|
||||
{
|
||||
Con_Printf("Switching to %s\n", gamemode_info[i].argname+1);
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
FS_ChangeGame(FS_GenerateLegacyManifest(NULL, 0, true, i), true, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (!Host_RunFile(arg, strlen(arg), NULL))
|
||||
Con_Printf("Game unknown\n");
|
||||
#endif
|
||||
|
|
|
@ -520,7 +520,7 @@ static void IPLog_Identify_f(void)
|
|||
//treading carefully here, to avoid dns name lookups weirding everything out.
|
||||
IPLog_Identify(&adr, &mask, "Identity of %s", NET_AdrToStringMasked(clean, sizeof(clean), &adr, &mask));
|
||||
}
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
else if (sv.active)
|
||||
{ //if server is active, walk players to see if there's a name match to get their address and guess an address mask
|
||||
client_t *cl;
|
||||
|
@ -537,7 +537,7 @@ static void IPLog_Identify_f(void)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
else if (cls.state >= ca_connected)
|
||||
{ //else if client is active, walk players to see if there's a name match, to get their address+mask if known via nq hacks
|
||||
int slot;
|
||||
|
@ -630,7 +630,7 @@ static void IPLog_Merge_f(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT //requires UI prompts
|
||||
struct certlog_s
|
||||
{
|
||||
link_t l;
|
||||
|
@ -849,7 +849,7 @@ void Log_Init(void)
|
|||
if (COM_CheckParm("-condebug"))
|
||||
Cvar_ForceSet(&log_enable[LOG_CONSOLE], "1");
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
ClearLink(&certlog);
|
||||
Cmd_AddCommand("dtls_untrustall", CertLog_UntrustAll_f);
|
||||
Cmd_AddCommand("dtls_importtrust", CertLog_Import_f);
|
||||
|
|
|
@ -131,14 +131,14 @@ void SVNET_RegisterCvars(void);
|
|||
void NET_InitClient (qboolean loopbackonly);
|
||||
void NET_CloseClient(void);
|
||||
void NET_InitServer (void);
|
||||
qboolean NET_WasSpecialPacket(netsrc_t netsrc);
|
||||
qboolean NET_WasSpecialPacket(struct ftenet_connections_s *col);
|
||||
void NET_CloseServer (void);
|
||||
void UDP_CloseSocket (int socket);
|
||||
void NET_Shutdown (void);
|
||||
qboolean NET_GetRates(struct ftenet_connections_s *collection, float *pi, float *po, float *bi, float *bo);
|
||||
qboolean NET_UpdateRates(struct ftenet_connections_s *collection, qboolean inbound, size_t size); //for demos to not be weird
|
||||
int NET_GetPacket (netsrc_t netsrc, int firstsock);
|
||||
neterr_t NET_SendPacket (netsrc_t socket, int length, const void *data, netadr_t *to);
|
||||
int NET_GetPacket (struct ftenet_connections_s *col, int firstsock);
|
||||
neterr_t NET_SendPacket (struct ftenet_connections_s *col, int length, const void *data, netadr_t *to);
|
||||
int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx);
|
||||
void NET_PrintAddresses(struct ftenet_connections_s *collection);
|
||||
qboolean NET_AddressSmellsFunny(netadr_t *a);
|
||||
|
|
|
@ -91,6 +91,14 @@ cvar_t pext_infoblobs = CVARD("_pext_infoblobs", "0", "RENAME ME WHEN STABLE. En
|
|||
cvar_t pext_replacementdeltas = CVARD("pext_replacementdeltas", "1", "Enables the use of alternative nack-based entity deltas");
|
||||
cvar_t pext_predinfo = CVARD("pext_predinfo", "1", "Enables some extra things to support prediction over NQ protocols.");
|
||||
|
||||
#if defined(HAVE_CLIENT) && defined(HAVE_SERVER)
|
||||
#define NET_SendPacket(c,s,d,t) NET_SendPacket(((c)!=NS_CLIENT)?svs.sockets:cls.sockets,s,d,t)
|
||||
#elif defined(HAVE_SERVER)
|
||||
#define NET_SendPacket(c,s,d,t) NET_SendPacket(svs.sockets,s,d,t)
|
||||
#else
|
||||
#define NET_SendPacket(c,s,d,t) NET_SendPacket(cls.sockets,s,d,t)
|
||||
#endif
|
||||
|
||||
/*returns the entire bitmask of supported+enabled extensions*/
|
||||
unsigned int Net_PextMask(int maskset, qboolean fornq)
|
||||
{
|
||||
|
|
|
@ -209,7 +209,7 @@ qboolean NET_RTP_Transmit(unsigned int sequence, unsigned int timestamp, const c
|
|||
if (buf.overflowed)
|
||||
return built;
|
||||
}
|
||||
NET_SendPacket(NS_CLIENT, buf.cursize, buf.data, &con->chosenpeer);
|
||||
NET_SendPacket(cls.sockets, buf.cursize, buf.data, &con->chosenpeer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ void ICE_ToStunServer(struct icestate_s *con)
|
|||
data[2] = ((buf.cursize-20)>>8)&0xff;
|
||||
data[3] = ((buf.cursize-20)>>0)&0xff;
|
||||
|
||||
NET_SendPacket((con->proto==ICEP_QWSERVER)?NS_SERVER:NS_CLIENT, buf.cursize, data, &con->pubstunserver);
|
||||
NET_SendPacket(collection, buf.cursize, data, &con->pubstunserver);
|
||||
}
|
||||
|
||||
void QDECL ICE_AddRCandidateInfo(struct icestate_s *con, struct icecandinfo_s *n)
|
||||
|
@ -1129,10 +1129,10 @@ icefuncs_t iceapi =
|
|||
ICE_GetLCandidateSDP
|
||||
};
|
||||
|
||||
qboolean ICE_WasStun(netsrc_t netsrc)
|
||||
qboolean ICE_WasStun(ftenet_connections_t *col)
|
||||
{
|
||||
#if !defined(SERVERONLY) && defined(VOICECHAT)
|
||||
if (netsrc == NS_CLIENT)
|
||||
#if defined(HAVE_CLIENT) && defined(VOICECHAT)
|
||||
if (col == cls.sockets)
|
||||
{
|
||||
if (NET_RTP_Parse())
|
||||
return true;
|
||||
|
@ -1528,7 +1528,7 @@ qboolean ICE_WasStun(netsrc_t netsrc)
|
|||
|
||||
data[2] = ((buf.cursize-20)>>8)&0xff;
|
||||
data[3] = ((buf.cursize-20)>>0)&0xff;
|
||||
NET_SendPacket(netsrc, buf.cursize, data, &net_from);
|
||||
NET_SendPacket(col, buf.cursize, data, &net_from);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -463,7 +463,7 @@ static struct
|
|||
|
||||
static int SSL_CheckUserTrust(gnutls_session_t session, gnutlsfile_t *file, int ret)
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
//when using dtls, we expect self-signed certs and persistent trust.
|
||||
if (file->datagram)
|
||||
{
|
||||
|
|
|
@ -108,10 +108,14 @@ void (*pfreeaddrinfo) (struct addrinfo*);
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_IPV4) && !defined(CLIENTONLY)
|
||||
#if defined(HAVE_IPV4) && defined(HAVE_SERVER)
|
||||
#define HAVE_NATPMP
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SERVER) || defined(MASTERONLY)
|
||||
#define HAVE_HTTPSV
|
||||
#endif
|
||||
|
||||
void NET_GetLocalAddress (int socket, netadr_t *out);
|
||||
//int TCP_OpenListenSocket (const char *localip, int port);
|
||||
#ifdef HAVE_IPV6
|
||||
|
@ -124,17 +128,23 @@ cvar_t timeout = CVARD("timeout","65", "Connections will time out if no pack
|
|||
cvar_t net_hybriddualstack = CVARD("net_hybriddualstack", "1", "Uses hybrid ipv4+ipv6 sockets where possible. Not supported on xp or below.");
|
||||
cvar_t net_fakeloss = CVARFD("net_fakeloss", "0", CVAR_CHEAT, "Simulates packetloss in both receiving and sending, on a scale from 0 to 1.");
|
||||
cvar_t net_enabled = CVARD("net_enabled", "1", "If 0, disables all network access, including name resolution and socket creation. Does not affect loopback/internal connections.");
|
||||
#if defined(TCPCONNECT) && !defined(CLIENTONLY)
|
||||
#if defined(TCPCONNECT) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
|
||||
#ifdef HAVE_SERVER
|
||||
cvar_t net_enable_qizmo = CVARD("net_enable_qizmo", "1", "Enables compatibility with qizmo's tcp connections serverside. Frankly, using sv_port_tcp without this is a bit pointless.");
|
||||
cvar_t net_enable_qtv = CVARD("net_enable_qtv", "1", "Listens for qtv proxies, or clients using the qtvplay command.");
|
||||
#endif
|
||||
#if defined(HAVE_SSL)
|
||||
cvar_t net_enable_tls = CVARD("net_enable_tls", "1", "If enabled, binary data sent to a non-tls tcp port will be interpretted as a tls handshake (enabling https or wss over the same tcp port.");
|
||||
#endif
|
||||
#ifdef SV_MASTER
|
||||
cvar_t net_enable_http = CVARD("net_enable_http", "1", "If enabled, tcp ports will accept http clients, potentially serving large files which could distrupt gameplay.");
|
||||
#else
|
||||
cvar_t net_enable_http = CVARD("net_enable_http", "0", "If enabled, tcp ports will accept http clients, potentially serving large files which could distrupt gameplay.");
|
||||
#endif
|
||||
cvar_t net_enable_websockets = CVARD("net_enable_websockets", "1", "If enabled, tcp ports will accept websocket game clients.");
|
||||
cvar_t net_enable_webrtcbroker = CVARD("net_enable_webrtcbroker", "0", "If 1, tcp ports will accept websocket connections from clients trying to broker direct webrtc connections. This should be low traffic, but might involve a lot of mostly-idle connections.");
|
||||
#endif
|
||||
#if defined(HAVE_DTLS) && !defined(CLIENTONLY)
|
||||
#if defined(HAVE_DTLS) && defined(HAVE_SERVER)
|
||||
static void QDECL NET_Enable_DTLS_Changed(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
//set up the default value
|
||||
|
@ -156,7 +166,7 @@ static void QDECL NET_Enable_DTLS_Changed(struct cvar_s *var, char *oldvalue)
|
|||
cvar_t net_enable_dtls = CVARAFCD("net_enable_dtls", "", "sv_listen_dtls", 0, NET_Enable_DTLS_Changed, "Controls serverside dtls support.\n0: dtls blocked, not advertised.\n1: available in desired.\n2: used where possible (recommended setting).\n3: disallow non-dtls clients (sv_port_tcp should be eg tls://[::]:27500 to also disallow unencrypted tcp connections).");
|
||||
#endif
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
static void QDECL cl_delay_packets_Announce(cvar_t *var, char *oldval)
|
||||
{
|
||||
if (cls.state >= ca_connected && cl.fpd & FPD_ANOUNCE_FAKE_LAG)
|
||||
|
@ -2079,7 +2089,7 @@ int TLS_GetChannelBinding(vfsfile_t *stream, qbyte *data, size_t *datasize)
|
|||
/////////////////////////////////////////////
|
||||
//loopback stuff
|
||||
|
||||
#if !defined(CLIENTONLY) && !defined(SERVERONLY)
|
||||
#if defined(HAVE_SERVER) && defined(HAVE_CLIENT)
|
||||
|
||||
qboolean NET_GetLoopPacket (int sock, netadr_t *from, sizebuf_t *message)
|
||||
{
|
||||
|
@ -2240,7 +2250,7 @@ ftenet_connections_t *FTENET_CreateCollection(qboolean listen)
|
|||
col->islisten = listen;
|
||||
return col;
|
||||
}
|
||||
#if !defined(SERVERONLY) && !defined(CLIENTONLY)
|
||||
#if defined(HAVE_CLIENT) && defined(HAVE_SERVER)
|
||||
static ftenet_generic_connection_t *FTENET_Loop_EstablishConnection(qboolean isserver, const char *address, netadr_t adr);
|
||||
#endif
|
||||
#ifdef HAVE_PACKET
|
||||
|
@ -2438,11 +2448,11 @@ static void FTENET_NATPMP_Refresh(pmpcon_t *pmp, short oldport, ftenet_connectio
|
|||
|
||||
//get the public ip.
|
||||
pmpreqmsg.op = 0;
|
||||
NET_SendPacket(NS_SERVER, 2, &pmpreqmsg, &pmp->pmpaddr);
|
||||
NET_SendPacket(collection, 2, &pmpreqmsg, &pmp->pmpaddr);
|
||||
|
||||
//open the firewall/nat.
|
||||
pmpreqmsg.op = 1;
|
||||
NET_SendPacket(NS_SERVER, sizeof(pmpreqmsg), &pmpreqmsg, &pmp->pmpaddr);
|
||||
NET_SendPacket(collection, sizeof(pmpreqmsg), &pmpreqmsg, &pmp->pmpaddr);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -2837,7 +2847,7 @@ qboolean FTENET_AddToCollection(ftenet_connections_t *col, const char *name, con
|
|||
#ifdef HAVE_NATPMP
|
||||
if (adr[i].prot == NP_NATPMP&& adr[i].type == NA_IP) establish[i] = FTENET_NATPMP_EstablishConnection; else
|
||||
#endif
|
||||
#if !defined(CLIENTONLY) && !defined(SERVERONLY)
|
||||
#if defined(HAVE_CLIENT) && defined(HAVE_SERVER)
|
||||
if (adr[i].prot == NP_DGRAM && adr[i].type == NA_LOOPBACK) establish[i] = FTENET_Loop_EstablishConnection; else
|
||||
#endif
|
||||
#ifdef HAVE_IPV4
|
||||
|
@ -3231,7 +3241,7 @@ qboolean FTENET_Datagram_GetPacket(ftenet_generic_connection_t *con)
|
|||
else
|
||||
Con_TPrintf ("Connection lost or aborted\n"); //server died/connection lost.
|
||||
resettime = curtime;
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
//fixme: synthesise a reset packet for the caller to handle? "\xff\xff\xff\xffreset" ?
|
||||
if (cls.state != ca_disconnected && !con->islisten)
|
||||
{
|
||||
|
@ -3324,6 +3334,9 @@ neterr_t FTENET_Datagram_SendPacket(ftenet_generic_connection_t *con, int length
|
|||
if (ecode == NET_EMSGSIZE)
|
||||
return NETERR_MTU;
|
||||
|
||||
if (ecode == EADDRNOTAVAIL)
|
||||
return NETERR_NOROUTE; //this interface doesn't actually support that (eg: happens when ipv6 is disabled on a specific interface).
|
||||
|
||||
if (ecode == NET_EACCES)
|
||||
{
|
||||
Con_Printf("Access denied: check firewall\n");
|
||||
|
@ -3340,7 +3353,7 @@ neterr_t FTENET_Datagram_SendPacket(ftenet_generic_connection_t *con, int length
|
|||
default: prot = ""; break;
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
if (ecode == NET_EADDRNOTAVAIL)
|
||||
Con_DPrintf("NET_Send%sPacket Warning: %i\n", prot, ecode);
|
||||
else
|
||||
|
@ -3652,7 +3665,7 @@ typedef struct ftenet_tcpconnect_stream_s {
|
|||
TCPC_WEBSOCKETU, //utf-8 encoded data.
|
||||
TCPC_WEBSOCKETB, //binary encoded data (subprotocol = 'binary')
|
||||
TCPC_WEBSOCKETNQ, //raw nq msg buffers with no encapsulation or handshake
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
TCPC_HTTPCLIENT, //we're sending a file to this victim.
|
||||
TCPC_WEBRTC_CLIENT, //for brokering webrtc connections, doesn't carry any actual game data itself.
|
||||
TCPC_WEBRTC_HOST //for brokering webrtc connections, doesn't carry any actual game data itself.
|
||||
|
@ -3670,7 +3683,7 @@ typedef struct ftenet_tcpconnect_stream_s {
|
|||
|
||||
int fakesequence; //TCPC_WEBSOCKETNQ
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
struct
|
||||
{
|
||||
qboolean connection_close;
|
||||
|
@ -3810,7 +3823,7 @@ neterr_t FTENET_TCPConnect_WebSocket_Splurge(ftenet_tcpconnect_stream_t *st, qby
|
|||
return NETERR_SENT;
|
||||
}
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
enum
|
||||
{
|
||||
WCATTR_METHOD,
|
||||
|
@ -3866,7 +3879,9 @@ qboolean FTENET_TCPConnect_HTTPResponse(ftenet_tcpconnect_stream_t *st, httparg_
|
|||
char *extraheaders = "";
|
||||
time_t modificationtime = 0;
|
||||
char *query = strchr(arg[WCATTR_URL]+1, '?');
|
||||
#ifdef HAVE_SERVER
|
||||
func_t func = 0;
|
||||
#endif
|
||||
if (query)
|
||||
*query++ = 0;
|
||||
|
||||
|
@ -3875,6 +3890,7 @@ qboolean FTENET_TCPConnect_HTTPResponse(ftenet_tcpconnect_stream_t *st, httparg_
|
|||
if (!*name)
|
||||
name = "index.html";
|
||||
|
||||
#ifdef HAVE_SERVER
|
||||
if (sv.state && svs.gametype == GT_PROGS && svprogfuncs)
|
||||
func = svprogfuncs->FindFunction(svprogfuncs, "HTTP_GeneratePage", PR_ANY);
|
||||
|
||||
|
@ -3898,42 +3914,12 @@ qboolean FTENET_TCPConnect_HTTPResponse(ftenet_tcpconnect_stream_t *st, httparg_
|
|||
resp = va("%s%s", *body?"HTTP/1.1 200 Ok\r\n":"HTTP/1.1 404 File Not Found\r\n", resp);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//FIXME: provide some resource->filename mapping that allows various misc files.
|
||||
|
||||
if (body)
|
||||
;
|
||||
else if (!strcmp(name, "index.html"))
|
||||
{
|
||||
resp = "HTTP/1.1 200 Ok\r\n"
|
||||
"Content-Type: text/html\r\n";
|
||||
|
||||
body = va(
|
||||
"<html lang='en-us'>"
|
||||
"<head>"
|
||||
"<meta charset='utf-8'>"
|
||||
"<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"
|
||||
"<meta name=viewport content='width=device-width, initial-scale=1'>"
|
||||
#ifdef _WIN32
|
||||
"<link rel='icon' type='image/vnd.microsoft.icon' href='/favicon.ico' />"
|
||||
#else
|
||||
"<link rel='icon' type='image/vnd.microsoft.icon' href='"ENGINEWEBSITE"/favicon.ico' />"
|
||||
#endif
|
||||
"<title>%s - %s</title>"
|
||||
"<style>"
|
||||
"body { background-color:#000000; color:#808080; height:100%%;width:100%%;margin:0;padding:0;}"
|
||||
"</style>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<iframe name='steve'"
|
||||
" src='%s/%s?+connect%%20%s%s' allowfullscreen=true"
|
||||
" frameborder='0' scrolling='no' marginheight='0' marginwidth='0' width='100%%' height='100%%'"
|
||||
" onerror=\"alert('Failed to load engine')\">"
|
||||
"</iframe>"
|
||||
"</body>"
|
||||
"</html>"
|
||||
,fs_manifest->formalname, hostname.string, ENGINEWEBSITE, fs_manifest->installation, (st->remoteaddr.prot==NP_TLS)?"wss://":"ws://", arg[WCATTR_HOST]);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else if (!strcmp(name, "favicon.ico"))
|
||||
{ //we can serve up the icon from the exe. we just have to reformat it a little.
|
||||
|
@ -4001,6 +3987,42 @@ qboolean FTENET_TCPConnect_HTTPResponse(ftenet_tcpconnect_stream_t *st, httparg_
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(SV_MASTER) && !defined(HAVE_SERVER)
|
||||
else if ((st->dlfile=SVM_GenerateIndex(name)))
|
||||
;
|
||||
#endif
|
||||
#ifdef HAVE_SERVER
|
||||
else if (!strcmp(name, "index.html"))
|
||||
{
|
||||
resp = "HTTP/1.1 200 Ok\r\n"
|
||||
"Content-Type: text/html\r\n";
|
||||
|
||||
body = va(
|
||||
"<html lang='en-us'>"
|
||||
"<head>"
|
||||
"<meta charset='utf-8'>"
|
||||
"<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"
|
||||
"<meta name=viewport content='width=device-width, initial-scale=1'>"
|
||||
#ifdef _WIN32
|
||||
"<link rel='icon' type='image/vnd.microsoft.icon' href='/favicon.ico' />"
|
||||
#else
|
||||
"<link rel='icon' type='image/vnd.microsoft.icon' href='"ENGINEWEBSITE"/favicon.ico' />"
|
||||
#endif
|
||||
"<title>%s - %s</title>"
|
||||
"<style>"
|
||||
"body { background-color:#000000; color:#808080; height:100%%;width:100%%;margin:0;padding:0;}"
|
||||
"</style>"
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<iframe name='steve'"
|
||||
" src='%s/%s?+connect%%20%s%s' allowfullscreen=true"
|
||||
" frameborder='0' scrolling='no' marginheight='0' marginwidth='0' width='100%%' height='100%%'"
|
||||
" onerror=\"alert('Failed to load engine')\">"
|
||||
"</iframe>"
|
||||
"</body>"
|
||||
"</html>"
|
||||
,fs_manifest->formalname, hostname.string, ENGINEWEBSITE, fs_manifest->installation, (st->remoteaddr.prot==NP_TLS)?"wss://":"ws://", arg[WCATTR_HOST]);
|
||||
}
|
||||
/*else if (!strcmp(name, "default.fmf") && (st->dlfile = FS_OpenVFS("default.fmf", "rb", FS_ROOT)))
|
||||
{
|
||||
resp = "HTTP/1.1 200 Ok\r\n"
|
||||
|
@ -4095,6 +4117,7 @@ qboolean FTENET_TCPConnect_HTTPResponse(ftenet_tcpconnect_stream_t *st, httparg_
|
|||
else
|
||||
st->dlfile = NULL;
|
||||
}
|
||||
#endif
|
||||
if (st->dlfile)
|
||||
{
|
||||
char etag[64];
|
||||
|
@ -4700,7 +4723,7 @@ void FTENET_TCPConnect_PrintStatus(ftenet_generic_connection_t *gcon)
|
|||
case TCPC_WEBSOCKETNQ:
|
||||
Con_Printf("websocket %s\n", adr);
|
||||
break;
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_HTTPCLIENT:
|
||||
Con_Printf("http %s\n", adr);
|
||||
break;
|
||||
|
@ -4750,7 +4773,7 @@ qboolean FTENET_TCPConnect_GetPacket(ftenet_generic_connection_t *gcon)
|
|||
|
||||
if (st->timeouttime < timeval)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
if (!st->pinging && (st->clienttype==TCPC_WEBRTC_CLIENT||st->clienttype==TCPC_WEBRTC_HOST) && *st->webrtc.resource)
|
||||
{ //ping broker clients. there usually shouldn't be any data flow to keep it active otherwise.
|
||||
st->timeouttime = timeval + 30;
|
||||
|
@ -4761,7 +4784,7 @@ qboolean FTENET_TCPConnect_GetPacket(ftenet_generic_connection_t *gcon)
|
|||
else
|
||||
#endif
|
||||
{
|
||||
Con_Printf ("tcp peer %s timed out\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr));
|
||||
Con_DPrintf ("tcp peer %s timed out\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr));
|
||||
goto closesvstream;
|
||||
}
|
||||
}
|
||||
|
@ -4784,10 +4807,11 @@ closesvstream:
|
|||
if (st->inlen < 6)
|
||||
continue;
|
||||
|
||||
#if defined(HAVE_SSL) && !defined(CLIENTONLY) //if its non-ascii, then try and upgrade the connection to tls
|
||||
#if defined(HAVE_SSL) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV)) //if its non-ascii, then try and upgrade the connection to tls
|
||||
if (net_enable_tls.ival && con->generic.islisten && st->remoteaddr.prot == NP_STREAM && st->clientstream && !((st->inbuffer[0] >= 'a' && st->inbuffer[0] <= 'z') || (st->inbuffer[0] >= 'A' && st->inbuffer[0] <= 'Z')))
|
||||
{
|
||||
//copy off our buffer so we can read it into the tls stream's buffer instead.
|
||||
char tmpbuf[256];
|
||||
vfsfile_t *stream = st->clientstream;
|
||||
int (QDECL *realread) (struct vfsfile_s *file, void *buffer, int bytestoread);
|
||||
realread = stream->ReadBytes;
|
||||
|
@ -4806,6 +4830,8 @@ closesvstream:
|
|||
}
|
||||
if (!st->clientstream || net_message.cursize)
|
||||
goto closesvstream; //something cocked up. we didn't give the tls stream all the data.
|
||||
if (developer.ival)
|
||||
Con_Printf("promoted peer to tls: %s\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &st->remoteaddr));
|
||||
net_message.cursize = 0;
|
||||
continue;
|
||||
}
|
||||
|
@ -4813,11 +4839,11 @@ closesvstream:
|
|||
|
||||
if (!strncmp(st->inbuffer, "qizmo\n", 6))
|
||||
{
|
||||
#ifdef CLIENTONLY
|
||||
if (1)
|
||||
#else
|
||||
if (net_enable_qizmo.ival || !con->generic.islisten)
|
||||
if (
|
||||
#ifdef HAVE_SERVER
|
||||
net_enable_qizmo.ival ||
|
||||
#endif
|
||||
!con->generic.islisten)
|
||||
{
|
||||
memmove(st->inbuffer, st->inbuffer+6, st->inlen - (6));
|
||||
st->inlen -= 6;
|
||||
|
@ -4830,9 +4856,9 @@ closesvstream:
|
|||
}
|
||||
else
|
||||
goto closesvstream;
|
||||
}
|
||||
#ifndef CLIENTONLY
|
||||
else if (con->generic.islisten)// && !strncmp(st->inbuffer, "GET ", 4))
|
||||
}else
|
||||
#ifdef HAVE_HTTPSV
|
||||
if (con->generic.islisten)// && !strncmp(st->inbuffer, "GET ", 4))
|
||||
{
|
||||
//qtv or http request header. these terminate with a blank line.
|
||||
int i = 0;
|
||||
|
@ -4889,16 +4915,15 @@ closesvstream:
|
|||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
else
|
||||
{
|
||||
Con_Printf ("Unknown TCP handshake from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr));
|
||||
Con_DPrintf ("Unknown TCP handshake from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr));
|
||||
goto closesvstream;
|
||||
}
|
||||
|
||||
break;
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_HTTPCLIENT:
|
||||
if (st->outlen)
|
||||
{ /*try and flush the old data*/
|
||||
|
@ -4924,7 +4949,7 @@ closesvstream:
|
|||
VFS_CLOSE(st->dlfile);
|
||||
st->dlfile = NULL;
|
||||
st->clienttype = TCPC_UNKNOWN;
|
||||
Con_Printf ("Outgoing file transfer complete\n");
|
||||
Con_DPrintf ("Outgoing file transfer complete\n");
|
||||
if (st->httpstate.connection_close)
|
||||
goto closesvstream;
|
||||
}
|
||||
|
@ -4958,7 +4983,7 @@ closesvstream:
|
|||
case TCPC_WEBSOCKETU:
|
||||
case TCPC_WEBSOCKETB:
|
||||
case TCPC_WEBSOCKETNQ:
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_WEBRTC_HOST:
|
||||
case TCPC_WEBRTC_CLIENT:
|
||||
#endif
|
||||
|
@ -5108,7 +5133,7 @@ closesvstream:
|
|||
Con_TPrintf ("Warning: Oversize packet from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr));
|
||||
goto closesvstream;
|
||||
}
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
#ifdef SUPPORT_RTC_ICE
|
||||
if (st->clienttype == TCPC_WEBRTC_CLIENT && !*st->webrtc.resource)
|
||||
{ //this is a client that's corrected directly to us via webrtc.
|
||||
|
@ -5211,6 +5236,8 @@ closesvstream:
|
|||
st = Z_Malloc(sizeof(*con->tcpstreams));
|
||||
/*grab the net address*/
|
||||
SockadrToNetadr(&from, fromlen, &st->remoteaddr);
|
||||
if (developer.ival)
|
||||
Con_Printf("new TCP connection from %s\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &st->remoteaddr));
|
||||
st->clienttype = TCPC_UNKNOWN;
|
||||
st->next = con->tcpstreams;
|
||||
con->tcpstreams = st;
|
||||
|
@ -5489,7 +5516,7 @@ int FTENET_TCPConnect_SetFDSets(ftenet_generic_connection_t *gcon, fd_set *readf
|
|||
#endif
|
||||
if (st->clientstream == NULL || st->socketnum == INVALID_SOCKET)
|
||||
continue;
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_HTTPSV
|
||||
if (st->clienttype == TCPC_HTTPCLIENT)
|
||||
FD_SET(st->socketnum, writefdset); // network socket
|
||||
#endif
|
||||
|
@ -6839,7 +6866,7 @@ qboolean NET_GetRates(ftenet_connections_t *collection, float *pi, float *po, fl
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
//for demo playback
|
||||
qboolean NET_UpdateRates(ftenet_connections_t *collection, qboolean inbound, size_t size)
|
||||
{
|
||||
|
@ -6877,29 +6904,10 @@ qboolean NET_UpdateRates(ftenet_connections_t *collection, qboolean inbound, siz
|
|||
#endif
|
||||
|
||||
/*firstsock is a cookie*/
|
||||
int NET_GetPacket (netsrc_t netsrc, int firstsock)
|
||||
int NET_GetPacket (ftenet_connections_t *collection, int firstsock)
|
||||
{
|
||||
struct ftenet_delayed_packet_s *p;
|
||||
ftenet_connections_t *collection;
|
||||
unsigned int ctime;
|
||||
if (netsrc == NS_SERVER)
|
||||
{
|
||||
#ifdef CLIENTONLY
|
||||
Sys_Error("NET_GetPacket: Bad netsrc");
|
||||
collection = NULL;
|
||||
#else
|
||||
collection = svs.sockets;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SERVERONLY
|
||||
Sys_Error("NET_GetPacket: Bad netsrc");
|
||||
collection = NULL;
|
||||
#else
|
||||
collection = cls.sockets;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!collection)
|
||||
return -1;
|
||||
|
@ -7032,28 +7040,13 @@ static neterr_t NET_SendPacketCol (ftenet_connections_t *collection, int length,
|
|||
return NETERR_NOROUTE;
|
||||
}
|
||||
|
||||
neterr_t NET_SendPacket (netsrc_t netsrc, int length, const void *data, netadr_t *to)
|
||||
neterr_t NET_SendPacket (ftenet_connections_t *collection, int length, const void *data, netadr_t *to)
|
||||
{
|
||||
ftenet_connections_t *collection;
|
||||
|
||||
if (netsrc == NS_SERVER)
|
||||
{
|
||||
#ifdef CLIENTONLY
|
||||
Sys_Error("NET_GetPacket: Bad netsrc");
|
||||
if (!collection)
|
||||
return NETERR_NOROUTE;
|
||||
#else
|
||||
collection = svs.sockets;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SERVERONLY
|
||||
Sys_Error("NET_GetPacket: Bad netsrc");
|
||||
return NETERR_NOROUTE;
|
||||
#else
|
||||
collection = cls.sockets;
|
||||
|
||||
if (cl_delay_packets.ival >= 1 && !(cl.fpd & FPD_NO_FAKE_LAG))
|
||||
#ifdef HAVE_CLIENT
|
||||
if (collection == cls.sockets && cl_delay_packets.ival >= 1 && !(cl.fpd & FPD_NO_FAKE_LAG))
|
||||
{
|
||||
struct ftenet_delayed_packet_s *p, **l;
|
||||
if (!collection)
|
||||
|
@ -7070,7 +7063,7 @@ neterr_t NET_SendPacket (netsrc_t netsrc, int length, const void *data, netadr_t
|
|||
return NETERR_SENT; //fixme: mtu, noroute, etc... panic? only allow if udp dest?
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_DTLS
|
||||
if (to->prot == NP_DTLS)
|
||||
return FTENET_DTLS_SendPacket(collection, length, data, to);
|
||||
|
@ -7592,7 +7585,6 @@ void IPX_CloseSocket (int socket)
|
|||
// sleeps msec or until net socket is ready
|
||||
//stdin can sometimes be a socket. As a result,
|
||||
//we give the option to select it for nice console imput with timeouts.
|
||||
#ifndef CLIENTONLY
|
||||
qboolean NET_Sleep(float seconds, qboolean stdinissocket)
|
||||
{
|
||||
#ifdef HAVE_PACKET
|
||||
|
@ -7613,6 +7605,34 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket)
|
|||
maxfd = sock;
|
||||
}
|
||||
|
||||
#ifdef SV_MASTER
|
||||
{
|
||||
extern ftenet_connections_t *svm_sockets;
|
||||
if (svm_sockets)
|
||||
for (con = 0; con < MAX_CONNECTIONS; con++)
|
||||
{
|
||||
if (!svm_sockets->conn[con])
|
||||
continue;
|
||||
if (svm_sockets->conn[con]->SetFDSets)
|
||||
{
|
||||
sock = svm_sockets->conn[con]->SetFDSets(svm_sockets->conn[con], &readfdset, &writefdset);
|
||||
if (sock > maxfd)
|
||||
maxfd = sock;
|
||||
}
|
||||
else
|
||||
{
|
||||
sock = svm_sockets->conn[con]->thesocket;
|
||||
if (sock != INVALID_SOCKET)
|
||||
{
|
||||
FD_SET(sock, &readfdset); // network socket
|
||||
if (sock > maxfd)
|
||||
maxfd = sock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_SERVER
|
||||
if (svs.sockets)
|
||||
for (con = 0; con < MAX_CONNECTIONS; con++)
|
||||
{
|
||||
|
@ -7635,6 +7655,7 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (seconds > 4.0) //realy? oh well.
|
||||
seconds = 4.0;
|
||||
|
@ -7654,7 +7675,6 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket)
|
|||
#endif
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
//this function is used to determine the 'default' local address.
|
||||
//this is used for compat with gamespy which insists on sending us a packet via that interface and not something more sensible like 127.0.0.1
|
||||
|
@ -7725,7 +7745,7 @@ void NET_GetLocalAddress (int socket, netadr_t *out)
|
|||
out->type = NA_INVALID;
|
||||
}
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
void SVNET_AddPort_f(void)
|
||||
{
|
||||
char *s = Cmd_Argv(1);
|
||||
|
@ -7745,7 +7765,7 @@ void SVNET_AddPort_f(void)
|
|||
if (!svs.sockets)
|
||||
{
|
||||
svs.sockets = FTENET_CreateCollection(true);
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
FTENET_AddToCollection(svs.sockets, "SVLoopback", STRINGIFY(PORT_DEFAULTSERVER), NA_LOOPBACK, NP_DGRAM);
|
||||
#endif
|
||||
}
|
||||
|
@ -7754,7 +7774,7 @@ void SVNET_AddPort_f(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
void NET_ClientPort_f(void)
|
||||
{
|
||||
Con_Printf("Active Client ports:\n");
|
||||
|
@ -7763,31 +7783,15 @@ void NET_ClientPort_f(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
qboolean NET_WasSpecialPacket(netsrc_t netsrc)
|
||||
qboolean NET_WasSpecialPacket(ftenet_connections_t *collection)
|
||||
{
|
||||
#if defined(HAVE_NATPMP)
|
||||
ftenet_connections_t *collection = NULL;
|
||||
if (netsrc == NS_SERVER)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
collection = svs.sockets;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef SERVERONLY
|
||||
collection = cls.sockets;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATPMP
|
||||
if (NET_Was_NATPMP(collection))
|
||||
return true;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_ICE
|
||||
if (ICE_WasStun(netsrc))
|
||||
if (ICE_WasStun(collection))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
|
@ -7833,10 +7837,25 @@ void NET_Init (void)
|
|||
Cvar_Register(&net_hybriddualstack, "networking");
|
||||
Cvar_Register(&net_fakeloss, "networking");
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#if defined(TCPCONNECT) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
|
||||
#ifdef HAVE_SERVER
|
||||
Cvar_Register(&net_enable_qizmo, "networking");
|
||||
Cvar_Register(&net_enable_qtv, "networking");
|
||||
#endif
|
||||
#if defined(HAVE_SSL)
|
||||
Cvar_Register(&net_enable_tls, "networking");
|
||||
#endif
|
||||
Cvar_Register(&net_enable_http, "networking");
|
||||
Cvar_Register(&net_enable_websockets, "networking");
|
||||
Cvar_Register(&net_enable_webrtcbroker, "networking");
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_SERVER
|
||||
Cmd_AddCommand("sv_addport", SVNET_AddPort_f);
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
Cvar_Register(&cl_delay_packets, "networking");
|
||||
Cmd_AddCommand("cl_addport", NET_ClientPort_f);
|
||||
#endif
|
||||
|
@ -7854,9 +7873,11 @@ void NET_Init (void)
|
|||
SSL_Init();
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CLIENT)||defined(HAVE_SERVER)
|
||||
Net_Master_Init();
|
||||
#endif
|
||||
}
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
void NET_CloseClient(void)
|
||||
{ //called by disconnect console command
|
||||
FTENET_CloseCollection(cls.sockets);
|
||||
|
@ -7881,7 +7902,7 @@ void NET_InitClient(qboolean loopbackonly)
|
|||
|
||||
if (!cls.sockets)
|
||||
cls.sockets = FTENET_CreateCollection(false);
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
FTENET_AddToCollection(cls.sockets, "CLLoopback", "1", NA_LOOPBACK, NP_DGRAM);
|
||||
#endif
|
||||
if (loopbackonly)
|
||||
|
@ -7909,7 +7930,7 @@ void NET_InitClient(qboolean loopbackonly)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
#ifdef HAVE_IPV4
|
||||
static void QDECL SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
|
@ -8018,18 +8039,7 @@ void SVNET_RegisterCvars(void)
|
|||
// Cvar_Register (&sv_port_unix, "networking");
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(TCPCONNECT) && !defined(CLIENTONLY)
|
||||
Cvar_Register (&net_enable_qizmo, "networking");
|
||||
Cvar_Register (&net_enable_qtv, "networking");
|
||||
#if defined(HAVE_SSL)
|
||||
Cvar_Register (&net_enable_tls, "networking");
|
||||
#endif
|
||||
Cvar_Register (&net_enable_http, "networking");
|
||||
Cvar_Register (&net_enable_websockets, "networking");
|
||||
Cvar_Register (&net_enable_webrtcbroker, "networking");
|
||||
#endif
|
||||
#if defined(HAVE_DTLS) && !defined(CLIENTONLY)
|
||||
#if defined(HAVE_DTLS) && defined(HAVE_SERVER)
|
||||
Cvar_Register (&net_enable_dtls, "networking");
|
||||
#endif
|
||||
}
|
||||
|
@ -8052,7 +8062,7 @@ void NET_InitServer(void)
|
|||
if (!svs.sockets)
|
||||
{
|
||||
svs.sockets = FTENET_CreateCollection(true);
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
FTENET_AddToCollection(svs.sockets, "SVLoopback", STRINGIFY(PORT_DEFAULTSERVER), NA_LOOPBACK, NP_DGRAM);
|
||||
#endif
|
||||
}
|
||||
|
@ -8092,7 +8102,7 @@ void NET_InitServer(void)
|
|||
{
|
||||
NET_CloseServer();
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
svs.sockets = FTENET_CreateCollection(true);
|
||||
FTENET_AddToCollection(svs.sockets, "SVLoopback", STRINGIFY(PORT_DEFAULTSERVER), NA_LOOPBACK, NP_DGRAM);
|
||||
#endif
|
||||
|
@ -8113,10 +8123,10 @@ NET_Shutdown
|
|||
*/
|
||||
void NET_Shutdown (void)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
#ifdef HAVE_SERVER
|
||||
NET_CloseServer();
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
FTENET_CloseCollection(cls.sockets);
|
||||
cls.sockets = NULL;
|
||||
#endif
|
||||
|
|
|
@ -365,7 +365,7 @@ typedef struct ftenet_connections_s
|
|||
} ftenet_connections_t;
|
||||
|
||||
void ICE_Tick(void);
|
||||
qboolean ICE_WasStun(netsrc_t netsrc);
|
||||
qboolean ICE_WasStun(ftenet_connections_t *col);
|
||||
void QDECL ICE_AddLCandidateConn(ftenet_connections_t *col, netadr_t *addr, int type);
|
||||
void QDECL ICE_AddLCandidateInfo(struct icestate_s *con, netadr_t *adr, int adrno, int type);
|
||||
|
||||
|
|
|
@ -1463,8 +1463,12 @@ static qintptr_t VARGS Plug_Net_SendTo(void *offset, quintptr_t mask, const qint
|
|||
struct sockaddr_qstorage sockaddr;
|
||||
if (handle == -1)
|
||||
{
|
||||
NET_SendPacket(NS_CLIENT, srclen, src, address);
|
||||
#ifdef HAVE_CLIENT
|
||||
NET_SendPacket(cls.sockets, srclen, src, address);
|
||||
return srclen;
|
||||
#else
|
||||
return -2;
|
||||
#endif
|
||||
}
|
||||
|
||||
NetadrToSockadr(address, &sockaddr);
|
||||
|
|
|
@ -1404,7 +1404,7 @@ cvar_t *PF_Cvar_FindOrGet(const char *var_name)
|
|||
|
||||
var = Cvar_Get(var_name, def, 0, "Implicit QC variables");
|
||||
if (var)
|
||||
Con_Printf("^3Created QC Cvar %s\n", var_name);
|
||||
Con_DPrintf("^3Created QC Cvar %s\n", var_name);
|
||||
else
|
||||
Con_Printf(CON_ERROR"Unable to create QC Cvar %s\n", var_name);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,14 @@
|
|||
//field info, netchan, and the WriteBits stuff (which should probably be moved to common.c with the others)
|
||||
//also contains vm filesystem
|
||||
|
||||
#if defined(HAVE_CLIENT) && defined(HAVE_SERVER)
|
||||
#define NET_SendPacket(c,s,d,t) NET_SendPacket(((c)!=NS_CLIENT)?svs.sockets:cls.sockets,s,d,t)
|
||||
#elif defined(HAVE_SERVER)
|
||||
#define NET_SendPacket(c,s,d,t) NET_SendPacket(svs.sockets,s,d,t)
|
||||
#else
|
||||
#define NET_SendPacket(c,s,d,t) NET_SendPacket(cls.sockets,s,d,t)
|
||||
#endif
|
||||
|
||||
#define MAX_VM_FILES 8
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -8,26 +8,21 @@
|
|||
//untranslate is lang->english for console commands.
|
||||
|
||||
|
||||
|
||||
int com_language;
|
||||
char sys_language[64] = "";
|
||||
static char langpath[MAX_OSPATH] = "";
|
||||
struct language_s languages[MAX_LANGUAGES];
|
||||
|
||||
static void QDECL TL_LanguageChanged(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
#ifndef CLIENTONLY
|
||||
svs.language = TL_FindLanguage(var->string);
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
cls.language = TL_FindLanguage(var->string);
|
||||
#endif
|
||||
com_language = TL_FindLanguage(var->string);
|
||||
}
|
||||
|
||||
cvar_t language = CVARAFC("lang", sys_language, "prvm_language", CVAR_USERINFO, TL_LanguageChanged);
|
||||
|
||||
void TranslateInit(void)
|
||||
{
|
||||
Cvar_Register(&language, "International variables");
|
||||
Cvar_Register(&language, "Internationalisation");
|
||||
}
|
||||
|
||||
void TL_Shutdown(void)
|
||||
|
@ -145,12 +140,7 @@ void TL_InitLanguages(const char *newlangpath)
|
|||
*lang = 0;
|
||||
//but we do support territories.
|
||||
|
||||
#ifndef CLIENTONLY
|
||||
svs.language = TL_FindLanguage(sys_language);
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
cls.language = TL_FindLanguage(sys_language);
|
||||
#endif
|
||||
com_language = TL_FindLanguage(sys_language);
|
||||
|
||||
//make sure a fallback exists, but not as language 0
|
||||
TL_FindLanguage("");
|
||||
|
@ -226,7 +216,7 @@ char *T_GetString(int num)
|
|||
return strings_table[num];
|
||||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#ifdef HAVE_CLIENT
|
||||
//for hexen2's objectives and stuff.
|
||||
static char *info_strings_list;
|
||||
static char **info_strings_table;
|
||||
|
|
|
@ -14,6 +14,8 @@ struct language_s
|
|||
struct po_s *po;
|
||||
};
|
||||
extern struct language_s languages[MAX_LANGUAGES];
|
||||
extern int com_language;
|
||||
extern cvar_t language;
|
||||
#define langtext(t,l) PO_GetText(languages[l].po, t)
|
||||
int TL_FindLanguage(const char *lang);
|
||||
|
||||
|
|
|
@ -174,7 +174,8 @@ typedef struct wedict_s wedict_t;
|
|||
typedef struct
|
||||
{
|
||||
qboolean present;
|
||||
vec3_t laggedpos;
|
||||
vec3_t origin;
|
||||
vec3_t angles;
|
||||
} laggedentinfo_t;
|
||||
|
||||
#ifdef USERBE
|
||||
|
@ -206,6 +207,7 @@ struct world_s
|
|||
qboolean (QDECL *Event_ContentsTransition) (struct world_s *w, wedict_t *ent, int oldwatertype, int newwatertype);
|
||||
model_t *(QDECL *Get_CModel)(struct world_s *w, int modelindex);
|
||||
void (QDECL *Get_FrameState)(struct world_s *w, wedict_t *s, framestate_t *fstate);
|
||||
void (QDECL *Event_Backdate)(struct world_s *w, wedict_t *s, float timestamp); //called for MOVE_LAGGED+MOVE_HITMODEL traces
|
||||
|
||||
unsigned int keydestmask; //menu:kdm_menu, csqc:kdm_game, server:0
|
||||
unsigned int max_edicts; //limiting factor... 1024 fields*4*MAX_EDICTS == a heck of a lot.
|
||||
|
@ -242,6 +244,7 @@ struct world_s
|
|||
|
||||
/*antilag*/
|
||||
float lagentsfrac;
|
||||
float lagentstime;
|
||||
laggedentinfo_t *lagents;
|
||||
unsigned int maxlagents;
|
||||
|
||||
|
|
|
@ -641,14 +641,16 @@ CACHE MEMORY
|
|||
void Cache_Flush(void)
|
||||
{
|
||||
//this generically named function is hyjacked to flush models and sounds, as well as ragdolls etc
|
||||
#ifdef HAVE_CLIENT
|
||||
S_Purge(false);
|
||||
#endif
|
||||
#if defined(HAVE_CLIENT) || defined(HAVE_SERVER)
|
||||
#ifdef RAGDOLL
|
||||
rag_flushdolls(true);
|
||||
#endif
|
||||
#ifndef SERVERONLY
|
||||
S_Purge(false);
|
||||
#endif
|
||||
Mod_Purge(MP_FLUSH);
|
||||
#ifndef SERVERONLY
|
||||
#endif
|
||||
#ifdef HAVE_CLIENT
|
||||
Image_Purge();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -3450,13 +3450,11 @@ static void BE_Program_Set_Attributes(const program_t *prog, struct programpermu
|
|||
case SP_M_MODEL:
|
||||
qglUniformMatrix4fvARB(ph, 1, false, shaderstate.modelmatrix);
|
||||
break;
|
||||
case SP_M_ENTBONES:
|
||||
{
|
||||
if (sh_config.maxver>=120)
|
||||
qglUniformMatrix3x4fv(ph, shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones);
|
||||
else
|
||||
case SP_M_ENTBONES_PACKED:
|
||||
qglUniform4fvARB(ph, shaderstate.sourcevbo->numbones*3, shaderstate.sourcevbo->bones);
|
||||
}
|
||||
break;
|
||||
case SP_M_ENTBONES_MAT3X4:
|
||||
qglUniformMatrix3x4fv(ph, shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones);
|
||||
break;
|
||||
case SP_M_INVVIEWPROJECTION:
|
||||
{
|
||||
|
@ -4561,7 +4559,7 @@ static void DrawMeshes(void)
|
|||
#endif
|
||||
break;
|
||||
case BEM_DEPTHDARK:
|
||||
if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright))
|
||||
if ((shaderstate.curshader->flags & (SHADER_HASLIGHTMAP|SHADER_NODLIGHT))==SHADER_HASLIGHTMAP && !TEXVALID(shaderstate.curtexnums->fullbright))
|
||||
{
|
||||
if (gl_config.arb_shader_objects)
|
||||
{
|
||||
|
|
|
@ -777,6 +777,7 @@ void Mod_Init (qboolean initial)
|
|||
Cvar_Register(&mod_loadentfiles, NULL);
|
||||
Cvar_Register(&mod_loadentfiles_dir, NULL);
|
||||
Cvar_Register(&temp_lit2support, NULL);
|
||||
Cvar_Register (&r_meshpitch, "Gamecode");
|
||||
Cmd_AddCommandD("sv_saveentfile", Mod_SaveEntFile_f, "Dumps a copy of the map's entities to disk, so that it can be edited and used as a replacement for slightly customised maps.");
|
||||
Cmd_AddCommandD("mod_showent", Mod_ShowEnt_f, "Allows you to quickly search through a map's entities.");
|
||||
Cmd_AddCommand("version_modelformats", Mod_PrintFormats_f);
|
||||
|
|
|
@ -1659,6 +1659,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
|
||||
prog->preshade = Z_StrDup(prescript);
|
||||
prog->supportedpermutations = (~nopermutation) & (PERMUTATIONS-1);
|
||||
prog->shaderver = ver;
|
||||
|
||||
if (cvarcount)
|
||||
{
|
||||
|
@ -1954,7 +1955,8 @@ struct shader_field_names_s shader_unif_names[] =
|
|||
{"m_modelview", SP_M_MODELVIEW},//the combined modelview matrix
|
||||
{"m_projection", SP_M_PROJECTION},//projection matrix
|
||||
/**/{"m_modelviewprojection", SP_M_MODELVIEWPROJECTION},//fancy mvp matrix. probably has degraded precision.
|
||||
{"m_bones", SP_M_ENTBONES}, //bone matrix array. should normally be read via sys/skeletal.h
|
||||
{"m_bones_packed", SP_M_ENTBONES_PACKED}, //bone matrix array. should normally be read via sys/skeletal.h
|
||||
{"m_bones_mat3x4", SP_M_ENTBONES_MAT3X4}, //bone matrix array. should normally be read via sys/skeletal.h
|
||||
{"m_invviewprojection", SP_M_INVVIEWPROJECTION},//inverted vp matrix
|
||||
{"m_invmodelviewprojection",SP_M_INVMODELVIEWPROJECTION},//inverted mvp matrix.
|
||||
/**///m_modelinv
|
||||
|
@ -4966,9 +4968,9 @@ done:;
|
|||
}
|
||||
}
|
||||
|
||||
pass = s->passes;
|
||||
for (i = 0; i < s->numpasses; i++, pass++)
|
||||
for (i = 0; i < s->numpasses; i += (pass->prog?pass->numMergedPasses:1))
|
||||
{
|
||||
pass = s->passes+i;
|
||||
if (!(pass->shaderbits & (SBITS_BLEND_BITS|SBITS_MASK_BITS)))
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -1133,6 +1133,7 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
|
|||
gl_config.arb_depth_texture = GL_CheckExtension("GL_ARB_depth_texture");
|
||||
}
|
||||
gl_config.arb_shadow = GL_CheckExtension("GL_ARB_shadow");
|
||||
gl_config.arb_shadow |= gl_config.glversion >= 3.0; //seems about right, for both gles and desktop...
|
||||
//gl_config.arb_shadow |= GL_CheckExtension("GL_EXT_shadow_samplers"); //gles2. nvidia fucks up. depend on brute-force. :s
|
||||
|
||||
if (GL_CheckExtension("GL_ARB_seamless_cube_map"))
|
||||
|
@ -1325,13 +1326,7 @@ static const char *glsl_hdrs[] =
|
|||
"attribute vec4 v_colour4;"
|
||||
#endif
|
||||
"\n#endif\n"
|
||||
#ifdef SHADOWDBG_COLOURNOTDEPTH
|
||||
"#define sampler2DShadow sampler2D\n"
|
||||
#else
|
||||
"#ifndef USE_ARB_SHADOW\n" //fall back on regular samplers if we must
|
||||
"#define sampler2DShadow sampler2D\n"
|
||||
"#endif\n"
|
||||
#endif
|
||||
|
||||
"#ifndef SPECEXP\n"
|
||||
"#define SPECEXP 1.0\n"
|
||||
"#endif\n"
|
||||
|
@ -1420,9 +1415,9 @@ static const char *glsl_hdrs[] =
|
|||
"layout(std140) unform u_bones\n"
|
||||
"{\n"
|
||||
"#ifdef PACKEDBONES\n"
|
||||
"vec4 m_bones[3*MAX_GPU_BONES];\n"
|
||||
"vec4 m_bones_packed[3*MAX_GPU_BONES];\n"
|
||||
"#else\n"
|
||||
"mat3x4 m_bones[MAX_GPU_BONES]\n"
|
||||
"mat3x4 m_bones_mat3x4[MAX_GPU_BONES]\n"
|
||||
"#endif\n"
|
||||
"};\n"
|
||||
"#endif\n"
|
||||
|
@ -1436,9 +1431,9 @@ static const char *glsl_hdrs[] =
|
|||
"#endif\n"
|
||||
"#ifdef SKELETAL\n" //skeletal permutation tends to require glsl 120
|
||||
"#ifdef PACKEDBONES\n"
|
||||
"uniform vec4 m_bones[3*MAX_GPU_BONES];\n"
|
||||
"uniform vec4 m_bones_packed[3*MAX_GPU_BONES];\n"
|
||||
"#else\n"
|
||||
"uniform mat3x4 m_bones[MAX_GPU_BONES];\n"
|
||||
"uniform mat3x4 m_bones_mat3x4[MAX_GPU_BONES];\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
"uniform mat4 m_invviewprojection;"
|
||||
|
@ -1497,9 +1492,9 @@ static const char *glsl_hdrs[] =
|
|||
"attribute vec4 v_bone;"
|
||||
"attribute vec4 v_weight;\n"
|
||||
"#ifdef PACKEDBONES\n"
|
||||
"uniform vec4 m_bones[3*MAX_GPU_BONES];\n"
|
||||
"uniform vec4 m_bones_packed[3*MAX_GPU_BONES];\n"
|
||||
"#else\n"
|
||||
"uniform mat3x4 m_bones[MAX_GPU_BONES];\n"
|
||||
"uniform mat3x4 m_bones_mat3x4[MAX_GPU_BONES];\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
|
||||
|
@ -1507,36 +1502,36 @@ static const char *glsl_hdrs[] =
|
|||
"vec4 skeletaltransform()"
|
||||
"{"
|
||||
"mat4 wmat;"
|
||||
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[0] = m_bones_packed[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones_packed[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones_packed[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[3] = vec4(0.0,0.0,0.0,1.0);\n"
|
||||
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
|
||||
"}\n"
|
||||
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
|
||||
"{"
|
||||
"mat4 wmat;"
|
||||
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[0] = m_bones_packed[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones_packed[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones_packed[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[3] = vec4(0.0,0.0,0.0,1.0);"
|
||||
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
|
||||
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
|
||||
|
@ -1546,18 +1541,18 @@ static const char *glsl_hdrs[] =
|
|||
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
|
||||
"{"
|
||||
"mat4 wmat;"
|
||||
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[0] = m_bones_packed[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones_packed[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones_packed[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[3] = vec4(0.0,0.0,0.0,1.0);"
|
||||
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
|
||||
"t = (vec4(v_svector.xyz, 0.0) * wmat).xyz;"
|
||||
|
@ -1568,18 +1563,18 @@ static const char *glsl_hdrs[] =
|
|||
"vec4 skeletaltransform_n(out vec3 n)"
|
||||
"{"
|
||||
"mat4 wmat;"
|
||||
"wmat[0] = m_bones[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[0] = m_bones_packed[0+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[0] += m_bones_packed[0+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[1] = m_bones_packed[1+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[1] += m_bones_packed[1+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[2] = m_bones_packed[2+3*int(v_bone.x)] * v_weight.x;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.y)] * v_weight.y;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.z)] * v_weight.z;"
|
||||
"wmat[2] += m_bones_packed[2+3*int(v_bone.w)] * v_weight.w;"
|
||||
"wmat[3] = vec4(0.0,0.0,0.0,1.0);"
|
||||
"n = (vec4(v_normal.xyz, 0.0) * wmat).xyz;"
|
||||
"return m_modelviewprojection * (vec4(v_position.xyz, 1.0) * wmat);"
|
||||
|
@ -1588,19 +1583,19 @@ static const char *glsl_hdrs[] =
|
|||
"vec4 skeletaltransform()"
|
||||
"{"
|
||||
"mat3x4 wmat;"
|
||||
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
|
||||
"wmat = m_bones_mat3x4[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.w)] * v_weight.w;"
|
||||
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
|
||||
"}\n"
|
||||
"vec4 skeletaltransform_nst(out vec3 n, out vec3 t, out vec3 b)"
|
||||
"{"
|
||||
"mat3x4 wmat;"
|
||||
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
|
||||
"wmat = m_bones_mat3x4[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.w)] * v_weight.w;"
|
||||
"n = vec4(v_normal.xyz, 0.0) * wmat;"
|
||||
"t = vec4(v_svector.xyz, 0.0) * wmat;"
|
||||
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
|
||||
|
@ -1609,10 +1604,10 @@ static const char *glsl_hdrs[] =
|
|||
"vec4 skeletaltransform_wnst(out vec3 w, out vec3 n, out vec3 t, out vec3 b)"
|
||||
"{"
|
||||
"mat3x4 wmat;"
|
||||
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
|
||||
"wmat = m_bones_mat3x4[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.w)] * v_weight.w;"
|
||||
"n = vec4(v_normal.xyz, 0.0) * wmat;"
|
||||
"t = vec4(v_svector.xyz, 0.0) * wmat;"
|
||||
"b = vec4(v_tvector.xyz, 0.0) * wmat;"
|
||||
|
@ -1622,10 +1617,10 @@ static const char *glsl_hdrs[] =
|
|||
"vec4 skeletaltransform_n(out vec3 n)"
|
||||
"{"
|
||||
"mat3x4 wmat;"
|
||||
"wmat = m_bones[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones[int(v_bone.w)] * v_weight.w;"
|
||||
"wmat = m_bones_mat3x4[int(v_bone.x)] * v_weight.x;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.y)] * v_weight.y;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.z)] * v_weight.z;"
|
||||
"wmat += m_bones_mat3x4[int(v_bone.w)] * v_weight.w;"
|
||||
"n = vec4(v_normal.xyz, 0.0) * wmat;"
|
||||
"return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);"
|
||||
"}\n"
|
||||
|
@ -1748,9 +1743,9 @@ static const char *glsl_hdrs[] =
|
|||
"vec2 tc = base;\n"
|
||||
"tc += OffsetVector;\n"
|
||||
"OffsetVector *= 0.333;\n"
|
||||
"tc -= OffsetVector * texture2D(normtex, tc).w;\n"
|
||||
"tc -= OffsetVector * texture2D(normtex, tc).w;\n"
|
||||
"tc -= OffsetVector * texture2D(normtex, tc).w;\n"
|
||||
"tc -= OffsetVector * texture2D(normtex, tc).a;\n"
|
||||
"tc -= OffsetVector * texture2D(normtex, tc).a;\n"
|
||||
"tc -= OffsetVector * texture2D(normtex, tc).a;\n"
|
||||
"return tc;\n"
|
||||
"#else\n"
|
||||
"return base;\n"
|
||||
|
@ -2071,6 +2066,8 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
|
|||
GLSlang_GenerateInternal(&glsl, *precompilerconstants++);
|
||||
|
||||
GLSlang_GenerateInternal(&glsl, "#define ENGINE_"DISTRIBUTION"\n");
|
||||
if (ver < 120)
|
||||
GLSlang_GenerateInternal(&glsl, "#define PACKEDBONES\n");
|
||||
|
||||
switch (shadertype)
|
||||
{
|
||||
|
@ -2126,7 +2123,15 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
|
|||
#if 1//def NOLEGACY
|
||||
const char *defaultsamplernames[] =
|
||||
{
|
||||
#ifdef SHADOWDBG_COLOURNOTDEPTH
|
||||
"#define sampler2DShadow sampler2D\n"
|
||||
#else
|
||||
"#ifndef USE_ARB_SHADOW\n" //fall back on regular samplers if we must
|
||||
"#define sampler2DShadow sampler2D\n"
|
||||
"#endif\n"
|
||||
#endif
|
||||
"uniform sampler2DShadow s_shadowmap;\n",
|
||||
|
||||
"uniform samplerCube s_projectionmap;\n",
|
||||
"uniform sampler2D s_diffuse;\n",
|
||||
"uniform sampler2D s_normalmap;\n",
|
||||
|
@ -2201,8 +2206,6 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
|
|||
"#define varying out\n"
|
||||
);
|
||||
}
|
||||
else if (ver < 120)
|
||||
GLSlang_GenerateInternal(&glsl, "#define PACKEDBONES\n");
|
||||
|
||||
if (gl_config_nofixedfunc)
|
||||
{
|
||||
|
@ -2365,19 +2368,41 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
|
|||
|
||||
if (developer.ival>1)
|
||||
{ //could use echo console-link I guess (with embedded line numbers). shaders can get quite big though.
|
||||
unsigned int line;
|
||||
char *eol, *start;
|
||||
unsigned int rawline, line, filenum = 0;
|
||||
char *eol, *start, *e;
|
||||
const char *filename = name;
|
||||
qglGetShaderSource(shader, sizeof(str), NULL, str);
|
||||
Con_Printf("Shader \"%s\" source:\n", name);
|
||||
for(start = str, line = 1; ;line++)
|
||||
for(start = str, line = 1, rawline = 1; ;)
|
||||
{
|
||||
eol = strchr(start, '\n');
|
||||
if (eol)
|
||||
*eol=0;
|
||||
Con_Printf("%3u: %s\n", line, start);
|
||||
// if (filename)
|
||||
// Con_Printf("%s:%u:%u: %s\n", filename, line, rawline, start);
|
||||
// else
|
||||
Con_Printf("%u:%u:%u: %s\n", filenum, line, rawline, start);
|
||||
if (!strncmp(start, "#line ", 6))
|
||||
{
|
||||
line = strtoul(start+6, &e, 0);
|
||||
while(*e == ' ')
|
||||
e++;
|
||||
if (*e)
|
||||
{
|
||||
filenum = strtoul(e, &e, 0);
|
||||
while(*e == ' ')
|
||||
e++;
|
||||
filename = NULL;
|
||||
if (e[0]=='/'&&e[1]=='/')
|
||||
filename = e+2;
|
||||
}
|
||||
}
|
||||
else
|
||||
line++;
|
||||
if (!eol)
|
||||
break;
|
||||
start = eol+1;
|
||||
rawline++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2589,11 +2614,7 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, struct programpermu_s *perm
|
|||
if (gl_config.gles)
|
||||
ver = 100;
|
||||
else
|
||||
{
|
||||
ver = 110;
|
||||
if (sh_config.maxver>=120 && (permu->permutation & PERMUTATION_SKELETAL))
|
||||
ver = 120;
|
||||
}
|
||||
}
|
||||
if ((permu->permutation & PERMUTATION_SKELETAL) && gl_config.maxattribs < 10)
|
||||
return false; //can happen in gles2
|
||||
|
|
|
@ -1327,10 +1327,344 @@ static void GLX_CloseLibrary(void)
|
|||
}
|
||||
*/
|
||||
|
||||
#if 0//def _DEBUG
|
||||
//this is a list of the functions that exist in opengles2, as well as wglCreateContextAttribsARB.
|
||||
//functions not in this list *should* be stubs that just return errors, but we can't always depend on drivers for that... they shouldn't get called.
|
||||
//this list is just to make it easier to test+debug android gles2 stuff using windows.
|
||||
static char *gles2funcs[] =
|
||||
{
|
||||
#define f(n) #n,
|
||||
f(glActiveTexture)
|
||||
f(glAttachShader)
|
||||
f(glBindAttribLocation)
|
||||
f(glBindBuffer)
|
||||
f(glBindFramebuffer)
|
||||
f(glBindRenderbuffer)
|
||||
f(glBindTexture)
|
||||
f(glBlendColor)
|
||||
f(glBlendEquation)
|
||||
f(glBlendEquationSeparate)
|
||||
f(glBlendFunc)
|
||||
f(glBlendFuncSeparate)
|
||||
f(glBufferData)
|
||||
f(glBufferSubData)
|
||||
f(glCheckFramebufferStatus)
|
||||
f(glClear)
|
||||
f(glClearColor)
|
||||
f(glClearDepthf)
|
||||
f(glClearStencil)
|
||||
f(glColorMask)
|
||||
f(glCompileShader)
|
||||
f(glCompressedTexImage2D)
|
||||
f(glCompressedTexSubImage2D)
|
||||
f(glCopyTexImage2D)
|
||||
f(glCopyTexSubImage2D)
|
||||
f(glCreateProgram)
|
||||
f(glCreateShader)
|
||||
f(glCullFace)
|
||||
f(glDeleteBuffers)
|
||||
f(glDeleteFramebuffers)
|
||||
f(glDeleteProgram)
|
||||
f(glDeleteRenderbuffers)
|
||||
f(glDeleteShader)
|
||||
f(glDeleteTextures)
|
||||
f(glDepthFunc)
|
||||
f(glDepthMask)
|
||||
f(glDepthRangef)
|
||||
f(glDetachShader)
|
||||
f(glDisable)
|
||||
f(glDisableVertexAttribArray)
|
||||
f(glDrawArrays)
|
||||
f(glDrawElements)
|
||||
f(glEnable)
|
||||
f(glEnableVertexAttribArray)
|
||||
f(glFinish)
|
||||
f(glFlush)
|
||||
f(glFramebufferRenderbuffer)
|
||||
f(glFramebufferTexture2D)
|
||||
f(glFrontFace)
|
||||
f(glGenBuffers)
|
||||
f(glGenerateMipmap)
|
||||
f(glGenFramebuffers)
|
||||
f(glGenRenderbuffers)
|
||||
f(glGenTextures)
|
||||
f(glGetActiveAttrib)
|
||||
f(glGetActiveUniform)
|
||||
f(glGetAttachedShaders)
|
||||
f(glGetAttribLocation)
|
||||
f(glGetBooleanv)
|
||||
f(glGetBufferParameteriv)
|
||||
f(glGetError)
|
||||
f(glGetFloatv)
|
||||
f(glGetFramebufferAttachmentParameteriv)
|
||||
f(glGetIntegerv)
|
||||
f(glGetProgramiv)
|
||||
f(glGetProgramInfoLog)
|
||||
f(glGetRenderbufferParameteriv)
|
||||
f(glGetShaderiv)
|
||||
f(glGetShaderInfoLog)
|
||||
f(glGetShaderPrecisionFormat)
|
||||
f(glGetShaderSource)
|
||||
f(glGetString)
|
||||
f(glGetTexParameterfv)
|
||||
f(glGetTexParameteriv)
|
||||
f(glGetUniformfv)
|
||||
f(glGetUniformiv)
|
||||
f(glGetUniformLocation)
|
||||
f(glGetVertexAttribfv)
|
||||
f(glGetVertexAttribiv)
|
||||
f(glGetVertexAttribPointerv)
|
||||
f(glHint)
|
||||
f(glIsBuffer)
|
||||
f(glIsEnabled)
|
||||
f(glIsFramebuffer)
|
||||
f(glIsProgram)
|
||||
f(glIsRenderbuffer)
|
||||
f(glIsShader)
|
||||
f(glIsTexture)
|
||||
f(glLineWidth)
|
||||
f(glLinkProgram)
|
||||
f(glPixelStorei)
|
||||
f(glPolygonOffset)
|
||||
f(glReadPixels)
|
||||
f(glReleaseShaderCompiler)
|
||||
f(glRenderbufferStorage)
|
||||
f(glSampleCoverage)
|
||||
f(glScissor)
|
||||
f(glShaderBinary)
|
||||
f(glShaderSource)
|
||||
f(glStencilFunc)
|
||||
f(glStencilFuncSeparate)
|
||||
f(glStencilMask)
|
||||
f(glStencilMaskSeparate)
|
||||
f(glStencilOp)
|
||||
f(glStencilOpSeparate)
|
||||
f(glTexImage2D)
|
||||
f(glTexParameterf)
|
||||
f(glTexParameterfv)
|
||||
f(glTexParameteri)
|
||||
f(glTexParameteriv)
|
||||
f(glTexSubImage2D)
|
||||
f(glUniform1f)
|
||||
f(glUniform1fv)
|
||||
f(glUniform1i)
|
||||
f(glUniform1iv)
|
||||
f(glUniform2f)
|
||||
f(glUniform2fv)
|
||||
f(glUniform2i)
|
||||
f(glUniform2iv)
|
||||
f(glUniform3f)
|
||||
f(glUniform3fv)
|
||||
f(glUniform3i)
|
||||
f(glUniform3iv)
|
||||
f(glUniform4f)
|
||||
f(glUniform4fv)
|
||||
f(glUniform4i)
|
||||
f(glUniform4iv)
|
||||
f(glUniformMatrix2fv)
|
||||
f(glUniformMatrix3fv)
|
||||
f(glUniformMatrix4fv)
|
||||
f(glUseProgram)
|
||||
f(glValidateProgram)
|
||||
f(glVertexAttrib1f)
|
||||
f(glVertexAttrib1fv)
|
||||
f(glVertexAttrib2f)
|
||||
f(glVertexAttrib2fv)
|
||||
f(glVertexAttrib3f)
|
||||
f(glVertexAttrib3fv)
|
||||
f(glVertexAttrib4f)
|
||||
f(glVertexAttrib4fv)
|
||||
f(glVertexAttribPointer)
|
||||
f(glViewport)
|
||||
f(wglCreateContextAttribsARB)
|
||||
NULL
|
||||
};
|
||||
|
||||
//this is a list of the functions that exist in opengles2, as well as wglCreateContextAttribsARB.
|
||||
//functions not in this list *should* be stubs that just return errors, but we can't always depend on drivers for that... they shouldn't get called.
|
||||
//this list is just to make it easier to test+debug android gles2 stuff using windows.
|
||||
static char *gles1funcs[] =
|
||||
{
|
||||
#define f(n) #n,
|
||||
|
||||
/* Available only in Common profile */
|
||||
f(glAlphaFunc)
|
||||
f(glClearColor)
|
||||
f(glClearDepthf)
|
||||
f(glClipPlanef)
|
||||
f(glColor4f)
|
||||
f(glDepthRangef)
|
||||
f(glFogf)
|
||||
f(glFogfv)
|
||||
f(glFrustumf)
|
||||
f(glGetClipPlanef)
|
||||
f(glGetFloatv)
|
||||
f(glGetLightfv)
|
||||
f(glGetMaterialfv)
|
||||
f(glGetTexEnvfv)
|
||||
f(glGetTexParameterfv)
|
||||
f(glLightModelf)
|
||||
f(glLightModelfv)
|
||||
f(glLightf)
|
||||
f(glLightfv)
|
||||
f(glLineWidth)
|
||||
f(glLoadMatrixf)
|
||||
f(glMaterialf)
|
||||
f(glMaterialfv)
|
||||
f(glMultMatrixf)
|
||||
f(glMultiTexCoord4f)
|
||||
f(glNormal3f)
|
||||
f(glOrthof)
|
||||
f(glPointParameterf)
|
||||
f(glPointParameterfv)
|
||||
f(glPointSize)
|
||||
f(glPolygonOffset)
|
||||
f(glRotatef)
|
||||
f(glScalef)
|
||||
f(glTexEnvf)
|
||||
f(glTexEnvfv)
|
||||
f(glTexParameterf)
|
||||
f(glTexParameterfv)
|
||||
f(glTranslatef)
|
||||
|
||||
/* Available in both Common and Common-Lite profiles */
|
||||
f(glActiveTexture)
|
||||
f(glAlphaFuncx)
|
||||
f(glBindBuffer)
|
||||
f(glBindTexture)
|
||||
f(glBlendFunc)
|
||||
f(glBufferData)
|
||||
f(glBufferSubData)
|
||||
f(glClear)
|
||||
f(glClearColorx)
|
||||
f(glClearDepthx)
|
||||
f(glClearStencil)
|
||||
f(glClientActiveTexture)
|
||||
f(glClipPlanex)
|
||||
f(glColor4ub)
|
||||
f(glColor4x)
|
||||
f(glColorMask)
|
||||
f(glColorPointer)
|
||||
f(glCompressedTexImage2D)
|
||||
f(glCompressedTexSubImage2D)
|
||||
f(glCopyTexImage2D)
|
||||
f(glCopyTexSubImage2D)
|
||||
f(glCullFace)
|
||||
f(glDeleteBuffers)
|
||||
f(glDeleteTextures)
|
||||
f(glDepthFunc)
|
||||
f(glDepthMask)
|
||||
f(glDepthRangex)
|
||||
f(glDisable)
|
||||
f(glDisableClientState)
|
||||
f(glDrawArrays)
|
||||
f(glDrawElements)
|
||||
f(glEnable)
|
||||
f(glEnableClientState)
|
||||
f(glFinish)
|
||||
f(glFlush)
|
||||
f(glFogx)
|
||||
f(glFogxv)
|
||||
f(glFrontFace)
|
||||
f(glFrustumx)
|
||||
f(glGetBooleanv)
|
||||
f(glGetBufferParameteriv)
|
||||
f(glGetClipPlanex)
|
||||
f(glGenBuffers)
|
||||
f(glGenTextures)
|
||||
f(glGetError)
|
||||
f(glGetFixedv)
|
||||
f(glGetIntegerv)
|
||||
f(glGetLightxv)
|
||||
f(glGetMaterialxv)
|
||||
f(glGetPointerv)
|
||||
f(glGetString)
|
||||
f(glGetTexEnviv)
|
||||
f(glGetTexEnvxv)
|
||||
f(glGetTexParameteriv)
|
||||
f(glGetTexParameterxv)
|
||||
f(glHint)
|
||||
f(glIsBuffer)
|
||||
f(glIsEnabled)
|
||||
f(glIsTexture)
|
||||
f(glLightModelx)
|
||||
f(glLightModelxv)
|
||||
f(glLightx)
|
||||
f(glLightxv)
|
||||
f(glLineWidthx)
|
||||
f(glLoadIdentity)
|
||||
f(glLoadMatrixx)
|
||||
f(glLogicOp)
|
||||
f(glMaterialx)
|
||||
f(glMaterialxv)
|
||||
f(glMatrixMode)
|
||||
f(glMultMatrixx)
|
||||
f(glMultiTexCoord4x)
|
||||
f(glNormal3x)
|
||||
f(glNormalPointer)
|
||||
f(glOrthox)
|
||||
f(glPixelStorei)
|
||||
f(glPointParameterx)
|
||||
f(glPointParameterxv)
|
||||
f(glPointSizex)
|
||||
f(glPolygonOffsetx)
|
||||
f(glPopMatrix)
|
||||
f(glPushMatrix)
|
||||
f(glReadPixels)
|
||||
f(glRotatex)
|
||||
f(glSampleCoverage)
|
||||
f(glSampleCoveragex)
|
||||
f(glScalex)
|
||||
f(glScissor)
|
||||
f(glShadeModel)
|
||||
f(glStencilFunc)
|
||||
f(glStencilMask)
|
||||
f(glStencilOp)
|
||||
f(glTexCoordPointer)
|
||||
f(glTexEnvi)
|
||||
f(glTexEnvx)
|
||||
f(glTexEnviv)
|
||||
f(glTexEnvxv)
|
||||
f(glTexImage2D)
|
||||
f(glTexParameteri)
|
||||
f(glTexParameterx)
|
||||
f(glTexParameteriv)
|
||||
f(glTexParameterxv)
|
||||
f(glTexSubImage2D)
|
||||
f(glTranslatex)
|
||||
f(glVertexPointer)
|
||||
f(glViewport)
|
||||
|
||||
/*required to switch stuff around*/
|
||||
f(wglCreateContextAttribsARB)
|
||||
f(glXGetProcAddress)
|
||||
f(glXQueryExtensionsString)
|
||||
f(glXChooseFBConfig)
|
||||
f(glXGetFBConfigAttrib)
|
||||
f(glXGetVisualFromFBConfig)
|
||||
f(glXCreateContextAttribsARB)
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
static void *GLX_GetSymbol(char *name)
|
||||
{
|
||||
void *symb;
|
||||
|
||||
#if 0//def _DEBUG
|
||||
if (1)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; gles1funcs[i]; i++)
|
||||
{
|
||||
if (!strcmp(name, gles1funcs[i]))
|
||||
break;
|
||||
}
|
||||
if (!gles1funcs[i])
|
||||
return NULL; //not in the list
|
||||
}
|
||||
#endif
|
||||
|
||||
if (glx.GetProcAddress)
|
||||
symb = glx.GetProcAddress(name);
|
||||
else
|
||||
|
|
|
@ -437,7 +437,8 @@ typedef struct {
|
|||
SP_W_FOG,
|
||||
SP_W_USER, //user-specified blob of data.
|
||||
|
||||
SP_M_ENTBONES,
|
||||
SP_M_ENTBONES_PACKED,
|
||||
SP_M_ENTBONES_MAT3X4,
|
||||
SP_M_VIEW,
|
||||
SP_M_MODEL,
|
||||
SP_M_MODELVIEW,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
//simple tool to read the particle configs and generate a header file for inclusion in the engine.
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct
|
||||
|
@ -30,7 +31,7 @@ int main(void)
|
|||
if (!c || !h)
|
||||
{
|
||||
printf("unable to open a file\n");
|
||||
return;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fprintf(h, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n");
|
||||
|
@ -46,7 +47,7 @@ int main(void)
|
|||
if (!s)
|
||||
{
|
||||
printf("unable to open %s\n", effects[i].filename);
|
||||
return;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
*strchr(effects[i].filename, '.') = 0;
|
||||
|
||||
|
@ -114,4 +115,6 @@ int main(void)
|
|||
|
||||
fclose(h);
|
||||
fclose(c);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -412,6 +412,7 @@ r_part te_teleport
|
|||
surfaceparm nodlight
|
||||
glslprogram
|
||||
{
|
||||
!!samps screen=0
|
||||
varying vec2 tcoord;
|
||||
varying vec4 scoord;
|
||||
varying float alph;
|
||||
|
@ -439,7 +440,7 @@ r_part te_teleport
|
|||
// f = 1.0 - tcoord*tcoord;
|
||||
if (f < 0.0) discard;
|
||||
f *= alph;
|
||||
gl_FragColor = texture2D(s_t0, nst - tcoord*f);
|
||||
gl_FragColor = texture2D(s_screen, nst - tcoord*f);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -348,6 +348,21 @@ void Hash_RemoveBucket(hashtable_t *table, const char *name, bucket_t *data)
|
|||
return;
|
||||
}
|
||||
|
||||
void Hash_RemoveDataKey(hashtable_t *table, unsigned int key, void *data)
|
||||
{
|
||||
unsigned int bucknum = key%table->numbuckets;
|
||||
bucket_t **link, *buck;
|
||||
|
||||
for (link = &table->bucket[bucknum]; *link; link = &(*link)->next)
|
||||
{
|
||||
buck = *link;
|
||||
if (buck->data == data && buck->key.value == key)
|
||||
{
|
||||
*link = buck->next;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
void Hash_RemoveKey(hashtable_t *table, unsigned int key)
|
||||
{
|
||||
unsigned int bucknum = key%table->numbuckets;
|
||||
|
|
|
@ -39,6 +39,7 @@ void Hash_RemoveData(hashtable_t *table, const char *name, void *data);
|
|||
void Hash_RemoveDataInsensitive(hashtable_t *table, const char *name, void *data);
|
||||
void Hash_RemoveBucket(hashtable_t *table, const char *name, bucket_t *data);
|
||||
void Hash_RemoveKey(hashtable_t *table, unsigned int key);
|
||||
void Hash_RemoveDataKey(hashtable_t *table, unsigned int key, void *data);
|
||||
void *Hash_AddKey(hashtable_t *table, unsigned int key, void *data, bucket_t *buck);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10116,7 +10116,7 @@ static void QCBUILTIN PF_SendPacket(pubprogfuncs_t *prinst, struct globalvars_s
|
|||
char *send = Z_Malloc(4+strlen(contents));
|
||||
send[0] = send[1] = send[2] = send[3] = 0xff;
|
||||
memcpy(send+4, contents, strlen(contents));
|
||||
G_FLOAT(OFS_RETURN) = NET_SendPacket(NS_SERVER, 4+strlen(contents), send, &to);
|
||||
G_FLOAT(OFS_RETURN) = NET_SendPacket(svs.sockets, 4+strlen(contents), send, &to);
|
||||
Z_Free(send);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -334,7 +334,7 @@ typedef struct
|
|||
// received from client
|
||||
|
||||
// reply
|
||||
double senttime; //time we sent this frame to the client, for ping calcs
|
||||
double senttime; //time we sent this frame to the client, for ping calcs (realtime)
|
||||
int sequence; //the outgoing sequence - without mask, meaning we know if its current or stale
|
||||
float ping_time; //how long it took for the client to ack it, may be negative
|
||||
float move_msecs; //
|
||||
|
@ -365,8 +365,9 @@ typedef struct
|
|||
float pmwaterjumptime;
|
||||
usercmd_t cmd;
|
||||
//these are old positions of players, to give more accurate victim positions
|
||||
vec3_t playerpositions[MAX_CLIENTS]; //where each player was in this frame, for antilag
|
||||
qboolean playerpresent[MAX_CLIENTS]; //whether the player was actually present
|
||||
laggedentinfo_t laggedplayer[MAX_CLIENTS];
|
||||
unsigned int numlaggedplayers;
|
||||
float laggedtime; //sv.time of when this frame was sent
|
||||
} client_frame_t;
|
||||
|
||||
#ifdef Q2SERVER
|
||||
|
@ -524,6 +525,7 @@ typedef struct client_s
|
|||
laggedentinfo_t laggedents[MAX_CLIENTS];
|
||||
unsigned int laggedents_count;
|
||||
float laggedents_frac;
|
||||
float laggedents_time;
|
||||
|
||||
// spawn parms are carried from level to level
|
||||
float spawn_parms[NUM_SPAWN_PARMS];
|
||||
|
@ -939,7 +941,6 @@ typedef struct
|
|||
|
||||
struct netprim_s netprim;
|
||||
|
||||
int language; //the server operators language
|
||||
laggedpacket_t *free_lagged_packet;
|
||||
packet_entities_t entstatebuffer; /*just a temp buffer*/
|
||||
|
||||
|
@ -1325,6 +1326,7 @@ void SV_ClientProtocolExtensionsChanged(client_t *client);
|
|||
|
||||
//sv_master.c
|
||||
void SVM_Think(int port);
|
||||
vfsfile_t *SVM_GenerateIndex(const char *fname);
|
||||
|
||||
|
||||
//
|
||||
|
@ -1333,6 +1335,9 @@ void SVM_Think(int port);
|
|||
typedef enum {RD_NONE, RD_CLIENT, RD_PACKET, RD_PACKET_LOG, RD_OBLIVION, RD_MASTER} redirect_t; //oblivion is provided so people can read the output before the buffer is wiped.
|
||||
void SV_BeginRedirect (redirect_t rd, int lang);
|
||||
void SV_EndRedirect (void);
|
||||
extern char sv_redirected_buf[8000];
|
||||
extern redirect_t sv_redirected;
|
||||
extern int sv_redirectedlang;
|
||||
|
||||
|
||||
qboolean PR_GameCodePacket(char *s);
|
||||
|
|
|
@ -63,7 +63,7 @@ crosses a waterline.
|
|||
=============================================================================
|
||||
*/
|
||||
|
||||
int needcleanup;
|
||||
static int needcleanup;
|
||||
|
||||
//int fatbytes;
|
||||
|
||||
|
@ -106,9 +106,9 @@ void SV_ExpandNackFrames(client_t *client, int require)
|
|||
// because there can be a lot of nails, there is a special
|
||||
// network protocol for them
|
||||
#define MAX_NAILS 32
|
||||
edict_t *nails[MAX_NAILS];
|
||||
int numnails;
|
||||
int nailcount = 0;
|
||||
static edict_t *nails[MAX_NAILS];
|
||||
static int numnails;
|
||||
static int nailcount = 0;
|
||||
extern int sv_nailmodel, sv_supernailmodel, sv_playermodel;
|
||||
|
||||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
|
@ -1564,6 +1564,7 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
|
|||
frame->numresend = outno;
|
||||
frame->sequence = sequence;
|
||||
|
||||
frame->laggedtime = sv.time;
|
||||
for (i = 0; i < to->num_entities; i++)
|
||||
{
|
||||
n = &to->entities[i];
|
||||
|
@ -1582,9 +1583,10 @@ qboolean SVFTE_EmitPacketEntities(client_t *client, packet_entities_t *to, sizeb
|
|||
age = sv.time - sv.world.physicstime;
|
||||
age = bound(0, age, 0.1);
|
||||
|
||||
VectorMA(n->origin, (sv.time - cl->localtime)/8.0, n->u.q1.velocity, frame->playerpositions[j]);
|
||||
VectorMA(n->origin, (sv.time - cl->localtime)/8.0, n->u.q1.velocity, frame->laggedplayer[j].origin);
|
||||
VectorCopy(n->angles, frame->laggedplayer[j].angles);
|
||||
//FIXME: add framestate_t info.
|
||||
frame->playerpresent[j] = true;
|
||||
frame->laggedplayer[j].present = true;
|
||||
}
|
||||
|
||||
return overflow;
|
||||
|
@ -2762,13 +2764,14 @@ void SV_WritePlayersToClient (client_t *client, client_frame_t *frame, edict_t *
|
|||
clst.lastcmd = NULL;
|
||||
clst.velocity = NULL;
|
||||
clst.localtime = sv.time;
|
||||
VectorCopy(clst.origin, frame->playerpositions[j]);
|
||||
VectorCopy(clst.origin, frame->laggedplayer[j].origin);
|
||||
}
|
||||
else
|
||||
{
|
||||
VectorMA(clst.origin, (sv.time - clst.localtime), clst.velocity, frame->playerpositions[j]);
|
||||
VectorMA(clst.origin, (sv.time - clst.localtime), clst.velocity, frame->laggedplayer[j].origin);
|
||||
}
|
||||
frame->playerpresent[j] = true;
|
||||
VectorCopy(clst.angles, frame->laggedplayer[j].angles);
|
||||
frame->laggedplayer[j].present = true;
|
||||
SV_WritePlayerToClient(msg, &clst);
|
||||
}
|
||||
|
||||
|
@ -2983,7 +2986,7 @@ typedef struct gibfilter_s {
|
|||
int minframe;
|
||||
int maxframe;
|
||||
} gibfilter_t;
|
||||
gibfilter_t *gibfilter;
|
||||
static gibfilter_t *gibfilter;
|
||||
void SV_GibFilterPurge(void)
|
||||
{
|
||||
gibfilter_t *gf;
|
||||
|
@ -3881,9 +3884,7 @@ svc_playerinfo messages
|
|||
*/
|
||||
void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignorepvs)
|
||||
{
|
||||
#ifdef NQPROT
|
||||
int e;
|
||||
#endif
|
||||
int i;
|
||||
packet_entities_t *pack;
|
||||
edict_t *clent;
|
||||
client_frame_t *frame;
|
||||
|
@ -3893,7 +3894,8 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
|
||||
// this is the frame we are creating
|
||||
frame = &client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK];
|
||||
memset(frame->playerpresent, 0, sizeof(frame->playerpresent));
|
||||
for (i = 0; i < sv.allocated_client_slots; i++)
|
||||
frame->laggedplayer[i].present = 0;
|
||||
|
||||
// find the client's PVS
|
||||
if (ignorepvs)
|
||||
|
@ -3977,6 +3979,7 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore
|
|||
SVDP_EmitEntitiesUpdate(client, frame, pack, msg);
|
||||
else
|
||||
{
|
||||
int e;
|
||||
for (e = 0; e < pack->num_entities; e++)
|
||||
{
|
||||
if (pack->entities[e].number > sv.allocated_client_slots)
|
||||
|
|
|
@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
#define INVIS_CHAR2 (char)138
|
||||
#define INVIS_CHAR3 (char)160
|
||||
|
||||
#ifdef SERVERONLY
|
||||
#ifndef HAVE_CLIENT
|
||||
double host_frametime;
|
||||
double realtime; // without any filtering or bounding
|
||||
qboolean host_initialized; // true if into command execution (compatability)
|
||||
|
@ -35,13 +35,6 @@ quakeparms_t host_parms;
|
|||
int host_hunklevel;
|
||||
#endif
|
||||
|
||||
// callbacks
|
||||
void SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue);
|
||||
void SV_Tcpport6_Callback(struct cvar_s *var, char *oldvalue);
|
||||
void SV_Port_Callback(struct cvar_s *var, char *oldvalue);
|
||||
void SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue);
|
||||
void SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue);
|
||||
|
||||
client_t *host_client; // current client
|
||||
|
||||
// bound the size of the physics time tic
|
||||
|
@ -63,12 +56,9 @@ cvar_t zombietime = CVARD("zombietime", "2", "Client slots will not be reuse
|
|||
cvar_t sv_crypt_rcon = CVARFD("sv_crypt_rcon", "", CVAR_ARCHIVE, "Controls whether the rcon password must be hashed or not. Hashed passwords also partially prevent replay attacks, but does NOT prevent malicious actors from reading the commands/results.\n0: completely insecure. ONLY allows plain-text passwords. Do not use.\n1: Mandatory hashing (recommended).\nEmpty: Allow either, whether the password is secure or not is purely the client's responsibility/fault. Only use this for comptibility with old clients.");
|
||||
cvar_t sv_crypt_rcon_clockskew = CVARFD("sv_timestamplen", "60", CVAR_ARCHIVE, "Limits clock skew to reduce (delayed) replay attacks");
|
||||
#ifdef SERVERONLY
|
||||
cvar_t developer = CVAR("developer","0"); // show extra messages
|
||||
|
||||
cvar_t rcon_password = CVARF("rcon_password", "", CVAR_NOUNSAFEEXPAND); // password for remote server commands
|
||||
cvar_t password = CVARF("password", "", CVAR_NOUNSAFEEXPAND); // password for entering the game
|
||||
#else
|
||||
extern cvar_t developer;
|
||||
extern cvar_t rcon_password;
|
||||
extern cvar_t password;
|
||||
#endif
|
||||
|
@ -108,6 +98,7 @@ cvar_t sv_listen_q3 = CVAR("sv_listen_q3", "0");
|
|||
cvar_t sv_reconnectlimit = CVARD("sv_reconnectlimit", "0", "Blocks dupe connection within the specified length of time .");
|
||||
extern cvar_t net_enable_dtls;
|
||||
cvar_t sv_reportheartbeats = CVARD("sv_reportheartbeats", "2", "Print a notice each time a heartbeat is sent to a master server. When set to 2, the message will be displayed once.");
|
||||
cvar_t sv_heartbeat_interval = CVARD("sv_heartbeat_interval", "110", "Interval between heartbeats. Low values are abusive, high values may cause NAT/ghost issues.");
|
||||
cvar_t sv_highchars = CVAR("sv_highchars", "1");
|
||||
cvar_t sv_maxrate = CVARD("sv_maxrate", "50000", "This controls the maximum number of bytes any indivual player may receive (when not downloading). The individual user's rate will also be controlled by the user's rate cvar.");
|
||||
cvar_t sv_maxdrate = CVARAFD("sv_maxdrate", "500000",
|
||||
|
@ -272,7 +263,9 @@ void SV_Shutdown (void)
|
|||
#endif
|
||||
Cvar_Shutdown();
|
||||
Cmd_Shutdown();
|
||||
#ifdef PACKAGEMANAGER
|
||||
PM_Shutdown();
|
||||
#endif
|
||||
|
||||
|
||||
InfoBuf_Clear(&svs.info, true);
|
||||
|
@ -1290,7 +1283,7 @@ static void SVC_GetInfo (char *challenge, int fullstatus)
|
|||
}
|
||||
}
|
||||
|
||||
NET_SendPacket (NS_SERVER, resp-response, response, &net_from);
|
||||
NET_SendPacket (svs.sockets, resp-response, response, &net_from);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1378,7 +1371,7 @@ static void SVC_Log (void)
|
|||
else if (seq == svs.logsequence)
|
||||
{ //current log isn't available as its not complete yet.
|
||||
data[0] = A2A_NACK;
|
||||
NET_SendPacket (NS_SERVER, 1, data, &net_from);
|
||||
NET_SendPacket (svs.sockets, 1, data, &net_from);
|
||||
return;
|
||||
}
|
||||
else if (seq > svs.logsequence) //future logs are not valid either. reply with the last that was. this is for compat, just in case.
|
||||
|
@ -1392,7 +1385,7 @@ static void SVC_Log (void)
|
|||
if (!fraglog_public.ival)
|
||||
{ //frag logs are not public (for DoS protection perhaps?.
|
||||
data[0] = A2A_NACK;
|
||||
NET_SendPacket (NS_SERVER, 1, data, &net_from);
|
||||
NET_SendPacket (svs.sockets, 1, data, &net_from);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1404,7 +1397,7 @@ static void SVC_Log (void)
|
|||
Q_snprintfz(data, sizeof(data), "stdlog %i %s\n%s", seq, av, (char *)svs.log_buf[seq&(FRAGLOG_BUFFERS-1)]);
|
||||
else
|
||||
Q_snprintfz(data, sizeof(data), "stdlog %i\n%s", seq, (char *)svs.log_buf[seq&(FRAGLOG_BUFFERS-1)]);
|
||||
NET_SendPacket (NS_SERVER, strlen(data)+1, data, &net_from);
|
||||
NET_SendPacket (svs.sockets, strlen(data)+1, data, &net_from);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1420,7 +1413,7 @@ void SVC_Ping (void)
|
|||
|
||||
data = A2A_ACK;
|
||||
|
||||
NET_SendPacket (NS_SERVER, 1, &data, &net_from);
|
||||
NET_SendPacket (svs.sockets, 1, &data, &net_from);
|
||||
}
|
||||
|
||||
//from net_from
|
||||
|
@ -1777,7 +1770,7 @@ void VARGS SV_RejectMessage(int protocol, char *format, ...)
|
|||
vsnprintf (string+5,sizeof(string)-1-5, format,argptr);
|
||||
len = strlen(string+4)+1+4;
|
||||
*(int*)string = BigLong(NETFLAG_CTL|len);
|
||||
NET_SendPacket(NS_SERVER, len, string, &net_from);
|
||||
NET_SendPacket(svs.sockets, len, string, &net_from);
|
||||
return;
|
||||
case SCP_DARKPLACES6:
|
||||
case SCP_DARKPLACES7:
|
||||
|
@ -1840,7 +1833,7 @@ void SV_AcceptMessage(client_t *newcl)
|
|||
MSG_WriteByte(&sb, 0/*flags*/);
|
||||
}
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return;
|
||||
}
|
||||
case SCP_DARKPLACES6:
|
||||
|
@ -3484,7 +3477,7 @@ void SVC_RemoteCommand (void)
|
|||
Con_TPrintf ("Bad rcon from %s:\t%s\n"
|
||||
, NET_AdrToString (adr, sizeof(adr), &net_from), net_message.data+4);
|
||||
|
||||
SV_BeginRedirect (RD_PACKET, svs.language);
|
||||
SV_BeginRedirect (RD_PACKET, com_language);
|
||||
|
||||
Con_TPrintf ("Bad rcon_password. Passwords might be logged. Be careful.\n");
|
||||
}
|
||||
|
@ -3501,7 +3494,7 @@ void SVC_RemoteCommand (void)
|
|||
Con_TPrintf ("Rcon from %s:\t%s\n"
|
||||
, NET_AdrToString (adr, sizeof(adr), &net_from), net_message.data+4);
|
||||
|
||||
SV_BeginRedirect (RD_PACKET_LOG, svs.language);
|
||||
SV_BeginRedirect (RD_PACKET_LOG, com_language);
|
||||
|
||||
remaining[0] = 0;
|
||||
|
||||
|
@ -3725,7 +3718,7 @@ qboolean SV_ConnectionlessPacket (void)
|
|||
|
||||
if (secure.value) //FIXME: possible problem for nq clients when enabled
|
||||
{
|
||||
Netchan_OutOfBandTPrintf (NS_SERVER, &net_from, svs.language, "%c\nThis server requires client validation.\nPlease use the "FULLENGINENAME" validation program\n", A2C_PRINT);
|
||||
Netchan_OutOfBandTPrintf (NS_SERVER, &net_from, com_language, "%c\nThis server requires client validation.\nPlease use the "FULLENGINENAME" validation program\n", A2C_PRINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3891,7 +3884,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
SZ_Clear(&sb);
|
||||
MSG_WriteLong(&sb, BigLong(NETFLAG_ACK | 8));
|
||||
MSG_WriteLong(&sb, sequence);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3907,7 +3900,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteString(&sb, va("cmd challengeconnect %i %i\n", SV_NewChallenge(), MOD_PROQUAKE));
|
||||
|
||||
*(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -3935,7 +3928,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteByte(&sb, CCREP_REJECT);
|
||||
MSG_WriteString(&sb, "Incorrect game\n");
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return false; //not our game.
|
||||
}
|
||||
if (MSG_ReadByte() != NQ_NETCHAN_VERSION)
|
||||
|
@ -3945,7 +3938,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteByte(&sb, CCREP_REJECT);
|
||||
MSG_WriteString(&sb, "Incorrect version\n");
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return false; //not our version...
|
||||
}
|
||||
|
||||
|
@ -3957,7 +3950,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteByte(&sb, CCREP_REJECT);
|
||||
MSG_WriteString(&sb, *banreason?va("You are banned: %s\n", banreason):"You are banned\n");
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return false; //not our version...
|
||||
}
|
||||
|
||||
|
@ -3982,7 +3975,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteByte(&sb, CCREP_REJECT);
|
||||
MSG_WriteString(&sb, "NQ clients are not supported with hexen2 gamecode\n");
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return false; //not our version...
|
||||
}
|
||||
if (sv_listen_nq.ival == 2)
|
||||
|
@ -3995,7 +3988,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteByte(&sb, MOD_PROQUAKE);
|
||||
MSG_WriteByte(&sb, MOD_PROQUAKE_VERSION);
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
|
||||
|
||||
SZ_Clear(&sb);
|
||||
|
@ -4006,7 +3999,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteString(&sb, va("cmd challengeconnect %i %i %i %i %i\n", SV_NewChallenge(), mod, modver, flags, passwd));
|
||||
|
||||
*(int*)sb.data = BigLong(NETFLAG_UNRELIABLE|sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
/*don't worry about repeating, the nop case above will recover it*/
|
||||
}
|
||||
else
|
||||
|
@ -4048,7 +4041,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteByte (&sb, maxclients.value);
|
||||
MSG_WriteByte (&sb, NQ_NETCHAN_VERSION);
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return true;
|
||||
case CCREQ_PLAYER_INFO:
|
||||
if (sv_showconnectionlessmessages.ival)
|
||||
|
@ -4082,7 +4075,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteString (&sb, SV_PlayerPublicAddress(cl)); /*player's address, leave blank, don't spam that info as it can result in personal attacks exploits*/
|
||||
}
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return true;
|
||||
case CCREQ_RULE_INFO:
|
||||
if (sv_showconnectionlessmessages.ival)
|
||||
|
@ -4132,7 +4125,7 @@ qboolean SVNQ_ConnectionlessPacket(void)
|
|||
MSG_WriteString (&sb, rval);
|
||||
}
|
||||
*(int*)sb.data = BigLong(NETFLAG_CTL+sb.cursize);
|
||||
NET_SendPacket(NS_SERVER, sb.cursize, sb.data, &net_from);
|
||||
NET_SendPacket(svs.sockets, sb.cursize, sb.data, &net_from);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -4285,7 +4278,7 @@ qboolean SV_ReadPackets (float *delay)
|
|||
#ifdef SERVER_DEMO_PLAYBACK
|
||||
while (giveup-- > 0 && SV_GetPacket()>=0)
|
||||
#else
|
||||
while (giveup-- > 0 && (cookie=NET_GetPacket (NS_SERVER, cookie)) >= 0)
|
||||
while (giveup-- > 0 && (cookie=NET_GetPacket (svs.sockets, cookie)) >= 0)
|
||||
#endif
|
||||
{
|
||||
// check for connectionless packet (0xffffffff) first
|
||||
|
@ -4299,9 +4292,9 @@ qboolean SV_ReadPackets (float *delay)
|
|||
if (ct - lt > 5*1000)
|
||||
{
|
||||
if (*banreason)
|
||||
Netchan_OutOfBandTPrintf(NS_SERVER, &net_from, svs.language, "You are banned: %s\n", banreason);
|
||||
Netchan_OutOfBandTPrintf(NS_SERVER, &net_from, com_language, "You are banned: %s\n", banreason);
|
||||
else
|
||||
Netchan_OutOfBandTPrintf(NS_SERVER, &net_from, svs.language, "You are banned\n");
|
||||
Netchan_OutOfBandTPrintf(NS_SERVER, &net_from, com_language, "You are banned\n");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -4454,7 +4447,7 @@ dominping:
|
|||
if (SV_BannedReason (&net_from))
|
||||
continue;
|
||||
|
||||
if (NET_WasSpecialPacket(NS_SERVER))
|
||||
if (NET_WasSpecialPacket(svs.sockets))
|
||||
continue;
|
||||
|
||||
// packet is not from a known client
|
||||
|
@ -5125,8 +5118,6 @@ void SV_InitLocal (void)
|
|||
if (isDedicated)
|
||||
#endif
|
||||
{
|
||||
Cvar_Register (&developer, cvargroup_servercontrol);
|
||||
|
||||
Cvar_Register (&password, cvargroup_servercontrol);
|
||||
Cvar_Register (&rcon_password, cvargroup_servercontrol);
|
||||
|
||||
|
@ -5563,7 +5554,7 @@ void SV_ExtractFromUserinfo (client_t *cl, qboolean verbose)
|
|||
}
|
||||
|
||||
val = InfoBuf_ValueForKey (&cl->userinfo, "lang");
|
||||
cl->language = *val?TL_FindLanguage(val):svs.language;
|
||||
cl->language = *val?TL_FindLanguage(val):com_language;
|
||||
|
||||
val = InfoBuf_ValueForKey (&cl->userinfo, "nogib");
|
||||
cl->gibfilter = !!atoi(val);
|
||||
|
|
|
@ -11,60 +11,213 @@
|
|||
|
||||
#include "netinc.h"
|
||||
|
||||
//quake1 protocol
|
||||
//
|
||||
//
|
||||
//quakeworld protocol
|
||||
// heartbeat: "a"
|
||||
// query: "c\n%i<sequence>\n%i<numplayers>\n"
|
||||
//queryresponse: "d\naaaappaaaapp"
|
||||
|
||||
//quake2 protocol
|
||||
//client sends "query\0"
|
||||
//server sends "0xff0xff0xff0xffservers" follwed by lots of ips.
|
||||
// heartbeat: "heartbeat\n%s<serverinfo>\n%i<frags> %i<ping> \"%s\"<name>\n<repeat>"
|
||||
// query: "query\0"
|
||||
//queryresponse: "servers\naaaappaaaapp"
|
||||
|
||||
#define SVM_Q1HEARTBEATTIME 330
|
||||
#define SVM_Q2HEARTBEATTIME 330
|
||||
//quake3/dpmaster protocol
|
||||
// heartbeat: "heartbeat DarkPlaces\n"
|
||||
// query: "getservers[Ext<ipv6>] [%s<game>] %u<version> [empty] [full] [ipv6]"
|
||||
//queryresponse: "getservers[Ext]Response\\aaaapp/aaaaaaaaaaaapp\\EOF"
|
||||
|
||||
enum gametypes_e
|
||||
{
|
||||
GT_FFA=0,
|
||||
GT_TOURNEY=1,
|
||||
GT_TEAM=3,
|
||||
GT_CTF=4,
|
||||
};
|
||||
typedef struct svm_server_s {
|
||||
netadr_t adr;
|
||||
int clients;
|
||||
int protover;
|
||||
unsigned int clients;
|
||||
unsigned int maxclients;
|
||||
char hostname[48]; //just for our own listings.
|
||||
char mapname[16]; //just for our own listings.
|
||||
char gamedir[16]; //again...
|
||||
unsigned short gametype;
|
||||
float expiretime;
|
||||
|
||||
bucket_t bucket;
|
||||
struct svm_game_s *game;
|
||||
struct svm_server_s *next;
|
||||
} svm_server_t;
|
||||
|
||||
typedef struct {
|
||||
SOCKET socketudp;
|
||||
float time;
|
||||
int port;
|
||||
typedef struct svm_game_s {
|
||||
struct svm_game_s *next;
|
||||
|
||||
svm_server_t *firstserver;
|
||||
int numservers;
|
||||
size_t numservers;
|
||||
char name[1];
|
||||
} svm_game_t;
|
||||
|
||||
typedef struct {
|
||||
float time;
|
||||
|
||||
svm_game_t *firstgame;
|
||||
size_t numgames;
|
||||
|
||||
hashtable_t serverhash;
|
||||
size_t numservers;
|
||||
|
||||
struct rates_s
|
||||
{
|
||||
double timestamp;
|
||||
size_t heartbeats;
|
||||
size_t queries;
|
||||
size_t junk;
|
||||
|
||||
size_t drops;
|
||||
size_t adds;
|
||||
} total, stamps[60];
|
||||
size_t stampring;
|
||||
double nextstamp;
|
||||
} masterserver_t;
|
||||
|
||||
masterserver_t svm = {INVALID_SOCKET};
|
||||
static masterserver_t svm;
|
||||
ftenet_connections_t *svm_sockets;
|
||||
|
||||
void SVM_RemoveOldServers(void)
|
||||
static void QDECL SVM_Tcpport_Callback(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
svm_server_t *server, *next, *prev=NULL;
|
||||
for (server = svm.firstserver; server; server = next)
|
||||
FTENET_AddToCollection(svm_sockets, var->name, var->string, NA_IP, NP_STREAM);
|
||||
}
|
||||
static void QDECL SVM_Port_Callback(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
next = server->next;
|
||||
if (server->expiretime < svm.time)
|
||||
FTENET_AddToCollection(svm_sockets, var->name, var->string, NA_IP, NP_DGRAM);
|
||||
}
|
||||
static cvar_t sv_heartbeattimeout = CVARD("sv_heartbeattimeout", "600", "How many seconds a server should remain listed after its latest heartbeat. Larger values can avoid issues from packetloss, but can also make dos attacks easier.");
|
||||
static cvar_t sv_masterport = CVARC("sv_masterport", "27000 28000", SVM_Port_Callback);
|
||||
static cvar_t sv_masterport_tcp = CVARC("sv_masterport_tcp", "27000 28000", SVM_Tcpport_Callback);
|
||||
static cvar_t sv_maxgames = CVARD("sv_maxgames", "100", "Limits the number of games that may be known. This is to reduce denial of service attacks.");
|
||||
static cvar_t sv_maxservers = CVARD("sv_maxservers", "1000", "Limits the number of servers (total from all games) that may be known. This is to reduce denial of service attacks.");
|
||||
|
||||
//returns a hash key for a server's address.
|
||||
static unsigned int SVM_GenerateAddressKey(const netadr_t *adr)
|
||||
{
|
||||
BZ_Free(server);
|
||||
if (prev)
|
||||
prev->next = next;
|
||||
else
|
||||
svm.firstserver = next;
|
||||
unsigned int key;
|
||||
switch(adr->type)
|
||||
{
|
||||
case NA_IP:
|
||||
key = *(const unsigned int*)adr->address.ip;
|
||||
key ^= 0xffff0000; //match ipv6's ipv4-mapped addresses.
|
||||
key ^= adr->port;
|
||||
break;
|
||||
case NA_IPV6:
|
||||
key = *(const unsigned int*)(adr->address.ip6+0);
|
||||
key ^= *(const unsigned int*)(adr->address.ip6+4);
|
||||
key ^= *(const unsigned int*)(adr->address.ip6+8);
|
||||
key ^= *(const unsigned int*)(adr->address.ip6+12);
|
||||
key ^= adr->port;
|
||||
break;
|
||||
default:
|
||||
key = 0;
|
||||
break;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
static svm_server_t *SVM_GetServer(netadr_t *adr)
|
||||
{
|
||||
svm_server_t *server;
|
||||
unsigned int key = SVM_GenerateAddressKey(adr);
|
||||
|
||||
server = Hash_GetKey(&svm.serverhash, key);
|
||||
while (server && !NET_CompareAdr(&server->adr, adr))
|
||||
{
|
||||
server = Hash_GetNextKey(&svm.serverhash, key, server);
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
static svm_game_t *SVM_FindGame(const char *game, qboolean create)
|
||||
{
|
||||
svm_game_t *g;
|
||||
for (g = svm.firstgame; g; g = g->next)
|
||||
{
|
||||
if (!Q_strcasecmp(game, g->name))
|
||||
return g;
|
||||
}
|
||||
|
||||
if (create)
|
||||
{
|
||||
if (svm.numgames >= sv_maxgames.ival)
|
||||
{
|
||||
Con_DPrintf("game limit exceeded\n");
|
||||
return NULL;
|
||||
}
|
||||
//block some chars that may cause issues/exploits. sorry.
|
||||
if (strchr(game, '.') || strchr(game, '\"') || strchr(game, '/') || strchr(game, '?') || strchr(game, '&') || strchr(game, '+') || strchr(game, '\'') || strchr(game, '<') || strchr(game, '>'))
|
||||
return NULL;
|
||||
if (!*game || (*game >= '0' && *game <= '9'))
|
||||
return NULL; //must not start with a number either.
|
||||
g = ZF_Malloc(sizeof(*g) + strlen(game));
|
||||
if (g)
|
||||
{
|
||||
strcpy(g->name, game);
|
||||
g->next = svm.firstgame;
|
||||
svm.firstgame = g;
|
||||
svm.numgames++;
|
||||
Con_DPrintf("Creating game \"%s\"\n", g->name);
|
||||
}
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
static void SVM_RemoveOldServers(void)
|
||||
{
|
||||
svm_game_t **gamelink, *g;
|
||||
svm_server_t **serverlink, *s;
|
||||
for (gamelink = &svm.firstgame; (g=*gamelink); )
|
||||
{
|
||||
for (serverlink = &g->firstserver; (s=*serverlink); )
|
||||
{
|
||||
if (s->expiretime < svm.time)
|
||||
{
|
||||
if (developer.ival)
|
||||
{
|
||||
char buf[256];
|
||||
Con_Printf("timeout: %s\n", NET_AdrToString(buf, sizeof(buf), &s->adr));
|
||||
}
|
||||
|
||||
Hash_RemoveDataKey(&svm.serverhash, SVM_GenerateAddressKey(&s->adr), s);
|
||||
|
||||
svm.total.drops++;
|
||||
*serverlink = s->next;
|
||||
BZ_Free(s);
|
||||
g->numservers--;
|
||||
svm.numservers--;
|
||||
}
|
||||
else
|
||||
prev = server;
|
||||
serverlink = &s->next;
|
||||
}
|
||||
|
||||
if (!g->firstserver)
|
||||
{
|
||||
Con_DPrintf("game \"%s\" has no active servers\n", g->name);
|
||||
*gamelink = g->next;
|
||||
Z_Free(g);
|
||||
svm.numgames--;
|
||||
}
|
||||
else
|
||||
gamelink = &g->next;
|
||||
}
|
||||
}
|
||||
|
||||
int SVM_AddIPAddresses(sizebuf_t *sb, int first)
|
||||
int SVM_AddIPAddresses(sizebuf_t *sb, int first, const char *gamename, int v4, int v6, qboolean prefixes)
|
||||
{
|
||||
int number = 0;
|
||||
svm_server_t *server;
|
||||
|
||||
for (server = svm.firstserver; server; server = server->next)
|
||||
int prefix;
|
||||
int len;
|
||||
svm_game_t *game = SVM_FindGame(gamename, false);
|
||||
if (game)
|
||||
{
|
||||
for (server = game->firstserver; server; server = server->next)
|
||||
{
|
||||
if (number == first)
|
||||
break;
|
||||
|
@ -74,93 +227,203 @@ int SVM_AddIPAddresses(sizebuf_t *sb, int first)
|
|||
|
||||
for (; server; server = server->next)
|
||||
{
|
||||
if (sb->cursize + 6 >= sb->maxsize)
|
||||
switch(server->adr.type)
|
||||
{
|
||||
case NA_IP:
|
||||
if (!v4)
|
||||
continue;
|
||||
prefix = '\\';
|
||||
len = 4;
|
||||
break;
|
||||
case NA_IPV6:
|
||||
if (!v6)
|
||||
continue;
|
||||
prefix = '/';
|
||||
len = 16;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
MSG_WriteByte(sb, server->adr.address.ip[0]);
|
||||
MSG_WriteByte(sb, server->adr.address.ip[1]);
|
||||
MSG_WriteByte(sb, server->adr.address.ip[2]);
|
||||
MSG_WriteByte(sb, server->adr.address.ip[3]);
|
||||
if (prefixes)
|
||||
MSG_WriteByte(sb, prefixes);
|
||||
|
||||
SZ_Write(sb, server->adr.address.ip, len);
|
||||
MSG_WriteShort(sb, server->adr.port);
|
||||
|
||||
number++;
|
||||
}
|
||||
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
void SVM_Heartbeat(netadr_t *adr, int numclients, float validuntil)
|
||||
vfsfile_t *SVM_GenerateIndex(const char *fname)
|
||||
{
|
||||
static const char *thecss =
|
||||
"<style type=\"text/css\">"
|
||||
"body {"
|
||||
"background-color: #303030;"
|
||||
"color: #998080;"
|
||||
"font-family: verdanah, trebuchet ms, arial, sans-serif;"
|
||||
"}"
|
||||
"a { text-decoration: none; }"
|
||||
"a:link { color: #308090; }"
|
||||
"a:visited { color: #308090; }"
|
||||
"a:hover { color: #308090; text-decoration: underline; }"
|
||||
".header { text-align: center; }"
|
||||
".footer { text-align: center; }"
|
||||
".main { width: 1024px; margin: 0 auto; }"
|
||||
"H1 {"
|
||||
"text-align: center;"
|
||||
"background-color: #202020;"
|
||||
"color: #808080;"
|
||||
"}"
|
||||
"table { width: 100%; border-collapse: collapse; }"
|
||||
"th { text-align: left; }"
|
||||
"tr:hover { background-color: #202020; }"
|
||||
"</style>";
|
||||
char tmpbuf[256];
|
||||
svm_game_t *game;
|
||||
svm_server_t *server;
|
||||
|
||||
for (server = svm.firstserver; server; server = server->next)
|
||||
vfsfile_t *f = NULL;
|
||||
unsigned clients = 0, maxclients=0;
|
||||
if (!strcmp(fname, "index.html"))
|
||||
{
|
||||
if (NET_CompareAdr(&server->adr, adr))
|
||||
break;
|
||||
f = VFSPIPE_Open(1, false);
|
||||
VFS_PRINTF(f, "%s", thecss);
|
||||
VFS_PRINTF(f, "<h1>FTE-Master</h1>\n");
|
||||
VFS_PRINTF(f, "<table border=1>\n");
|
||||
for (game = svm.firstgame; game; game = game->next)
|
||||
{
|
||||
VFS_PRINTF(f, "<tr><td><a href=\"game/%s.html\">%s</a></td><td%u server(s)</td></tr>\n", game->name, game->name, (unsigned)game->numservers);
|
||||
clients += game->numservers;
|
||||
}
|
||||
VFS_PRINTF(f, "</table>\n");
|
||||
VFS_PRINTF(f, "%u game(s), %u server(s)\n", (unsigned)svm.numgames, clients);
|
||||
}
|
||||
else if (!strncmp(fname, "server/", 7))
|
||||
{
|
||||
netadr_t adr[64];
|
||||
int count;
|
||||
|
||||
f = VFSPIPE_Open(1, false);
|
||||
VFS_PRINTF(f, "%s", thecss);
|
||||
VFS_PRINTF(f, "<h1>Single Server Info</h1>\n", tmpbuf);
|
||||
|
||||
VFS_PRINTF(f, "<table border=1>\n");
|
||||
VFS_PRINTF(f, "<tr><th>Game</th><th>Address</th><th>Hostname</th><th>Mod dir</th><th>Mapname</th><th>Players</th></tr>\n");
|
||||
count = NET_StringToAdr2(fname+7, 0, adr, countof(adr));
|
||||
while(count-->0)
|
||||
{
|
||||
server = SVM_GetServer(&adr[count]);
|
||||
if (server)
|
||||
VFS_PRINTF(f, "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%u/%u</td></tr>\n", server->game?server->game->name:"Unknown", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr), server->hostname, server->gamedir, server->mapname, server->clients, server->maxclients);
|
||||
else
|
||||
VFS_PRINTF(f, "<tr><td>?</td><td>%s</td><td>?</td><td>?</td><td>?</td><td>?/?</td></tr>\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &adr[count]));
|
||||
}
|
||||
VFS_PRINTF(f, "</table>\n");
|
||||
}
|
||||
else if (!strncmp(fname, "game/", 5))
|
||||
{
|
||||
COM_StripExtension(fname+5, tmpbuf, sizeof(tmpbuf));
|
||||
game = SVM_FindGame(tmpbuf, false);
|
||||
|
||||
f = VFSPIPE_Open(1, false);
|
||||
VFS_PRINTF(f, "%s", thecss);
|
||||
VFS_PRINTF(f, "<h1>Servers for %s</h1>\n", tmpbuf);
|
||||
|
||||
if(game)
|
||||
{
|
||||
VFS_PRINTF(f, "<table border=1>\n");
|
||||
VFS_PRINTF(f, "<tr><th>Address</th><th>Hostname</th><th>Gamedir</th><th>Mapname</th><th>Players</th></tr>\n");
|
||||
for (server = game->firstserver; server; server = server->next)
|
||||
{
|
||||
VFS_PRINTF(f, "<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%u/%u</td></tr>\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr), server->hostname, server->gamedir, server->mapname, server->clients, server->maxclients);
|
||||
clients += server->clients;
|
||||
maxclients += server->maxclients;
|
||||
}
|
||||
VFS_PRINTF(f, "</table>\n");
|
||||
VFS_PRINTF(f, "%u server(s), %u/%u client(s)\n", (unsigned)game->numservers, clients, maxclients);
|
||||
}
|
||||
else
|
||||
VFS_PRINTF(f, "No servers known for %s\n", tmpbuf);
|
||||
}
|
||||
else if (!strncmp(fname, "raw/", 4))
|
||||
{ //just spews all
|
||||
COM_StripExtension(fname+4, tmpbuf, sizeof(tmpbuf));
|
||||
game = SVM_FindGame(tmpbuf, false);
|
||||
|
||||
f = VFSPIPE_Open(1, false);
|
||||
for (server = (game?game->firstserver:NULL); server; server = server->next)
|
||||
VFS_PRINTF(f, "%s\n", NET_AdrToString(tmpbuf, sizeof(tmpbuf), &server->adr));
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
static svm_server_t *SVM_Heartbeat(const char *gamename, netadr_t *adr, int numclients, float validuntil)
|
||||
{
|
||||
svm_server_t *server = SVM_GetServer(adr);
|
||||
svm_game_t *game = SVM_FindGame(gamename, true);
|
||||
if (!game)
|
||||
return NULL;
|
||||
|
||||
if (server && server->game != game)
|
||||
{
|
||||
server->expiretime = realtime - 1;
|
||||
server = NULL;
|
||||
}
|
||||
|
||||
if (!server) //not found
|
||||
{
|
||||
if (svm.numservers >= sv_maxservers.ival)
|
||||
{
|
||||
Con_DPrintf("server limit exceeded\n");
|
||||
return NULL;
|
||||
}
|
||||
if (developer.ival)
|
||||
{
|
||||
char buf[256];
|
||||
Con_Printf("heartbeat(new - %s): %s\n", game->name, NET_AdrToString(buf, sizeof(buf), adr));
|
||||
}
|
||||
|
||||
server = Z_Malloc(sizeof(svm_server_t));
|
||||
server->next = svm.firstserver;
|
||||
svm.firstserver = server;
|
||||
server->game = game;
|
||||
server->next = game->firstserver;
|
||||
game->firstserver = server;
|
||||
game->numservers++;
|
||||
svm.numservers++;
|
||||
|
||||
server->adr = *adr;
|
||||
|
||||
svm.total.adds++;
|
||||
|
||||
Hash_AddKey(&svm.serverhash, SVM_GenerateAddressKey(adr), server, &server->bucket);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (developer.ival)
|
||||
{
|
||||
char buf[256];
|
||||
Con_Printf("heartbeat(refresh): %s\n", NET_AdrToString(buf, sizeof(buf), &server->adr));
|
||||
}
|
||||
}
|
||||
|
||||
server->clients = numclients;
|
||||
server->expiretime = validuntil;
|
||||
}
|
||||
|
||||
|
||||
void SVM_Init(int port)
|
||||
{
|
||||
if (svm.socketudp == INVALID_SOCKET)
|
||||
svm.socketudp = UDP_OpenSocket(port, false);
|
||||
}
|
||||
|
||||
void SVM_ShutDown (void)
|
||||
{
|
||||
if (svm.socketudp != INVALID_SOCKET)
|
||||
{
|
||||
UDP_CloseSocket(svm.socketudp);
|
||||
svm.socketudp = INVALID_SOCKET;
|
||||
}
|
||||
return server;
|
||||
}
|
||||
|
||||
void SVM_Think(int port)
|
||||
{
|
||||
char *s;
|
||||
struct sockaddr_qstorage addr;
|
||||
int addrlen;
|
||||
netadr_t netaddr;
|
||||
if (!port)
|
||||
int cookie = 0;
|
||||
int giveup = 500;
|
||||
|
||||
while (giveup-- > 0 && (cookie=NET_GetPacket (svm_sockets, cookie)) >= 0)
|
||||
{
|
||||
SVM_ShutDown();
|
||||
return;
|
||||
}
|
||||
|
||||
if (port != svm.port)
|
||||
{
|
||||
SVM_ShutDown(); //shut down (to cause a restart)
|
||||
svm.port = port;
|
||||
}
|
||||
|
||||
SVM_Init(port);
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
net_message.cursize = recvfrom(svm.socketudp, net_message_buffer, sizeof(net_message_buffer)-1, 0, (struct sockaddr *)&addr, &addrlen);
|
||||
if (net_message.cursize <= 0)
|
||||
{
|
||||
addrlen = neterrno();
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
net_message.data[net_message.cursize] = '\0'; //null term all strings.
|
||||
SockadrToNetadr(&addr, &netaddr);
|
||||
svm.time = Sys_DoubleTime();
|
||||
|
||||
SVM_RemoveOldServers();
|
||||
svm.time = Sys_DoubleTime();
|
||||
|
||||
MSG_BeginReading(msg_nullnetprim);
|
||||
if (MSG_ReadLong() != -1 || msg_badread)
|
||||
|
@ -169,55 +432,308 @@ void SVM_Think(int port)
|
|||
}
|
||||
s = MSG_ReadStringLine();
|
||||
s = COM_Parse(s);
|
||||
if (!strcmp(com_token, "getservers"))
|
||||
{
|
||||
if (!strcmp(com_token, "getservers") || !strcmp(com_token, "getserversExt"))
|
||||
{ //q3
|
||||
sizebuf_t sb;
|
||||
int ver;
|
||||
char *eos;
|
||||
char game[64];
|
||||
qboolean ext = !strcmp(com_token, "getserversExt");
|
||||
qboolean empty = false;
|
||||
qboolean full = false;
|
||||
qboolean ipv4 = !ext;
|
||||
qboolean ipv6 = false;
|
||||
int gametype = -1;
|
||||
s = COM_ParseOut(s, game, sizeof(game));
|
||||
ver = strtol(game, &eos, 0);
|
||||
if (*eos)
|
||||
{
|
||||
s = COM_Parse(s);
|
||||
ver = strtol(com_token, NULL, 0);
|
||||
}
|
||||
else
|
||||
Q_strncpyz(game, "Quake3", sizeof(game));
|
||||
for(;s&&*s;)
|
||||
{
|
||||
s = COM_Parse(s);
|
||||
if (!strcmp(com_token, "empty"))
|
||||
empty = true;
|
||||
else if (!strcmp(com_token, "full"))
|
||||
full = true;
|
||||
|
||||
else if (!strcmp(com_token, "ipv4"))
|
||||
ipv4 = true;
|
||||
else if (!strcmp(com_token, "ipv6"))
|
||||
ipv6 = true;
|
||||
|
||||
else if (!strcmp(com_token, "ffa"))
|
||||
gametype = GT_FFA;
|
||||
else if (!strcmp(com_token, "tourney"))
|
||||
gametype = GT_TOURNEY;
|
||||
else if (!strcmp(com_token, "team"))
|
||||
gametype = GT_TEAM;
|
||||
else if (!strcmp(com_token, "ctf"))
|
||||
gametype = GT_CTF;
|
||||
else if (!strncmp(com_token, "gametype=", 9))
|
||||
gametype = atoi(com_token+9);
|
||||
}
|
||||
svm.total.queries++;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
sb.maxsize = sizeof(net_message_buffer)-2;
|
||||
sb.data = net_message_buffer;
|
||||
MSG_WriteLong(&sb, -1);
|
||||
MSG_WriteString(&sb, "getserversResponse\\");
|
||||
sb.cursize--;
|
||||
SVM_AddIPAddresses(&sb, 0);
|
||||
|
||||
if (!ipv4 && !ipv6)
|
||||
ipv4 = ipv6 = true; //neither specified? use both
|
||||
if (ext)
|
||||
{ //ipv6 and ipv4 addresses
|
||||
MSG_WriteString(&sb, "getserversExtResponse");
|
||||
SVM_AddIPAddresses(&sb, 0, game, ipv4, ipv6, true);
|
||||
}
|
||||
else
|
||||
{ //ipv4 only
|
||||
MSG_WriteString(&sb, "getserversResponse");
|
||||
SVM_AddIPAddresses(&sb, 0, game, ipv4, ipv6, true);
|
||||
}
|
||||
sb.maxsize+=2;
|
||||
MSG_WriteShort(&sb, 0);
|
||||
sendto(svm.socketudp, sb.data, sb.cursize, 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||
MSG_WriteByte(&sb, '\\'); //otherwise the last may be considered invalid and ignored.
|
||||
// MSG_WriteByte(&sb, 'E');
|
||||
// MSG_WriteByte(&sb, 'O');
|
||||
// MSG_WriteByte(&sb, 'T');
|
||||
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from);
|
||||
}
|
||||
else if (!strcmp(com_token, "heartbeat"))
|
||||
{ //quake2 heartbeat. Serverinfo and players follow.
|
||||
SVM_Heartbeat(&netaddr, 0, svm.time + SVM_Q2HEARTBEATTIME);
|
||||
{ //quake2 heartbeat. Serverinfo and players should follow.
|
||||
if (*s == '\n' && s[1] == '\\')
|
||||
{ //there's some serverinfo there, must be q2...
|
||||
svm.total.heartbeats++;
|
||||
SVM_Heartbeat("Quake2", &net_from, 0, svm.time + sv_heartbeattimeout.ival);
|
||||
}
|
||||
else
|
||||
{ //dp/q3/etc are annoying, but we can query from an emphemerial socket to check NAT rules.
|
||||
sizebuf_t sb;
|
||||
svm.total.queries++;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
sb.maxsize = sizeof(net_message_buffer);
|
||||
sb.data = net_message_buffer;
|
||||
MSG_WriteLong(&sb, -1);
|
||||
MSG_WriteString(&sb, "getinfo CAKE\n");
|
||||
sb.cursize--;
|
||||
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from);
|
||||
}
|
||||
}
|
||||
else if (!strcmp(com_token, "infoResponse"))
|
||||
{
|
||||
int clients;
|
||||
const char *game, *chal;
|
||||
svm_server_t *srv;
|
||||
s = MSG_ReadStringLine();
|
||||
svm.total.heartbeats++;
|
||||
chal = Info_ValueForKey(s, "challenge");
|
||||
if (!strcmp(chal, "CAKE"))
|
||||
{
|
||||
clients = atoi(Info_ValueForKey(s, "clients"));
|
||||
game = Info_ValueForKey(s, "gamename");
|
||||
srv = SVM_Heartbeat(game, &net_from, clients, svm.time + sv_heartbeattimeout.ival);
|
||||
if (srv)
|
||||
{
|
||||
if (developer.ival)
|
||||
Info_Print(s, "\t");
|
||||
srv->protover = atoi(Info_ValueForKey(s, "protocol"));
|
||||
srv->maxclients = atoi(Info_ValueForKey(s, "sv_maxclients"));
|
||||
Q_strncpyz(srv->hostname, Info_ValueForKey(s, "hostname"), sizeof(srv->hostname));
|
||||
Q_strncpyz(srv->gamedir, Info_ValueForKey(s, "modname"), sizeof(srv->gamedir));
|
||||
Q_strncpyz(srv->mapname, Info_ValueForKey(s, "mapname"), sizeof(srv->mapname));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strcmp(com_token, "query"))
|
||||
{ //quake2 server listing request
|
||||
sizebuf_t sb;
|
||||
svm.total.queries++;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
sb.maxsize = sizeof(net_message_buffer);
|
||||
sb.data = net_message_buffer;
|
||||
MSG_WriteLong(&sb, -1);
|
||||
MSG_WriteString(&sb, "servers\n");
|
||||
sb.cursize--;
|
||||
// MSG_WriteLong(&sb, 0);
|
||||
// MSG_WriteShort(&sb, 0);
|
||||
SVM_AddIPAddresses(&sb, 0);
|
||||
sendto(svm.socketudp, sb.data, sb.cursize, 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||
SVM_AddIPAddresses(&sb, 0, "Quake2", true, false, false);
|
||||
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from);
|
||||
}
|
||||
else if (*com_token == S2M_HEARTBEAT) //sequence, players
|
||||
{ //quakeworld heartbeat
|
||||
SVM_Heartbeat(&netaddr, 0, svm.time + SVM_Q1HEARTBEATTIME);
|
||||
int players;
|
||||
s = MSG_ReadStringLine();
|
||||
//sequence = atoi(s);
|
||||
s = MSG_ReadStringLine();
|
||||
players = atoi(s);
|
||||
svm.total.heartbeats++;
|
||||
SVM_Heartbeat("QuakeWorld", &net_from, players, svm.time + sv_heartbeattimeout.ival);
|
||||
}
|
||||
else if (*com_token == S2C_CHALLENGE)
|
||||
else if (*com_token == C2M_MASTER_REQUEST)
|
||||
{ //quakeworld server listing request
|
||||
sizebuf_t sb;
|
||||
svm.total.queries++;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
sb.maxsize = sizeof(net_message_buffer);
|
||||
sb.data = net_message_buffer;
|
||||
MSG_WriteLong(&sb, -1);
|
||||
MSG_WriteByte(&sb, M2C_MASTER_REPLY);
|
||||
MSG_WriteByte(&sb, '\n');
|
||||
SVM_AddIPAddresses(&sb, 0);
|
||||
sendto(svm.socketudp, sb.data, sb.cursize, 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||
SVM_AddIPAddresses(&sb, 0, "QuakeWorld", true, false, false);
|
||||
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from);
|
||||
}
|
||||
else if (*com_token == A2A_PING)
|
||||
{ //quakeworld server listing request
|
||||
sizebuf_t sb;
|
||||
svm.total.queries++;
|
||||
memset(&sb, 0, sizeof(sb));
|
||||
sb.maxsize = sizeof(net_message_buffer);
|
||||
sb.data = net_message_buffer;
|
||||
MSG_WriteLong(&sb, -1);
|
||||
MSG_WriteByte(&sb, A2A_ACK);
|
||||
MSG_WriteByte(&sb, '\n');
|
||||
NET_SendPacket(svm_sockets, sb.cursize, sb.data, &net_from);
|
||||
}
|
||||
else
|
||||
svm.total.junk++;
|
||||
}
|
||||
|
||||
SVM_RemoveOldServers();
|
||||
}
|
||||
#else
|
||||
void SVM_Think(int port){}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MASTERONLY
|
||||
static void SV_Quit_f (void)
|
||||
{
|
||||
Con_TPrintf ("Shutting down.\n");
|
||||
Sys_Quit ();
|
||||
}
|
||||
static void SVM_Status_f(void)
|
||||
{
|
||||
svm_game_t *g;
|
||||
svm_server_t *s;
|
||||
unsigned clients;
|
||||
struct rates_s *s1, *s2;
|
||||
float period;
|
||||
size_t r;
|
||||
|
||||
NET_PrintAddresses(svm_sockets);
|
||||
NET_PrintConnectionsStatus(svm_sockets);
|
||||
Con_Printf("Game count: %u\n", (unsigned)svm.numgames);
|
||||
for (g = svm.firstgame; g; g = g->next)
|
||||
{
|
||||
clients = 0;
|
||||
for (s = g->firstserver; s; s = s->next)
|
||||
clients += s->clients;
|
||||
Con_Printf("Game %s: %u servers, %u clients\n", g->name, (unsigned)g->numservers, clients);
|
||||
}
|
||||
|
||||
s1 = &svm.total;
|
||||
r = (svm.stampring >= countof(svm.stamps)-1)?svm.stampring-countof(svm.stamps)-1:0;
|
||||
s2 = &svm.stamps[r%countof(svm.stamps)];
|
||||
|
||||
period = s1->timestamp-s2->timestamp;
|
||||
period/=60;
|
||||
if (!period)
|
||||
period=1;
|
||||
Con_Printf("Heartbeats/min: %f\n", (s1->heartbeats-s2->heartbeats)/period);
|
||||
Con_Printf("Queries/min: %f\n", (s1->queries-s2->queries)/period);
|
||||
}
|
||||
|
||||
void SV_Init (struct quakeparms_s *parms)
|
||||
{
|
||||
int manarg;
|
||||
|
||||
COM_InitArgv (parms->argc, parms->argv);
|
||||
|
||||
host_parms = *parms;
|
||||
|
||||
Cvar_Init();
|
||||
|
||||
Memory_Init();
|
||||
|
||||
Sys_Init();
|
||||
|
||||
COM_ParsePlusSets(false);
|
||||
|
||||
Cbuf_Init ();
|
||||
Cmd_Init ();
|
||||
|
||||
NET_Init ();
|
||||
COM_Init ();
|
||||
|
||||
#ifdef WEBSERVER
|
||||
IWebInit();
|
||||
#endif
|
||||
|
||||
Cmd_AddCommand ("quit", SV_Quit_f);
|
||||
Cmd_AddCommand ("status", SVM_Status_f);
|
||||
|
||||
svm_sockets = FTENET_CreateCollection(true);
|
||||
Hash_InitTable(&svm.serverhash, 1024, Z_Malloc(Hash_BytesForBuckets(1024)));
|
||||
|
||||
Cvar_Register(&sv_masterport, "server control variables");
|
||||
Cvar_Register(&sv_masterport_tcp, "server control variables");
|
||||
Cvar_Register(&sv_heartbeattimeout, "server control variables");
|
||||
Cvar_Register(&sv_maxgames, "server control variables");
|
||||
Cvar_Register(&sv_maxservers, "server control variables");
|
||||
|
||||
Cvar_ParseWatches();
|
||||
host_initialized = true;
|
||||
|
||||
manarg = COM_CheckParm("-manifest");
|
||||
if (manarg && manarg < com_argc-1 && com_argv[manarg+1])
|
||||
{
|
||||
char *man = FS_MallocFile(com_argv[manarg+1], FS_SYSTEM, NULL);
|
||||
|
||||
FS_ChangeGame(FS_Manifest_Parse(NULL, man), true, true);
|
||||
BZ_Free(man);
|
||||
}
|
||||
else
|
||||
FS_ChangeGame(NULL, true, true);
|
||||
|
||||
Cmd_StuffCmds();
|
||||
Cbuf_Execute ();
|
||||
|
||||
Cvar_ForceCallback(&sv_masterport);
|
||||
Cvar_ForceCallback(&sv_masterport_tcp);
|
||||
|
||||
|
||||
Con_TPrintf ("Exe: %s %s\n", __DATE__, __TIME__);
|
||||
|
||||
Con_Printf ("%s\n", version_string());
|
||||
|
||||
Con_TPrintf ("======== %s Initialized ========\n", "FTEMaster");
|
||||
}
|
||||
float SV_Frame (void)
|
||||
{
|
||||
realtime = Sys_DoubleTime();
|
||||
while (1)
|
||||
{
|
||||
const char *cmd = Sys_ConsoleInput ();
|
||||
if (!cmd)
|
||||
break;
|
||||
Log_String(LOG_CONSOLE, cmd);
|
||||
Cbuf_AddText (cmd, RESTRICT_LOCAL);
|
||||
Cbuf_AddText ("\n", RESTRICT_LOCAL);
|
||||
}
|
||||
Cbuf_Execute ();
|
||||
|
||||
SVM_Think(sv_masterport.ival);
|
||||
|
||||
//record lots of info over multiple frames, for smoother stats info.
|
||||
svm.total.timestamp = realtime;
|
||||
if (svm.nextstamp < realtime)
|
||||
{
|
||||
svm.stamps[svm.stampring%countof(svm.stamps)] = svm.total;
|
||||
svm.stampring++;
|
||||
svm.nextstamp = realtime+60;
|
||||
}
|
||||
|
||||
return 4;
|
||||
}
|
||||
#endif
|
|
@ -41,7 +41,7 @@ Con_Printf redirection
|
|||
=============================================================================
|
||||
*/
|
||||
|
||||
char sv_redirected_buf[8000];
|
||||
char sv_redirected_buf[countof(sv_redirected_buf)];
|
||||
|
||||
redirect_t sv_redirected;
|
||||
int sv_redirectedlang;
|
||||
|
@ -74,7 +74,7 @@ void SV_FlushRedirect (void)
|
|||
send[4] = A2C_PRINT;
|
||||
memcpy (send+5, sv_redirected_buf, strlen(sv_redirected_buf)+1);
|
||||
|
||||
NET_SendPacket (NS_SERVER, strlen(send)+1, send, &net_from);
|
||||
NET_SendPacket (svs.sockets, strlen(send)+1, send, &net_from);
|
||||
}
|
||||
#ifdef SUBSERVERS
|
||||
else if (sv_redirected == RD_MASTER)
|
||||
|
@ -145,208 +145,6 @@ void SV_EndRedirect (void)
|
|||
sv_redirected = RD_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
================
|
||||
Con_Printf
|
||||
|
||||
Handles cursor positioning, line wrapping, etc
|
||||
================
|
||||
*/
|
||||
#define MAXPRINTMSG 4096
|
||||
// FIXME: make a buffer size safe vsprintf?
|
||||
#ifdef SERVERONLY
|
||||
vfsfile_t *con_pipe;
|
||||
vfsfile_t *Con_POpen(char *conname)
|
||||
{
|
||||
if (!conname || !*conname)
|
||||
{
|
||||
if (con_pipe)
|
||||
VFS_CLOSE(con_pipe);
|
||||
con_pipe = VFSPIPE_Open(2, false);
|
||||
return con_pipe;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void Con_PrintFromThread (void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
Con_Printf("%s", (char*)data);
|
||||
BZ_Free(data);
|
||||
}
|
||||
void VARGS Con_Printf (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{
|
||||
COM_AddWork(WG_MAIN, Con_PrintFromThread, NULL, Z_StrDup(msg), 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
if (sv_redirected != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
Con_Log(msg); // log to console
|
||||
|
||||
if (con_pipe)
|
||||
VFS_PUTS(con_pipe, msg);
|
||||
}
|
||||
void Con_TPrintf (translation_t stringnum, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
const char *fmt;
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{ //shouldn't be redirected anyway...
|
||||
fmt = langtext(stringnum,svs.language);
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
COM_AddWork(WG_MAIN, Con_PrintFromThread, NULL, Z_StrDup(msg), 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
fmt = langtext(stringnum,sv_redirectedlang);
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
return;
|
||||
}
|
||||
|
||||
fmt = langtext(stringnum,svs.language);
|
||||
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
Con_Log(msg); // log to console
|
||||
|
||||
if (con_pipe)
|
||||
VFS_PUTS(con_pipe, msg);
|
||||
}
|
||||
/*
|
||||
================
|
||||
Con_DPrintf
|
||||
|
||||
A Con_Printf that only shows up if the "developer" cvar is set
|
||||
================
|
||||
*/
|
||||
static void Con_DPrintFromThread (void *ctx, void *data, size_t a, size_t b)
|
||||
{
|
||||
Con_DLPrintf(a, "%s", (char*)data);
|
||||
BZ_Free(data);
|
||||
}
|
||||
void Con_DPrintf (const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
extern cvar_t log_developer;
|
||||
|
||||
if (!developer.value && !log_developer.value)
|
||||
return;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{
|
||||
COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
if (sv_redirected != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (developer.value)
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
|
||||
if (log_developer.value)
|
||||
Con_Log(msg); // log to console
|
||||
}
|
||||
void Con_DLPrintf (int level, const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
extern cvar_t log_developer;
|
||||
|
||||
if (developer.ival < level && !log_developer.value)
|
||||
return;
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (!Sys_IsMainThread())
|
||||
{
|
||||
COM_AddWork(WG_MAIN, Con_DPrintFromThread, NULL, Z_StrDup(msg), level, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// add to redirected message
|
||||
if (sv_redirected)
|
||||
{
|
||||
if (strlen (msg) + strlen(sv_redirected_buf) > sizeof(sv_redirected_buf) - 1)
|
||||
SV_FlushRedirect ();
|
||||
strcat (sv_redirected_buf, msg);
|
||||
if (sv_redirected != -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (developer.ival >= level)
|
||||
Sys_Printf ("%s", msg); // also echo to debugging console
|
||||
|
||||
if (log_developer.value)
|
||||
Con_Log(msg); // log to console
|
||||
}
|
||||
|
||||
//for spammed warnings, so they don't spam prints with every single frame/call. the timer arg should be a static local.
|
||||
void VARGS Con_ThrottlePrintf (float *timer, int developerlevel, const char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
char msg[MAXPRINTMSG];
|
||||
|
||||
va_start (argptr,fmt);
|
||||
vsnprintf (msg,sizeof(msg)-1, fmt,argptr);
|
||||
va_end (argptr);
|
||||
|
||||
if (developerlevel)
|
||||
Con_DLPrintf (developerlevel, "%s", msg);
|
||||
else
|
||||
Con_Printf("%s", msg);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
=============================================================================
|
||||
|
||||
|
@ -624,7 +422,7 @@ void VARGS SV_BroadcastTPrintf (int level, translation_t stringnum, ...)
|
|||
client_t *cl;
|
||||
int i;
|
||||
int oldlang=-1;
|
||||
const char *fmt = langtext(stringnum, oldlang=svs.language);
|
||||
const char *fmt = langtext(stringnum, oldlang=com_language);
|
||||
|
||||
va_start (argptr,stringnum);
|
||||
vsnprintf (string,sizeof(string)-1, fmt,argptr);
|
||||
|
|
|
@ -765,7 +765,7 @@ static int Sys_CheckChRoot(void)
|
|||
freeaddrinfo(info);
|
||||
}
|
||||
|
||||
#ifdef SQL
|
||||
#if defined(SQL) && defined(HAVE_SERVER)
|
||||
SQL_Available();
|
||||
#endif
|
||||
#ifdef HAVE_GNUTLS
|
||||
|
|
|
@ -194,7 +194,7 @@ qboolean SV_CheckRealIP(client_t *client, qboolean force)
|
|||
if (client->realip_status == 1)
|
||||
{
|
||||
msg = va("\xff\xff\xff\xff%c %i", A2A_PING, client->realip_ping);
|
||||
NET_SendPacket(NS_SERVER, strlen(msg), msg, &client->realip);
|
||||
NET_SendPacket(svs.sockets, strlen(msg), msg, &client->realip);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2566,7 +2566,7 @@ void VARGS OutofBandPrintf(netadr_t *where, char *fmt, ...)
|
|||
vsnprintf (send+5, sizeof(send)-5, fmt, argptr);
|
||||
va_end (argptr);
|
||||
|
||||
NET_SendPacket (NS_SERVER, strlen(send)+1, send, where);
|
||||
NET_SendPacket (svs.sockets, strlen(send)+1, send, where);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4980,9 +4980,9 @@ void Cmd_SetPos_f(void)
|
|||
if (!svprogfuncs)
|
||||
return;
|
||||
|
||||
if (Cmd_Argc() != 4)
|
||||
if (Cmd_Argc() != 4 && Cmd_Argc() != 7)
|
||||
{
|
||||
SV_ClientPrintf(host_client, PRINT_HIGH, "setpos %f %f %f\n", sv_player->v->origin[0], sv_player->v->origin[1], sv_player->v->origin[2]);
|
||||
SV_ClientPrintf(host_client, PRINT_HIGH, "setpos %f %f %f %f %f %f\n", sv_player->v->origin[0], sv_player->v->origin[1], sv_player->v->origin[2], sv_player->v->v_angle[0], sv_player->v->v_angle[1], sv_player->v->v_angle[2]);
|
||||
return;
|
||||
}
|
||||
SV_LogPlayer(host_client, "setpos cheat");
|
||||
|
@ -4999,6 +4999,14 @@ void Cmd_SetPos_f(void)
|
|||
sv_player->v->origin[1] = atof(Cmd_Argv(2));
|
||||
sv_player->v->origin[2] = atof(Cmd_Argv(3));
|
||||
World_LinkEdict (&sv.world, (wedict_t*)sv_player, false);
|
||||
|
||||
if (Cmd_Argc() > 4)
|
||||
{
|
||||
sv_player->v->angles[0] = atof(Cmd_Argv(4));
|
||||
sv_player->v->angles[1] = atof(Cmd_Argv(5));
|
||||
sv_player->v->angles[2] = atof(Cmd_Argv(6));
|
||||
sv_player->v->fixangle = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SV_SetUpClientEdict (client_t *cl, edict_t *ent)
|
||||
|
@ -7657,7 +7665,7 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
vec3_t o;
|
||||
int checksumIndex;
|
||||
qbyte checksum, calculatedChecksum;
|
||||
int seq_hash, i;
|
||||
int seq_hash;
|
||||
|
||||
// calc ping time
|
||||
if (cl->frameunion.frames)
|
||||
|
@ -7694,14 +7702,9 @@ void SV_ExecuteClientMessage (client_t *cl)
|
|||
#ifdef warningmsg
|
||||
#pragma warningmsg("FIXME: make antilag optionally support non-player ents too")
|
||||
#endif
|
||||
for (i = 0; i < sv.allocated_client_slots; i++)
|
||||
{
|
||||
cl->laggedents[i].present = frame->playerpresent[i];
|
||||
if (cl->laggedents[i].present)
|
||||
VectorCopy(frame->playerpositions[i], cl->laggedents[i].laggedpos);
|
||||
}
|
||||
cl->laggedents_count = sv.allocated_client_slots;
|
||||
|
||||
memcpy(cl->laggedents, frame->laggedplayer, sizeof(*cl->laggedents)*cl->laggedents_count);
|
||||
cl->laggedents_time = frame->laggedtime;
|
||||
cl->laggedents_frac = !*sv_antilag_frac.string?1:sv_antilag_frac.value;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -649,12 +649,12 @@ static int SVQ3_PointContents(vec3_t pos, int entnum)
|
|||
mod = Q3G_GetCModel(es->s.modelindex);
|
||||
if (!mod)
|
||||
continue;
|
||||
World_TransformedTrace(mod, 0, 0, pos, pos, vec3_origin, vec3_origin, false, &tr, es->r.currentOrigin, es->r.currentAngles, 0xffffffff);
|
||||
World_TransformedTrace(mod, 0, NULL, pos, pos, vec3_origin, vec3_origin, false, &tr, es->r.currentOrigin, es->r.currentAngles, 0xffffffff);
|
||||
}
|
||||
else
|
||||
{
|
||||
mod = CM_TempBoxModel(es->r.mins, es->r.maxs);
|
||||
World_TransformedTrace(mod, 0, 0, pos, pos, vec3_origin, vec3_origin, false, &tr, es->r.currentOrigin, vec3_origin, 0xffffffff);
|
||||
World_TransformedTrace(mod, 0, NULL, pos, pos, vec3_origin, vec3_origin, false, &tr, es->r.currentOrigin, vec3_origin, 0xffffffff);
|
||||
}
|
||||
|
||||
cont |= tr.contents;
|
||||
|
@ -3405,7 +3405,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and
|
|||
{
|
||||
Con_Printf("%s\n", reason);
|
||||
reason = va("\377\377\377\377print\n%s", reason);
|
||||
NET_SendPacket (NS_SERVER, strlen(reason), reason, &net_from);
|
||||
NET_SendPacket (svs.sockets, strlen(reason), reason, &net_from);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3422,7 +3422,7 @@ void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and
|
|||
|
||||
cl->gamestatesequence = -1;
|
||||
|
||||
NET_SendPacket (NS_SERVER, 19, "\377\377\377\377connectResponse", &net_from);
|
||||
NET_SendPacket (svs.sockets, 19, "\377\377\377\377connectResponse", &net_from);
|
||||
|
||||
cl->frameunion.q3frames = BZ_Malloc(Q3UPDATE_BACKUP*sizeof(*cl->frameunion.q3frames));
|
||||
}
|
||||
|
|
|
@ -1241,7 +1241,7 @@ Handles selection or creation of a clipping hull, and offseting (and
|
|||
eventually rotation) of the end points
|
||||
==================
|
||||
*/
|
||||
static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel, qboolean capsule, unsigned int hitcontentsmask) //hullnum overrides min/max for q1 style bsps
|
||||
static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, vec3_t eang, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int hullnum, qboolean hitmodel, qboolean capsule, unsigned int hitcontentsmask) //hullnum overrides min/max for q1 style bsps
|
||||
{
|
||||
trace_t trace;
|
||||
model_t *model;
|
||||
|
@ -1285,16 +1285,16 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
if (ent->v->solid == SOLID_PORTAL)
|
||||
{
|
||||
//solid_portal cares only about origins and as such has no mins/max
|
||||
World_TransformedTrace(model, 0, &framestate, start, end, vec3_origin, vec3_origin, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, 0, &framestate, start, end, vec3_origin, vec3_origin, capsule, &trace, eorg, eang, hitcontentsmask);
|
||||
if (trace.startsolid) //portals should not block traces. this prevents infinite looping
|
||||
trace.startsolid = false;
|
||||
hitmodel = false;
|
||||
}
|
||||
else if (ent->v->solid != SOLID_BSP)
|
||||
{
|
||||
ent->v->angles[0]*=r_meshpitch.value; //carmack made bsp models rotate wrongly.
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
ent->v->angles[0]*=r_meshpitch.value;
|
||||
eang[0]*=r_meshpitch.value; //carmack made bsp models rotate wrongly.
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, eang, hitcontentsmask);
|
||||
eang[0]*=r_meshpitch.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1315,7 +1315,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
}
|
||||
if (hitcontentsmask & forcedcontents)
|
||||
{
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, ~0u);
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, eang, ~0u);
|
||||
if (trace.contents)
|
||||
trace.contents = forcedcontents;
|
||||
}
|
||||
|
@ -1330,7 +1330,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
}
|
||||
}
|
||||
else
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, eang, hitcontentsmask);
|
||||
}
|
||||
|
||||
// if using hitmodel, we know it hit the bounding box, so try a proper trace now.
|
||||
|
@ -1342,7 +1342,7 @@ static trace_t World_ClipMoveToEntity (world_t *w, wedict_t *ent, vec3_t eorg, v
|
|||
if (model && model->funcs.NativeTrace && model->loadstate == MLS_LOADED)
|
||||
{
|
||||
//do the second trace, using the actual mesh.
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, ent->v->angles, hitcontentsmask);
|
||||
World_TransformedTrace(model, hullnum, &framestate, start, end, mins, maxs, capsule, &trace, eorg, eang, hitcontentsmask);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1687,9 +1687,9 @@ void WorldQ2_ClipMoveToEntities (world_t *w, moveclip_t *clip )
|
|||
angles = vec3_origin; // boxes don't rotate
|
||||
|
||||
if (touch->svflags & SVF_MONSTER)
|
||||
World_TransformedTrace (model, 0, 0, clip->start, clip->end, clip->mins2, clip->maxs2, false, &trace, touch->s.origin, angles, clip->hitcontentsmask);
|
||||
World_TransformedTrace (model, 0, NULL, clip->start, clip->end, clip->mins2, clip->maxs2, false, &trace, touch->s.origin, angles, clip->hitcontentsmask);
|
||||
else
|
||||
World_TransformedTrace (model, 0, 0, clip->start, clip->end, clip->mins, clip->maxs, false, &trace, touch->s.origin, angles, clip->hitcontentsmask);
|
||||
World_TransformedTrace (model, 0, NULL, clip->start, clip->end, clip->mins, clip->maxs, false, &trace, touch->s.origin, angles, clip->hitcontentsmask);
|
||||
|
||||
if (trace.allsolid || trace.startsolid ||
|
||||
trace.fraction < clip->trace.fraction)
|
||||
|
@ -1875,9 +1875,9 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip)
|
|||
}
|
||||
|
||||
if ((int)touch->v->flags & FL_MONSTER)
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, touch->v->angles, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
else
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, touch->v->angles, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
if (trace.allsolid || trace.startsolid ||
|
||||
trace.fraction < clip->trace.fraction)
|
||||
{
|
||||
|
@ -2034,9 +2034,9 @@ static void World_ClipToLinks (world_t *w, areagridlink_t *node, moveclip_t *cli
|
|||
}
|
||||
|
||||
if ((int)touch->v->flags & FL_MONSTER)
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, touch->v->angles, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
else
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
trace = World_ClipMoveToEntity (w, touch, touch->v->origin, touch->v->angles, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL, clip->capsule, clip->hitcontentsmask);
|
||||
|
||||
if (trace.fraction < clip->trace.fraction)
|
||||
{
|
||||
|
@ -2561,18 +2561,18 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
if (type & MOVE_OTHERONLY)
|
||||
{
|
||||
wedict_t *other = WEDICT_NUM_UB(w->progs, *w->g.other);
|
||||
return World_ClipMoveToEntity (w, other, other->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
return World_ClipMoveToEntity (w, other, other->v->origin, other->v->angles, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
}
|
||||
#ifndef NOLEGACY
|
||||
if ((type&MOVE_WORLDONLY) == MOVE_WORLDONLY)
|
||||
{ //for compat with DP
|
||||
wedict_t *other = w->edicts;
|
||||
return World_ClipMoveToEntity (w, other, other->v->origin, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
return World_ClipMoveToEntity (w, other, other->v->origin, other->v->angles, start, mins, maxs, end, hullnum, type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
// clip to world
|
||||
clip.trace = World_ClipMoveToEntity (w, w->edicts, w->edicts->v->origin, start, mins, maxs, end, hullnum, false, clip.capsule, clip.hitcontentsmask);
|
||||
clip.trace = World_ClipMoveToEntity (w, w->edicts, w->edicts->v->origin, w->edicts->v->angles, start, mins, maxs, end, hullnum, false, clip.capsule, clip.hitcontentsmask);
|
||||
|
||||
clip.start = start;
|
||||
clip.end = end;
|
||||
|
@ -2622,6 +2622,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
w->lagents = svs.clients[passedict->entnum-1].laggedents;
|
||||
w->maxlagents = svs.clients[passedict->entnum-1].laggedents_count;
|
||||
w->lagentsfrac = svs.clients[passedict->entnum-1].laggedents_frac;
|
||||
w->lagentstime = svs.clients[passedict->entnum-1].laggedents_time;
|
||||
}
|
||||
else if (passedict->v->owner)
|
||||
{
|
||||
|
@ -2631,6 +2632,7 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
w->lagents = svs.clients[passedict->v->owner-1].laggedents;
|
||||
w->maxlagents = svs.clients[passedict->v->owner-1].laggedents_count;
|
||||
w->lagentsfrac = svs.clients[passedict->v->owner-1].laggedents_frac;
|
||||
w->lagentstime = svs.clients[passedict->entnum-1].laggedents_time;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2640,7 +2642,8 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
{
|
||||
trace_t trace;
|
||||
wedict_t *touch;
|
||||
vec3_t lp;
|
||||
vec3_t lp, la;
|
||||
int j;
|
||||
|
||||
#ifdef USEAREAGRID
|
||||
World_ClipToAllLinks (w, &clip);
|
||||
|
@ -2686,7 +2689,18 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
continue;
|
||||
}
|
||||
|
||||
VectorInterpolate(touch->v->origin, w->lagentsfrac, w->lagents[i].laggedpos, lp);
|
||||
VectorInterpolate(touch->v->origin, w->lagentsfrac, w->lagents[i].origin, lp);
|
||||
//I hate working with angles
|
||||
VectorSubtract(w->lagents[i].angles, touch->v->angles, la);
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
la[j] = (360.0/65536) * ((int)(la[j]*(65536/360.0)) & 65535);
|
||||
if (la[j]<-180)
|
||||
la[j] += 360;
|
||||
if (la[j]>180)
|
||||
la[j] -= 360;
|
||||
}
|
||||
VectorMA(touch->v->angles, 1, la, la);
|
||||
|
||||
if (clip.boxmins[0] > lp[0]+touch->v->maxs[0]
|
||||
|| clip.boxmins[1] > lp[1]+touch->v->maxs[1]
|
||||
|
@ -2707,7 +2721,13 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e
|
|||
continue; // don't clip against owner
|
||||
}
|
||||
|
||||
trace = World_ClipMoveToEntity (w, touch, lp, clip.start, clip.mins, clip.maxs, clip.end, clip.hullnum, clip.type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
if ((clip.type & MOVE_HITMODEL) && w->Event_Backdate)
|
||||
{
|
||||
w->Event_Backdate(w, touch, w->lagentstime);
|
||||
trace = World_ClipMoveToEntity (w, touch, lp, la, clip.start, clip.mins, clip.maxs, clip.end, clip.hullnum, clip.type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
}
|
||||
else
|
||||
trace = World_ClipMoveToEntity (w, touch, lp, la, clip.start, clip.mins, clip.maxs, clip.end, clip.hullnum, clip.type & MOVE_HITMODEL, clip.capsule, clip.hitcontentsmask);
|
||||
|
||||
if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
!!ver 100 150
|
||||
!!ver 100 300
|
||||
!!permu TESS
|
||||
!!permu BUMP
|
||||
!!permu FRAMEBLEND
|
||||
|
|
Loading…
Reference in a new issue