NQ-related bugfixes.
Added new project/target for easy integration into NQ engines - read nq_api.c for guidelines. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4024 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
810d28dd84
commit
3da350a3ed
11 changed files with 684 additions and 90 deletions
|
@ -165,8 +165,10 @@ unsigned char *FS_ReadFile(char *gamedir, char *filename, unsigned int *size)
|
|||
return data;
|
||||
}
|
||||
|
||||
|
||||
int SortFilesByDate(const void *a, const void *b)
|
||||
#ifndef _WIN32
|
||||
#define _cdecl
|
||||
#endif
|
||||
int _cdecl SortFilesByDate(const void *a, const void *b)
|
||||
{
|
||||
if (((availdemo_t*)a)->time < ((availdemo_t*)b)->time)
|
||||
return 1;
|
||||
|
@ -483,6 +485,7 @@ void DoCommandLine(cluster_t *cluster, int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef LIBQTV
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
cluster_t *cluster;
|
||||
|
@ -569,6 +572,7 @@ int main(int argc, char **argv)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void QTV_Printf(sv_t *qtv, char *fmt, ...)
|
||||
{
|
||||
|
@ -586,6 +590,13 @@ void QTV_Printf(sv_t *qtv, char *fmt, ...)
|
|||
Sys_Printf(qtv->cluster, "%s", string);
|
||||
}
|
||||
|
||||
//#ifdef LIBQTV
|
||||
//#ifndef _WIN32
|
||||
//#define _cdecl
|
||||
//#endif
|
||||
//void _cdecl Con_Printf(char *fmt, ...);
|
||||
//#endif
|
||||
|
||||
void Sys_Printf(cluster_t *cluster, char *fmt, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
|
@ -597,6 +608,10 @@ void Sys_Printf(cluster_t *cluster, char *fmt, ...)
|
|||
string[sizeof(string)-1] = 0;
|
||||
va_end (argptr);
|
||||
|
||||
//#ifdef LIBQTV
|
||||
// Con_Printf("QTV: %s", string);
|
||||
//#endif
|
||||
|
||||
for (t = (unsigned char*)string; *t; t++)
|
||||
{
|
||||
if (*t >= 146 && *t < 156)
|
||||
|
|
282
fteqtv/dotnet2005/libqtv.vcproj
Normal file
282
fteqtv/dotnet2005/libqtv.vcproj
Normal file
|
@ -0,0 +1,282 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="8.00"
|
||||
Name="libqtv"
|
||||
ProjectGUID="{EDBDDC82-6DEE-4BF1-B0BC-BBBCCFE65D4C}"
|
||||
RootNamespace="libqtv"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
PreprocessorDefinitions="LIBQTV;_CRT_SECURE_NO_WARNINGS"
|
||||
MinimalRebuild="true"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="3"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="4"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
GenerateDebugInformation="true"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="2"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
PreprocessorDefinitions="LIBQTV;_CRT_SECURE_NO_WARNINGS"
|
||||
RuntimeLibrary="2"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="true"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
GenerateDebugInformation="true"
|
||||
OptimizeReferences="2"
|
||||
EnableCOMDATFolding="2"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebDeploymentTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\bsp.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\control.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\crc.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\forward.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\libqtvc\glibc_sucks.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\httpsv.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\mdfour.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\menu.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\msg.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\libqtvc\msvc_sucks.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\netchan.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\nq_api.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\parse.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\pmove.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\qw.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\rcon.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sc_dsound.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\engine\common\sha1.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\source.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\sp_dsound.c"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\bsd_string.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\cmd.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\protocol.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\qtv.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
|
@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 9.00
|
|||
# Visual Studio 2005
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "qtvprox", "qtvprox.vcproj", "{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libqtv", "libqtv.vcproj", "{EDBDDC82-6DEE-4BF1-B0BC-BBBCCFE65D4C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
|
@ -13,6 +15,10 @@ Global
|
|||
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{62669E6C-7E18-4E4D-BA54-DFBE29E7D24E}.Release|Win32.Build.0 = Release|Win32
|
||||
{EDBDDC82-6DEE-4BF1-B0BC-BBBCCFE65D4C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EDBDDC82-6DEE-4BF1-B0BC-BBBCCFE65D4C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EDBDDC82-6DEE-4BF1-B0BC-BBBCCFE65D4C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EDBDDC82-6DEE-4BF1-B0BC-BBBCCFE65D4C}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -95,7 +95,7 @@ void Menu_Enter(cluster_t *cluster, viewer_t *viewer, int buttonnum)
|
|||
}
|
||||
if (i++ == viewer->menuop)
|
||||
{ //disconnect
|
||||
QTV_Shutdown(viewer->server);
|
||||
QTV_ShutdownStream(viewer->server);
|
||||
}
|
||||
if (i++ == viewer->menuop)
|
||||
{
|
||||
|
|
|
@ -122,11 +122,21 @@ SOCKET NET_ChooseSocket(SOCKET sock[2], netadr_t *adr)
|
|||
return sock[0];
|
||||
}
|
||||
|
||||
#ifdef LIBQTV
|
||||
void QTV_DoReceive(void *data, int length);
|
||||
#endif
|
||||
void NET_SendPacket(cluster_t *cluster, SOCKET sock, int length, void *data, netadr_t adr)
|
||||
{
|
||||
int ret;
|
||||
int alen;
|
||||
|
||||
#ifdef LIBQTV
|
||||
if (((struct sockaddr *)&adr.sockaddr)->sa_family == AF_UNSPEC)
|
||||
{
|
||||
QTV_DoReceive(data, length);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef AF_INET6
|
||||
if (((struct sockaddr *)&adr.sockaddr)->sa_family == AF_INET6)
|
||||
alen = sizeof(struct sockaddr_in6);
|
||||
|
@ -403,7 +413,7 @@ void Netchan_Setup (SOCKET sock, netchan_t *chan, netadr_t adr, int qport, qbool
|
|||
|
||||
chan->message.allowoverflow = true;
|
||||
|
||||
chan->rate = 1000.0f/2500;
|
||||
chan->rate = 10000*1000;
|
||||
}
|
||||
|
||||
|
||||
|
@ -485,11 +495,11 @@ void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const vo
|
|||
i = MAX_NQDATAGRAM;
|
||||
|
||||
WriteData (&send, chan->reliable_buf+chan->reliable_start, i);
|
||||
if (length && send.cursize + length < send.maxsize)
|
||||
{ //throw the unreliable packet into the same one as the reliable (but not sent reliably)
|
||||
WriteData (&send, data, length);
|
||||
length = 0;
|
||||
}
|
||||
// if (length && send.cursize + length < send.maxsize)
|
||||
// { //throw the unreliable packet into the same one as the reliable (but not sent reliably)
|
||||
// WriteData (&send, data, length);
|
||||
// length = 0;
|
||||
// }
|
||||
|
||||
|
||||
if (chan->reliable_start+i == chan->reliable_length)
|
||||
|
@ -497,12 +507,18 @@ void Netchan_Transmit (cluster_t *cluster, netchan_t *chan, int length, const vo
|
|||
else
|
||||
*(int*)send_buf = BigLong(NETFLAG_DATA | send.cursize);
|
||||
NET_SendPacket(cluster, chan->sock, send.cursize, send.data, chan->remote_address);
|
||||
send.cursize = 0;
|
||||
|
||||
if (chan->cleartime < curtime)
|
||||
chan->cleartime = curtime + (int)(send.cursize*chan->rate);
|
||||
else
|
||||
chan->cleartime += (int)(send.cursize*chan->rate);
|
||||
}
|
||||
// else if (!length)
|
||||
// {
|
||||
// length = 1;
|
||||
// data = "\x01";
|
||||
// }
|
||||
|
||||
//send out the unreliable (if still unsent)
|
||||
if (length)
|
||||
|
|
230
fteqtv/nq_api.c
Normal file
230
fteqtv/nq_api.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
This file is intended as a set of exports for an NQ-based engine.
|
||||
This is supported _purely_ for clients, and will not work for servers.
|
||||
|
||||
|
||||
|
||||
[EndUser] how to use:
|
||||
to join a qw server: connect "udp:127.0.0.1:27500"
|
||||
to watch a qtv stream: connect "tcp:3@127.0.0.1:27599" (where '3' is the streamid)
|
||||
to watch an mvd demo: connect "demo:blahblah.mvd" - the demo will be loaded from $WORKINGDIR/qw/demos/ - note that $WORKINGDIR is NOT always the same dir
|
||||
as your engine is running from. The -basedir argument will break it, or engines that hunt down a 'proper' installation of quake instead.
|
||||
|
||||
|
||||
[Developer] how to incorporate into an nq engine:
|
||||
load up net_win.c
|
||||
find the #include "net_wins.h" line.
|
||||
dupe it, call it net_qtv.h
|
||||
dupe the header itself too, changing all WINS_foo to QTV_foo.
|
||||
find the net_landrivers array. Dupe the first block, then edit the first block to be all QTV_foo functions.
|
||||
bump net_numlandrivers.
|
||||
For non-window operating systems, you'll need to do the same, just figure out which net_win.c equivelent function it uses first. :P
|
||||
certain engines may do weird things with the port. probably its best to just use Cmd_Args() for the connect command instead of Cmd_Argv(1), and to add
|
||||
port parsing to XXXX_GetAddrFromName instead of messing around with port cvars etc and ruining server configs.
|
||||
If your engine already has weird port behaviour, then its entirely your problem to fix. :P
|
||||
You probably want to tweak your menus a little to clean up the nq/qw/qtv connection distinctions.
|
||||
If you do want to make changes to libqtv, please consider joining the FTE team (or at least the irc channel) in order to contribute without forking.
|
||||
|
||||
[Developer] how to compile libqtv:
|
||||
cflags MUST define 'LIBQTV' or it won't compile properly.
|
||||
The relevent exports are all tagged as 'EXPORT void PUBLIC fname(...)' (dllexport+cdecl in windows), feel free to define those properly if you're making a linux shared object without exporting all (potentially conflicting) internals.
|
||||
This means you can compile it as a dll without any issues, one with a standardized interface. Any libqtv-specific bugfixes can be released independantly from engine(s).
|
||||
Compiling a dll with msvc will generally automatically produce a .lib which you can directly link against. Alternatively, include both projects in your workspace and set up dependancies properly and it'll be automatically imported.
|
||||
|
||||
[PowerUser] issues:
|
||||
its a full qtv proxy, but you can't get admin/rcon access to it.
|
||||
it doesn't read any configs, and has no console, thus you cannot set an rcon password/port.
|
||||
without console/rcon, you cannot enable any listening ports for other users.
|
||||
if you need a public qtv proxy, use a standalone version.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "qtv.h"
|
||||
int build_number(void);
|
||||
|
||||
static cluster_t *cluster;
|
||||
|
||||
//note that a qsockaddr is only 16 bytes.
|
||||
//this is not enough for ipv6 etc.
|
||||
struct qsockaddr
|
||||
{
|
||||
int ipid;
|
||||
};
|
||||
char resolvedadrstring[128];
|
||||
int lastadrid;
|
||||
|
||||
#ifdef _WIN32
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#define PUBLIC __cdecl
|
||||
#endif
|
||||
#ifndef EXPORT
|
||||
#define EXPORT
|
||||
#endif
|
||||
#ifndef PUBLIC
|
||||
#define PUBLIC
|
||||
#endif
|
||||
|
||||
EXPORT int PUBLIC QTV_Init (void)
|
||||
{
|
||||
cluster = malloc(sizeof(*cluster));
|
||||
if (cluster)
|
||||
{
|
||||
memset(cluster, 0, sizeof(*cluster));
|
||||
|
||||
cluster->qwdsocket[0] = INVALID_SOCKET;
|
||||
cluster->qwdsocket[1] = INVALID_SOCKET;
|
||||
cluster->tcpsocket[0] = INVALID_SOCKET;
|
||||
cluster->tcpsocket[1] = INVALID_SOCKET;
|
||||
cluster->anticheattime = 1*1000;
|
||||
cluster->tooslowdelay = 100;
|
||||
cluster->qwlistenportnum = 0;
|
||||
cluster->allownqclients = true;
|
||||
strcpy(cluster->hostname, DEFAULT_HOSTNAME);
|
||||
cluster->buildnumber = build_number();
|
||||
cluster->maxproxies = -1;
|
||||
|
||||
strcpy(cluster->demodir, "qw/demos/");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
EXPORT void PUBLIC QTV_Shutdown (void)
|
||||
{
|
||||
}
|
||||
EXPORT void PUBLIC QTV_Listen (qboolean state)
|
||||
{
|
||||
}
|
||||
EXPORT int PUBLIC QTV_OpenSocket (int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_CloseSocket (int socket)
|
||||
{
|
||||
//give it a chance to close any server connections from us disconnecting (should have already send disconnect message, but won't have run the server so not noticed the lack of viewers)
|
||||
Cluster_Run(cluster, false);
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_Connect (int socket, struct qsockaddr *addr)
|
||||
{
|
||||
if (addr->ipid == lastadrid)
|
||||
{
|
||||
strlcpy(cluster->autojoinadr, resolvedadrstring, sizeof(cluster->autojoinadr));
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cluster->autojoinadr[0] = 0;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_CheckNewConnections (void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static byte pendingbuf[8][1032];
|
||||
static int pendinglen[8];
|
||||
static unsigned int pendingin, pendingout;
|
||||
void QTV_DoReceive(void *data, int length)
|
||||
{
|
||||
int idx;
|
||||
if (length > sizeof(pendingbuf[0]))
|
||||
return;
|
||||
idx = pendingout++;
|
||||
idx &= 7;
|
||||
memcpy(pendingbuf[idx], data, length);
|
||||
pendinglen[idx] = length;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_Read (int socket, byte *buf, int len, struct qsockaddr *addr)
|
||||
{
|
||||
if (pendingout == pendingin)
|
||||
{
|
||||
Cluster_Run(cluster, false);
|
||||
Cluster_Run(cluster, false);
|
||||
}
|
||||
|
||||
while (pendingin != pendingout)
|
||||
{
|
||||
int idx = pendingin++;
|
||||
idx &= 7;
|
||||
if (pendinglen[idx] > len)
|
||||
continue; //error
|
||||
memcpy(buf, pendingbuf[idx], pendinglen[idx]);
|
||||
return pendinglen[idx];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_Write (int socket, byte *buf, int len, struct qsockaddr *addr)
|
||||
{
|
||||
netmsg_t m;
|
||||
netadr_t from;
|
||||
from.tcpcon = NULL;
|
||||
((struct sockaddr*)from.sockaddr)->sa_family = AF_UNSPEC;
|
||||
|
||||
m.cursize = len;
|
||||
m.data = buf;
|
||||
m.readpos = 0;
|
||||
|
||||
QW_ProcessUDPPacket(cluster, &m, from);
|
||||
|
||||
if (pendingout == pendingin)
|
||||
Cluster_Run(cluster, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_Broadcast (int socket, byte *buf, int len)
|
||||
{
|
||||
netmsg_t m;
|
||||
netadr_t from;
|
||||
from.tcpcon = NULL;
|
||||
((struct sockaddr*)from.sockaddr)->sa_family = AF_UNSPEC;
|
||||
|
||||
m.cursize = len;
|
||||
m.data = buf;
|
||||
m.readpos = 0;
|
||||
|
||||
QW_ProcessUDPPacket(cluster, &m, from);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT char *PUBLIC QTV_AddrToString (struct qsockaddr *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_StringToAddr (char *string, struct qsockaddr *addr)
|
||||
{
|
||||
if (!strncmp(string, "udp:", 4) || !strncmp(string, "tcp:", 4) || !strncmp(string, "file:", 5))
|
||||
{
|
||||
snprintf(resolvedadrstring, sizeof(resolvedadrstring), "%s", string);
|
||||
addr->ipid = ++lastadrid;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_GetSocketAddr (int socket, struct qsockaddr *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_GetNameFromAddr (struct qsockaddr *addr, char *name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_GetAddrFromName (char *name, struct qsockaddr *addr)
|
||||
{
|
||||
return QTV_StringToAddr(name, addr);
|
||||
}
|
||||
EXPORT int PUBLIC QTV_AddrCompare (struct qsockaddr *addr1, struct qsockaddr *addr2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_GetSocketPort (struct qsockaddr *addr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT int PUBLIC QTV_SetSocketPort (struct qsockaddr *addr, int port)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -127,6 +127,7 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
|||
return;
|
||||
}
|
||||
|
||||
tv->mapstarttime = tv->parsetime;
|
||||
tv->parsingconnectiondata = true;
|
||||
|
||||
tv->clservercount = ReadLong(m); //we don't care about server's servercount, it's all reliable data anyway.
|
||||
|
@ -169,7 +170,7 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
|||
v->thinksitsconnected = false;
|
||||
}
|
||||
|
||||
if (!tv->controller && tv->usequakeworldprotocols)
|
||||
if ((!tv->controller || tv->controller->netchan.isnqprotocol) && tv->usequakeworldprotocols)
|
||||
{
|
||||
tv->netchan.message.cursize = 0; //mvdsv sucks
|
||||
SendClientCommand(tv, "soundlist %i 0\n", tv->clservercount);
|
||||
|
@ -178,7 +179,10 @@ static void ParseServerData(sv_t *tv, netmsg_t *m, int to, unsigned int playerma
|
|||
ConnectionData(tv, (void*)((char*)m->data+m->startpos), m->readpos - m->startpos, to, dem_read, QW);
|
||||
|
||||
if (tv->controller)
|
||||
{
|
||||
QW_ClearViewerState(tv->controller);
|
||||
tv->controller->trackplayer = tv->map.thisplayer;
|
||||
}
|
||||
|
||||
strcpy(tv->status, "Receiving soundlist\n");
|
||||
}
|
||||
|
@ -273,14 +277,14 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
|||
|
||||
for (v = tv->cluster->viewers; v; v = v->next)
|
||||
{
|
||||
if (v->server == tv && v != tv->controller)
|
||||
if (v->server == tv && (v != tv->controller || v->netchan.isnqprotocol))
|
||||
{
|
||||
v->servercount++;
|
||||
SendBufferToViewer(v, newcmd, sizeof(newcmd), true);
|
||||
}
|
||||
}
|
||||
|
||||
if (tv->controller)
|
||||
if (tv->controller && !tv->controller->netchan.isnqprotocol)
|
||||
SendBufferToViewer(tv->controller, (char*)m->data+m->startpos, m->readpos - m->startpos, true);
|
||||
else if (tv->usequakeworldprotocols)
|
||||
SendClientCommand(tv, "begin %i\n", tv->clservercount);
|
||||
|
@ -304,6 +308,19 @@ static void ParseStufftext(sv_t *tv, netmsg_t *m, int to, unsigned int mask)
|
|||
SendBufferToViewer(tv->controller, (char*)m->data+m->startpos, m->readpos - m->startpos, true);
|
||||
return;
|
||||
}
|
||||
else if (!strncmp(text, "cmd prespawn ", 13))
|
||||
{
|
||||
if (tv->usequakeworldprotocols)
|
||||
SendClientCommand(tv, "%s", text+4);
|
||||
return; //commands the game server asked for are pointless.
|
||||
}
|
||||
else if (!strncmp(text, "cmd spawn ", 10))
|
||||
{
|
||||
if (tv->usequakeworldprotocols)
|
||||
SendClientCommand(tv, "%s", text+4);
|
||||
|
||||
return; //commands the game server asked for are pointless.
|
||||
}
|
||||
else if (!strncmp(text, "cmd ", 4))
|
||||
{
|
||||
if (tv->controller)
|
||||
|
@ -822,7 +839,7 @@ static void ParsePacketEntities(sv_t *tv, netmsg_t *m, int deltaframe)
|
|||
|
||||
tv->map.nailcount = 0;
|
||||
|
||||
tv->physicstime = tv->parsetime;
|
||||
tv->physicstime = tv->curtime;
|
||||
|
||||
if (tv->cluster->chokeonnotupdated)
|
||||
for (v = tv->cluster->viewers; v; v = v->next)
|
||||
|
@ -1710,7 +1727,7 @@ void ParseMessage(sv_t *tv, void *buffer, int length, int to, int mask)
|
|||
strcpy(tv->status, "Prespawning\n");
|
||||
}
|
||||
ConnectionData(tv, (void*)((char*)buf.data+buf.startpos), buf.readpos - buf.startpos, to, mask, QW);
|
||||
if (tv->usequakeworldprotocols && !tv->controller)
|
||||
if ((!tv->controller || tv->controller->netchan.isnqprotocol) && tv->usequakeworldprotocols)
|
||||
{
|
||||
if (i)
|
||||
SendClientCommand(tv, "modellist %i %i\n", tv->clservercount, i);
|
||||
|
@ -1755,7 +1772,7 @@ void ParseMessage(sv_t *tv, void *buffer, int length, int to, int mask)
|
|||
if (!i)
|
||||
strcpy(tv->status, "Receiving modellist\n");
|
||||
ConnectionData(tv, (void*)((char*)buf.data+buf.startpos), buf.readpos - buf.startpos, to, mask, QW);
|
||||
if (tv->usequakeworldprotocols && !tv->controller)
|
||||
if ((!tv->controller || tv->controller->netchan.isnqprotocol) && tv->usequakeworldprotocols)
|
||||
{
|
||||
if (i)
|
||||
SendClientCommand(tv, "soundlist %i %i\n", tv->clservercount, i);
|
||||
|
|
12
fteqtv/qtv.h
12
fteqtv/qtv.h
|
@ -226,6 +226,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|||
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
|
||||
#ifdef LIBQTV
|
||||
//#define Sys_Printf QTVSys_Printf
|
||||
#endif
|
||||
|
||||
#define VERSION "0.01" //this will be added to the serverinfo
|
||||
|
||||
#define PROX_DEFAULTSERVERPORT 27500
|
||||
|
@ -441,6 +446,7 @@ typedef struct viewer_s {
|
|||
|
||||
int lost; //packets
|
||||
usercmd_t ucmds[3];
|
||||
unsigned int lasttime;
|
||||
|
||||
|
||||
int settime; //the time that we last told the client.
|
||||
|
@ -628,6 +634,7 @@ struct sv_s { //details about a server connection (also known as stream)
|
|||
|
||||
qboolean parsingconnectiondata; //so reject any new connects for now
|
||||
|
||||
unsigned int mapstarttime;
|
||||
unsigned int physicstime; //the last time all the ents moved.
|
||||
unsigned int simtime;
|
||||
unsigned int curtime;
|
||||
|
@ -725,6 +732,7 @@ struct cluster_s {
|
|||
sv_t *viewserver;
|
||||
|
||||
//options
|
||||
char autojoinadr[128]; //new clients automatically .join this server
|
||||
int qwlistenportnum;
|
||||
int tcplistenportnum;
|
||||
char adminpassword[256];//password required for rcon etc
|
||||
|
@ -834,8 +842,8 @@ void BuildNQServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int servercount);
|
|||
void QW_UpdateUDPStuff(cluster_t *qtv);
|
||||
unsigned int Sys_Milliseconds(void);
|
||||
void Prox_SendInitialEnts(sv_t *qtv, oproxy_t *prox, netmsg_t *msg);
|
||||
qboolean QTV_Connect(sv_t *qtv, char *serverurl);
|
||||
void QTV_Shutdown(sv_t *qtv);
|
||||
qboolean QTV_ConnectStream(sv_t *qtv, char *serverurl);
|
||||
void QTV_ShutdownStream(sv_t *qtv);
|
||||
qboolean NET_StringToAddr (char *s, netadr_t *sadr, int defaultport);
|
||||
void QTV_Printf(sv_t *qtv, char *format, ...) PRINTFWARNING(2);
|
||||
|
||||
|
|
135
fteqtv/qw.c
135
fteqtv/qw.c
|
@ -266,7 +266,7 @@ void BuildNQServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int playernum)
|
|||
WriteByte(msg, 0);
|
||||
|
||||
WriteByte(msg, svc_nqsetview);
|
||||
WriteShort(msg, playernum);
|
||||
WriteShort(msg, playernum+1);
|
||||
|
||||
WriteByte(msg, svc_nqsignonnum);
|
||||
WriteByte(msg, 1);
|
||||
|
@ -274,7 +274,7 @@ void BuildNQServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int playernum)
|
|||
else
|
||||
{
|
||||
//dummy connection, for choosing a game to watch.
|
||||
WriteString(msg, "FTEQTV Proxy");
|
||||
WriteString(msg, tv->map.mapname);
|
||||
|
||||
|
||||
//modellist
|
||||
|
@ -296,7 +296,7 @@ void BuildNQServerData(sv_t *tv, netmsg_t *msg, qboolean mvd, int playernum)
|
|||
WriteByte(msg, tv->map.cdtrack);
|
||||
|
||||
WriteByte(msg, svc_nqsetview);
|
||||
WriteShort(msg, 15);
|
||||
WriteShort(msg, playernum+1);
|
||||
|
||||
WriteByte(msg, svc_nqsignonnum);
|
||||
WriteByte(msg, 1);
|
||||
|
@ -328,7 +328,7 @@ void SendServerData(sv_t *tv, viewer_t *viewer)
|
|||
SendBufferToViewer(viewer, msg.data, msg.cursize, true);
|
||||
|
||||
viewer->thinksitsconnected = false;
|
||||
if (tv && (tv->controller == viewer))
|
||||
if (tv && (tv->controller == viewer) && !viewer->netchan.isnqprotocol)
|
||||
viewer->thinksitsconnected = true;
|
||||
|
||||
QW_ClearViewerState(viewer);
|
||||
|
@ -341,7 +341,7 @@ void SendNQSpawnInfoToViewer(cluster_t *cluster, viewer_t *viewer, netmsg_t *msg
|
|||
int colours;
|
||||
sv_t *tv = viewer->server;
|
||||
WriteByte(msg, svc_nqtime);
|
||||
WriteFloat(msg, cluster->curtime/1000.0f);
|
||||
WriteFloat(msg, (cluster->curtime - (tv?tv->mapstarttime:0))/1000.0f);
|
||||
|
||||
if (tv)
|
||||
{
|
||||
|
@ -661,7 +661,7 @@ void QW_SetViewersServer(cluster_t *cluster, viewer_t *viewer, sv_t *sv)
|
|||
|
||||
if (sv != oldserver)
|
||||
{
|
||||
if (sv)
|
||||
if (sv && oldserver)
|
||||
{
|
||||
snprintf(buffer, sizeof(buffer), "%cQTV%c%s leaves to watch %s (%i)\n", 91+128, 93+128, viewer->name, *sv->map.hostname?sv->map.hostname:sv->server, sv->streamid);
|
||||
QW_StreamPrint(cluster, oldserver, viewer, buffer);
|
||||
|
@ -685,6 +685,23 @@ qboolean ChallengePasses(netadr_t *addr, int challenge)
|
|||
|
||||
void NewClient(cluster_t *cluster, viewer_t *viewer)
|
||||
{
|
||||
sv_t *initialserver;
|
||||
initialserver = NULL;
|
||||
if (*cluster->autojoinadr)
|
||||
{
|
||||
initialserver = QTV_NewServerConnection(cluster, 0, cluster->autojoinadr, "", false, AD_WHENEMPTY, true, false);
|
||||
if (initialserver && initialserver->sourcetype == SRC_UDP)
|
||||
initialserver->controller = viewer;
|
||||
}
|
||||
else if (cluster->nouserconnects && cluster->numservers == 1)
|
||||
{
|
||||
initialserver = cluster->servers;
|
||||
if (!initialserver->map.modellist[1].name[0])
|
||||
initialserver = NULL; //damn, that server isn't ready
|
||||
}
|
||||
|
||||
QW_SetViewersServer(cluster, viewer, initialserver);
|
||||
|
||||
viewer->userid = ++cluster->nextuserid;
|
||||
viewer->timeout = cluster->curtime + 15*1000;
|
||||
viewer->trackplayer = -1;
|
||||
|
@ -693,6 +710,7 @@ void NewClient(cluster_t *cluster, viewer_t *viewer)
|
|||
QW_SetMenu(viewer, MENU_NONE);
|
||||
|
||||
|
||||
#ifndef LIBQTV
|
||||
QW_PrintfToViewer(viewer, "Welcome to FTEQTV build %i\n", cluster->buildnumber);
|
||||
QW_StuffcmdToViewer(viewer, "alias admin \"cmd admin\"\n");
|
||||
|
||||
|
@ -719,6 +737,7 @@ void NewClient(cluster_t *cluster, viewer_t *viewer)
|
|||
// QW_StuffcmdToViewer(viewer, "alias \".observe\" \"say .observe\"\n");
|
||||
|
||||
QW_PrintfToViewer(viewer, "Type admin for the admin menu\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParseUserInfo(cluster_t *cluster, viewer_t *viewer)
|
||||
|
@ -760,7 +779,8 @@ void ParseUserInfo(cluster_t *cluster, viewer_t *viewer)
|
|||
|
||||
}
|
||||
|
||||
QW_StreamPrint(cluster, viewer->server, NULL, buf);
|
||||
if (!viewer->server || viewer->server->controller != viewer)
|
||||
QW_StreamPrint(cluster, viewer->server, NULL, buf);
|
||||
}
|
||||
|
||||
strlcpy(viewer->name, temp, sizeof(viewer->name));
|
||||
|
@ -839,18 +859,6 @@ void NewNQClient(cluster_t *cluster, netadr_t *addr)
|
|||
for (i = 0; i < ENTITY_FRAMES; i++)
|
||||
viewer->delta_frames[i] = -1;
|
||||
|
||||
initialserver = NULL;
|
||||
if (cluster->numservers == 1)
|
||||
{
|
||||
initialserver = cluster->servers;
|
||||
if (!initialserver->map.modellist[1].name[0])
|
||||
initialserver = NULL; //damn, that server isn't ready
|
||||
}
|
||||
|
||||
viewer->server = initialserver;
|
||||
if (viewer->server)
|
||||
viewer->server->numviewers++;
|
||||
|
||||
cluster->numviewers++;
|
||||
|
||||
sprintf(viewer->userinfo, "\\name\\%s", "unnamed");
|
||||
|
@ -859,9 +867,8 @@ void NewNQClient(cluster_t *cluster, netadr_t *addr)
|
|||
|
||||
NewClient(cluster, viewer);
|
||||
|
||||
QW_StuffcmdToViewer(viewer, "cmd new\n");
|
||||
|
||||
Sys_Printf(cluster, "New NQ client connected\n");
|
||||
if (!viewer->server)
|
||||
QW_StuffcmdToViewer(viewer, "cmd new\n");
|
||||
}
|
||||
|
||||
void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
||||
|
@ -907,18 +914,6 @@ void NewQWClient(cluster_t *cluster, netadr_t *addr, char *connectmessage)
|
|||
for (i = 0; i < ENTITY_FRAMES; i++)
|
||||
viewer->delta_frames[i] = -1;
|
||||
|
||||
initialserver = NULL;
|
||||
if (cluster->nouserconnects && cluster->numservers == 1)
|
||||
{
|
||||
initialserver = cluster->servers;
|
||||
if (!initialserver->map.modellist[1].name[0])
|
||||
initialserver = NULL; //damn, that server isn't ready
|
||||
}
|
||||
|
||||
viewer->server = initialserver;
|
||||
if (viewer->server)
|
||||
viewer->server->numviewers++;
|
||||
|
||||
cluster->numviewers++;
|
||||
|
||||
strlcpy(viewer->userinfo, infostring, sizeof(viewer->userinfo));
|
||||
|
@ -1642,23 +1637,20 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
|||
if (tv)
|
||||
{
|
||||
WriteByte(msg, svc_nqtime);
|
||||
WriteFloat(msg, tv->physicstime/1000.0f);
|
||||
WriteFloat(msg, (tv->physicstime - tv->mapstarttime)/1000.0f);
|
||||
|
||||
BSP_SetupForPosition(tv->map.bsp, v->origin[0], v->origin[1], v->origin[2]);
|
||||
|
||||
lerp = ((tv->simtime - tv->oldpackettime)/1000.0f) / ((tv->nextpackettime - tv->oldpackettime)/1000.0f);
|
||||
if (lerp < 0)
|
||||
lerp = 0;
|
||||
if (lerp > 1)
|
||||
lerp = 1;
|
||||
lerp = 1;
|
||||
|
||||
if (tv->controller == v)
|
||||
lerp = 1;
|
||||
// if (tv->controller == v)
|
||||
// lerp = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(msg, svc_nqtime);
|
||||
WriteFloat(msg, cluster->curtime/1000.0f);
|
||||
WriteFloat(msg, (cluster->curtime)/1000.0f);
|
||||
|
||||
lerp = 1;
|
||||
}
|
||||
|
@ -1667,23 +1659,24 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
|||
|
||||
if (tv)
|
||||
{
|
||||
|
||||
if (v->trackplayer >= 0)
|
||||
if (v != tv->controller)
|
||||
{
|
||||
WriteByte(msg, svc_nqsetview);
|
||||
WriteShort(msg, v->trackplayer+1);
|
||||
if (v->trackplayer >= 0)
|
||||
{
|
||||
WriteByte(msg, svc_nqsetview);
|
||||
WriteShort(msg, v->trackplayer+1);
|
||||
|
||||
WriteByte(msg, svc_setangle);
|
||||
WriteByte(msg, (int)InterpolateAngle(tv->map.players[v->trackplayer].old.angles[0], tv->map.players[v->trackplayer].current.angles[0], lerp)>>8);
|
||||
WriteByte(msg, (int)InterpolateAngle(tv->map.players[v->trackplayer].old.angles[1], tv->map.players[v->trackplayer].current.angles[1], lerp)>>8);
|
||||
WriteByte(msg, (int)InterpolateAngle(tv->map.players[v->trackplayer].old.angles[2], tv->map.players[v->trackplayer].current.angles[2], lerp)>>8);
|
||||
WriteByte(msg, svc_setangle);
|
||||
WriteByte(msg, (int)InterpolateAngle(tv->map.players[v->trackplayer].old.angles[0], tv->map.players[v->trackplayer].current.angles[0], lerp)>>8);
|
||||
WriteByte(msg, (int)InterpolateAngle(tv->map.players[v->trackplayer].old.angles[1], tv->map.players[v->trackplayer].current.angles[1], lerp)>>8);
|
||||
WriteByte(msg, (int)InterpolateAngle(tv->map.players[v->trackplayer].old.angles[2], tv->map.players[v->trackplayer].current.angles[2], lerp)>>8);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(msg, svc_nqsetview);
|
||||
WriteShort(msg, v->thisplayer+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteByte(msg, svc_nqsetview);
|
||||
WriteShort(msg, v->thisplayer+1);
|
||||
}
|
||||
|
||||
|
||||
for (e = 0; e < MAX_CLIENTS; e++)
|
||||
{
|
||||
|
@ -1736,8 +1729,9 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
|||
if (!pl->active)
|
||||
continue;
|
||||
|
||||
if (pl->current.modelindex >= tv->map.numinlines && !BSP_Visible(tv->map.bsp, pl->leafcount, pl->leafs))
|
||||
continue;
|
||||
if (v != tv->controller)
|
||||
if (pl->current.modelindex >= tv->map.numinlines && !BSP_Visible(tv->map.bsp, pl->leafcount, pl->leafs))
|
||||
continue;
|
||||
|
||||
pl->current.modelindex = 8;
|
||||
|
||||
|
@ -1839,8 +1833,9 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
|||
//pvs cull everything else
|
||||
newstate = &topacket->ents[newindex];
|
||||
newnum = topacket->entnums[newindex];
|
||||
if (newstate->modelindex >= tv->map.numinlines && !BSP_Visible(tv->map.bsp, tv->map.entity[newnum].leafcount, tv->map.entity[newnum].leafs))
|
||||
continue;
|
||||
if (v != tv->controller)
|
||||
if (newstate->modelindex >= tv->map.numinlines && !BSP_Visible(tv->map.bsp, tv->map.entity[newnum].leafcount, tv->map.entity[newnum].leafs))
|
||||
continue;
|
||||
|
||||
if (msg->cursize + 128 > msg->maxsize)
|
||||
break;
|
||||
|
@ -1851,7 +1846,7 @@ void SendNQPlayerStates(cluster_t *cluster, sv_t *tv, viewer_t *v, netmsg_t *msg
|
|||
for (i=0 ; i<3 ; i++)
|
||||
{
|
||||
miss = (int)(newstate->origin[i]) - ent->baseline.origin[i];
|
||||
if ( miss < -1 || miss > 1 )
|
||||
if ( miss <= -1 || miss >= 1 )
|
||||
bits |= UNQ_ORIGIN1<<i;
|
||||
}
|
||||
|
||||
|
@ -3405,7 +3400,7 @@ void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
char arg[3][ARG_LEN];
|
||||
char *command = buf;
|
||||
|
||||
for (i = 0; i < MAX_ARGS; i++)
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
command = COM_ParseToken(command, arg[i], ARG_LEN, TOKENIZE_PUNCTUATION);
|
||||
}
|
||||
|
@ -3458,6 +3453,14 @@ void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
QTV_Say(cluster, v->server, v, ".menu", false);
|
||||
}
|
||||
|
||||
else if (!strncmp(buf, "say \".", 6))
|
||||
QTV_Say(cluster, qtv, v, buf+5, false);
|
||||
else if (!strncmp(buf, "say .", 5))
|
||||
QTV_Say(cluster, qtv, v, buf+4, false);
|
||||
|
||||
else if (v->server && v == v->server->controller)
|
||||
SendClientCommand(v->server, "%s", buf);
|
||||
|
||||
// else if (!strcmp(buf, "pause"))
|
||||
// qtv->errored = ERR_PAUSED;
|
||||
|
||||
|
@ -3495,12 +3498,16 @@ void ParseNQC(cluster_t *cluster, sv_t *qtv, viewer_t *v, netmsg_t *m)
|
|||
v->ucmds[2].upmove = ReadShort(m);
|
||||
|
||||
//one button
|
||||
v->ucmds[1].buttons = v->ucmds[2].buttons;
|
||||
v->ucmds[2].buttons = ReadByte(m);
|
||||
//one impulse
|
||||
v->ucmds[2].impulse = ReadByte(m);
|
||||
|
||||
v->ucmds[2].msec = 1000/NQ_PACKETS_PER_SECOND;
|
||||
v->ucmds[2].msec = cluster->curtime - v->lasttime;
|
||||
v->lasttime = cluster->curtime;
|
||||
|
||||
if (v->server && v->server->controller == v)
|
||||
return;
|
||||
|
||||
PMove(v, &v->ucmds[2]);
|
||||
|
||||
if ((v->ucmds[1].buttons&1) != (v->ucmds[2].buttons&1) && (v->ucmds[2].buttons&1))
|
||||
|
|
|
@ -914,7 +914,7 @@ void Cmd_DemoSpeed(cmdctxt_t *ctx)
|
|||
|
||||
void Cmd_Disconnect(cmdctxt_t *ctx)
|
||||
{
|
||||
QTV_Shutdown(ctx->qtv);
|
||||
QTV_ShutdownStream(ctx->qtv);
|
||||
Cmd_Printf(ctx, "Disconnected\n");
|
||||
}
|
||||
|
||||
|
@ -1001,7 +1001,7 @@ void Cmd_Reconnect(cmdctxt_t *ctx)
|
|||
Cmd_Printf(ctx, "Stream is a reverse connection (command rejected)\n");
|
||||
// else if (ctx->qtv->autodisconnect == AD_STATUSPOLL && !ctx->qtv->numviewers && !ctx->qtv->proxies)
|
||||
// Cmd_Printf(ctx, "Not reconnecting to idle server\n");
|
||||
else if (QTV_Connect(ctx->qtv, ctx->qtv->server))
|
||||
else if (QTV_ConnectStream(ctx->qtv, ctx->qtv->server))
|
||||
Cmd_Printf(ctx, "Reconnected\n");
|
||||
else
|
||||
Cmd_Printf(ctx, "Failed to reconnect (will keep trying)\n");
|
||||
|
|
|
@ -206,6 +206,8 @@ qboolean Net_CompareAddress(netadr_t *s1, netadr_t *s2, int qp1, int qp2)
|
|||
return false;
|
||||
switch(g1->sa_family)
|
||||
{
|
||||
default:
|
||||
return true;
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *i1=(void*)s1->sockaddr, *i2=(void*)s2->sockaddr;
|
||||
|
@ -1063,7 +1065,7 @@ void Trim(char *s)
|
|||
*s = '\0';
|
||||
}
|
||||
|
||||
qboolean QTV_Connect(sv_t *qtv, char *serverurl)
|
||||
qboolean QTV_ConnectStream(sv_t *qtv, char *serverurl)
|
||||
{
|
||||
if (qtv->sourcesock != INVALID_SOCKET)
|
||||
{
|
||||
|
@ -1222,7 +1224,7 @@ void QTV_Cleanup(sv_t *qtv, qboolean leaveadmins)
|
|||
}
|
||||
}
|
||||
|
||||
void QTV_Shutdown(sv_t *qtv)
|
||||
void QTV_ShutdownStream(sv_t *qtv)
|
||||
{
|
||||
sv_t *peer;
|
||||
cluster_t *cluster;
|
||||
|
@ -1608,7 +1610,7 @@ void QTV_Run(sv_t *qtv)
|
|||
}
|
||||
else if (qtv->errored == ERR_DROP)
|
||||
{
|
||||
QTV_Shutdown(qtv); //destroys the stream
|
||||
QTV_ShutdownStream(qtv); //destroys the stream
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1679,7 +1681,7 @@ void QTV_Run(sv_t *qtv)
|
|||
strcpy(qtv->status, "Attemping challenge\n");
|
||||
if (qtv->sourcesock == INVALID_SOCKET && !qtv->sourcefile)
|
||||
{
|
||||
if (!QTV_Connect(qtv, qtv->server)) //reconnect it
|
||||
if (!QTV_ConnectStream(qtv, qtv->server)) //reconnect it
|
||||
{
|
||||
qtv->errored = ERR_PERMANENT;
|
||||
}
|
||||
|
@ -1735,6 +1737,10 @@ void QTV_Run(sv_t *qtv)
|
|||
}
|
||||
ChooseFavoriteTrack(qtv);
|
||||
|
||||
//if we froze somehow, don't speedcheat by a burst of 10000+ packets while we were frozen in a debugger or disk spinup or whatever
|
||||
if (qtv->packetratelimiter < qtv->curtime - UDPPACKETINTERVAL*2)
|
||||
qtv->packetratelimiter = qtv->curtime;
|
||||
|
||||
if (qtv->map.trackplayer >= 0)
|
||||
{
|
||||
qtv->packetratelimiter += UDPPACKETINTERVAL;
|
||||
|
@ -1748,6 +1754,13 @@ void QTV_Run(sv_t *qtv)
|
|||
{
|
||||
qtv->packetratelimiter += UDPPACKETINTERVAL;
|
||||
|
||||
if (qtv->controller->netchan.isnqprotocol)
|
||||
{
|
||||
memcpy(&qtv->controller->ucmds[0], &qtv->controller->ucmds[1], sizeof(qtv->controller->ucmds[0]));
|
||||
memcpy(&qtv->controller->ucmds[1], &qtv->controller->ucmds[2], sizeof(qtv->controller->ucmds[0]));
|
||||
qtv->controller->ucmds[2].msec = UDPPACKETINTERVAL;
|
||||
}
|
||||
|
||||
WriteByte(&msg, clc_tmove);
|
||||
WriteShort(&msg, qtv->controller->origin[0]);
|
||||
WriteShort(&msg, qtv->controller->origin[1]);
|
||||
|
@ -1836,7 +1849,7 @@ void QTV_Run(sv_t *qtv)
|
|||
qtv->errored = ERR_DROP;
|
||||
return;
|
||||
}
|
||||
if (!QTV_Connect(qtv, qtv->server)) //reconnect it
|
||||
if (!QTV_ConnectStream(qtv, qtv->server)) //reconnect it
|
||||
{
|
||||
qtv->errored = ERR_PERMANENT;
|
||||
return;
|
||||
|
@ -2205,7 +2218,7 @@ sv_t *QTV_NewServerConnection(cluster_t *cluster, int newstreamid, char *server,
|
|||
//warning review this logic
|
||||
if (qtv->errored == ERR_DISABLED)
|
||||
{
|
||||
if (!(!QTV_Connect(qtv, server) && !force)) //try and wake it up
|
||||
if (!(!QTV_ConnectStream(qtv, server) && !force)) //try and wake it up
|
||||
qtv->errored = ERR_NONE;
|
||||
}
|
||||
return qtv;
|
||||
|
@ -2256,7 +2269,7 @@ sv_t *QTV_NewServerConnection(cluster_t *cluster, int newstreamid, char *server,
|
|||
|
||||
if (autoclose != AD_REVERSECONNECT) //2 means reverse connection (don't ever try reconnecting)
|
||||
{
|
||||
if (!QTV_Connect(qtv, server) && !force)
|
||||
if (!QTV_ConnectStream(qtv, server) && !force)
|
||||
{
|
||||
QTV_Cleanup(qtv, false);
|
||||
free(qtv);
|
||||
|
|
Loading…
Reference in a new issue