Optimised the textures of defaultwall with fast preset.
Fix simpleitems transparency in gles2. Fix a couple of GL errors in gles2 (including some fixed function stuff that could result in segfaults). Dynamically adjust MTU values with legacy qw clients too. Added some small sleeps while waiting for downloads (this fixes insanely slow valgrind startups but might make non-valgrind start a smidge slower). Fix title metadata in the updates system. Clean up some issues for when WEBCLIENT is not defined. HAVE_HTTPSV also disables websocket connections, to completely avoid any http strings anywhere, in the hope that it reduces virus scanner false positives. Fix presets initial option, again. Writing files to FS_GAMEONLY no longer purges the entire fscache, which should give a speedup in certain situations. Added some new cvars to control heightmap lightmap generation. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5461 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
b3050121cf
commit
3c5518afa8
41 changed files with 735 additions and 279 deletions
|
@ -4195,7 +4195,7 @@ void CL_LinkPacketEntities (void)
|
|||
Q_snprintfz(name, sizeof(name), "textures/bmodels/simple_%s_%i.tga", basename, ent->skinnum);
|
||||
else
|
||||
Q_snprintfz(name, sizeof(name), "textures/models/simple_%s_%i.tga", basename, ent->skinnum);
|
||||
model->simpleskin[ent->skinnum] = R_RegisterShader(name, 0, va("{\nnomipmaps\nprogram defaultsprite\nsurfaceparm noshadows\nsurfaceparm nodlight\nsort seethrough\n{\nmap \"%s\"\nalphafunc ge128\n}\n}\n", name));
|
||||
model->simpleskin[ent->skinnum] = R_RegisterShader(name, 0, va("{\nnomipmaps\nprogram defaultsprite#MASK=0.5\nsurfaceparm noshadows\nsurfaceparm nodlight\nsort seethrough\n{\nmap \"%s\"\nalphafunc ge128\n}\n}\n", name));
|
||||
}
|
||||
VectorCopy(le->angles, angles);
|
||||
|
||||
|
|
|
@ -3493,9 +3493,14 @@ client_connect: //fixme: make function
|
|||
if (cls.protocol_q2 == PROTOCOL_VERSION_R1Q2 || cls.protocol_q2 == PROTOCOL_VERSION_Q2PRO)
|
||||
cls.netchan.qportsize = 1;
|
||||
}
|
||||
cls.netchan.fragmentsize = connectinfo.mtu;
|
||||
cls.netchan.pext_fragmentation = connectinfo.mtu?true:false;
|
||||
if (connectinfo.mtu >= 64)
|
||||
{
|
||||
cls.netchan.mtu = connectinfo.mtu;
|
||||
cls.netchan.message.maxsize = sizeof(cls.netchan.message_buf);
|
||||
}
|
||||
else
|
||||
cls.netchan.mtu = MAX_QWMSGLEN;
|
||||
#ifdef HUFFNETWORK
|
||||
cls.netchan.compresstable = Huff_CompressionCRC(connectinfo.compresscrc);
|
||||
#else
|
||||
|
@ -6396,7 +6401,12 @@ void Host_FinishLoading(void)
|
|||
FS_ChangeGame(NULL, true, true);
|
||||
|
||||
if (waitingformanifest)
|
||||
{
|
||||
#ifdef MULTITHREAD
|
||||
Sys_Sleep(0.1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
Con_History_Load();
|
||||
|
||||
|
@ -6437,7 +6447,12 @@ void Host_FinishLoading(void)
|
|||
}
|
||||
|
||||
if (PM_IsApplying(true))
|
||||
{
|
||||
#ifdef MULTITHREAD
|
||||
Sys_Sleep(0.1);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
//android may find that it has no renderer at various points.
|
||||
if (r_forceheadless)
|
||||
|
|
|
@ -1390,6 +1390,15 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag)
|
|||
return; //looks like its already picked. marking it again will do no harm.
|
||||
}
|
||||
|
||||
#ifndef WEBCLIENT
|
||||
//can't mark for download if we cannot download.
|
||||
if (!(package->flags & DPF_PRESENT))
|
||||
{ //though we can at least unmark it for deletion...
|
||||
package->flags &= ~DPF_PURGE;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
//any file-conflicts prevent the package from being installable.
|
||||
//this is mostly for pak1.pak
|
||||
for (dep = package->deps; dep; dep = dep->next)
|
||||
|
@ -1881,7 +1890,7 @@ static void PM_WriteInstalledPackages(void)
|
|||
if (*p->title && strcmp(p->title, p->name))
|
||||
{
|
||||
Q_strncatz(buf, " ", sizeof(buf));
|
||||
COM_QuotedConcat(va("title=%s", p->version), buf, sizeof(buf));
|
||||
COM_QuotedConcat(va("title=%s", p->title), buf, sizeof(buf));
|
||||
}
|
||||
if (*p->version)
|
||||
{
|
||||
|
@ -2745,7 +2754,6 @@ qboolean PM_CanInstall(const char *packagename)
|
|||
|
||||
void PM_Command_f(void)
|
||||
{
|
||||
size_t i;
|
||||
package_t *p;
|
||||
const char *act = Cmd_Argv(1);
|
||||
const char *key;
|
||||
|
@ -2878,6 +2886,7 @@ void PM_Command_f(void)
|
|||
}
|
||||
Con_Printf("<end of list>\n");
|
||||
}
|
||||
#ifdef WEBCLIENT
|
||||
else if (!strcmp(act, "sources") || !strcmp(act, "addsource"))
|
||||
{
|
||||
if (Cmd_Argc() == 2)
|
||||
|
@ -2890,6 +2899,7 @@ void PM_Command_f(void)
|
|||
else
|
||||
PM_AddSubList(Cmd_Argv(2), "", true, true);
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(act, "remsource"))
|
||||
PM_RemSubList(Cmd_Argv(2));
|
||||
else if (!strcmp(act, "apply"))
|
||||
|
@ -2908,8 +2918,10 @@ void PM_Command_f(void)
|
|||
{
|
||||
PM_RevertChanges();
|
||||
}
|
||||
#ifdef WEBCLIENT
|
||||
else if (!strcmp(act, "update"))
|
||||
{ //flush package cache, make a new request.
|
||||
int i;
|
||||
for (i = 0; i < numdownloadablelists; i++)
|
||||
downloadablelist[i].received = 0;
|
||||
}
|
||||
|
@ -2924,6 +2936,7 @@ void PM_Command_f(void)
|
|||
else
|
||||
Con_Printf("Already using latest versions of all packages\n");
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(act, "add") || !strcmp(act, "get") || !strcmp(act, "install") || !strcmp(act, "enable"))
|
||||
{ //FIXME: make sure this updates.
|
||||
int arg = 2;
|
||||
|
@ -2938,6 +2951,7 @@ void PM_Command_f(void)
|
|||
}
|
||||
PM_PrintChanges();
|
||||
}
|
||||
#ifdef WEBCLIENT
|
||||
else if (!strcmp(act, "reinstall"))
|
||||
{ //fixme: favour the current verson.
|
||||
int arg = 2;
|
||||
|
@ -2955,6 +2969,7 @@ void PM_Command_f(void)
|
|||
}
|
||||
PM_PrintChanges();
|
||||
}
|
||||
#endif
|
||||
else if (!strcmp(act, "disable") || !strcmp(act, "rem") || !strcmp(act, "remove"))
|
||||
{
|
||||
int arg = 2;
|
||||
|
@ -3234,9 +3249,11 @@ static qboolean MD_Key (struct menucustom_s *c, struct menu_s *m, int key, unsig
|
|||
case DPF_USERMARKED:
|
||||
case DPF_MARKED:
|
||||
p->flags |= DPF_PURGE;
|
||||
#ifdef WEBCLIENT
|
||||
//now: re-get despite already having it.
|
||||
if ((p->flags & DPF_CORRUPT) || ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p)))
|
||||
break; //only makes sense if we already have a cached copy that we're not going to use.
|
||||
#endif
|
||||
//fallthrough
|
||||
case DPF_USERMARKED|DPF_PURGE:
|
||||
case DPF_AUTOMARKED|DPF_PURGE:
|
||||
|
@ -3444,10 +3461,13 @@ static void MD_Download_UpdateStatus(struct menu_s *m)
|
|||
dlmenu_t *info = m->data;
|
||||
int i, y;
|
||||
package_t *p;
|
||||
unsigned int totalpackages=0, selectedpackages=0, addpackages=0, rempackages=0, downloads=0;
|
||||
unsigned int totalpackages=0, selectedpackages=0, addpackages=0, rempackages=0;
|
||||
menuoption_t *si;
|
||||
menubutton_t *b, *d;
|
||||
#ifdef WEBCLIENT
|
||||
unsigned int downloads=0;
|
||||
menucustom_t *c;
|
||||
#endif
|
||||
|
||||
if (info->downloadablessequence != downloadablessequence || !info->populated)
|
||||
{
|
||||
|
|
|
@ -1062,6 +1062,7 @@ void M_Menu_Preset_f (void)
|
|||
item = 6; //fast
|
||||
else
|
||||
item = 7; //simple
|
||||
item++; //the autosave option
|
||||
item -= bias;
|
||||
while (item --> 0)
|
||||
menu->selecteditem = menu->selecteditem->common.next;
|
||||
|
|
|
@ -306,15 +306,15 @@ static void S_Info(void);
|
|||
|
||||
static void S_Shutdown_f(void);
|
||||
*/
|
||||
static cvar_t s_al_debug = CVAR("s_al_debug", "0");
|
||||
static cvar_t s_al_use_reverb = CVAR("s_al_use_reverb", "1");
|
||||
static cvar_t s_al_debug = CVARD("s_al_debug", "0", "Enables periodic checks for OpenAL errors.");
|
||||
static cvar_t s_al_use_reverb = CVARD("s_al_use_reverb", "1", "Controls whether reverb effects will be used. Set to 0 to block them. Reverb requires gamecode to configure the reverb properties, other than underwater.");
|
||||
static cvar_t s_al_max_distance = CVARFC("s_al_max_distance", "1000",0,OnChangeALSettings);
|
||||
static cvar_t s_al_speedofsound = CVARFC("s_al_speedofsound", "343.3",0,OnChangeALSettings);
|
||||
static cvar_t s_al_dopplerfactor = CVARFC("s_al_dopplerfactor", "1.0",0,OnChangeALSettings);
|
||||
static cvar_t s_al_distancemodel = CVARFC("s_al_distancemodel", "2",0,OnChangeALSettings);
|
||||
static cvar_t s_al_rolloff_factor = CVAR("s_al_rolloff_factor", "1");
|
||||
static cvar_t s_al_reference_distance = CVAR("s_al_reference_distance", "120");
|
||||
static cvar_t s_al_velocityscale = CVAR("s_al_velocityscale", "1");
|
||||
static cvar_t s_al_speedofsound = CVARFCD("s_al_speedofsound", "343.3",0,OnChangeALSettings, "Configures the speed of sound, in game units per second. This affects doppler.");
|
||||
static cvar_t s_al_dopplerfactor = CVARFCD("s_al_dopplerfactor", "1.0",0,OnChangeALSettings, "Multiplies the strength of doppler effects.");
|
||||
static cvar_t s_al_distancemodel = CVARFCD("s_al_distancemodel", legacyval("2","0"),0,OnChangeALSettings, "Controls how sounds fade with distance.\n0: Inverse (most realistic)\n1: Inverse Clamped\n2: Linear (Quake-like)\n3: Linear Clamped\n4: Exponential\n5: Exponential Clamped\n6: None");
|
||||
//static cvar_t s_al_rolloff_factor = CVAR("s_al_rolloff_factor", "1");
|
||||
static cvar_t s_al_reference_distance = CVARD("s_al_reference_distance", "120", "This is the distance at which the sound is audiable with standard volume in the inverse distance models. Nearer sounds will be louder than the original sample.");
|
||||
static cvar_t s_al_velocityscale = CVARD("s_al_velocityscale", "1", "Rescales velocity values, before doppler can be calculated.");
|
||||
static cvar_t s_al_static_listener = CVAR("s_al_static_listener", "0"); //cheat
|
||||
extern cvar_t snd_doppler;
|
||||
|
||||
|
@ -503,7 +503,7 @@ static void QDECL OpenAL_CvarInit(void)
|
|||
Cvar_Register(&s_al_dopplerfactor, SOUNDVARS);
|
||||
Cvar_Register(&s_al_distancemodel, SOUNDVARS);
|
||||
Cvar_Register(&s_al_reference_distance, SOUNDVARS);
|
||||
Cvar_Register(&s_al_rolloff_factor, SOUNDVARS);
|
||||
// Cvar_Register(&s_al_rolloff_factor, SOUNDVARS);
|
||||
Cvar_Register(&s_al_velocityscale, SOUNDVARS);
|
||||
Cvar_Register(&s_al_static_listener, SOUNDVARS);
|
||||
Cvar_Register(&s_al_speedofsound, SOUNDVARS);
|
||||
|
|
|
@ -802,8 +802,7 @@ static void Friendly_Crash_Handler(int sig, siginfo_t *info, void *vcontext)
|
|||
|
||||
#if defined(__i386__)
|
||||
//x86 signals don't leave the stack in a clean state, so replace the signal handler with the real crash address, and hide this function
|
||||
ucontext_t *uc = vcontext;
|
||||
array[1] = (void*)uc->uc_mcontext.gregs[REG_EIP];
|
||||
array[1] = (void*)((ucontext_t*)vcontext)->uc_mcontext.gregs[REG_EIP];
|
||||
firstframe = 1;
|
||||
#elif defined(__amd64__)
|
||||
//amd64 is sane enough, but this function and the libc signal handler are on the stack, and should be ignored.
|
||||
|
@ -995,7 +994,6 @@ int main (int c, const char **v)
|
|||
#endif
|
||||
TL_InitLanguages(parms.binarydir);
|
||||
|
||||
|
||||
if (!isatty(STDIN_FILENO))
|
||||
noconinput = !isPlugin; //don't read the stdin if its probably screwed (running in qtcreator seems to pipe stdout to stdin in an attempt to screw everything up).
|
||||
else
|
||||
|
|
|
@ -3362,10 +3362,15 @@ static void *Q1MDL_LoadFrameGroup (galiasinfo_t *galias, dmdl_t *pq1inmodel, mod
|
|||
galias->numanimations++;
|
||||
|
||||
intervals = (daliasinterval_t *)(ingroup+1);
|
||||
sinter = LittleFloat(intervals->interval);
|
||||
if (sinter <= 0)
|
||||
sinter = 0.1;
|
||||
frame->rate = 1/sinter;
|
||||
if (frame->numposes == 0)
|
||||
frame->rate = 10;
|
||||
else
|
||||
{
|
||||
sinter = LittleFloat(intervals->interval);
|
||||
if (sinter <= 0)
|
||||
sinter = 0.1;
|
||||
frame->rate = 1/sinter;
|
||||
}
|
||||
|
||||
pinframe = (dtrivertx_t *)(intervals+frame->numposes);
|
||||
for (k = 0; k < frame->numposes; k++)
|
||||
|
|
|
@ -52,7 +52,8 @@ typedef struct
|
|||
#endif
|
||||
qboolean loop;
|
||||
int numposes;
|
||||
float rate;
|
||||
//float *poseendtime; //first starts at 0, anim duration is poseendtime[numposes-1]
|
||||
float rate; //average framerate of animation.
|
||||
#ifdef NONSKELETALMODELS
|
||||
galiaspose_t *poseofs;
|
||||
#endif
|
||||
|
@ -219,7 +220,7 @@ typedef struct modplugfuncs_s
|
|||
void (QDECL *UnRegisterModelFormat)(int idx);
|
||||
void (QDECL *UnRegisterAllModelFormats)(void);
|
||||
|
||||
void *(QDECL *ZG_Malloc)(zonegroup_t *ctx, int size); //ctx=&mod->memgroup and the data will be freed when the model is freed.
|
||||
void *(QDECL *ZG_Malloc)(zonegroup_t *ctx, size_t size); //ctx=&mod->memgroup and the data will be freed when the model is freed.
|
||||
|
||||
void (QDECL *ConcatTransforms) (const float in1[3][4], const float in2[3][4], float out[3][4]);
|
||||
void (QDECL *M3x4_Invert) (const float *in1, float *out);
|
||||
|
|
|
@ -131,6 +131,13 @@ typedef enum {false, true} qboolean;
|
|||
#define MAX_SERVERINFO_STRING 1024 //standard quake has 512 here.
|
||||
#define MAX_LOCALINFO_STRING 32768
|
||||
|
||||
|
||||
#ifdef HAVE_LEGACY
|
||||
#define legacyval(_legval,_newval) _legval
|
||||
#else
|
||||
#define legacyval(_legval,_newval) _newval
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CLIENT
|
||||
#define cls_state cls.state
|
||||
#else
|
||||
|
@ -448,7 +455,7 @@ struct cache_user_s;
|
|||
|
||||
extern char com_gamepath[MAX_OSPATH];
|
||||
extern char com_homepath[MAX_OSPATH];
|
||||
extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in
|
||||
//extern char com_configdir[MAX_OSPATH]; //dir to put cfg_save configs in
|
||||
//extern char *com_basedir;
|
||||
|
||||
//qofs_Make is used to 'construct' a variable of qofs_t type. this is so the code can merge two 32bit ints on old systems and use a long long type internally without generating warnings about bit shifts when qofs_t is only 32bit instead.
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
#define HAVE_WINSSPI //on windows
|
||||
#define FTPSERVER //sv_ftp cvar.
|
||||
#define WEBCLIENT //uri_get+any internal downloads etc
|
||||
#define HAVE_HTTPSV //net_enable_http/websocket
|
||||
#define TCPCONNECT //support for playing over tcp sockets, instead of just udp. compatible with qizmo.
|
||||
//#define IRCCONNECT //lame support for routing game packets via irc server. not a good idea.
|
||||
#define SUPPORT_ICE //Internet Connectivity Establishment, for use by plugins to establish voice or game connections.
|
||||
|
|
|
@ -144,7 +144,7 @@ typedef struct cvar_group_s
|
|||
#define CVAR_WATCHED (1<<22) //report any attempts to change this cvar.
|
||||
#define CVAR_VIDEOLATCH (1<<23)
|
||||
|
||||
#define CVAR_LASTFLAG CVAR_SHADERSYSTEM
|
||||
#define CVAR_LASTFLAG CVAR_VIDEOLATCH
|
||||
|
||||
#define CVAR_LATCHMASK (CVAR_LATCH|CVAR_RENDERERLATCH|CVAR_SERVEROVERRIDE|CVAR_CHEAT|CVAR_SEMICHEAT) //you're only allowed one of these.
|
||||
#define CVAR_NEEDDEFAULT CVAR_CHEAT
|
||||
|
|
|
@ -172,14 +172,15 @@ char gamedirfile[MAX_OSPATH];
|
|||
char pubgamedirfile[MAX_OSPATH]; //like gamedirfile, but not set to the fte-only paths
|
||||
|
||||
|
||||
|
||||
searchpath_t *gameonly_homedir;
|
||||
searchpath_t *gameonly_gamedir;
|
||||
|
||||
char com_gamepath[MAX_OSPATH]; //c:\games\quake
|
||||
char com_homepath[MAX_OSPATH]; //c:\users\foo\my docs\fte\quake
|
||||
qboolean com_homepathenabled;
|
||||
qboolean com_homepathusable; //com_homepath is safe, even if not enabled.
|
||||
|
||||
char com_configdir[MAX_OSPATH]; //homedir/fte/configs
|
||||
//char com_configdir[MAX_OSPATH]; //homedir/fte/configs
|
||||
|
||||
int fs_hash_dups;
|
||||
int fs_hash_files;
|
||||
|
@ -737,7 +738,7 @@ static void COM_Path_f (void)
|
|||
Con_Printf("pubgamedirfile: \"%s\"\n", pubgamedirfile);
|
||||
Con_Printf("com_gamepath: \"%s\"\n", com_gamepath);
|
||||
Con_Printf("com_homepath: \"%s\" (enabled: %s, usable: %s)\n", com_homepath, com_homepathenabled?"yes":"no", com_homepathusable?"yes":"no");
|
||||
Con_Printf("com_configdir: \"%s\"\n", com_configdir);
|
||||
// Con_Printf("com_configdir: \"%s\"\n", com_configdir);
|
||||
if (fs_manifest)
|
||||
FS_Manifest_Print(fs_manifest);
|
||||
return;
|
||||
|
@ -1915,6 +1916,9 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
|
|||
|
||||
fs_accessed_time = realtime;
|
||||
|
||||
if (fs_readonly && *mode == 'w')
|
||||
return NULL;
|
||||
|
||||
if (relativeto == FS_SYSTEM)
|
||||
return VFSOS_Open(filename, mode);
|
||||
|
||||
|
@ -1937,23 +1941,48 @@ vfsfile_t *QDECL FS_OpenVFS(const char *filename, const char *mode, enum fs_rela
|
|||
//if there can only be one file (eg: write access) find out where it is.
|
||||
switch (relativeto)
|
||||
{
|
||||
case FS_GAMEONLY: //OS access only, no paks
|
||||
case FS_GAMEONLY: //OS access only, no paks. Used for (re)writing files.
|
||||
vfs = NULL;
|
||||
//FIXME: go via a searchpath, because then the fscache can be selectively updated
|
||||
if (com_homepathenabled)
|
||||
{
|
||||
if (!try_snprintf(fullname, sizeof(fullname), "%s%s/%s", com_homepath, gamedirfile, filename))
|
||||
return NULL;
|
||||
if (*mode == 'w')
|
||||
COM_CreatePath(fullname);
|
||||
vfs = VFSOS_Open(fullname, mode);
|
||||
if (gameonly_homedir)
|
||||
{
|
||||
if ((*mode == 'w')
|
||||
? gameonly_homedir->handle->CreateFile(gameonly_homedir->handle, &loc, filename)
|
||||
: gameonly_homedir->handle->FindFile (gameonly_homedir->handle, &loc, filename, NULL))
|
||||
vfs = gameonly_homedir->handle->OpenVFS (gameonly_homedir->handle, &loc, mode);
|
||||
else
|
||||
vfs = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!try_snprintf(fullname, sizeof(fullname), "%s%s/%s", com_homepath, gamedirfile, filename))
|
||||
return NULL;
|
||||
if (*mode == 'w')
|
||||
COM_CreatePath(fullname);
|
||||
vfs = VFSOS_Open(fullname, mode);
|
||||
}
|
||||
}
|
||||
if (!vfs && *gamedirfile)
|
||||
{
|
||||
if (!try_snprintf(fullname, sizeof(fullname), "%s%s/%s", com_gamepath, gamedirfile, filename))
|
||||
return NULL;
|
||||
if (*mode == 'w')
|
||||
COM_CreatePath(fullname);
|
||||
vfs = VFSOS_Open(fullname, mode);
|
||||
if (gameonly_gamedir)
|
||||
{
|
||||
if ((*mode == 'w')
|
||||
? gameonly_gamedir->handle->CreateFile(gameonly_gamedir->handle, &loc, filename)
|
||||
: gameonly_gamedir->handle->FindFile (gameonly_gamedir->handle, &loc, filename, NULL))
|
||||
vfs = gameonly_gamedir->handle->OpenVFS (gameonly_gamedir->handle, &loc, mode);
|
||||
else
|
||||
vfs = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!try_snprintf(fullname, sizeof(fullname), "%s%s/%s", com_gamepath, gamedirfile, filename))
|
||||
return NULL;
|
||||
if (*mode == 'w')
|
||||
COM_CreatePath(fullname);
|
||||
vfs = VFSOS_Open(fullname, mode);
|
||||
}
|
||||
}
|
||||
if (vfs || !(*mode == 'w' || *mode == 'a'))
|
||||
return vfs;
|
||||
|
@ -2793,7 +2822,7 @@ Sets com_gamedir, adds the directory to the head of the path,
|
|||
then loads and adds pak1.pak pak2.pak ...
|
||||
================
|
||||
*/
|
||||
static void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, const char *dir, unsigned int loadstuff, unsigned int flags)
|
||||
static searchpath_t *FS_AddSingleGameDirectory (searchpath_t **oldpaths, const char *puredir, const char *dir, unsigned int loadstuff, unsigned int flags)
|
||||
{
|
||||
unsigned int keptflags;
|
||||
searchpath_t *search;
|
||||
|
@ -2808,7 +2837,7 @@ static void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, c
|
|||
if (!Q_strcasecmp(search->logicalpath, dir))
|
||||
{
|
||||
search->flags |= flags & SPF_WRITABLE;
|
||||
return; //already loaded (base paths?)
|
||||
return search; //already loaded (base paths?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2831,7 +2860,20 @@ static void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, c
|
|||
if (!handle)
|
||||
handle = VFSOS_OpenPath(NULL, NULL, dir, dir, "");
|
||||
|
||||
FS_AddPathHandle(oldpaths, puredir, dir, handle, "", flags|keptflags, loadstuff);
|
||||
return FS_AddPathHandle(oldpaths, puredir, dir, handle, "", flags|keptflags, loadstuff);
|
||||
}
|
||||
static void FS_AddGameDirectory (searchpath_t **oldpaths, const char *puredir, unsigned int loadstuff, unsigned int flags)
|
||||
{
|
||||
char syspath[MAX_OSPATH];
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, puredir);
|
||||
gameonly_gamedir = FS_AddSingleGameDirectory(oldpaths, puredir, syspath, loadstuff, flags&~(com_homepathenabled?SPF_WRITABLE:0u));
|
||||
if (com_homepathenabled)
|
||||
{
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, puredir);
|
||||
gameonly_homedir = FS_AddSingleGameDirectory(oldpaths, puredir, syspath, loadstuff, flags);
|
||||
}
|
||||
else
|
||||
gameonly_homedir = NULL;
|
||||
}
|
||||
|
||||
//if syspath, something like c:\quake\baseq2
|
||||
|
@ -3698,7 +3740,6 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
searchpath_t *next;
|
||||
int i;
|
||||
int orderkey;
|
||||
char syspath[MAX_OSPATH];
|
||||
|
||||
COM_AssertMainThread("FS_ReloadPackFilesFlags");
|
||||
COM_WorkerFullSync();
|
||||
|
@ -3715,6 +3756,7 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
com_searchpaths = NULL;
|
||||
com_purepaths = NULL;
|
||||
com_base_searchpaths = NULL;
|
||||
gameonly_gamedir = gameonly_homedir = NULL;
|
||||
|
||||
i = COM_CheckParm ("-basepack");
|
||||
while (i && i < com_argc-1)
|
||||
|
@ -3777,23 +3819,11 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
else if (*dir == '*')
|
||||
{
|
||||
//paths with a leading * are private, and not announced to clients that ask what the current gamedir is.
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir+1);
|
||||
FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|(com_homepathenabled?0:SPF_WRITABLE));
|
||||
if (com_homepathenabled)
|
||||
{
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir+1);
|
||||
FS_AddGameDirectory(&oldpaths, dir+1, syspath, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|SPF_WRITABLE);
|
||||
}
|
||||
FS_AddGameDirectory(&oldpaths, dir+1, reloadflags, SPF_EXPLICIT|SPF_PRIVATE|SPF_WRITABLE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_gamepath, dir);
|
||||
FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT|(com_homepathenabled?0:SPF_WRITABLE));
|
||||
if (com_homepathenabled)
|
||||
{
|
||||
Q_snprintfz(syspath, sizeof(syspath), "%s%s", com_homepath, dir);
|
||||
FS_AddGameDirectory(&oldpaths, dir, syspath, reloadflags, SPF_EXPLICIT|SPF_WRITABLE);
|
||||
}
|
||||
FS_AddGameDirectory(&oldpaths, dir, reloadflags, SPF_EXPLICIT|SPF_WRITABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3823,9 +3853,7 @@ static void FS_ReloadPackFilesFlags(unsigned int reloadflags)
|
|||
}
|
||||
else
|
||||
{
|
||||
FS_AddGameDirectory(&oldpaths, dir, va("%s%s", com_gamepath, dir), reloadflags, SPF_EXPLICIT|(com_homepathenabled?0:SPF_WRITABLE));
|
||||
if (com_homepathenabled)
|
||||
FS_AddGameDirectory(&oldpaths, dir, va("%s%s", com_homepath, dir), reloadflags, SPF_EXPLICIT|SPF_WRITABLE);
|
||||
FS_AddGameDirectory(&oldpaths, dir, reloadflags, SPF_EXPLICIT|SPF_WRITABLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6330,7 +6358,6 @@ static void COM_InitHomedir(ftemanifest_t *man)
|
|||
//but if it doesn't exist then we use $XDG_DATA_HOME/.fte instead
|
||||
//we used to use $HOME/.#HOMESUBDIR/ but this is now only used if it actually exists AND the new path doesn't.
|
||||
//new installs use $XDG_DATA_HOME/#HOMESUBDIR/ instead
|
||||
|
||||
char *ev = getenv("FTEHOME");
|
||||
if (ev && *ev)
|
||||
{
|
||||
|
|
|
@ -49,9 +49,9 @@ struct searchpathfuncs_s
|
|||
qboolean (QDECL *PollChanges)(searchpathfuncs_t *handle); //returns true if there were changes
|
||||
|
||||
qboolean (QDECL *FileStat)(searchpathfuncs_t *handle, flocation_t *loc, time_t *mtime);
|
||||
qboolean (QDECL *RenameFile)(searchpathfuncs_t *handle, const char *oldname, const char *newname); //returns true on success, false if source doesn't exist, or if dest does.
|
||||
qboolean (QDECL *CreateFile)(searchpathfuncs_t *handle, flocation_t *loc, const char *filename); //like FindFile, but returns a usable loc even if the file does not exist yet (may also create requisite directories too)
|
||||
qboolean (QDECL *RenameFile)(searchpathfuncs_t *handle, const char *oldname, const char *newname); //returns true on success, false if source doesn't exist, or if dest does (cached locs may refer to either new or old name).
|
||||
qboolean (QDECL *RemoveFile)(searchpathfuncs_t *handle, const char *filename); //returns true on success, false if it wasn't found or is readonly.
|
||||
qboolean (QDECL *MkDir)(searchpathfuncs_t *handle, const char *filename); //is this really needed?
|
||||
};
|
||||
//searchpathfuncs_t *(QDECL *OpenNew)(vfsfile_t *file, const char *desc); //returns a handle to a new pak/path
|
||||
|
||||
|
@ -87,7 +87,7 @@ int FS_EnumerateKnownGames(qboolean (*callback)(void *usr, ftemanifest_t *man),
|
|||
#define SPF_TEMPORARY 4 //a map-specific path, purged at map change.
|
||||
#define SPF_EXPLICIT 8 //a root gamedir (bumps depth on gamedir depth checks).
|
||||
#define SPF_UNTRUSTED 16 //has been downloaded from somewhere. configs inside it should never be execed with local access rights.
|
||||
#define SPF_PRIVATE 32 //private to the client. ie: the fte dir.
|
||||
#define SPF_PRIVATE 32 //private to the client. ie: the fte dir. name is not networked.
|
||||
#define SPF_WRITABLE 64 //safe to write here. lots of weird rules etc.
|
||||
#define SPF_BASEPATH 128 //part of the basegames, and not the mod gamedir(s).
|
||||
qboolean FS_LoadPackageFromFile(vfsfile_t *vfs, char *pname, char *localname, int *crc, unsigned int flags);
|
||||
|
|
|
@ -271,6 +271,30 @@ static void QDECL FSSTDIO_BuildHash(searchpathfuncs_t *handle, int depth, void (
|
|||
sp->AddFileHash = AddFileHash;
|
||||
Sys_EnumerateFiles(sp->rootpath, "*", FSSTDIO_RebuildFSHash, AddFileHash, handle);
|
||||
}
|
||||
|
||||
static unsigned int QDECL FSSTDIO_CreateLoc(searchpathfuncs_t *handle, flocation_t *loc, const char *filename)
|
||||
{
|
||||
stdiopath_t *sp = (void*)handle;
|
||||
char *ofs;
|
||||
|
||||
loc->len = 0;
|
||||
loc->offset = 0;
|
||||
loc->fhandle = handle;
|
||||
if ((unsigned int)snprintf(loc->rawname, sizeof(loc->rawname), "%s/%s", sp->rootpath, filename) > sizeof(loc->rawname)-1)
|
||||
return FF_NOTFOUND; //too long...
|
||||
|
||||
for (ofs = loc->rawname+1 ; *ofs ; ofs++)
|
||||
{
|
||||
if (*ofs == '/')
|
||||
{ // create the directory
|
||||
*ofs = 0;
|
||||
Sys_mkdir (loc->rawname);
|
||||
*ofs = '/';
|
||||
}
|
||||
}
|
||||
|
||||
return FF_FOUND;
|
||||
}
|
||||
static unsigned int QDECL FSSTDIO_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult)
|
||||
{
|
||||
stdiopath_t *sp = (void*)handle;
|
||||
|
@ -289,7 +313,8 @@ static unsigned int QDECL FSSTDIO_FLocate(searchpathfuncs_t *handle, flocation_t
|
|||
*/
|
||||
|
||||
// check a file in the directory tree
|
||||
snprintf (netpath, sizeof(netpath)-1, "%s/%s", sp->rootpath, filename);
|
||||
if ((unsigned int)snprintf (netpath, sizeof(netpath), "%s/%s", sp->rootpath, filename) > sizeof(netpath)-1)
|
||||
return FF_NOTFOUND;
|
||||
|
||||
#ifdef ANDROID
|
||||
{
|
||||
|
@ -378,6 +403,7 @@ searchpathfuncs_t *QDECL FSSTDIO_OpenPath(vfsfile_t *mustbenull, searchpathfuncs
|
|||
np->pub.OpenVFS = FSSTDIO_OpenVFS;
|
||||
np->pub.PollChanges = FSSTDIO_PollChanges;
|
||||
np->pub.FileStat = FSSTDIO_FileStat;
|
||||
np->pub.CreateFile = FSSTDIO_CreateLoc;
|
||||
return &np->pub;
|
||||
}
|
||||
|
||||
|
|
|
@ -522,6 +522,30 @@ static void QDECL VFSW32_BuildHash(searchpathfuncs_t *handle, int hashdepth, voi
|
|||
wp->hashdepth = hashdepth;
|
||||
Sys_EnumerateFiles(wp->rootpath, "*", VFSW32_RebuildFSHash, AddFileHash, handle);
|
||||
}
|
||||
static unsigned int QDECL VFSW32_CreateLoc(searchpathfuncs_t *handle, flocation_t *loc, const char *filename)
|
||||
{
|
||||
vfsw32path_t *wp = (void*)handle;
|
||||
char *ofs;
|
||||
|
||||
loc->len = 0;
|
||||
loc->offset = 0;
|
||||
loc->fhandle = handle;
|
||||
loc->rawname[sizeof(loc->rawname)-1] = 0;
|
||||
if ((unsigned int)snprintf (loc->rawname, sizeof(loc->rawname), "%s/%s", wp->rootpath, filename) > sizeof(loc->rawname)-1)
|
||||
return FF_NOTFOUND;
|
||||
for (ofs = loc->rawname+1 ; *ofs ; ofs++)
|
||||
{
|
||||
if (*ofs == '/')
|
||||
{ // create the directory
|
||||
*ofs = 0;
|
||||
Sys_mkdir (loc->rawname);
|
||||
*ofs = '/';
|
||||
}
|
||||
}
|
||||
|
||||
return FF_FOUND;
|
||||
}
|
||||
|
||||
#include <errno.h>
|
||||
static unsigned int QDECL VFSW32_FLocate(searchpathfuncs_t *handle, flocation_t *loc, const char *filename, void *hashedresult)
|
||||
{
|
||||
|
@ -545,7 +569,8 @@ static unsigned int QDECL VFSW32_FLocate(searchpathfuncs_t *handle, flocation_t
|
|||
*/
|
||||
|
||||
// check a file in the directory tree
|
||||
snprintf (netpath, sizeof(netpath)-1, "%s/%s", wp->rootpath, filename);
|
||||
if ((unsigned int)snprintf (netpath, sizeof(netpath), "%s/%s", wp->rootpath, filename) > sizeof(loc->rawname)-1)
|
||||
return FF_NOTFOUND;
|
||||
|
||||
if (!WinNT)
|
||||
{
|
||||
|
@ -634,16 +659,6 @@ static qboolean QDECL VFSW32_RemoveFile(searchpathfuncs_t *handle, const char *f
|
|||
snprintf (syspath, sizeof(syspath)-1, "%s/%s", wp->rootpath, filename);
|
||||
return Sys_remove(syspath);
|
||||
}
|
||||
static qboolean QDECL VFSW32_MkDir(searchpathfuncs_t *handle, const char *filename)
|
||||
{
|
||||
vfsw32path_t *wp = (vfsw32path_t*)handle;
|
||||
char syspath[MAX_OSPATH];
|
||||
if (fs_readonly)
|
||||
return false;
|
||||
snprintf (syspath, sizeof(syspath)-1, "%s/%s", wp->rootpath, filename);
|
||||
Sys_mkdir(syspath);
|
||||
return true;
|
||||
}
|
||||
|
||||
searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, searchpathfuncs_t *parent, const char *filename, const char *desc, const char *prefix)
|
||||
{
|
||||
|
@ -675,9 +690,10 @@ searchpathfuncs_t *QDECL VFSW32_OpenPath(vfsfile_t *mustbenull, searchpathfuncs_
|
|||
|
||||
np->pub.FileStat = VFSW32_FileStat;
|
||||
|
||||
#undef CreateFile //stoopid windows.h
|
||||
np->pub.CreateFile = VFSW32_CreateLoc;
|
||||
np->pub.RenameFile = VFSW32_RenameFile;
|
||||
np->pub.RemoveFile = VFSW32_RemoveFile;
|
||||
np->pub.MkDir = VFSW32_MkDir;
|
||||
|
||||
return &np->pub;
|
||||
}
|
||||
|
|
|
@ -313,7 +313,8 @@ typedef struct
|
|||
{
|
||||
struct
|
||||
{
|
||||
int cp[2];
|
||||
unsigned short cp[2];
|
||||
unsigned short fixedres[2];
|
||||
} patch;
|
||||
struct
|
||||
{
|
||||
|
@ -527,7 +528,7 @@ static int Patch_FlatnessTest( float maxflat2, const float *point0, const float
|
|||
Patch_GetFlatness
|
||||
===============
|
||||
*/
|
||||
static void Patch_GetFlatness( float maxflat, const float *points, int comp, const int *patch_cp, int *flat )
|
||||
static void Patch_GetFlatness( float maxflat, const float *points, int comp, const unsigned short *patch_cp, int *flat )
|
||||
{
|
||||
int i, p, u, v;
|
||||
float maxflat2 = maxflat * maxflat;
|
||||
|
@ -579,7 +580,7 @@ static void Patch_Evaluate_QuadricBezier( float t, const vec_t *point0, const ve
|
|||
Patch_Evaluate
|
||||
===============
|
||||
*/
|
||||
static void Patch_Evaluate( const vec_t *p, const int *numcp, const int *tess, vec_t *dest, int comp )
|
||||
static void Patch_Evaluate( const vec_t *p, const unsigned short *numcp, const int *tess, vec_t *dest, int comp )
|
||||
{
|
||||
int num_patches[2], num_tess[2];
|
||||
int index[3], dstpitch, i, u, v, x, y;
|
||||
|
@ -850,7 +851,7 @@ static int CM_CreateFacetFromPoints(q2cbrush_t *facet, vec3_t *verts, int numver
|
|||
/*
|
||||
* CM_CreatePatch
|
||||
*/
|
||||
static void CM_CreatePatch(model_t *loadmodel, q3cpatch_t *patch, q2mapsurface_t *shaderref, const vec_t *verts, const int *patch_cp )
|
||||
static void CM_CreatePatch(model_t *loadmodel, q3cpatch_t *patch, q2mapsurface_t *shaderref, const vec_t *verts, const unsigned short *patch_cp, const unsigned short *patch_subdiv)
|
||||
{
|
||||
int step[2], size[2], flat[2];
|
||||
int i, j, k ,u, v;
|
||||
|
@ -1088,7 +1089,7 @@ static qboolean CM_CreatePatchForFace (model_t *loadmodel, cminfo_t *prv, mleaf_
|
|||
checkout[facenum] = prv->numpatches++;
|
||||
|
||||
//gcc warns without this cast
|
||||
CM_CreatePatch (loadmodel, patch, surf, (const vec_t *)(prv->verts + face->firstvert), face->patch.cp );
|
||||
CM_CreatePatch (loadmodel, patch, surf, (const vec_t *)(prv->verts + face->firstvert), face->patch.cp, face->patch.fixedres );
|
||||
}
|
||||
leaf->contents |= patch->surface->c.value;
|
||||
leaf->numleafpatches++;
|
||||
|
@ -2554,8 +2555,12 @@ static qboolean CModRBSP_LoadFaces (model_t *mod, qbyte *mod_base, lump_t *l)
|
|||
|
||||
if (out->facetype == MST_PATCH)
|
||||
{
|
||||
out->patch.cp[0] = LittleLong ( in->patchwidth );
|
||||
out->patch.cp[1] = LittleLong ( in->patchheight );
|
||||
unsigned int w = LittleLong ( in->patchwidth );
|
||||
unsigned int h = LittleLong ( in->patchheight );
|
||||
out->patch.cp[0] = w&0xffff;
|
||||
out->patch.cp[1] = h&0xffff;
|
||||
out->patch.fixedres[0]=w>>16;
|
||||
out->patch.fixedres[1]=h>>16;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2658,11 +2663,12 @@ static index_t tempIndexesArray[MAX_ARRAY_VERTS*6];
|
|||
|
||||
static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert, cminfo_t *prv)
|
||||
{
|
||||
int patch_cp[2], step[2], size[2], flat[2];
|
||||
unsigned short patch_cp[2];
|
||||
int step[2], size[2], flat[2];
|
||||
float subdivlevel;
|
||||
|
||||
patch_cp[0] = patchwidth;
|
||||
patch_cp[1] = patchheight;
|
||||
patch_cp[0] = patchwidth&0xffff;
|
||||
patch_cp[1] = patchheight&0xffff;
|
||||
|
||||
if (patch_cp[0] <= 0 || patch_cp[1] <= 0 )
|
||||
{
|
||||
|
@ -2692,13 +2698,14 @@ static void GL_SizePatch(mesh_t *mesh, int patchwidth, int patchheight, int numv
|
|||
static void GL_CreateMeshForPatch (model_t *mod, mesh_t *mesh, int patchwidth, int patchheight, int numverts, int firstvert)
|
||||
{
|
||||
cminfo_t *prv = (cminfo_t*)mod->meshinfo;
|
||||
int numindexes, patch_cp[2], step[2], size[2], flat[2], i, u, v, p;
|
||||
int numindexes, step[2], size[2], flat[2], i, u, v, p;
|
||||
unsigned short patch_cp[2];
|
||||
index_t *indexes;
|
||||
float subdivlevel;
|
||||
int sty;
|
||||
|
||||
patch_cp[0] = patchwidth;
|
||||
patch_cp[1] = patchheight;
|
||||
patch_cp[0] = patchwidth&0xffff;
|
||||
patch_cp[1] = patchheight&0xffff;
|
||||
|
||||
if (patch_cp[0] <= 0 || patch_cp[1] <= 0 )
|
||||
{
|
||||
|
|
|
@ -209,9 +209,10 @@ typedef struct
|
|||
float nqreliable_resendtime;//force nqreliable_allowed, thereby forcing a resend of anything n
|
||||
qbyte nqunreliableonly; //nq can't cope with certain reliables some times. if 2, we have a reliable that result in a block (that should be sent). if 1, we are blocking. if 0, we can send reliables freely. if 3, then we just want to ignore clc_moves
|
||||
#endif
|
||||
qboolean pext_fragmentation; //fte's packet fragmentation extension, to avoid issues with low mtus.
|
||||
struct netprim_s netprim;
|
||||
int fragmentsize;
|
||||
int dupe;
|
||||
int mtu; //the path mtu, if known
|
||||
int dupe; //how many times to dupe packets
|
||||
|
||||
float last_received; // for timeouts
|
||||
|
||||
|
|
|
@ -692,7 +692,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
if (chan->message.overflowed)
|
||||
{
|
||||
chan->fatal_error = true;
|
||||
Con_TPrintf ("%s:Outgoing message overflow\n"
|
||||
Con_TPrintf ("%s: Outgoing message overflow\n"
|
||||
, NET_AdrToString (remote_adr, sizeof(remote_adr), &chan->remote_address));
|
||||
return 0;
|
||||
}
|
||||
|
@ -716,7 +716,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
|
||||
// write the packet header
|
||||
send.data = send_buf;
|
||||
send.maxsize = MAX_QWMSGLEN + PACKET_HEADER;
|
||||
send.maxsize = (chan->mtu?chan->mtu:MAX_QWMSGLEN) + PACKET_HEADER;
|
||||
send.cursize = 0;
|
||||
|
||||
w1 = chan->outgoing_sequence | (send_reliable<<31);
|
||||
|
@ -738,9 +738,9 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (chan->fragmentsize)
|
||||
if (chan->pext_fragmentation)
|
||||
{
|
||||
//allow the max size to be bigger
|
||||
//allow the max size to be bigger, sending everything available
|
||||
send.maxsize = MAX_OVERALLMSGLEN + PACKET_HEADER;
|
||||
MSG_WriteShort(&send, 0);
|
||||
}
|
||||
|
@ -748,6 +748,17 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
// copy the reliable message to the packet first
|
||||
if (send_reliable)
|
||||
{
|
||||
if (send.maxsize - send.cursize < chan->reliable_length)
|
||||
{
|
||||
if (!chan->fatal_error)
|
||||
{
|
||||
chan->fatal_error = true;
|
||||
Con_TPrintf ("%s: Path MTU is lower than %u\n"
|
||||
, NET_AdrToString (remote_adr, sizeof(remote_adr), &chan->remote_address), chan->reliable_length);
|
||||
}
|
||||
chan->outgoing_sequence--;
|
||||
return 0;
|
||||
}
|
||||
SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
|
||||
chan->last_reliable_sequence = chan->outgoing_sequence;
|
||||
}
|
||||
|
@ -765,7 +776,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
if (chan->compresstable)
|
||||
{
|
||||
//int oldsize = send.cursize;
|
||||
Huff_CompressPacket(chan->compresstable, &send, 8 + ((chan->sock == NS_CLIENT)?2:0) + (chan->fragmentsize?2:0));
|
||||
Huff_CompressPacket(chan->compresstable, &send, 8 + ((chan->sock == NS_CLIENT)?2:0) + (chan->pext_fragmentation?2:0));
|
||||
// Con_Printf("%i becomes %i\n", oldsize, send.cursize);
|
||||
// Huff_DecompressPacket(&send, (chan->sock == NS_CLIENT)?10:8);
|
||||
}
|
||||
|
@ -779,20 +790,23 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
{
|
||||
int hsz = 10 + ((chan->sock == NS_CLIENT)?chan->qportsize:0); /*header size, if fragmentation is in use*/
|
||||
|
||||
if ((!chan->fragmentsize))// || send.cursize < ((chan->fragmentsize - hsz)&~7))
|
||||
{
|
||||
if ((!chan->pext_fragmentation))// || send.cursize < ((chan->mtu - hsz)&~7))
|
||||
{ //vanilla sends
|
||||
for (i = -1; i < chan->dupe && e == NETERR_SENT; i++)
|
||||
e = NET_SendPacket (chan->sock, send.cursize, send.data, &chan->remote_address);
|
||||
send.cursize += send.cursize * i;
|
||||
|
||||
if (e == NETERR_MTU && chan->fragmentsize > 560)
|
||||
//ipv4 'guarentees' mtu sizes of at least 560ish.
|
||||
//our reliable/backbuf messages are limited to 1024 bytes.
|
||||
//this means that large reliables may be unsendable.
|
||||
if (e == NETERR_MTU && chan->mtu > 560)
|
||||
{
|
||||
Con_Printf("Reducing MSS to %i\n", chan->fragmentsize);
|
||||
chan->fragmentsize -= 10;
|
||||
Con_Printf("Reducing MSS to %i\n", chan->mtu);
|
||||
chan->mtu -= 10;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{ //fte's fragmentaton protocol
|
||||
int offset = 0, no;
|
||||
qboolean more;
|
||||
|
||||
|
@ -801,7 +815,7 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
/*send the additional parts, adding new headers within the previous packet*/
|
||||
do
|
||||
{
|
||||
no = offset + chan->fragmentsize - hsz;
|
||||
no = offset + chan->mtu - hsz;
|
||||
if (no < send.cursize-hsz)
|
||||
{
|
||||
no &= ~7;
|
||||
|
@ -831,10 +845,10 @@ int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate)
|
|||
for (i = -1; i < chan->dupe && e == NETERR_SENT; i++)
|
||||
{
|
||||
e = NET_SendPacket (chan->sock, (no - offset) + hsz, send.data + offset, &chan->remote_address);
|
||||
if (e == NETERR_MTU && !offset && chan->fragmentsize > 560)
|
||||
if (e == NETERR_MTU && !offset && chan->mtu > 560)
|
||||
{
|
||||
chan->fragmentsize -= 16;
|
||||
Con_Printf("Reducing MSS to %i\n", chan->fragmentsize);
|
||||
chan->mtu -= 16;
|
||||
Con_Printf("Reducing MSS to %i\n", chan->mtu);
|
||||
no = offset;
|
||||
more = true;
|
||||
break;
|
||||
|
@ -917,7 +931,7 @@ qboolean Netchan_Process (netchan_t *chan)
|
|||
MSG_ReadShort ();
|
||||
#endif
|
||||
|
||||
if (chan->fragmentsize)
|
||||
if (chan->pext_fragmentation)
|
||||
offset = (unsigned short)MSG_ReadShort();
|
||||
else
|
||||
offset = 0;
|
||||
|
|
|
@ -101,9 +101,9 @@ FTE_ALIGN(4) qbyte net_message_buffer[MAX_OVERALLMSGLEN];
|
|||
#define HAVE_NATPMP
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SERVER) || defined(MASTERONLY)
|
||||
#define HAVE_HTTPSV
|
||||
#endif
|
||||
//#if !defined(HAVE_SERVER) && !defined(MASTERONLY)
|
||||
// #undef HAVE_HTTPSV
|
||||
//#endif
|
||||
|
||||
void NET_GetLocalAddress (int socket, netadr_t *out);
|
||||
//int TCP_OpenListenSocket (const char *localip, int port);
|
||||
|
@ -127,6 +127,7 @@ cvar_t net_enable_qtv = CVARD("net_enable_qtv", "1", "Listens for qtv proxie
|
|||
#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 HAVE_HTTPSV
|
||||
#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
|
||||
|
@ -135,6 +136,7 @@ cvar_t net_enable_http = CVARD("net_enable_http", "0", "If enabled, tcp port
|
|||
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
|
||||
#endif
|
||||
#if defined(HAVE_DTLS) && defined(HAVE_SERVER)
|
||||
static void QDECL NET_Enable_DTLS_Changed(struct cvar_s *var, char *oldvalue)
|
||||
{
|
||||
|
@ -3693,10 +3695,10 @@ typedef struct ftenet_tcpconnect_stream_s {
|
|||
{
|
||||
TCPC_UNKNOWN, //waiting to see what they send us.
|
||||
TCPC_QIZMO, //'qizmo\n' handshake, followed by packets prefixed with a 16bit packet length.
|
||||
#ifdef HAVE_HTTPSV
|
||||
TCPC_WEBSOCKETU, //utf-8 encoded data.
|
||||
TCPC_WEBSOCKETB, //binary encoded data (subprotocol = 'binary')
|
||||
TCPC_WEBSOCKETNQ, //raw nq msg buffers with no encapsulation or handshake
|
||||
#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.
|
||||
|
@ -4718,8 +4720,8 @@ qboolean FTENET_TCP_ParseHTTPRequest(ftenet_tcpconnect_connection_t *con, ftenet
|
|||
return FTENET_TCPConnect_HTTPResponse(st, arg, acceptsgzip);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_SSL
|
||||
#endif
|
||||
#if defined(HAVE_SSL) && (defined(HAVE_SERVER) || defined(HAVE_HTTPSV))
|
||||
static int QDECL TLSPromoteRead (struct vfsfile_s *file, void *buffer, int bytestoread)
|
||||
{
|
||||
if (bytestoread > net_message.cursize)
|
||||
|
@ -4730,7 +4732,6 @@ static int QDECL TLSPromoteRead (struct vfsfile_s *file, void *buffer, int bytes
|
|||
return bytestoread;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
void FTENET_TCPConnect_PrintStatus(ftenet_generic_connection_t *gcon)
|
||||
{
|
||||
ftenet_tcpconnect_connection_t *con = (ftenet_tcpconnect_connection_t*)gcon;
|
||||
|
@ -4749,12 +4750,12 @@ void FTENET_TCPConnect_PrintStatus(ftenet_generic_connection_t *gcon)
|
|||
case TCPC_QIZMO:
|
||||
Con_Printf("qizmo %s\n", adr);
|
||||
break;
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_WEBSOCKETU:
|
||||
case TCPC_WEBSOCKETB:
|
||||
case TCPC_WEBSOCKETNQ:
|
||||
Con_Printf("websocket %s\n", adr);
|
||||
break;
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_HTTPCLIENT:
|
||||
Con_Printf("http %s\n", adr);
|
||||
break;
|
||||
|
@ -5011,13 +5012,12 @@ closesvstream:
|
|||
net_from = st->remoteaddr;
|
||||
|
||||
return true;
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_WEBSOCKETU:
|
||||
case TCPC_WEBSOCKETB:
|
||||
case TCPC_WEBSOCKETNQ:
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_WEBRTC_HOST:
|
||||
case TCPC_WEBRTC_CLIENT:
|
||||
#endif
|
||||
while (st->inlen >= 2)
|
||||
{
|
||||
unsigned short ctrl = ((unsigned char*)st->inbuffer)[0]<<8 | ((unsigned char*)st->inbuffer)[1];
|
||||
|
@ -5164,7 +5164,6 @@ closesvstream:
|
|||
Con_TPrintf ("Warning: Oversize packet from %s\n", NET_AdrToString (adr, sizeof(adr), &st->remoteaddr));
|
||||
goto closesvstream;
|
||||
}
|
||||
#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.
|
||||
|
@ -5203,7 +5202,6 @@ closesvstream:
|
|||
net_message.cursize = 0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
#ifdef NQPROT
|
||||
if (st->clienttype == TCPC_WEBSOCKETNQ)
|
||||
{ //hack in an 8-byte header
|
||||
|
@ -5248,6 +5246,7 @@ closesvstream:
|
|||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5298,7 +5297,6 @@ closesvstream:
|
|||
|
||||
neterr_t FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, const void *data, netadr_t *to)
|
||||
{
|
||||
neterr_t e;
|
||||
ftenet_tcpconnect_connection_t *con = (ftenet_tcpconnect_connection_t*)gcon;
|
||||
ftenet_tcpconnect_stream_t *st;
|
||||
|
||||
|
@ -5333,6 +5331,7 @@ neterr_t FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int len
|
|||
}
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_HTTPSV
|
||||
case TCPC_WEBSOCKETNQ:
|
||||
if (length < 8 || ((char*)data)[0] & 0x80)
|
||||
break;
|
||||
|
@ -5344,10 +5343,13 @@ neterr_t FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int len
|
|||
//fallthrough
|
||||
case TCPC_WEBSOCKETU:
|
||||
case TCPC_WEBSOCKETB:
|
||||
e = FTENET_TCPConnect_WebSocket_Splurge(st, (st->clienttype==TCPC_WEBSOCKETU)?1:2, data, length);
|
||||
if (e != NETERR_SENT)
|
||||
return e;
|
||||
{
|
||||
neterr_t e = FTENET_TCPConnect_WebSocket_Splurge(st, (st->clienttype==TCPC_WEBSOCKETU)?1:2, data, length);
|
||||
if (e != NETERR_SENT)
|
||||
return e;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -7877,10 +7879,12 @@ void NET_Init (void)
|
|||
#if defined(HAVE_SSL)
|
||||
Cvar_Register(&net_enable_tls, "networking");
|
||||
#endif
|
||||
#ifdef HAVE_HTTPSV
|
||||
Cvar_Register(&net_enable_http, "networking");
|
||||
Cvar_Register(&net_enable_websockets, "networking");
|
||||
Cvar_Register(&net_enable_webrtcbroker, "networking");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ void Plug_RegisterBuiltin(char *name, Plug_Builtin_t bi, int flags)
|
|||
}
|
||||
|
||||
//got an empty number.
|
||||
Con_DPrintf("%s: %i\n", name, newnum);
|
||||
Con_DLPrintf(2, "%s: %i\n", name, newnum);
|
||||
plugbuiltins[newnum].name = name;
|
||||
plugbuiltins[newnum].func = bi;
|
||||
plugbuiltins[newnum].flags = flags;
|
||||
|
|
|
@ -364,7 +364,9 @@ pubsubserver_t *Sys_ForkServer(void)
|
|||
//make sure we're fully synced, so that workers can't mess up
|
||||
Cvar_Set(Cvar_FindVar("worker_count"), "0");
|
||||
COM_WorkerFullSync();
|
||||
#ifdef WEBCLIENT
|
||||
DL_DeThread();
|
||||
#endif
|
||||
#ifdef SQL
|
||||
SQL_KillServers(); //FIXME: this is bad...
|
||||
#endif
|
||||
|
|
|
@ -52,11 +52,11 @@ qbyte sentinalkey;
|
|||
|
||||
#define TAGLESS 1
|
||||
|
||||
int zmemtotal;
|
||||
int zmemdelta;
|
||||
size_t zmemtotal;
|
||||
size_t zmemdelta;
|
||||
|
||||
typedef struct memheader_s {
|
||||
int size;
|
||||
size_t size;
|
||||
int tag;
|
||||
} memheader_t;
|
||||
|
||||
|
@ -108,13 +108,13 @@ static void Z_DumpTree(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
void *VARGS Z_TagMalloc(int size, int tag)
|
||||
void *Z_TagMalloc(size_t size, int tag)
|
||||
{
|
||||
zone_t *zone;
|
||||
|
||||
zone = (zone_t *)malloc(size + sizeof(zone_t));
|
||||
if (!zone)
|
||||
Sys_Error("Z_Malloc: Failed on allocation of %i bytes", size);
|
||||
Sys_Error("Z_Malloc: Failed on allocation of %"PRIuSIZE" bytes", size);
|
||||
Q_memset(zone, 0, size + sizeof(zone_t));
|
||||
zone->mh.tag = tag;
|
||||
zone->mh.size = size;
|
||||
|
@ -184,7 +184,7 @@ void *Z_MallocNamed(int size, char *file, int line)
|
|||
return mem;
|
||||
}
|
||||
#else
|
||||
void *ZF_Malloc(int size)
|
||||
void *ZF_Malloc(size_t size)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
void *ret = NULL;
|
||||
|
@ -202,11 +202,11 @@ void *ZF_Malloc(int size)
|
|||
return calloc(size, 1);
|
||||
#endif
|
||||
}
|
||||
void *Z_Malloc(int size)
|
||||
void *Z_Malloc(size_t size)
|
||||
{
|
||||
void *mem = ZF_Malloc(size);
|
||||
if (!mem)
|
||||
Sys_Error("Z_Malloc: Failed on allocation of %i bytes", size);
|
||||
Sys_Error("Z_Malloc: Failed on allocation of %"PRIuSIZE" bytes", size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ void *BZF_MallocNamed(int size, const char *file, int line) //BZ_MallocNamed but
|
|||
return mem;
|
||||
}
|
||||
#else
|
||||
void *BZF_Malloc(int size) //BZ_Malloc but allowed to fail - like straight malloc.
|
||||
void *BZF_Malloc(size_t size) //BZ_Malloc but allowed to fail - like straight malloc.
|
||||
{
|
||||
void *mem;
|
||||
mem = malloc(size);
|
||||
|
@ -446,11 +446,11 @@ void *BZ_MallocNamed(int size, const char *file, int line) //BZ_MallocNamed but
|
|||
return mem;
|
||||
}
|
||||
#else
|
||||
void *BZ_Malloc(int size) //Doesn't clear. The expectation is a large file, rather than sensitive data structures.
|
||||
void *BZ_Malloc(size_t size) //Doesn't clear. The expectation is a large file, rather than sensitive data structures.
|
||||
{
|
||||
void *mem = BZF_Malloc(size);
|
||||
if (!mem)
|
||||
Sys_Error("BZ_Malloc: Failed on allocation of %i bytes", size);
|
||||
Sys_Error("BZ_Malloc: Failed on allocation of %"PRIuSIZE" bytes", size);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
@ -472,17 +472,17 @@ void *BZ_ReallocNamed(void *data, int newsize, const char *file, int line)
|
|||
return mem;
|
||||
}
|
||||
#else
|
||||
void *BZF_Realloc(void *data, int newsize)
|
||||
void *BZF_Realloc(void *data, size_t newsize)
|
||||
{
|
||||
return realloc(data, newsize);
|
||||
}
|
||||
|
||||
void *BZ_Realloc(void *data, int newsize)
|
||||
void *BZ_Realloc(void *data, size_t newsize)
|
||||
{
|
||||
void *mem = BZF_Realloc(data, newsize);
|
||||
|
||||
if (!mem)
|
||||
Sys_Error("BZ_Realloc: Failed on reallocation of %i bytes", newsize);
|
||||
Sys_Error("BZ_Realloc: Failed on reallocation of %"PRIuSIZE" bytes", newsize);
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
@ -508,7 +508,7 @@ typedef struct zonegroupblock_s
|
|||
void *QDECL ZG_Malloc(zonegroup_t *ctx, int size){return ZG_MallocNamed(ctx, size, "ZG_Malloc", size);}
|
||||
void *ZG_MallocNamed(zonegroup_t *ctx, int size, char *file, int line)
|
||||
#else
|
||||
void *QDECL ZG_Malloc(zonegroup_t *ctx, int size)
|
||||
void *QDECL ZG_Malloc(zonegroup_t *ctx, size_t size)
|
||||
#endif
|
||||
{
|
||||
zonegroupblock_t *newm;
|
||||
|
@ -590,7 +590,7 @@ void Hunk_TempFree(void)
|
|||
|
||||
//allocates without clearing previous temp.
|
||||
//safer than my hack that fuh moaned about...
|
||||
void *Hunk_TempAllocMore (int size)
|
||||
void *Hunk_TempAllocMore (size_t size)
|
||||
{
|
||||
void *buf;
|
||||
|
||||
|
@ -624,7 +624,7 @@ void *Hunk_TempAllocMore (int size)
|
|||
}
|
||||
|
||||
|
||||
void *Hunk_TempAlloc (int size)
|
||||
void *Hunk_TempAlloc (size_t size)
|
||||
{
|
||||
Hunk_TempFree();
|
||||
|
||||
|
@ -657,8 +657,8 @@ void Cache_Flush(void)
|
|||
|
||||
static void Hunk_Print_f (void)
|
||||
{
|
||||
Con_Printf("Z Delta: %iKB\n", zmemdelta/1024); zmemdelta = 0;
|
||||
Con_Printf("Z Total: %iKB\n", zmemtotal/1024);
|
||||
Con_Printf("Z Delta: %"PRIuSIZE"KB\n", zmemdelta/1024); zmemdelta = 0;
|
||||
Con_Printf("Z Total: %"PRIuSIZE"KB\n", zmemtotal/1024);
|
||||
//note: Zone memory isn't tracked reliably. we don't track the mem that is freed, so it'll just climb and climb
|
||||
//we don't track reallocs either.
|
||||
|
||||
|
|
|
@ -87,12 +87,12 @@ void Memory_Init (void);
|
|||
void Memory_DeInit(void);
|
||||
|
||||
void VARGS Z_Free (void *ptr);
|
||||
void *Z_Malloc (int size); // returns 0 filled memory
|
||||
void *ZF_Malloc (int size); // allowed to fail
|
||||
void *Z_MallocNamed (int size, char *file, int line); // returns 0 filled memory
|
||||
void *ZF_MallocNamed (int size, char *file, int line); // allowed to fail
|
||||
void *Z_Malloc (size_t size); // returns 0 filled memory
|
||||
void *ZF_Malloc (size_t size); // allowed to fail
|
||||
void *Z_MallocNamed (size_t size, char *file, int line); // returns 0 filled memory
|
||||
void *ZF_MallocNamed (size_t size, char *file, int line); // allowed to fail
|
||||
//#define Z_Malloc(x) Z_MallocNamed2(x, __FILE__, __LINE__ )
|
||||
void *VARGS Z_TagMalloc (int size, int tag);
|
||||
void *Z_TagMalloc (size_t size, int tag);
|
||||
void VARGS Z_TagFree(void *ptr);
|
||||
void VARGS Z_FreeTags(int tag);
|
||||
qboolean ZF_ReallocElements(void **ptr, size_t *elements, size_t newelements, size_t elementsize); //returns false on error
|
||||
|
@ -101,14 +101,14 @@ qboolean ZF_ReallocElementsNamed(void **ptr, size_t *elements, size_t newelement
|
|||
|
||||
//Big Zone: allowed to fail, doesn't clear. The expectation is a large file, rather than sensitive data structures.
|
||||
//(this is a nicer name for malloc)
|
||||
void *BZ_Malloc(int size);
|
||||
void *BZF_Malloc(int size);
|
||||
void *BZ_MallocNamed (int size, const char *file, int line); // returns 0 filled memory
|
||||
void *BZF_MallocNamed (int size, const char *file, int line); // allowed to fail
|
||||
void *BZ_Realloc(void *ptr, int size);
|
||||
void *BZ_ReallocNamed(void *data, int newsize, const char *file, int line);
|
||||
void *BZF_Realloc(void *data, int newsize);
|
||||
void *BZF_ReallocNamed(void *data, int newsize, const char *file, int line);
|
||||
void *BZ_Malloc(size_t size);
|
||||
void *BZF_Malloc(size_t size);
|
||||
void *BZ_MallocNamed (size_t size, const char *file, int line); // returns 0 filled memory
|
||||
void *BZF_MallocNamed (size_t size, const char *file, int line); // allowed to fail
|
||||
void *BZ_Realloc(void *ptr, size_t size);
|
||||
void *BZ_ReallocNamed(void *data, size_t newsize, const char *file, int line);
|
||||
void *BZF_Realloc(void *data, size_t newsize);
|
||||
void *BZF_ReallocNamed(void *data, size_t newsize, const char *file, int line);
|
||||
void BZ_Free(void *ptr);
|
||||
|
||||
//ctx should start off as void*ctx=NULL
|
||||
|
@ -117,8 +117,8 @@ typedef struct zonegroup_s
|
|||
void *first;
|
||||
int bytes;
|
||||
} zonegroup_t;
|
||||
void *QDECL ZG_Malloc(zonegroup_t *ctx, int size);
|
||||
void *ZG_MallocNamed(zonegroup_t *ctx, int size, char *file, int line);
|
||||
void *QDECL ZG_Malloc(zonegroup_t *ctx, size_t size);
|
||||
void *ZG_MallocNamed(zonegroup_t *ctx, size_t size, char *file, int line);
|
||||
void ZG_FreeGroup(zonegroup_t *ctx);
|
||||
|
||||
#ifdef USE_MSVCRT_DEBUG
|
||||
|
@ -141,8 +141,8 @@ void *Hunk_Alloc (int size); // returns 0 filled memory
|
|||
void *Hunk_AllocName (int size, char *name);
|
||||
*/
|
||||
|
||||
void *Hunk_TempAlloc (int size);
|
||||
void *Hunk_TempAllocMore (int size); //Don't clear old temp
|
||||
void *Hunk_TempAlloc (size_t size);
|
||||
void *Hunk_TempAllocMore (size_t size); //Don't clear old temp
|
||||
|
||||
/*
|
||||
typedef struct cache_user_s
|
||||
|
|
|
@ -15,4 +15,5 @@ vid_conwidth "0" //make something up based upon aspect ratio
|
|||
vid_conheight "300" //not using autoscale as it can make the menu unusable.
|
||||
vid_conautoscale "0" // Text/Menu size. 2 is the default. 4 is bigger
|
||||
|
||||
scr_consize 0.4 //android's onscreen keyboard can take up over half the screen (and we don't know exactly where it is).
|
||||
exec touch.cfg
|
||||
|
|
|
@ -4725,6 +4725,20 @@ static void DrawMeshes(void)
|
|||
p = &shaderstate.curshader->passes[passno];
|
||||
passno += p->numMergedPasses;
|
||||
|
||||
if (p->prog)
|
||||
{
|
||||
shaderstate.pendingcolourvbo = shaderstate.sourcevbo->colours[0].gl.vbo;
|
||||
shaderstate.pendingcolourpointer = shaderstate.sourcevbo->colours[0].gl.addr;
|
||||
shaderstate.colourarraytype = shaderstate.sourcevbo->colours_bytes?GL_UNSIGNED_BYTE:GL_FLOAT;
|
||||
|
||||
shaderstate.pendingtexcoordparts[0] = 2;
|
||||
shaderstate.pendingtexcoordvbo[0] = shaderstate.sourcevbo->texcoord.gl.vbo;
|
||||
shaderstate.pendingtexcoordpointer[0] = shaderstate.sourcevbo->texcoord.gl.addr;
|
||||
|
||||
BE_RenderMeshProgram(shaderstate.curshader, p, p->prog);
|
||||
continue;
|
||||
}
|
||||
|
||||
emumode = 0;
|
||||
emumode = (p->shaderbits & SBITS_ATEST_BITS) >> SBITS_ATEST_SHIFT;
|
||||
|
||||
|
|
|
@ -135,11 +135,11 @@ void GL_SetupFormats(void)
|
|||
if (gl_config_gles)
|
||||
{
|
||||
//pre-3 gles doesn't support sized formats, and only a limited number of them too
|
||||
glfmtc(PTI_RGB8, GL_RGB, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, tc_rgb);
|
||||
glfmtc(PTI_RGBA8, GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgba8);
|
||||
glfmt(PTI_L8A8, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
|
||||
glfmt(PTI_L8, GL_LUMINANCE, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);
|
||||
// glfmt(PTI_RGBA8, GL_ALPHA, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
|
||||
glfmtc(PTI_RGB8, 0, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, tc_rgb);
|
||||
glfmtc(PTI_RGBA8, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgba8);
|
||||
glfmt(PTI_L8A8, 0, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
|
||||
glfmt(PTI_L8, 0, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);
|
||||
// glfmt(PTI_A8, 0, GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE);
|
||||
|
||||
if (!gl_config.webgl_ie)
|
||||
{ //these should work on all gles2+webgl1 devices, but microsoft doesn't give a shit.
|
||||
|
@ -754,7 +754,6 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
|
|||
{
|
||||
qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, nummips-1);
|
||||
qglTexParameteri(targ, GL_TEXTURE_LOD_BIAS, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ struct patchvert_s
|
|||
cvar_t mod_terrain_networked = CVARD("mod_terrain_networked", "0", "Terrain edits are networked. Clients will download sections on demand, and servers will notify clients of changes.");
|
||||
cvar_t mod_terrain_defaulttexture = CVARD("mod_terrain_defaulttexture", "", "Newly created terrain tiles will use this texture. This should generally be updated by the terrain editor.");
|
||||
cvar_t mod_terrain_savever = CVARD("mod_terrain_savever", "", "Which terrain section version to write if terrain was edited.");
|
||||
cvar_t mod_terrain_sundir = CVARD("mod_terrain_sundir", "0.4 0.7 2", "The direction of the sun (vector will be normalised).");
|
||||
cvar_t mod_terrain_ambient = CVARD("mod_terrain_ambient", "0.5", "Proportion of ambient light.");
|
||||
cvar_t mod_terrain_shadows = CVARD("mod_terrain_shadows", "0", "Cast rays to determine whether parts of the terrain should be in shadow.");
|
||||
cvar_t mod_terrain_shadow_dist = CVARD("mod_terrain_shadow_dist", "2048", "How far rays should be cast in order to look for occlusing geometry.");
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -81,7 +85,7 @@ void validatelinks2(link_t *firstnode, link_t *panic)
|
|||
|
||||
|
||||
#ifndef SERVERONLY
|
||||
static void ted_dorelight(heightmap_t *hm);
|
||||
static void ted_dorelight(model_t *m, heightmap_t *hm);
|
||||
static void Terr_WorkerLoadedSectionLightmap(void *ctx, void *data, size_t a, size_t b);
|
||||
static qboolean Terr_Collect(heightmap_t *hm);
|
||||
#endif
|
||||
|
@ -1933,6 +1937,18 @@ void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusa
|
|||
if (!s || s->loadstate < TSLS_LOADING2)
|
||||
return;
|
||||
|
||||
{
|
||||
int cx = s->sx/MAXSECTIONS;
|
||||
int cy = s->sy/MAXSECTIONS;
|
||||
hmcluster_t *c = hm->cluster[cx + cy*MAXCLUSTERS];
|
||||
int sx = s->sx & (MAXSECTIONS-1);
|
||||
int sy = s->sy & (MAXSECTIONS-1);
|
||||
|
||||
if (c->section[sx+sy*MAXSECTIONS] != s)
|
||||
Sys_Error("Section %i,%i already destroyed...\n", s->sx, s->sy);
|
||||
c->section[sx+sy*MAXSECTIONS] = NULL;
|
||||
}
|
||||
|
||||
validatelinks(&hm->recycle);
|
||||
|
||||
RemoveLink(&s->recycle);
|
||||
|
@ -1966,10 +1982,16 @@ void Terr_DestroySection(heightmap_t *hm, hmsection_t *s, qboolean lightmapreusa
|
|||
{
|
||||
if (qglDeleteBuffersARB)
|
||||
{
|
||||
qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo);
|
||||
s->vbo.coord.gl.vbo = 0;
|
||||
qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo);
|
||||
s->vbo.indicies.gl.vbo = 0;
|
||||
if (s->vbo.coord.gl.vbo)
|
||||
{
|
||||
qglDeleteBuffersARB(1, &s->vbo.coord.gl.vbo);
|
||||
s->vbo.coord.gl.vbo = 0;
|
||||
}
|
||||
if (s->vbo.indicies.gl.vbo)
|
||||
{
|
||||
qglDeleteBuffersARB(1, &s->vbo.indicies.gl.vbo);
|
||||
s->vbo.indicies.gl.vbo = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2123,8 +2145,6 @@ validatelinks(&hm->recycle);
|
|||
}
|
||||
else
|
||||
{
|
||||
c->section[sx+sy*MAXSECTIONS] = NULL;
|
||||
|
||||
validatelinks(&hm->recycle);
|
||||
Terr_DestroySection(hm, s, lightmapreusable);
|
||||
validatelinks(&hm->recycle);
|
||||
|
@ -2999,7 +3019,7 @@ void Terr_DrawTerrainModel (batch_t **batches, entity_t *e)
|
|||
|
||||
// hm->beinglazy = false;
|
||||
if (hm->relight)
|
||||
ted_dorelight(hm);
|
||||
ted_dorelight(m, hm);
|
||||
|
||||
if (e->model == cl.worldmodel && hm->skyshader)
|
||||
{
|
||||
|
@ -3310,9 +3330,10 @@ unsigned int Heightmap_NativeBoxContents(model_t *model, int hulloverride, frame
|
|||
return Heightmap_PointContentsHM(hm, mins[2], org);
|
||||
}
|
||||
|
||||
void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
|
||||
float Heightmap_Normal(heightmap_t *hm, vec2_t org, vec3_t norm) //returns the z
|
||||
{
|
||||
#if 0
|
||||
float z = 0;
|
||||
norm[0] = 0;
|
||||
norm[1] = 0;
|
||||
norm[2] = 1;
|
||||
|
@ -3322,6 +3343,7 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
|
|||
vec3_t d1, d2;
|
||||
const float wbias = CHUNKBIAS * hm->sectionsize;
|
||||
hmsection_t *s;
|
||||
float z;
|
||||
|
||||
norm[0] = 0;
|
||||
norm[1] = 0;
|
||||
|
@ -3330,12 +3352,12 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
|
|||
sx = (org[0]+wbias)/hm->sectionsize;
|
||||
sy = (org[1]+wbias)/hm->sectionsize;
|
||||
if (sx < hm->firstsegx || sy < hm->firstsegy)
|
||||
return;
|
||||
return hm->defaultgroundheight;
|
||||
if (sx >= hm->maxsegx || sy >= hm->maxsegy)
|
||||
return;
|
||||
return hm->defaultgroundheight;
|
||||
s = Terr_GetSection(hm, sx, sy, TGS_TRYLOAD);
|
||||
if (!s)
|
||||
return;
|
||||
return hm->defaultgroundheight;
|
||||
|
||||
x = (org[0]+wbias - (sx*hm->sectionsize))*(SECTHEIGHTSIZE-1)/hm->sectionsize;
|
||||
y = (org[1]+wbias - (sy*hm->sectionsize))*(SECTHEIGHTSIZE-1)/hm->sectionsize;
|
||||
|
@ -3354,6 +3376,10 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
|
|||
d2[0] = 0;
|
||||
d2[1] = (hm->sectionsize / SECTHEIGHTSIZE);
|
||||
d2[2] = (s->heights[(sx+1)+(sy+1)*SECTHEIGHTSIZE] - s->heights[(sx+1)+(sy+0)*SECTHEIGHTSIZE]);
|
||||
|
||||
z = (s->heights[(sx+0)+(sy+1)*SECTHEIGHTSIZE]*(1-y) +
|
||||
s->heights[(sx+1)+(sy+1)*SECTHEIGHTSIZE]*(x+y-1) +
|
||||
s->heights[(sx+1)+(sy+0)*SECTHEIGHTSIZE]*(1-x));
|
||||
}
|
||||
else
|
||||
{ //the 0,0 triangle
|
||||
|
@ -3366,13 +3392,19 @@ void Heightmap_Normal(heightmap_t *hm, vec3_t org, vec3_t norm)
|
|||
d2[0] = 0;
|
||||
d2[1] = (hm->sectionsize / SECTHEIGHTSIZE);
|
||||
d2[2] = (s->heights[(sx+0)+(sy+1)*SECTHEIGHTSIZE] - s->heights[(sx+0)+(sy+0)*SECTHEIGHTSIZE]);
|
||||
|
||||
z = (s->heights[(sx+0)+(sy+1)*SECTHEIGHTSIZE]*(y) +
|
||||
s->heights[(sx+1)+(sy+0)*SECTHEIGHTSIZE]*(x) +
|
||||
s->heights[(sx+0)+(sy+0)*SECTHEIGHTSIZE]*(1-y-x));
|
||||
}
|
||||
|
||||
|
||||
VectorNormalize(d1);
|
||||
VectorNormalize(d2);
|
||||
CrossProduct(d1, d2, norm);
|
||||
VectorNormalize(norm);
|
||||
#endif
|
||||
return z;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -4244,11 +4276,11 @@ qboolean Heightmap_Trace_Test(struct model_s *model, int hulloverride, framestat
|
|||
qboolean ret = Heightmap_Trace(model, hulloverride, framestate, mataxis, start, end, mins, maxs, capsule, against, trace);
|
||||
|
||||
if (!trace->startsolid)
|
||||
{
|
||||
{ //FIXME: this code should not be needed.
|
||||
trace_t testtrace;
|
||||
Heightmap_Trace(model, hulloverride, framestate, mataxis, trace->endpos, trace->endpos, mins, maxs, capsule, against, &testtrace);
|
||||
if (testtrace.startsolid)
|
||||
{
|
||||
{ //yup, we're bugged.
|
||||
Con_DPrintf("Trace became solid\n");
|
||||
trace->fraction = 0;
|
||||
VectorCopy(start, trace->endpos);
|
||||
|
@ -4370,32 +4402,37 @@ static unsigned char *QDECL Terr_GetLightmap(hmsection_t *s, int idx, qboolean e
|
|||
}
|
||||
return lightmap[s->lightmap]->lightmaps + ((s->lmy+y) * HMLMSTRIDE + (s->lmx+x)) * lightmap[s->lightmap]->pixbytes;
|
||||
}
|
||||
static void ted_dorelight(heightmap_t *hm)
|
||||
static void ted_dorelight(model_t *m, heightmap_t *hm)
|
||||
{
|
||||
unsigned char *lm = Terr_GetLightmap(hm->relight, 0, true);
|
||||
int x, y;
|
||||
int x, y, k;
|
||||
#define EXPAND 2
|
||||
vec3_t surfnorms[(SECTTEXSIZE+EXPAND*2)*(SECTTEXSIZE+EXPAND*2)];
|
||||
vec3_t surfpoint[(SECTTEXSIZE+EXPAND*2)*(SECTTEXSIZE+EXPAND*2)];
|
||||
// float scaletab[EXPAND*2*EXPAND*2];
|
||||
vec3_t ldir = {0.4, 0.7, 2};
|
||||
vec3_t ldir;
|
||||
hmsection_t *s = hm->relight;
|
||||
float ambient, diffuse;
|
||||
trace_t trace;
|
||||
s->flags &= ~TSF_RELIGHT;
|
||||
hm->relight = NULL;
|
||||
|
||||
if (s->lightmap < 0)
|
||||
return;
|
||||
|
||||
ambient = 255*mod_terrain_ambient.value;
|
||||
diffuse = 255-ambient;
|
||||
|
||||
for (y = -EXPAND; y < SECTTEXSIZE+EXPAND; y++)
|
||||
for (x = -EXPAND; x < SECTTEXSIZE+EXPAND; x++)
|
||||
{
|
||||
vec3_t pos;
|
||||
pos[0] = hm->relightmin[0] + (x*hm->sectionsize/(SECTTEXSIZE-1));
|
||||
pos[1] = hm->relightmin[1] + (y*hm->sectionsize/(SECTTEXSIZE-1));
|
||||
pos[2] = 0;
|
||||
Heightmap_Normal(s->hmmod, pos, surfnorms[x+EXPAND + (y+EXPAND)*(SECTTEXSIZE+EXPAND*2)]);
|
||||
k = x+EXPAND + (y+EXPAND)*(SECTTEXSIZE+EXPAND*2);
|
||||
surfpoint[k][0] = hm->relightmin[0] + (x*hm->sectionsize/(SECTTEXSIZE-1));
|
||||
surfpoint[k][1] = hm->relightmin[1] + (y*hm->sectionsize/(SECTTEXSIZE-1));
|
||||
surfpoint[k][2] = Heightmap_Normal(s->hmmod, surfpoint[k], surfnorms[k])+0.1;
|
||||
}
|
||||
|
||||
VectorNormalize(ldir);
|
||||
VectorNormalize2(mod_terrain_sundir.vec4, ldir);
|
||||
|
||||
for (y = 0; y < SECTTEXSIZE; y++, lm += (HMLMSTRIDE-SECTTEXSIZE)*4)
|
||||
for (x = 0; x < SECTTEXSIZE; x++, lm += 4)
|
||||
|
@ -4415,10 +4452,18 @@ static void ted_dorelight(heightmap_t *hm)
|
|||
d = DotProduct(ldir, norm);
|
||||
if (d < 0)
|
||||
d = 0;
|
||||
else if (mod_terrain_shadows.ival)
|
||||
{
|
||||
float *point = surfpoint[x+EXPAND + (y+EXPAND)*(SECTTEXSIZE+EXPAND*2)];
|
||||
vec3_t sun;
|
||||
VectorMA(point, mod_terrain_shadow_dist.value, ldir, sun);
|
||||
if (m->funcs.NativeTrace(m, 0, NULL, NULL, point, sun, vec3_origin, vec3_origin, false, FTECONTENTS_SOLID|FTECONTENTS_BODY, &trace))
|
||||
d = 0;
|
||||
}
|
||||
// lm[0] = norm[0]*127 + 128;
|
||||
// lm[1] = norm[1]*127 + 128;
|
||||
// lm[2] = norm[2]*127 + 128;
|
||||
lm[3] = 127 + d*128;
|
||||
lm[3] = ambient + d*diffuse;
|
||||
}
|
||||
|
||||
lightmap[s->lightmap]->modified = true;
|
||||
|
@ -7102,11 +7147,11 @@ void Terr_WriteBrushInfo(vfsfile_t *file, brushes_t *br)
|
|||
}
|
||||
hasrgba = (y < br->patch->ypoints*br->patch->xpoints);
|
||||
|
||||
VFS_PRINTF(file, "\n\tpatchDef%s\n\t{\n\t\t\"%s\"\n\t\t( %.9g %.9g %.9g %.9g %.9g )\n\t\t(\n",
|
||||
VFS_PRINTF(file, "\n\tpatchDef%s\n\t{\n\t\t\"%s\"\n\t\t( %u %u %.9g %.9g %.9g )\n\t\t(\n",
|
||||
hasrgba?"WS":"2",
|
||||
br->patch->tex?br->patch->tex->shadername:"",
|
||||
0.0/*xoffset*/,
|
||||
0.0/*yoffset*/,
|
||||
br->patch->xpoints/*width*/,
|
||||
br->patch->ypoints/*height*/,
|
||||
0.0/*rotation*/,
|
||||
1.0/*xscale*/,
|
||||
1.0/*yscale*/);
|
||||
|
@ -7480,9 +7525,10 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
else if (inbrush && (!strcmp(token, "patchDef2") || !strcmp(token, "patchDefWS")))
|
||||
else if (inbrush && (!strcmp(token, "patchDef2") || !strcmp(token, "patchDef3") || !strcmp(token, "patchDefWS")))
|
||||
{
|
||||
int x, y;
|
||||
qboolean patchdef3 = !strcmp(token, "patchDef3"); //fancy alternative with rgba colours per control point
|
||||
qboolean parsergba = !strcmp(token, "patchDefWS"); //fancy alternative with rgba colours per control point
|
||||
if (numplanes || patch_tex)
|
||||
{
|
||||
|
@ -7498,10 +7544,17 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
|||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
/*xoffset = atof(token);*/
|
||||
/*patch_w = atof(token);*/
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
/*yoffset = atof(token);*/
|
||||
/*patch_h = atof(token);*/
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
if (patchdef3)
|
||||
{
|
||||
/*xsubdiv = atof(token);*/
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
/*ysubdiv = atof(token);*/
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
}
|
||||
/*rotation = atof(token);*/
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
/*xscale = atof(token);*/
|
||||
|
@ -7532,7 +7585,12 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities)
|
|||
patch_v[y][x].tc[1] = atof(token);
|
||||
|
||||
if (parsergba)
|
||||
{
|
||||
{ //the following four lines are stupid.
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
if (strcmp(token, ")")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
if (strcmp(token, "(")) {Con_Printf(CON_ERROR "%s: invalid patch\n", mod->name);return false;}
|
||||
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
patch_v[y][x].rgba[0] = atof(token);
|
||||
entities = COM_ParseTokenOut(entities, brushpunct, token, sizeof(token), NULL);
|
||||
|
@ -7981,31 +8039,33 @@ void *Mod_LoadTerrainInfo(model_t *mod, char *loadname, qboolean force)
|
|||
}
|
||||
|
||||
#ifndef SERVERONLY
|
||||
#if 0 //not yet ready
|
||||
struct ted_import_s
|
||||
{
|
||||
int x, y;
|
||||
int width;
|
||||
int height;
|
||||
size_t x, y;
|
||||
size_t width;
|
||||
size_t height;
|
||||
unsigned short *data;
|
||||
};
|
||||
//static void ted_itterate(heightmap_t *hm, int distribution, float *pos, float radius, float strength, int steps,
|
||||
void ted_import_heights(void *vctx, hmsection_t *s, int idx, float wx, float wy, float strength)
|
||||
static void ted_import_heights_r16(void *vctx, hmsection_t *s, int idx, float wx, float wy, float strength)
|
||||
{
|
||||
struct ted_import_s *ctx = vctx;
|
||||
unsigned int y = idx/SECTHEIGHTSIZE;
|
||||
unsigned int x = idx%SECTHEIGHTSIZE;
|
||||
x += s->sx*(SECTHEIGHTSIZE-1) - ctx->x;
|
||||
y += s->sy*(SECTHEIGHTSIZE-1) - ctx->y;
|
||||
if (x < 0 || x >= ctx->width || y < 0 || y >= ctx->height)
|
||||
if (x >= ctx->width || y >= ctx->height)
|
||||
return;
|
||||
s->flags |= TSF_NOTIFY|TSF_EDITED|TSF_DIRTY|TSF_RELIGHT;
|
||||
s->heights[idx] = ctx->data[x + y*ctx->width] * (8192.0/(1<<16));
|
||||
}
|
||||
void Mod_Terrain_Import_f(void)
|
||||
static void Mod_Terrain_Import_f(void)
|
||||
{
|
||||
model_t *mod;
|
||||
struct ted_import_s ctx;
|
||||
const char *mapname = Cmd_Argv(1);
|
||||
const char *filename;
|
||||
size_t fsize;
|
||||
heightmap_t *hm;
|
||||
vec3_t pos = {0};
|
||||
|
@ -8025,16 +8085,142 @@ void Mod_Terrain_Import_f(void)
|
|||
return;
|
||||
|
||||
fsize = 0;
|
||||
ctx.data = (void*)FS_LoadMallocFile("quake8km/height8km.r16", &fsize);
|
||||
filename = va("maps/%s.r16", mapname);
|
||||
ctx.data = (void*)FS_LoadMallocFile(filename, &fsize);
|
||||
if (!ctx.data)
|
||||
{
|
||||
Con_Printf("Unable to read %s\n", filename);
|
||||
return;
|
||||
}
|
||||
ctx.width = ctx.height = sqrt(fsize/2);
|
||||
ctx.x = 0;
|
||||
ctx.y = 0;
|
||||
pos[0] += hm->sectionsize * CHUNKBIAS;
|
||||
pos[1] += hm->sectionsize * CHUNKBIAS;
|
||||
if (fsize == ctx.width*ctx.height*2)
|
||||
ted_itterate(hm, tid_flat, pos, max(ctx.width, ctx.height), 1, SECTHEIGHTSIZE, ted_import_heights, &ctx);
|
||||
ted_itterate(hm, tid_flat, pos, max(ctx.width, ctx.height), 1, SECTHEIGHTSIZE, ted_import_heights_r16, &ctx);
|
||||
FS_FreeFile(ctx.data);
|
||||
}
|
||||
static void Mod_Terrain_Export_f(void)
|
||||
{
|
||||
model_t *mod;
|
||||
struct ted_import_s ctx;
|
||||
char mapname[MAX_QPATH];
|
||||
const char *filename;
|
||||
heightmap_t *hm;
|
||||
size_t w, h;
|
||||
size_t tx, ty;
|
||||
size_t sx, sy;
|
||||
unsigned int outtilex=0,outtiley=0;
|
||||
qboolean populated;
|
||||
if (Cmd_IsInsecure())
|
||||
{
|
||||
Con_Printf("Please use this command via the console\n");
|
||||
return;
|
||||
}
|
||||
if (*Cmd_Argv(1))
|
||||
mod = NULL;//Mod_FindName(va("maps/%s", mapname));
|
||||
else
|
||||
mod = cl.worldmodel;
|
||||
if (!mod || mod->type == mod_dummy)
|
||||
return;
|
||||
hm = mod->terrain;
|
||||
if (!hm)
|
||||
return;
|
||||
|
||||
COM_StripExtension(mod->name, mapname, sizeof(mapname));
|
||||
|
||||
ctx.x = hm->firstsegx * (SECTHEIGHTSIZE-1);
|
||||
w = (hm->maxsegx-hm->firstsegx) * (SECTHEIGHTSIZE-1) + 1;
|
||||
while(w)
|
||||
{
|
||||
ctx.width = w;
|
||||
if (ctx.width > 2048+1)
|
||||
ctx.width = 2048;
|
||||
|
||||
outtiley = 0;
|
||||
ctx.y = hm->firstsegy * (SECTHEIGHTSIZE-1);
|
||||
h = (hm->maxsegy-hm->firstsegy) * (SECTHEIGHTSIZE-1) + 1;
|
||||
while(h)
|
||||
{
|
||||
ctx.height = h;
|
||||
if (ctx.height > 2048+1)
|
||||
ctx.height = 2048;
|
||||
|
||||
populated = false;
|
||||
ctx.data = Z_Malloc(ctx.width*ctx.height*2);
|
||||
for (sy = ctx.y/(SECTHEIGHTSIZE-1); sy < (ctx.y+ctx.height + SECTHEIGHTSIZE-3)/(SECTHEIGHTSIZE-1); sy++)
|
||||
for (sx = ctx.x/(SECTHEIGHTSIZE-1); sx < (ctx.x+ctx.width + SECTHEIGHTSIZE-3)/(SECTHEIGHTSIZE-1); sx++)
|
||||
{
|
||||
hmsection_t *s = Terr_GetSection(hm, sx, sy, TGS_WAITLOAD|TGS_ANYSTATE);
|
||||
if (s->loadstate == TSLS_FAILED)
|
||||
{ //we're doing this weirdly so we can destroy sections as we go.
|
||||
Terr_DestroySection(hm, s, true);
|
||||
s = NULL;
|
||||
}
|
||||
if (s)
|
||||
{
|
||||
populated = true;
|
||||
for (ty = 0; ty < SECTHEIGHTSIZE; ty++)
|
||||
{
|
||||
size_t y = sy*(SECTHEIGHTSIZE-1)+ty - ctx.y;
|
||||
if (y >= ctx.height)
|
||||
continue;
|
||||
for (tx = 0; tx < SECTHEIGHTSIZE; tx++)
|
||||
{
|
||||
size_t x = sx*(SECTHEIGHTSIZE-1)+tx - ctx.x;
|
||||
if (x >= ctx.width)
|
||||
continue;
|
||||
ctx.data[x + y*ctx.width] = s->heights[tx+y*SECTHEIGHTSIZE] / (8192.0/(1<<16));
|
||||
}
|
||||
}
|
||||
if (!(s->flags & TSF_EDITED))
|
||||
Terr_DestroySection(hm, s, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (ty = 0; ty < SECTHEIGHTSIZE; ty++)
|
||||
{
|
||||
size_t y = sy*(SECTHEIGHTSIZE-1)+ty - ctx.y;
|
||||
if (y >= ctx.height)
|
||||
continue;
|
||||
for (tx = 0; tx < SECTHEIGHTSIZE; tx++)
|
||||
{
|
||||
size_t x = sx*(SECTHEIGHTSIZE-1)+tx - ctx.x;
|
||||
if (x >= ctx.width)
|
||||
continue;
|
||||
ctx.data[x + y*ctx.width] = hm->defaultgroundheight / (8192.0/(1<<16));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filename = va("%s/x%u_y%u.r16", mapname, outtilex, outtiley);
|
||||
if (populated)
|
||||
{
|
||||
if (FS_WriteFile(filename, ctx.data, ctx.width*ctx.height*2, FS_GAMEONLY))
|
||||
{
|
||||
char sysname[1024];
|
||||
FS_NativePath(filename, FS_GAMEONLY, sysname, sizeof(sysname));
|
||||
Con_Printf("Wrote %s\n", sysname);
|
||||
}
|
||||
else
|
||||
Con_Printf("Unable to write %s\n", filename);
|
||||
}
|
||||
else
|
||||
Con_Printf("Skipping unpopulated %s\n", filename);
|
||||
Z_Free(ctx.data);
|
||||
|
||||
outtiley++;
|
||||
ctx.y += ctx.height;
|
||||
h -= ctx.height;
|
||||
}
|
||||
outtilex++;
|
||||
ctx.x += ctx.width;
|
||||
w -= ctx.width;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Mod_Terrain_Create_f(void)
|
||||
{
|
||||
|
@ -8279,9 +8465,15 @@ void Terr_Init(void)
|
|||
Cmd_AddCommand("mod_terrain_save", Mod_Terrain_Save_f);
|
||||
Cmd_AddCommand("mod_terrain_reload", Mod_Terrain_Reload_f);
|
||||
#ifndef SERVERONLY
|
||||
Cmd_AddCommandD("mod_terrain_import", Mod_Terrain_Import_f, "Import a raw heightmap");
|
||||
// Cmd_AddCommandD("mod_terrain_export", Mod_Terrain_Export_f, "Export a raw heightmap");
|
||||
// Cmd_AddCommandD("mod_terrain_import", Mod_Terrain_Import_f, "Import a raw heightmap");
|
||||
Cmd_AddCommand("mod_terrain_create", Mod_Terrain_Create_f);
|
||||
Cmd_AddCommandD("mod_terrain_convert", Mod_Terrain_Convert_f, "mod_terrain_convert [mapname] [texkill]\nConvert a terrain to the current format. If texkill is specified, only tiles with the named texture will be converted, and tiles with that texture will be stripped. This is a slow operation.");
|
||||
|
||||
Cvar_Register(&mod_terrain_sundir, "Terrain");
|
||||
Cvar_Register(&mod_terrain_ambient, "Terrain");
|
||||
Cvar_Register(&mod_terrain_shadows, "Terrain");
|
||||
Cvar_Register(&mod_terrain_shadow_dist, "Terrain");
|
||||
#endif
|
||||
|
||||
Mod_RegisterModelFormatText(NULL, "FTE Heightmap Map (hmp)", "terrain", Terr_LoadTerrainModel);
|
||||
|
|
|
@ -1256,6 +1256,7 @@ struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p)
|
|||
size_t n, pn = 0;
|
||||
char defines[8192];
|
||||
size_t offset;
|
||||
qboolean fail = false;
|
||||
|
||||
extern cvar_t gl_specular, gl_specular_power;
|
||||
|
||||
|
@ -1294,14 +1295,14 @@ struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p)
|
|||
permutationdefines[pn++] = NULL;
|
||||
|
||||
if (!sh_config.pCreateProgram(prog, pp, prog->shaderver, permutationdefines, prog->shadertext, prog->tess?prog->shadertext:NULL, prog->tess?prog->shadertext:NULL, prog->geom?prog->shadertext:NULL, prog->shadertext, prog->warned, NULL))
|
||||
prog->warned = true;
|
||||
prog->warned = fail = true;
|
||||
|
||||
//extra loop to validate the programs actually linked properly.
|
||||
//delaying it like this gives certain threaded drivers a chance to compile them all while we're messing around with other junk
|
||||
if (sh_config.pValidateProgram && !sh_config.pValidateProgram(prog, pp, prog->warned, NULL))
|
||||
prog->warned = true;
|
||||
if (!fail && sh_config.pValidateProgram && !sh_config.pValidateProgram(prog, pp, prog->warned, NULL))
|
||||
prog->warned = fail = true;
|
||||
|
||||
if (sh_config.pProgAutoFields)
|
||||
if (!fail && sh_config.pProgAutoFields)
|
||||
{
|
||||
cvar_t *cvarrefs[64];
|
||||
char *cvarnames[64+1];
|
||||
|
@ -1320,9 +1321,52 @@ struct programpermu_s *Shader_LoadPermutation(program_t *prog, unsigned int p)
|
|||
cvarnames[i] = NULL; //no more
|
||||
sh_config.pProgAutoFields(prog, pp, cvarrefs, cvarnames, cvartypes);
|
||||
}
|
||||
if (fail)
|
||||
{
|
||||
Z_Free(pp);
|
||||
return NULL;
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
||||
qboolean Shader_PermutationEnabled(unsigned int bit)
|
||||
{
|
||||
if (bit == PERMUTATION_REFLECTCUBEMASK)
|
||||
return gl_load24bit.ival;
|
||||
if (bit == PERMUTATION_BUMPMAP)
|
||||
return r_loadbumpmapping;
|
||||
return true;
|
||||
}
|
||||
qboolean Com_PermuOrFloatArgument(const char *shadername, char *arg, size_t arglen, float def)
|
||||
{
|
||||
extern cvar_t gl_specular;
|
||||
size_t p;
|
||||
//load-time-only permutations...
|
||||
if (arglen == 8 && !strncmp("SPECULAR", arg, arglen) && gl_specular.value)
|
||||
return true;
|
||||
if ((arglen==5||arglen==6) && !strncmp("DELUXE", arg, arglen) && r_deluxemapping && Shader_PermutationEnabled(PERMUTATION_BUMPMAP))
|
||||
return true;
|
||||
if (arglen == 13 && !strncmp("OFFSETMAPPING", arg, arglen) && r_glsl_offsetmapping.ival)
|
||||
return true;
|
||||
if (arglen == 13 && !strncmp("RELIEFMAPPING", arg, arglen) && r_glsl_offsetmapping.ival && r_glsl_offsetmapping_reliefmapping.ival)
|
||||
return true;
|
||||
|
||||
//real permutations
|
||||
if (arglen == 5 && (!strncmp("UPPER", arg, arglen)||!strncmp("LOWER", arg, arglen)) && Shader_PermutationEnabled(PERMUTATION_BIT_UPPERLOWER))
|
||||
return true;
|
||||
for (p = 0; p < countof(permutations); p++)
|
||||
{
|
||||
if (arglen == strlen(permutations[p].name) && !strncmp(permutations[p].name, arg, arglen))
|
||||
{
|
||||
if (Shader_PermutationEnabled(permutations[p].bitmask))
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Com_FloatArgument(shadername, arg, arglen, def) != 0;
|
||||
}
|
||||
|
||||
static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *script, int qrtype, int ver, char *blobfilename)
|
||||
{
|
||||
#if defined(GLQUAKE) || defined(D3DQUAKE)
|
||||
|
@ -1412,15 +1456,16 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
if (*token == '=' || *token == '!')
|
||||
{
|
||||
len = strlen(token);
|
||||
if (*token == (Com_FloatArgument(name, token+1, len-1, 0)?'!':'='))
|
||||
if (*token == (Com_PermuOrFloatArgument(name, token+1, len-1, 0)?'!':'='))
|
||||
ignore = true;
|
||||
continue;
|
||||
}
|
||||
else if (ignore)
|
||||
continue;
|
||||
#ifdef HAVE_LEGACY
|
||||
#if 1//def HAVE_LEGACY
|
||||
else if (!strncmp(token, "deluxmap", 8))
|
||||
{ //FIXME: remove this some time.
|
||||
Con_DPrintf("Outdated texture name \"%s\" in program \"%s\"\n", token, name);
|
||||
token = va("deluxemap%s",token+8);
|
||||
}
|
||||
#endif
|
||||
|
@ -1470,7 +1515,7 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
prog->numsamplers = i;
|
||||
}
|
||||
else
|
||||
Con_Printf("Unknown texture name in %s\n", name);
|
||||
Con_Printf("Unknown texture name \"%s\" in program \"%s\"\n", token, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1667,7 +1712,8 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
{
|
||||
if (!strncmp(permutations[p].name, script, end - script) && permutations[p].name[end-script] == '\0')
|
||||
{
|
||||
nopermutation &= ~permutations[p].bitmask;
|
||||
if (Shader_PermutationEnabled(permutations[p].bitmask))
|
||||
nopermutation &= ~permutations[p].bitmask;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1738,10 +1784,10 @@ static qboolean Shader_LoadPermutations(char *name, program_t *prog, char *scrip
|
|||
nopermutation |= PERMUTATION_SKELETAL;
|
||||
|
||||
//multiple lightmaps is kinda hacky. if any are set, all must be.
|
||||
#define ALTLIGHTMAPSAMP 13
|
||||
#define ALTLIGHTMAPSAMP 14
|
||||
if (prog->defaulttextures & ((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2))))
|
||||
prog->defaulttextures |=((1u<<(ALTLIGHTMAPSAMP+0)) | (1u<<(ALTLIGHTMAPSAMP+1)) | (1u<<(ALTLIGHTMAPSAMP+2)));
|
||||
#define ALTDELUXMAPSAMP 16
|
||||
#define ALTDELUXMAPSAMP 17
|
||||
if (prog->defaulttextures & ((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2))))
|
||||
prog->defaulttextures |=((1u<<(ALTDELUXMAPSAMP+0)) | (1u<<(ALTDELUXMAPSAMP+1)) | (1u<<(ALTDELUXMAPSAMP+2)));
|
||||
|
||||
|
|
|
@ -420,7 +420,7 @@ qboolean GL_CheckExtension(char *extname)
|
|||
for (i = 0; i < gl_num_extensions; i++)
|
||||
if (!strcmp(qglGetStringi(GL_EXTENSIONS, i), extname))
|
||||
{
|
||||
Con_DPrintf("Detected GL extension %s\n", extname);
|
||||
Con_DPrintf("GL: Found %s\n", extname);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2280,6 +2280,9 @@ static GLhandleARB GLSlang_CreateShader (program_t *prog, const char *name, int
|
|||
"#ifndef USE_ARB_SHADOW\n" //fall back on regular samplers if we must
|
||||
"#define sampler2DShadow sampler2D\n"
|
||||
"#elif defined(GL_ES)\n"
|
||||
"#if __VERSION__ < 300\n"
|
||||
"#extension GL_EXT_shadow_samplers : require\n"
|
||||
"#endif\n"
|
||||
"precision lowp sampler2DShadow;\n" //gah
|
||||
"#endif\n"
|
||||
#endif
|
||||
|
|
|
@ -2975,7 +2975,7 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
|
||||
//the vertex shader is responsible for calculating lighting values.
|
||||
|
||||
"#if gl_affinemodels==1 && __VERSION__ >= 130\n"
|
||||
"#if gl_affinemodels==1 && __VERSION__ >= 130 && !defined(GL_ES)\n"
|
||||
"#define affine noperspective\n"
|
||||
"#else\n"
|
||||
"#define affine\n"
|
||||
|
@ -5599,11 +5599,17 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"!!permu REFLECTCUBEMASK\n"
|
||||
"!!cvarf r_glsl_offsetmapping_scale\n"
|
||||
"!!cvardf r_tessellation_level=5\n"
|
||||
"!!samps !EIGHTBIT diffuse specular normalmap fullbright reflectmask reflectcube\n"
|
||||
"!!samps diffuse\n"
|
||||
"!!samps !EIGHTBIT =FULLBRIGHT fullbright\n"
|
||||
"!!samps !EIGHTBIT =BUMP normalmap\n"
|
||||
"!!samps !EIGHTBIT =REFLECTCUBEMASK reflectmask reflectcube\n"
|
||||
//diffuse gives us alpha, and prevents dlight from bugging out when there's no diffuse.
|
||||
"!!samps =EIGHTBIT paletted 1 specular diffuse\n"
|
||||
"!!samps lightmap deluxemap\n"
|
||||
"!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3\n"
|
||||
"!!samps =EIGHTBIT paletted 1\n"
|
||||
"!!samps =SPECULAR specular\n"
|
||||
"!!samps lightmap\n"
|
||||
"!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3\n"
|
||||
"!!samps =DELUXE deluxmap\n"
|
||||
"!!samps =LIGHTSTYLED =DELUXE deluxemap1 deluxemap2 deluxemap3\n"
|
||||
|
||||
"#if defined(ORM) || defined(SG)\n"
|
||||
"#define PBR\n"
|
||||
|
@ -5960,7 +5966,6 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"#else\n"
|
||||
//now we have our diffuse+specular terms, modulate by lightmap values.
|
||||
"col.rgb *= lightmaps.rgb;\n"
|
||||
|
||||
//add on the fullbright
|
||||
"#ifdef FULLBRIGHT\n"
|
||||
"col.rgb += texture2D(s_fullbright, tc).rgb;\n"
|
||||
|
@ -10603,10 +10608,11 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
#endif
|
||||
#ifdef GLQUAKE
|
||||
{QR_OPENGL, 110, "terrain",
|
||||
"!!ver 100 300\n"
|
||||
"!!permu FOG\n"
|
||||
//t0-t3 are the diffusemaps, t4 is the blend factors
|
||||
"!!samps 4\n"
|
||||
"!!samps mix=4\n"
|
||||
//RTLIGHT (+PCF,CUBE,SPOT,etc)
|
||||
"!!samps tr=0 tg=1 tb=2 tx=3 //the four texturemaps\n"
|
||||
"!!samps mix=4 //how the ground is blended\n"
|
||||
"!!samps =PCF shadowmap\n"
|
||||
"!!samps =CUBE projectionmap\n"
|
||||
|
||||
|
@ -10703,10 +10709,12 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND
|
|||
"vec4 r;\n"
|
||||
"vec4 m = texture2D(s_mix, lm);\n"
|
||||
|
||||
"r = texture2D(s_t0, tc)*m.r;\n"
|
||||
"r += texture2D(s_t1, tc)*m.g;\n"
|
||||
"r += texture2D(s_t2, tc)*m.b;\n"
|
||||
"r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));\n"
|
||||
"r = texture2D(s_tr, tc)*m.r;\n"
|
||||
"r += texture2D(s_tg, tc)*m.g;\n"
|
||||
"r += texture2D(s_tb, tc)*m.b;\n"
|
||||
"r += texture2D(s_tx, tc)*(1.0 - (m.r + m.g + m.b));\n"
|
||||
|
||||
"r.rgb *= 1.0/r.a; //fancy maths, so low alpha values give other textures a greater focus\n"
|
||||
|
||||
//vertex colours provide a scaler that applies even through rtlights.
|
||||
"r *= vc;\n"
|
||||
|
|
|
@ -23,7 +23,7 @@ void *PRHunkAlloc(progfuncs_t *progfuncs, int ammount, const char *name)
|
|||
|
||||
return ((char *)mem)+sizeof(prmemb_t);
|
||||
}
|
||||
void *PDECL QC_HunkAlloc(pubprogfuncs_t *ppf, int ammount, char *name)
|
||||
static void *PDECL QC_HunkAlloc(pubprogfuncs_t *ppf, int ammount, char *name)
|
||||
{
|
||||
return PRHunkAlloc((progfuncs_t*)ppf, ammount, name);
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ void PRHunkFree(progfuncs_t *progfuncs, int mark)
|
|||
}
|
||||
|
||||
/*if we ran out of memory, the vm can allocate a new block, but doing so requires fixing up all sorts of pointers*/
|
||||
void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen)
|
||||
static void PRAddressableRelocate(progfuncs_t *progfuncs, char *oldb, char *newb, int oldlen)
|
||||
{
|
||||
unsigned int i;
|
||||
edictrun_t *e;
|
||||
|
@ -583,7 +583,7 @@ static void PDECL PR_Configure (pubprogfuncs_t *ppf, size_t addressable_size, in
|
|||
|
||||
|
||||
|
||||
struct globalvars_s *PDECL PR_globals (pubprogfuncs_t *ppf, progsnum_t pnum)
|
||||
static struct globalvars_s *PDECL PR_globals (pubprogfuncs_t *ppf, progsnum_t pnum)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
if (pnum < 0)
|
||||
|
@ -598,7 +598,7 @@ struct globalvars_s *PDECL PR_globals (pubprogfuncs_t *ppf, progsnum_t pnum)
|
|||
return (struct globalvars_s *)pr_progstate[pnum].globals;
|
||||
}
|
||||
|
||||
struct entvars_s *PDECL PR_entvars (pubprogfuncs_t *ppf, struct edict_s *ed)
|
||||
static struct entvars_s *PDECL PR_entvars (pubprogfuncs_t *ppf, struct edict_s *ed)
|
||||
{
|
||||
// progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
if (((edictrun_t *)ed)->ereftype != ER_ENTITY)
|
||||
|
@ -607,7 +607,7 @@ struct entvars_s *PDECL PR_entvars (pubprogfuncs_t *ppf, struct edict_s *ed)
|
|||
return (struct entvars_s *)edvars(ed);
|
||||
}
|
||||
|
||||
pbool PDECL PR_GetFunctionInfo(pubprogfuncs_t *ppf, func_t func, int *args, int *builtinnum, char *funcname, size_t funcnamesize)
|
||||
static pbool PDECL PR_GetFunctionInfo(pubprogfuncs_t *ppf, func_t func, int *args, int *builtinnum, char *funcname, size_t funcnamesize)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
|
||||
|
@ -697,7 +697,7 @@ func_t PDECL PR_FindFunc(pubprogfuncs_t *ppf, const char *funcname, progsnum_t p
|
|||
return 0;
|
||||
}
|
||||
|
||||
void PDECL QC_FindPrefixedGlobals(pubprogfuncs_t *ppf, int pnum, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type, void *ctx), void *ctx)
|
||||
static void PDECL QC_FindPrefixedGlobals(pubprogfuncs_t *ppf, int pnum, char *prefix, void (PDECL *found) (pubprogfuncs_t *progfuncs, char *name, union eval_s *val, etype_t type, void *ctx), void *ctx)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
unsigned int i;
|
||||
|
@ -795,7 +795,7 @@ eval_t *PDECL PR_FindGlobal(pubprogfuncs_t *ppf, const char *globname, progsnum_
|
|||
return NULL;
|
||||
}
|
||||
|
||||
char *PDECL PR_VarString (pubprogfuncs_t *ppf, int first)
|
||||
static char *PDECL PR_VarString (pubprogfuncs_t *ppf, int first)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
int i;
|
||||
|
@ -816,7 +816,7 @@ char *PDECL PR_VarString (pubprogfuncs_t *ppf, int first)
|
|||
return out;
|
||||
}
|
||||
|
||||
int PDECL PR_QueryField (pubprogfuncs_t *ppf, unsigned int fieldoffset, etype_t *type, char const**name, evalc_t *fieldcache)
|
||||
static int PDECL PR_QueryField (pubprogfuncs_t *ppf, unsigned int fieldoffset, etype_t *type, char const**name, evalc_t *fieldcache)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
fdef_t *var;
|
||||
|
@ -868,7 +868,7 @@ eval_t *PDECL QC_GetEdictFieldValue(pubprogfuncs_t *ppf, struct edict_s *ed, con
|
|||
return (eval_t *) &(((int*)(((edictrun_t*)ed)->fields))[cache->ofs32->ofs]);
|
||||
}
|
||||
|
||||
struct edict_s *PDECL ProgsToEdict (pubprogfuncs_t *ppf, int progs)
|
||||
static struct edict_s *PDECL ProgsToEdict (pubprogfuncs_t *ppf, int progs)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
if ((unsigned)progs >= (unsigned)prinst.maxedicts)
|
||||
|
@ -883,7 +883,7 @@ struct edict_s *PDECL ProgsToEdict (pubprogfuncs_t *ppf, int progs)
|
|||
}
|
||||
return (struct edict_s *)PROG_TO_EDICT_PB(progfuncs.inst, progs);
|
||||
}
|
||||
int PDECL EdictToProgs (pubprogfuncs_t *ppf, struct edict_s *ed)
|
||||
static int PDECL EdictToProgs (pubprogfuncs_t *ppf, struct edict_s *ed)
|
||||
{
|
||||
// progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
return EDICT_TO_PROG(progfuncs, ed);
|
||||
|
@ -935,7 +935,7 @@ string_t PDECL PR_StringToProgs (pubprogfuncs_t *ppf, const char *str)
|
|||
return (string_t)((unsigned int)i | STRING_STATIC);
|
||||
}
|
||||
//if ed is null, fld points to a global. if str_is_static, then s doesn't need its own memory allocated.
|
||||
void PDECL PR_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed, string_t *fld, const char *str, pbool str_is_static)
|
||||
static void PDECL PR_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed, string_t *fld, const char *str, pbool str_is_static)
|
||||
{
|
||||
if (!str)
|
||||
*fld = 0;
|
||||
|
@ -951,7 +951,7 @@ void PDECL PR_SetStringField(pubprogfuncs_t *progfuncs, struct edict_s *ed, stri
|
|||
}
|
||||
}
|
||||
|
||||
char *PDECL PR_RemoveProgsString (pubprogfuncs_t *ppf, string_t str)
|
||||
static char *PDECL PR_RemoveProgsString (pubprogfuncs_t *ppf, string_t str)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
char *ret;
|
||||
|
@ -1110,7 +1110,7 @@ void QCBUILTIN PF_memsetval (pubprogfuncs_t *inst, struct globalvars_s *globals)
|
|||
}
|
||||
|
||||
|
||||
string_t PDECL PR_AllocTempStringLen (pubprogfuncs_t *ppf, char **str, unsigned int len)
|
||||
static string_t PDECL PR_AllocTempStringLen (pubprogfuncs_t *ppf, char **str, unsigned int len)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
tempstr_t **ntable;
|
||||
|
@ -1319,7 +1319,7 @@ static void PR_FreeAllTemps (progfuncs_t *progfuncs)
|
|||
prinst.numtempstrings = 0;
|
||||
prinst.nexttempstring = 0;
|
||||
}
|
||||
pbool PDECL PR_DumpProfiles (pubprogfuncs_t *ppf, pbool resetprofiles)
|
||||
static pbool PDECL PR_DumpProfiles (pubprogfuncs_t *ppf, pbool resetprofiles)
|
||||
{
|
||||
progfuncs_t *progfuncs = (progfuncs_t*)ppf;
|
||||
struct progstate_s *ps;
|
||||
|
@ -1391,7 +1391,7 @@ static void PDECL PR_CloseProgs(pubprogfuncs_t *ppf);
|
|||
|
||||
static void PDECL RegisterBuiltin(pubprogfuncs_t *progfncs, const char *name, builtin_t func);
|
||||
|
||||
pubprogfuncs_t deffuncs = {
|
||||
static pubprogfuncs_t deffuncs = {
|
||||
PROGSTRUCT_VERSION,
|
||||
PR_CloseProgs,
|
||||
PR_Configure,
|
||||
|
@ -1510,11 +1510,11 @@ static void PDECL qclib_free(void *ptr)
|
|||
#endif
|
||||
|
||||
//defs incase following structure is not passed.
|
||||
struct edict_s *safesv_edicts;
|
||||
int safesv_num_edicts;
|
||||
double safetime=0;
|
||||
static struct edict_s *safesv_edicts;
|
||||
static int safesv_num_edicts;
|
||||
static double safetime=0;
|
||||
|
||||
progexterns_t defexterns = {
|
||||
static progexterns_t defexterns = {
|
||||
PROGSTRUCT_VERSION,
|
||||
|
||||
NULL, //char *(*ReadFile) (char *fname, void *buffer, int len);
|
||||
|
|
|
@ -10451,9 +10451,14 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
|
|||
{"bprint", PF_bprint, 0, 23, 0, 0, D("void(float msglvl, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "QW: Concatenates all string arguments, and prints the messsage on the console of only all clients who's 'msg' infokey is set lower or equal to the supplied 'msglvl' argument.")},
|
||||
{"sprint", PF_sprint, 24, 0, 24, 0, D("void(entity client, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6, optional string s7)", "NQ: Concatenates all string arguments, and prints the messsage on the named client's console")},
|
||||
{"sprint", PF_sprint, 0, 24, 0, 0, D("void(entity client, float msglvl, string s, optional string s2, optional string s3, optional string s4, optional string s5, optional string s6)", "QW: Concatenates all string arguments, and prints the messsage on the named client's console, but only if that client's 'msg' infokey is set lower or equal to the supplied 'msglvl' argument.")},
|
||||
#ifdef HAVE_LEGACY
|
||||
//these have subtly different behaviour, and are implemented using different internal builtins, which is a bit weird in the extensions file. documentation is documentation.
|
||||
{"dprint", PF_dprint, 25, 0, 25, 0, D("void(string s, ...)", "NQ: Prints the given message on the server's console, but only if the developer cvar is set. Arguments will be concatenated into a single message.")},
|
||||
{"dprint", PF_print, 0, 25, 0, 0, D("void(string s, ...)", "QW: Unconditionally prints the given message on the server's console. Arguments will be concatenated into a single message.")},
|
||||
#else
|
||||
//going forward, we have print and dprint
|
||||
{"dprint", PF_dprint, 25, 25, 25, 0, D("void(string s, ...)", "NQ: Prints the given message on the server's console, but only if the developer cvar is set. Arguments will be concatenated into a single message.")},
|
||||
#endif
|
||||
{"ftos", PF_ftos, 26, 26, 26, 0, D("string(float val)", "Returns a tempstring containing a representation of the given float. Precision depends upon engine.")},
|
||||
{"vtos", PF_vtos, 27, 27, 27, 0, D("string(vector val)", "Returns a tempstring containing a representation of the given vector. Precision depends upon engine.")},
|
||||
{"coredump", PF_coredump, 28, 28, 28, 0, D("void()", "Writes out a coredump. This contains stack, globals, and field info for all ents. This can be handy for debugging.")},
|
||||
|
|
|
@ -565,7 +565,10 @@ void SV_Map_f (void)
|
|||
#ifdef Q3SERVER
|
||||
q3singleplayer = !strcmp(Cmd_Argv(0), "spmap");
|
||||
#endif
|
||||
flushparms = !strcmp(Cmd_Argv(0), "map") || !strcmp(Cmd_Argv(0), "spmap");
|
||||
if ((svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) && progstype == PROG_QW)
|
||||
flushparms = !strcmp(Cmd_Argv(0), "spmap"); //quakeworld's map command preserves spawnparms.
|
||||
else
|
||||
flushparms = !strcmp(Cmd_Argv(0), "map") || !strcmp(Cmd_Argv(0), "spmap"); //[sp]map flushes in nq+h2+q2+etc
|
||||
#ifdef SAVEDGAMES
|
||||
newunit = flushparms || (!strcmp(Cmd_Argv(0), "changelevel") && !startspot);
|
||||
q2savetos0 = !strcmp(Cmd_Argv(0), "gamemap") && !isDedicated; //q2
|
||||
|
@ -1910,7 +1913,10 @@ static void SV_Status_f (void)
|
|||
#if defined(HAVE_SSL)
|
||||
extern cvar_t net_enable_tls;
|
||||
#endif
|
||||
extern cvar_t net_enable_http, net_enable_webrtcbroker, net_enable_websockets, net_enable_qizmo, net_enable_qtv;
|
||||
#ifdef HAVE_HTTPSV
|
||||
extern cvar_t net_enable_http, net_enable_webrtcbroker, net_enable_websockets;
|
||||
#endif
|
||||
extern cvar_t net_enable_qizmo, net_enable_qtv;
|
||||
#endif
|
||||
#ifdef NQPROT
|
||||
extern cvar_t sv_listen_nq, sv_listen_dp;
|
||||
|
@ -1990,12 +1996,14 @@ static void SV_Status_f (void)
|
|||
if (net_enable_tls.ival)
|
||||
Con_Printf(" TLS");
|
||||
#endif
|
||||
#ifdef HAVE_HTTPSV
|
||||
if (net_enable_http.ival)
|
||||
Con_Printf(" HTTP");
|
||||
if (net_enable_webrtcbroker.ival)
|
||||
Con_Printf(" WebRTC");
|
||||
if (net_enable_websockets.ival)
|
||||
Con_Printf(" WS");
|
||||
#endif
|
||||
if (net_enable_qizmo.ival)
|
||||
Con_Printf(" QZ");
|
||||
if (net_enable_qtv.ival)
|
||||
|
|
|
@ -3140,13 +3140,27 @@ client_t *SVC_DirectConnect(void)
|
|||
else
|
||||
#endif
|
||||
newcl->netchan.compresstable = NULL;
|
||||
newcl->netchan.pext_fragmentation = mtu?true:false;
|
||||
//this is the upper bound of the mtu, if its too high we'll get EMSGSIZE and we'll reduce it.
|
||||
//however, if it drops below newcl->netchan.message.maxsize then we'll start to see undeliverable reliables, which means dropped clients.
|
||||
newcl->netchan.mtu = MAX_DATAGRAM; //vanilla qw clients are assumed to have an mtu of this size.
|
||||
if (mtu >= 64)
|
||||
{ //if we support application fragmenting, then we can send massive reliables without too much issue
|
||||
newcl->netchan.fragmentsize = mtu;
|
||||
newcl->netchan.mtu = mtu;
|
||||
newcl->netchan.message.maxsize = sizeof(newcl->netchan.message_buf);
|
||||
}
|
||||
else //otherwise we can't fragment the packets, and the only way to honour the mtu is to send less data. yay for more round-trips.
|
||||
newcl->netchan.message.maxsize = min(newcl->netchan.message.maxsize, max(net_mtu.ival, 512));
|
||||
{
|
||||
mtu = atoi(Info_ValueForKey (userinfo[0], "mtu"));
|
||||
if (mtu)
|
||||
newcl->netchan.mtu = mtu; //locked mtu size, because not everyone has a working connection (we need icmp would-fragment responses for mtu detection)
|
||||
else //if its not set then use some 'safe' fallback.
|
||||
mtu = MAX_BACKBUFLEN; //MAX_BACKBUFLEN of 1200 is < ipv6 required segment size so should always work for reliables.
|
||||
//enforce some boundaries
|
||||
mtu = bound(512-8, mtu, sizeof(newcl->netchan.message_buf));
|
||||
newcl->netchan.message.maxsize = mtu;
|
||||
}
|
||||
Con_DLPrintf(2, "MTU size: %i - %i\n", newcl->netchan.message.maxsize, newcl->netchan.mtu);
|
||||
|
||||
newcl->protocol = protocol;
|
||||
#ifdef NQPROT
|
||||
|
|
|
@ -35,7 +35,7 @@ void ClientReliableCheckBlock(client_t *cl, int maxsize)
|
|||
memset(&cl->backbuf, 0, sizeof(cl->backbuf));
|
||||
cl->backbuf.allowoverflow = true;
|
||||
cl->backbuf.data = cl->backbuf_data[0];
|
||||
cl->backbuf.maxsize = sizeof(cl->backbuf_data[0]);
|
||||
cl->backbuf.maxsize = min(cl->netchan.message.maxsize, sizeof(cl->backbuf_data[0]));
|
||||
cl->backbuf_size[0] = 0;
|
||||
cl->num_backbuf++;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ void ClientReliableCheckBlock(client_t *cl, int maxsize)
|
|||
memset(&cl->backbuf, 0, sizeof(cl->backbuf));
|
||||
cl->backbuf.allowoverflow = true;
|
||||
cl->backbuf.data = cl->backbuf_data[cl->num_backbuf];
|
||||
cl->backbuf.maxsize = sizeof(cl->backbuf_data[cl->num_backbuf]);
|
||||
cl->backbuf.maxsize = min(cl->netchan.message.maxsize, sizeof(cl->backbuf_data[cl->num_backbuf]));
|
||||
cl->backbuf_size[cl->num_backbuf] = 0;
|
||||
cl->num_backbuf++;
|
||||
}
|
||||
|
|
|
@ -2573,13 +2573,15 @@ qboolean SV_SendClientDatagram (client_t *client)
|
|||
client->edict->v->goalentity = 0;
|
||||
}
|
||||
|
||||
if (client->netchan.fragmentsize)
|
||||
if (client->netchan.pext_fragmentation)
|
||||
{
|
||||
if (client->netchan.remote_address.type == NA_LOOPBACK)
|
||||
clientlimit = countof(buf); //biiiig...
|
||||
else
|
||||
clientlimit = client->netchan.fragmentsize; //try not to overflow
|
||||
clientlimit = client->netchan.mtu; //try not to overflow
|
||||
}
|
||||
else if (client->netchan.mtu)
|
||||
clientlimit = client->netchan.mtu;
|
||||
else if (client->protocol == SCP_NETQUAKE)
|
||||
clientlimit = MAX_NQDATAGRAM; //vanilla client is limited.
|
||||
else
|
||||
|
@ -3411,7 +3413,7 @@ void SV_SendClientMessages (void)
|
|||
memset(&c->backbuf, 0, sizeof(c->backbuf));
|
||||
c->backbuf.data = c->backbuf_data[c->num_backbuf - 1];
|
||||
c->backbuf.cursize = c->backbuf_size[c->num_backbuf - 1];
|
||||
c->backbuf.maxsize = sizeof(c->backbuf_data[c->num_backbuf - 1]);
|
||||
c->backbuf.maxsize = min(c->netchan.message.maxsize, sizeof(c->backbuf_data[c->num_backbuf-1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3526,6 +3528,9 @@ void SV_SendClientMessages (void)
|
|||
c->datagram.cursize = 0;
|
||||
}
|
||||
c->lastoutgoingphysicstime = sv.world.physicstime;
|
||||
|
||||
if (c->netchan.fatal_error)
|
||||
c->drop = true;
|
||||
}
|
||||
#ifdef MVD_RECORDING
|
||||
if (sv.mvdrecording)
|
||||
|
|
|
@ -987,12 +987,12 @@ void SV_SendClientPrespawnInfo(client_t *client)
|
|||
return;
|
||||
}
|
||||
|
||||
//just because we CAN generate huge messages doesn't meant that we should.
|
||||
//just because we CAN generate huge messages doesn't mean that we should.
|
||||
//try to keep packets within reasonable sizes so that we don't trigger insane burst+packetloss on map changes.
|
||||
maxsize = client->netchan.message.maxsize/2;
|
||||
if (client->netchan.fragmentsize && maxsize > client->netchan.fragmentsize-200)
|
||||
if (client->netchan.mtu && maxsize > client->netchan.mtu-200)
|
||||
{
|
||||
maxsize = client->netchan.fragmentsize-200;
|
||||
maxsize = client->netchan.mtu-200;
|
||||
if (maxsize < 500)
|
||||
maxsize = 500;
|
||||
}
|
||||
|
@ -1933,7 +1933,6 @@ void SVQW_Spawn_f (void)
|
|||
// when that is completed, a begin command will be issued
|
||||
ClientReliableWrite_Begin (host_client, svc_stufftext, 8);
|
||||
ClientReliableWrite_String (host_client, "skins\n" );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7733,6 +7732,8 @@ void SV_ReadQCRequest(void)
|
|||
done:
|
||||
args[i] = 0;
|
||||
rname = MSG_ReadString();
|
||||
//We used to use Cmd_foo_args, but that conflicts with a zquake extension and would cause [e]zquake mods that use it to be remotely exploitable (mostly crashes from uninitialised args though).
|
||||
//Instead, we've switched to some more weird prefix that's much less likly to conflict.
|
||||
if (i)
|
||||
fname = va("CSEv_%s_%s", rname, args);
|
||||
else if (strchr(rname, '_')) //this is awkward, as not forcing an underscore would allow people to mis-call things with lingering data (the alternative is to block underscores entirely).
|
||||
|
@ -7749,7 +7750,10 @@ done:
|
|||
rname = va("Cmd_%s", rname);
|
||||
f = PR_FindFunction(svprogfuncs, rname, PR_ANY);
|
||||
if (f)
|
||||
SV_ClientPrintf(host_client, PRINT_HIGH, "the name \"%s\" is deprecated\n", rname);
|
||||
{
|
||||
SV_ClientPrintf(host_client, PRINT_HIGH, "\"%s\" is no longer supported.\n", rname);
|
||||
f = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (host_client->drop)
|
||||
|
|
|
@ -809,6 +809,10 @@ static void QDECL PFQ2_SetAreaPortalState(unsigned int p, qboolean s)
|
|||
CMQ2_SetAreaPortalState(sv.world.worldmodel, p, s);
|
||||
}
|
||||
|
||||
static void *VARGS ZQ2_TagMalloc(int size, int tag)
|
||||
{
|
||||
return Z_TagMalloc(size, tag);
|
||||
}
|
||||
qboolean SVQ2_InitGameProgs(void)
|
||||
{
|
||||
extern cvar_t maxclients;
|
||||
|
@ -862,7 +866,7 @@ qboolean SVQ2_InitGameProgs(void)
|
|||
import.WriteDir = PFQ2_WriteDir;
|
||||
import.WriteAngle = PFQ2_WriteAngle;
|
||||
|
||||
import.TagMalloc = Z_TagMalloc;
|
||||
import.TagMalloc = ZQ2_TagMalloc;
|
||||
import.TagFree = Z_TagFree;
|
||||
import.FreeTags = Z_FreeTags;
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
//must support skeletal and 2-way vertex blending or Bad Things Will Happen.
|
||||
//the vertex shader is responsible for calculating lighting values.
|
||||
|
||||
#if gl_affinemodels==1 && __VERSION__ >= 130
|
||||
#if gl_affinemodels==1 && __VERSION__ >= 130 && !defined(GL_ES)
|
||||
#define affine noperspective
|
||||
#else
|
||||
#define affine
|
||||
|
|
|
@ -9,11 +9,17 @@
|
|||
!!permu REFLECTCUBEMASK
|
||||
!!cvarf r_glsl_offsetmapping_scale
|
||||
!!cvardf r_tessellation_level=5
|
||||
!!samps !EIGHTBIT diffuse specular normalmap fullbright reflectmask reflectcube
|
||||
!!samps diffuse
|
||||
!!samps !EIGHTBIT =FULLBRIGHT fullbright
|
||||
!!samps !EIGHTBIT =BUMP normalmap
|
||||
!!samps !EIGHTBIT =REFLECTCUBEMASK reflectmask reflectcube
|
||||
//diffuse gives us alpha, and prevents dlight from bugging out when there's no diffuse.
|
||||
!!samps =EIGHTBIT paletted 1 specular diffuse
|
||||
!!samps lightmap deluxemap
|
||||
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3 deluxemap deluxemap1 deluxemap2 deluxemap3
|
||||
!!samps =EIGHTBIT paletted 1
|
||||
!!samps =SPECULAR specular
|
||||
!!samps lightmap
|
||||
!!samps =LIGHTSTYLED lightmap1 lightmap2 lightmap3
|
||||
!!samps =DELUXE deluxmap
|
||||
!!samps =LIGHTSTYLED =DELUXE deluxemap1 deluxemap2 deluxemap3
|
||||
|
||||
#if defined(ORM) || defined(SG)
|
||||
#define PBR
|
||||
|
@ -299,7 +305,7 @@ void main ()
|
|||
vec3 deluxe = (texture2D(s_deluxemap, lm0).rgb-0.5);
|
||||
#ifdef BUMPMODELSPACE
|
||||
deluxe = normalize(deluxe*invsurface);
|
||||
#else
|
||||
#else
|
||||
deluxe = normalize(deluxe);
|
||||
lightmaps *= 2.0 / max(0.25, deluxe.z); //counter the darkening from deluxemaps
|
||||
#endif
|
||||
|
@ -370,7 +376,6 @@ void main ()
|
|||
#else
|
||||
//now we have our diffuse+specular terms, modulate by lightmap values.
|
||||
col.rgb *= lightmaps.rgb;
|
||||
|
||||
//add on the fullbright
|
||||
#ifdef FULLBRIGHT
|
||||
col.rgb += texture2D(s_fullbright, tc).rgb;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
!!ver 100 300
|
||||
!!permu FOG
|
||||
//t0-t3 are the diffusemaps, t4 is the blend factors
|
||||
!!samps 4
|
||||
!!samps mix=4
|
||||
//RTLIGHT (+PCF,CUBE,SPOT,etc)
|
||||
!!samps tr=0 tg=1 tb=2 tx=3 //the four texturemaps
|
||||
!!samps mix=4 //how the ground is blended
|
||||
!!samps =PCF shadowmap
|
||||
!!samps =CUBE projectionmap
|
||||
|
||||
|
@ -98,10 +99,12 @@ void main (void)
|
|||
vec4 r;
|
||||
vec4 m = texture2D(s_mix, lm);
|
||||
|
||||
r = texture2D(s_t0, tc)*m.r;
|
||||
r += texture2D(s_t1, tc)*m.g;
|
||||
r += texture2D(s_t2, tc)*m.b;
|
||||
r += texture2D(s_t3, tc)*(1.0 - (m.r + m.g + m.b));
|
||||
r = texture2D(s_tr, tc)*m.r;
|
||||
r += texture2D(s_tg, tc)*m.g;
|
||||
r += texture2D(s_tb, tc)*m.b;
|
||||
r += texture2D(s_tx, tc)*(1.0 - (m.r + m.g + m.b));
|
||||
|
||||
r.rgb *= 1.0/r.a; //fancy maths, so low alpha values give other textures a greater focus
|
||||
|
||||
//vertex colours provide a scaler that applies even through rtlights.
|
||||
r *= vc;
|
||||
|
|
Loading…
Reference in a new issue