Rework android code to avoid google's nativeactivity limitations.

Fix a number of gles2 bugs.
Fix infoblobs. they should be much more reliable now.
Added callbacks so csqc can know when serverinfo|playerinfo changes (at least for processing blob changes anyway).
Fix 'pkg addsource' not saving (and remsource).



git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5475 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2019-06-17 04:21:41 +00:00
parent b0083491a7
commit 5721e754a6
42 changed files with 961 additions and 443 deletions

View File

@ -67,7 +67,7 @@ cvar_t cl_nopext = CVARF("cl_nopext", "0", CVAR_ARCHIVE);
cvar_t cl_pext_mask = CVAR("cl_pext_mask", "0xffffffff");
cvar_t cl_nolerp = CVARD("cl_nolerp", "0", "Disables interpolation. If set, missiles/monsters will be show exactly what was last received, which will be jerky. Does not affect players. A value of 2 means 'interpolate only in single-player/coop'.");
cvar_t cl_nolerp_netquake = CVARD("cl_nolerp_netquake", "0", "Disables interpolation when connected to an NQ server. Does affect players, even the local player. You probably don't want to set this.");
cvar_t cl_fullpitch_nq = CVARAFD("cl_fullpitch", "0", "pq_fullpitch", CVAR_SEMICHEAT, "When set, attempts to unlimit the default view pitch. Note that some servers will screw over your angles if you use this, resulting in terrible gameplay, while some may merely clamp your angle serverside. This is also considered a cheat in quakeworld, so this will not function there. For the equivelent in quakeworld, use serverinfo minpitch+maxpitch instead, which applies to all players fairly.");
cvar_t cl_fullpitch_nq = CVARAFD("cl_fullpitch", "0", "pq_fullpitch", CVAR_SEMICHEAT, "When set, attempts to unlimit the default view pitch. Note that some servers will screw over your angles if you use this, resulting in terrible gameplay, while some may merely clamp your angle serverside. This is also considered a cheat in quakeworld, ^1so this will not function there^7. For the equivelent in quakeworld, use serverinfo minpitch+maxpitch instead, which applies to all players fairly.");
cvar_t *hud_tracking_show;
cvar_t *hud_miniscores_show;
extern cvar_t net_compress;
@ -2387,6 +2387,8 @@ void CL_CheckServerInfo(void)
if (oldteamplay != cl.teamplay)
Skin_FlushPlayers();
CSQC_ServerInfoChanged();
}
/*
@ -4924,7 +4926,8 @@ void Host_WriteConfiguration (void)
f = FS_OpenVFS(savename, "wb", FS_GAMEONLY);
if (!f)
{
Con_TPrintf (CON_ERROR "Couldn't write config.cfg.\n");
FS_NativePath(savename, FS_GAMEONLY, sysname, sizeof(sysname));
Con_TPrintf (CON_ERROR "Couldn't write %s.\n", sysname);
return;
}

View File

@ -143,7 +143,7 @@ static const char *svc_qwstrings[] =
"svcfte_movepic",
"svcfte_updatepic",
"???",
"NEW PROTOCOL(73)",
"svcfte_effect",
"svcfte_effect2",
@ -165,26 +165,26 @@ static const char *svc_qwstrings[] =
"svcfte_updateentities",
"svcfte_brushedit",
"svcfte_updateseats",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"???",
"svcfte_setinfoblob", //89
"NEW PROTOCOL(90)",
"NEW PROTOCOL(91)",
"NEW PROTOCOL(92)",
"NEW PROTOCOL(93)",
"NEW PROTOCOL(94)",
"NEW PROTOCOL(95)",
"NEW PROTOCOL(96)",
"NEW PROTOCOL(97)",
"NEW PROTOCOL(98)",
"NEW PROTOCOL(99)",
"NEW PROTOCOL(100)",
"NEW PROTOCOL(101)",
"NEW PROTOCOL(102)",
"NEW PROTOCOL(103)",
"NEW PROTOCOL(104)",
"NEW PROTOCOL(105)",
"NEW PROTOCOL(106)",
"NEW PROTOCOL(107)",
"NEW PROTOCOL(108)",
};
#ifdef NQPROT
@ -286,7 +286,8 @@ static const char *svc_nqstrings[] =
"nqsvcfte_setangledelta(85)", //85
"nqsvcfte_updateentities", //86
"NEW PROTOCOL(87)", //87
"NEW PROTOCOL(88)" //88
"NEW PROTOCOL(88)", //88
"svcfte_setinfoblob"//89
};
#endif
@ -5236,6 +5237,8 @@ static void CL_ProcessUserInfo (int slot, player_info_t *player)
CL_NewTranslation (slot);
#endif
Sbar_Changed ();
CSQC_PlayerInfoChanged(slot);
}
/*
@ -5284,7 +5287,11 @@ static void CL_ParseSetInfoBlob (void)
key = InfoBuf_DecodeString(key, key+strlen(key), &keysize);
if (slot-- == 0)
{
InfoBuf_SyncReceive(&cl.serverinfo, key, keysize, val, valsize, offset, final);
if (final)
CL_CheckServerInfo();
}
else if (slot >= MAX_CLIENTS)
Con_Printf("INVALID SETINFO %i: %s=%s\n", slot, key, val);
else

View File

@ -757,7 +757,9 @@ beam_t *CL_NewBeam (int entity, int tag, tentmodels_t *btype)
return NULL;
}
#define STREAM_ATTACHED 16
#define STREAM_ATTACHTOPLAYER 1 //if owned by the viewentity then attach to camera (but don't for other entities).
#define STREAM_JITTER 2 //moves up to 30qu forward/back (40qu per sec)
#define STREAM_ATTACHED 16 //attach it to any entity's origin
#define STREAM_TRANSLUCENT 32
beam_t *CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ numbers instead of 0 - 5
{
@ -847,7 +849,7 @@ beam_t *CL_AddBeam (enum beamtype_e tent, int ent, vec3_t start, vec3_t end) //f
b->entity = ent;
b->info = &beamtypes[tent];
b->tag = -1;
b->bflags |= /*STREAM_ATTACHED|*/1;
b->bflags |= /*STREAM_ATTACHED|*/STREAM_ATTACHTOPLAYER;
b->endtime = cl.time + 0.2;
b->alpha = 1;
VectorCopy (start, b->start);
@ -953,15 +955,15 @@ void CL_ParseStream (int type)
{
case TEH2_STREAM_LIGHTNING_SMALL:
info = &beamtypes[BT_H2LIGHTNING_SMALL];
flags |= 2;
flags |= STREAM_JITTER;
break;
case TEH2_STREAM_LIGHTNING:
info = &beamtypes[BT_H2LIGHTNING];
flags |= 2;
flags |= STREAM_JITTER;
break;
case TEH2_STREAM_ICECHUNKS:
info = &beamtypes[BT_H2ICECHUNKS];
flags |= 2;
flags |= STREAM_JITTER;
if (cl_legacystains.ival) Surf_AddStain(end, -10, -10, 0, 20);
break;
case TEH2_STREAM_SUNSTAFF1:
@ -2832,7 +2834,7 @@ void CL_UpdateBeams (void)
lastrunningbeam = bnum;
// if coming from the player, update the start position
if ((b->bflags & 1) && b->entity > 0 && b->entity <= cl.allocated_client_slots)
if ((b->bflags & STREAM_ATTACHTOPLAYER) && b->entity > 0 && b->entity <= cl.allocated_client_slots)
{
for (j = 0; j < cl.splitclients; j++)
{
@ -2981,7 +2983,7 @@ void CL_UpdateBeams (void)
// add new entities for the lightning
d = VectorNormalize(dist);
if(b->bflags & 2)
if(b->bflags & STREAM_JITTER)
{
offset = (int)(cl.time*40)%30;
for(i = 0; i < 3; i++)

View File

@ -1093,6 +1093,7 @@ void CL_ConnectionlessPacket (void);
qboolean CL_DemoBehind(void);
void CL_SaveInfo(vfsfile_t *f);
void CL_SetInfo (int pnum, const char *key, const char *value);
void CL_SetInfoBlob (int pnum, const char *key, const char *value, size_t valuesize);
void CL_BeginServerConnect(const char *host, int port, qboolean noproxy);
char *CL_TryingToConnect(void);
@ -1433,6 +1434,8 @@ void CSQC_MapEntityEdited(int modelindex, int idx, const char *newe);
qboolean CSQC_ParsePrint(char *message, int printlevel);
qboolean CSQC_ParseGamePacket(int seat);
qboolean CSQC_CenterPrint(int seat, const char *cmd);
void CSQC_ServerInfoChanged(void);
void CSQC_PlayerInfoChanged(int player);
qboolean CSQC_Parse_Damage(int seat, float save, float take, vec3_t source);
qboolean CSQC_Parse_SetAngles(int seat, vec3_t newangles, qboolean wasdelta);
void CSQC_Input_Frame(int seat, usercmd_t *cmd);
@ -1460,6 +1463,8 @@ void CSQC_CvarChanged(cvar_t *var);
#define CSQC_UnconnectedInit() false
#define CSQC_UseGamecodeLoadingScreen() false
#define CSQC_Parse_SetAngles(seat,newangles,wasdelta) false
#define CSQC_ServerInfoChanged() false
#define CSQC_PlayerInfoChanged(player) false
#endif
//

View File

@ -2630,7 +2630,13 @@ void Con_DrawConsole (int lines, qboolean noback)
float x = 0;
// float r = x+w->wnd_w-16;
const char *buttons[] = {"bck", "fwd", "rld", "home", "", ((w->linebuffered == Con_Navigate)?(char*)key_lines[edit_line]:url)};
const char *buttoncmds[] = {"cmd:back", "cmd:forward", "cmd:refresh", ENGINEWEBSITE, NULL, NULL};
const char *buttoncmds[] = {"cmd:back", "cmd:forward", "cmd:refresh",
#ifdef QUAKETC //total conversions should have their own website.
ENGINEWEBSITE
#else //otherwise use some more useful page, for quake mods.
"https://www.quakeworld.nu/wiki/Overview"
#endif
, NULL, NULL};
float tw;
int i, fl;

View File

@ -662,12 +662,17 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_
return NULL;
mul = tgaheader.bpp/8;
*format = (mul==4)?PTI_RGBA8:PTI_RGBX8;;
//flip +convert to 32 bit
if (forceformat==PTI_L8)
{
*format = forceformat;
outrow = &initbuf[(int)(0)*tgaheader.width];
}
else
{
outrow = &initbuf[(int)(0)*tgaheader.width*mul];
*format = (mul==4)?PTI_RGBA8:PTI_RGBX8;
}
for (y = 0; y < tgaheader.height; y+=1)
{
if (flipped)
@ -5885,6 +5890,32 @@ static void Image_4X16to8888(struct pendingtextureinfo *mips)
}
}
//R8,G8,B8,X8 (aligned) -> R8,G8,B8 (tightly packed)
static void Image_32To24(struct pendingtextureinfo *mips)
{
int mip;
for (mip = 0; mip < mips->mipcount; mip++)
{
qbyte *in = mips->mip[mip].data;
qbyte *out = mips->mip[mip].data;
unsigned int w = mips->mip[mip].width;
unsigned int h = mips->mip[mip].height;
unsigned int p = w*h;
if (!mips->mip[mip].needfree && !mips->extrafree)
{
mips->mip[mip].needfree = true;
mips->mip[mip].data = out = BZ_Malloc(sizeof(*out)*p*3);
}
while(p-->0)
{
*out++ = *in++;
*out++ = *in++;
*out++ = *in++;
in++;
}
}
}
//may operate in place
static void Image_8_BGR_RGB_Swap(qbyte *data, unsigned int w, unsigned int h)
{
@ -6541,12 +6572,12 @@ const char *Image_FormatName(uploadfmt_t fmt)
case PTI_ARGB1555: return "ARGB1555";
case PTI_RGBA8: return "RGBA8";
case PTI_RGBX8: return "RGBX8";
case PTI_BGRA8: return "RGBA8";
case PTI_BGRX8: return "RGBX8";
case PTI_BGRA8: return "BGRA8";
case PTI_BGRX8: return "BGRX8";
case PTI_RGBA8_SRGB: return "RGBA8_SRGB";
case PTI_RGBX8_SRGB: return "RGBX8_SRGB";
case PTI_BGRA8_SRGB: return "RGBA8_SRGB";
case PTI_BGRX8_SRGB: return "RGBX8_SRGB";
case PTI_BGRA8_SRGB: return "BGRA8_SRGB";
case PTI_BGRX8_SRGB: return "BGRX8_SRGB";
case PTI_A2BGR10: return "A2BGR10";
case PTI_E5BGR9: return "E5BGR9";
case PTI_R16F: return "R16F";
@ -6948,6 +6979,12 @@ static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int fla
}
if ((mips->encoding == PTI_RGBX8 && sh_config.texfmt[PTI_BGRX8]) ||
(mips->encoding == PTI_BGRX8 && sh_config.texfmt[PTI_BGRX8]))
{
Image_32To24(mips);
mips->encoding = (mips->encoding == PTI_RGBX8)?PTI_RGB8:PTI_BGR8;
}
else if ((mips->encoding == PTI_RGBX8 && sh_config.texfmt[PTI_BGRX8]) ||
(mips->encoding == PTI_BGRX8 && sh_config.texfmt[PTI_RGBX8]) ||
(mips->encoding == PTI_RGBA8 && sh_config.texfmt[PTI_BGRA8]) ||
(mips->encoding == PTI_BGRA8 && sh_config.texfmt[PTI_RGBA8]))
@ -8728,6 +8765,8 @@ image_t *QDECL Image_GetTexture(const char *identifier, const char *subpath, uns
case TF_HEIGHT8PAL: //we don't care about the actual palette.
b *= 1;
break;
// case PTI_LLLX8:
// case PTI_LLLA8:
case TF_RGBX32:
case TF_RGBA32:
case TF_BGRX32:

View File

@ -621,7 +621,7 @@ static void PM_RemSubList(const char *url)
}
}
static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, const char *prefix)
static qboolean PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, const char *prefix)
{
char line[65536];
package_t *p;
@ -634,9 +634,10 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c
int nummirrors = 0;
qboolean isauto;
char *tokstart;
qboolean forcewrite = false;
if (!f)
return;
return forcewrite;
Q_strncpyz(defaultgamedir, FS_GetGamedir(false), sizeof(defaultgamedir));
@ -660,13 +661,13 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c
} while (!Cmd_Argc());
if (strcmp(Cmd_Argv(0), "version"))
return; //it's not the right format.
return forcewrite; //it's not the right format.
version = atoi(Cmd_Argv(1));
if (version != 0 && version != 1 && version != 2)
{
Con_Printf("Packagelist is of a future or incompatible version\n");
return; //it's not the right version.
return forcewrite; //it's not the right version.
}
while(1)
@ -691,6 +692,16 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c
subprefix = va("%s/%s", prefix, com_token);
else
subprefix = com_token;
#ifdef HAVE_LEGACY
//hack. I'm trying to retire the self-signed cert on [fte.]triptohell.info
if (!strcmp(url, "https://triptohell.info/downloadables.php") || !strcmp(url, "https://fte.triptohell.info/downloadables.php"))
{
Q_strncpyz(url, "https://updates.triptohell.info/downloadables.php", sizeof(url));
forcewrite = true;
}
#endif
PM_AddSubList(url, subprefix, (parseflags & DPF_ENABLED)?true:false, (parseflags&DPF_TRUSTED));
continue;
}
@ -722,7 +733,7 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c
{
tokstart = COM_StringParse (tokstart, com_token, sizeof(com_token), false, false);
if (parseflags & DPF_ENABLED) //don't use a downloaded file's version of this, only use the local version of it.
Cvar_ForceSet(&pm_autoupdate, com_token);
Cvar_ForceSet(&pkg_autoupdate, com_token);
}
else if (!strcmp(com_token, "declined"))
{
@ -1041,6 +1052,8 @@ static void PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *url, c
PM_InsertPackage(p);
}
}
return forcewrite;
}
#ifdef PLUGINS
@ -1168,7 +1181,8 @@ static void PM_PreparePackageList(void)
loadedinstalled = true;
if (f)
{
PM_ParsePackageList(f, DPF_FORGETONUNINSTALL|DPF_ENABLED, NULL, "");
if (PM_ParsePackageList(f, DPF_FORGETONUNINSTALL|DPF_ENABLED, NULL, ""))
PM_WriteInstalledPackages();
VFS_CLOSE(f);
}
@ -1232,7 +1246,7 @@ void PM_LoadPackages(searchpath_t **oldpaths, const char *parent_pure, const cha
void PM_Shutdown(void)
{
//free everything...
pm_downloads_url.modified = false;
pkg_downloads_url.modified = false;
downloadablessequence++;
@ -1545,7 +1559,7 @@ unsigned int PM_MarkUpdates (void)
{
if ((p->flags & DPF_ENGINE) && !(p->flags & DPF_HIDDEN))
{
if (!(p->flags & DPF_TESTING) || pm_autoupdate.ival >= UPD_TESTING)
if (!(p->flags & DPF_TESTING) || pkg_autoupdate.ival >= UPD_TESTING)
if (!e || strcmp(e->version, p->version) < 0) //package must be more recent than the previously found engine
if (strcmp(SVNREVISIONSTR, "-") && strcmp(SVNREVISIONSTR, p->version) < 0) //package must be more recent than the current engine too, there's no point auto-updating to an older revision.
e = p;
@ -1557,7 +1571,7 @@ unsigned int PM_MarkUpdates (void)
{
if (p == o || (o->flags & DPF_HIDDEN))
continue;
if (!(o->flags & DPF_TESTING) || pm_autoupdate.ival >= UPD_TESTING)
if (!(o->flags & DPF_TESTING) || pkg_autoupdate.ival >= UPD_TESTING)
if (!strcmp(o->name, p->name) && !strcmp(o->arch?o->arch:"", p->arch?p->arch:"") && strcmp(o->version, p->version) > 0)
{
if (!b || strcmp(b->version, o->version) < 0)
@ -1575,7 +1589,7 @@ unsigned int PM_MarkUpdates (void)
}
if (e && !(e->flags & DPF_MARKED))
{
if (pm_autoupdate.ival >= UPD_STABLE)
if (pkg_autoupdate.ival >= UPD_STABLE)
{
changecount++;
PM_MarkPackage(e, DPF_AUTOMARKED);
@ -1763,14 +1777,14 @@ static void PM_UpdatePackageList(qboolean autoupdate, int retry)
{
unsigned int i;
if (retry>1 || pm_downloads_url.modified)
if (retry>1 || pkg_downloads_url.modified)
PM_Shutdown();
PM_PreparePackageList();
//make sure our sources are okay.
if (*pm_downloads_url.string)
PM_AddSubList(pm_downloads_url.string, "", false, true);
if (*pkg_downloads_url.string)
PM_AddSubList(pkg_downloads_url.string, "", false, true);
#ifndef WEBCLIENT
for (i = 0; i < numdownloadablelists; i++)
@ -1853,14 +1867,14 @@ static void PM_WriteInstalledPackages(void)
vfsfile_t *f = FS_OpenVFS(INSTALLEDFILES, "wb", FS_ROOT);
if (!f)
{
Con_Printf("menu_download: Can't update installed list\n");
Con_Printf("package manager: Can't update installed list\n");
return;
}
s = "version 2\n";
VFS_WRITE(f, s, strlen(s));
s = va("set updatemode %s\n", COM_QuotedString(pm_autoupdate.string, buf, sizeof(buf), false));
s = va("set updatemode %s\n", COM_QuotedString(pkg_autoupdate.string, buf, sizeof(buf), false));
VFS_WRITE(f, s, strlen(s));
s = va("set declined %s\n", COM_QuotedString(declinedpackages?declinedpackages:"", buf, sizeof(buf), false));
VFS_WRITE(f, s, strlen(s));
@ -2900,11 +2914,17 @@ void PM_Command_f(void)
Con_Printf("<%i sources>\n", numdownloadablelists);
}
else
{
PM_AddSubList(Cmd_Argv(2), "", true, true);
PM_WriteInstalledPackages();
}
}
#endif
else if (!strcmp(act, "remsource"))
{
PM_RemSubList(Cmd_Argv(2));
PM_WriteInstalledPackages();
}
else if (!strcmp(act, "apply"))
{
Con_Printf("Applying package changes\n");
@ -3317,7 +3337,7 @@ static void MD_AutoUpdate_Draw (int x, int y, struct menucustom_s *c, struct men
"Test Updates"
};
char *text;
int setting = bound(0, pm_autoupdate.ival, 2);
int setting = bound(0, pkg_autoupdate.ival, 2);
text = va("Auto Update: ^a%s", settings[setting]);
// if (&m->selecteditem->common == &c->common)
// Draw_AltFunString (x, y, text);
@ -3329,9 +3349,9 @@ static qboolean MD_AutoUpdate_Key (struct menucustom_s *c, struct menu_s *m, int
if (key == K_ENTER || key == K_KP_ENTER || key == K_GP_START || key == K_MOUSE1)
{
char nv[8] = "0";
if (pm_autoupdate.ival < UPD_TESTING && pm_autoupdate.ival >= 0)
Q_snprintfz(nv, sizeof(nv), "%i", pm_autoupdate.ival+1);
Cvar_ForceSet(&pm_autoupdate, nv);
if (pkg_autoupdate.ival < UPD_TESTING && pkg_autoupdate.ival >= 0)
Q_snprintfz(nv, sizeof(nv), "%i", pkg_autoupdate.ival+1);
Cvar_ForceSet(&pkg_autoupdate, nv);
PM_WriteInstalledPackages();
PM_UpdatePackageList(true, 0);
@ -3623,7 +3643,7 @@ void Menu_DownloadStuff_f (void)
//should only be called AFTER the filesystem etc is inited.
void Menu_Download_Update(void)
{
if (!pm_autoupdate.ival)
if (!pkg_autoupdate.ival)
return;
PM_UpdatePackageList(true, 2);

View File

@ -5172,7 +5172,7 @@ void Media_Init(void)
Cmd_AddCommand("playclip", Media_PlayVideoWindowed_f);
Cmd_AddCommand("playvideo", Media_PlayFilm_f);
Cmd_AddCommand("playfilm", Media_PlayFilm_f);
Cmd_AddCommand("cinematic", Media_PlayFilm_f);
Cmd_AddCommand("cinematic", Media_PlayFilm_f); //q3: name <1:hold, 2:loop>
#endif
Cmd_AddCommand("music", Media_NamedTrack_f);

View File

@ -991,7 +991,7 @@ const char *presetexec[] =
"r_glsl_offsetmapping 1;"
"r_shadow_realtime_world 1;"
"gl_texture_anisotropic_filtering 16;"
"vid_hardwaregamma 6;" //scene gamma
"vid_hardwaregamma 4;" //scene gamma
};
typedef struct fpsmenuinfo_s

View File

@ -414,37 +414,37 @@ void M_Menu_SinglePlayer_f (void)
//yes, hexen2 has per-class names for the skill levels. because being weird and obtuse is kinda its forte
static char *skillnames[6][4] =
{
{
{ //generic/random
"Easy",
"Medium",
"Hard",
"Nightmare"
},
{
"Apprentice",
{ //barbarian
"Servant", //string changed, because somehow the original is malicious. was: "Apprentice",
"Squire",
"Adept",
"Lord"
},
{
{ //paladin
"Gallant",
"Holy Avenger",
"Divine Hero",
"Legend"
},
{
{ //necromancer
"Sorcerer",
"Dark Servant",
"Warlock",
"Lich King"
},
{
{ //assassin
"Rogue",
"Cutthroat",
"Executioner",
"Widow Maker"
},
{
{ //demoness
"Larva",
"Spawn",
"Fiend",

View File

@ -978,6 +978,79 @@ void QCBUILTIN PF_cl_localsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_
S_LocalSound2(s, chan, vol);
}
void QCBUILTIN PF_cl_getlocaluserinfoblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int seat = G_FLOAT(OFS_PARM0);
const char *keyname = PR_GetStringOfs(prinst, OFS_PARM1);
int qcptr = G_INT(OFS_PARM2);
int qcsize = G_INT(OFS_PARM3);
void *ptr;
const char *blob;
size_t blobsize = 0;
infobuf_t *info;
if (seat < 0 || seat >= MAX_SPLITS)
{
PR_BIError(prinst, "PF_cs_getlocaluserinfoblob: invalid seat\n");
return;
}
info = &cls.userinfo[seat];
if (qcptr < 0 || qcptr+qcsize >= prinst->stringtablesize)
{
PR_BIError(prinst, "PF_cs_getplayerkeyblob: invalid pointer\n");
return;
}
ptr = (struct reverbproperties_s*)(prinst->stringtable + qcptr);
blob = InfoBuf_BlobForKey(info, keyname, &blobsize, NULL);
if (qcptr)
{
blobsize = min(blobsize, qcsize);
memcpy(ptr, blob, blobsize);
G_INT(OFS_RETURN) = blobsize;
}
else
G_INT(OFS_RETURN) = blobsize;
}
void QCBUILTIN PF_cl_getlocaluserinfostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int seat = G_FLOAT(OFS_PARM0);
const char *keyname = PR_GetStringOfs(prinst, OFS_PARM1);
infobuf_t *info;
if (seat < 0 || seat >= MAX_SPLITS)
{
PR_BIError(prinst, "PF_cs_getlocaluserinfoblob: invalid seat\n");
return;
}
info = &cls.userinfo[seat];
RETURN_TSTRING(InfoBuf_ValueForKey(info, keyname));
}
void QCBUILTIN PF_cl_setlocaluserinfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals)
{
int seat = G_FLOAT(OFS_PARM0);
const char *keyname = PR_GetStringOfs(prinst, OFS_PARM1);
if (seat < 0 || seat >= MAX_SPLITS)
{
PR_BIError(prinst, "PF_cs_getlocaluserinfoblob: invalid seat\n");
return;
}
if (prinst->callargc < 4)
CL_SetInfo(seat, keyname, PR_GetStringOfs(prinst, OFS_PARM2));
else
{
int qcptr = G_INT(OFS_PARM2);
int qcsize = G_INT(OFS_PARM3);
const void *ptr;
if (qcptr < 0 || qcptr+qcsize >= prinst->stringtablesize)
{
PR_BIError(prinst, "PF_cs_getplayerkeyblob: invalid pointer\n");
return;
}
ptr = (struct reverbproperties_s*)(prinst->stringtable + qcptr);
CL_SetInfoBlob(seat, keyname, ptr, qcsize);
}
}
#include "fs.h"
static struct modlist_s

View File

@ -128,6 +128,8 @@ extern sfx_t *cl_sfx_r_exp3;
globalfunction(parse_event, "CSQC_Parse_Event"); \
globalfunction(parse_damage, "CSQC_Parse_Damage"); \
globalfunction(parse_setangles, "CSQC_Parse_SetAngles"); \
globalfunction(playerinfochanged, "CSQC_PlayerInfoChanged"); \
globalfunction(serverinfochanged, "CSQC_ServerInfoChanged"); \
globalfunction(input_event, "CSQC_InputEvent"); \
globalfunction(input_frame, "CSQC_Input_Frame");/*EXT_CSQC_1*/ \
globalfunction(rendererrestarted, "CSQC_RendererRestarted"); \
@ -6511,6 +6513,10 @@ static struct {
{"getplayerkeyvalue", PF_cs_getplayerkeystring, 348}, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC)
{"getplayerkeyfloat", PF_cs_getplayerkeyfloat, 0}, // #348 string(float playernum, string keyname) getplayerkeyvalue
{"getplayerkeyblob", PF_cs_getplayerkeyblob, 0}, // #0 int(float playernum, string keyname, optional void *outptr, int size) getplayerkeyblob
{"setlocaluserinfo", PF_cl_setlocaluserinfo, 0},
{"getlocaluserinfo", PF_cl_getlocaluserinfostring, 0},
{"setlocaluserinfoblob", PF_cl_setlocaluserinfo, 0},
{"getlocaluserinfoblob", PF_cl_getlocaluserinfoblob, 0},
{"isdemo", PF_cl_playingdemo, 349}, // #349 float() isdemo (EXT_CSQC)
//350
@ -7576,7 +7582,7 @@ qboolean CSQC_Init (qboolean anycsqc, const char *csprogsname, unsigned int chec
return false;
}
if (csqc_nogameaccess && !PR_FindFunction (csqcprogs, "CSQC_DrawHud", PR_ANY))
if (csqc_nogameaccess && !PR_FindFunction (csqcprogs, "CSQC_DrawHud", PR_ANY) && !PR_FindFunction (csqcprogs, "CSQC_DrawScores", PR_ANY))
{ //simple csqc module is not csqc. abort now.
CSQC_Shutdown();
Con_DPrintf("progs.dat is not suitable for SimpleCSQC - no CSQC_DrawHud\n");
@ -8449,6 +8455,28 @@ static void CSQC_GameCommand_f(void)
PR_ExecuteProgram (csqcprogs, csqcg.gamecommand);
}
void CSQC_PlayerInfoChanged(int player)
{
void *pr_globals;
if (!csqcprogs || !csqcg.playerinfochanged)
return;
pr_globals = PR_globals(csqcprogs, PR_CURRENT);
G_FLOAT(OFS_PARM0) = player;
// (((string_t *)pr_globals)[OFS_PARM1] = PR_TempString(csqcprogs, keyname));
PR_ExecuteProgram (csqcprogs, csqcg.playerinfochanged);
}
void CSQC_ServerInfoChanged(void)
{
// void *pr_globals;
if (!csqcprogs || !csqcg.serverinfochanged)
return;
// pr_globals = PR_globals(csqcprogs, PR_CURRENT);
// (((string_t *)pr_globals)[OFS_PARM0] = PR_TempString(csqcprogs, keyname));
PR_ExecuteProgram (csqcprogs, csqcg.serverinfochanged);
}
qboolean CSQC_ParseTempEntity(void)
{
int orc;

View File

@ -2367,6 +2367,13 @@ static struct {
{"digest_hex", PF_digest_hex, 639},
{"digest_ptr", PF_digest_ptr, 0},
{"crypto_getmyidstatus", PF_crypto_getmyidfp, 641},
{"setlocaluserinfo", PF_cl_setlocaluserinfo, 0},
{"getlocaluserinfo", PF_cl_getlocaluserinfostring, 0},
{"setlocaluserinfoblob", PF_cl_setlocaluserinfo, 0},
{"getlocaluserinfoblob", PF_cl_getlocaluserinfoblob, 0},
{NULL}
};
static builtin_t menu_builtins[1024];

View File

@ -305,8 +305,8 @@ extern qboolean noclip_anglehack;
extern quakeparms_t host_parms;
extern cvar_t fs_gamename;
extern cvar_t pm_downloads_url;
extern cvar_t pm_autoupdate;
extern cvar_t pkg_downloads_url;
extern cvar_t pkg_autoupdate;
extern cvar_t com_protocolname;
extern cvar_t com_protocolversion;
extern cvar_t com_nogamedirnativecode;

View File

@ -45,6 +45,7 @@ struct
{
lmalloc_t allocation;
qboolean dirty;
uploadfmt_t fmt;
int lastid;
unsigned int *data;
shader_t *shader;
@ -480,8 +481,9 @@ apic_t *R2D_LoadAtlasedPic(const char *name)
{
atlas.lastid = atlasid;
if (atlas.dirty)
Image_Upload(atlas.tex, TF_BGRA32, atlas.data, NULL, atlas.allocation.width, atlas.allocation.height, IF_NOMIPMAP);
Image_Upload(atlas.tex, atlas.fmt, atlas.data, NULL, atlas.allocation.width, atlas.allocation.height, IF_NOMIPMAP);
atlas.tex = r_nulltex;
atlas.fmt = sh_config.texfmt[PTI_BGRA8]?PTI_BGRA8:PTI_RGBA8;
atlas.shader = NULL;
atlas.dirty = false;
if (atlas.data) //clear atlas data instead of reallocating it.
@ -515,25 +517,50 @@ apic_t *R2D_LoadAtlasedPic(const char *name)
out += apic->y * atlas.allocation.width;
apic->atlas = atlas.shader;
//pad above. extra casts because 64bit msvc is RETARDED.
out[-1 - (qintptr_t)atlas.allocation.width] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x-(qintptr_t)atlas.allocation.width] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]];
out[x - (qintptr_t)atlas.allocation.width] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right
for (y = 0; y < apic->height; y++)
if (atlas.fmt == PTI_BGRA8)
{
//pad above. extra casts because 64bit msvc is RETARDED.
out[-1 - (qintptr_t)atlas.allocation.width] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x-(qintptr_t)atlas.allocation.width] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]];
out[x - (qintptr_t)atlas.allocation.width] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right
for (y = 0; y < apic->height; y++)
{
out[-1] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]];
out[x] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right
indata += x;
out += atlas.allocation.width;
}
//pad below
out[-1] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]];
out[x] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right
indata += x;
out += atlas.allocation.width;
}
//pad below
out[-1] = (indata[0] == 255)?0:d_8to24bgrtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x] = (indata[x] == 255)?0:d_8to24bgrtable[indata[x]];
out[x] = (indata[x-1] == 255)?0:d_8to24bgrtable[indata[x-1]]; //pad right
else
{
//pad above. extra casts because 64bit msvc is RETARDED.
out[-1 - (qintptr_t)atlas.allocation.width] = (indata[0] == 255)?0:d_8to24rgbtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x-(qintptr_t)atlas.allocation.width] = (indata[x] == 255)?0:d_8to24rgbtable[indata[x]];
out[x - (qintptr_t)atlas.allocation.width] = (indata[x-1] == 255)?0:d_8to24rgbtable[indata[x-1]]; //pad right
for (y = 0; y < apic->height; y++)
{
out[-1] = (indata[0] == 255)?0:d_8to24rgbtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x] = (indata[x] == 255)?0:d_8to24rgbtable[indata[x]];
out[x] = (indata[x-1] == 255)?0:d_8to24rgbtable[indata[x-1]]; //pad right
indata += x;
out += atlas.allocation.width;
}
//pad below
out[-1] = (indata[0] == 255)?0:d_8to24rgbtable[indata[0]]; //pad left
for (x = 0; x < apic->width; x++)
out[x] = (indata[x] == 255)?0:d_8to24rgbtable[indata[x]];
out[x] = (indata[x-1] == 255)?0:d_8to24rgbtable[indata[x-1]]; //pad right
}
//pinch inwards, for linear sampling
apic->sl = (apic->x+0.5)/(float)atlas.allocation.width;
@ -593,7 +620,7 @@ void R2D_ImageAtlas(float x, float y, float w, float h, float s1, float t1, floa
return;
if (atlas.dirty)
{
Image_Upload(atlas.tex, TF_BGRA32, atlas.data, NULL, atlas.allocation.width, atlas.allocation.height, IF_NOMIPMAP);
Image_Upload(atlas.tex, atlas.fmt, atlas.data, NULL, atlas.allocation.width, atlas.allocation.height, IF_NOMIPMAP);
atlas.dirty = false;
}

View File

@ -4162,13 +4162,13 @@ void Surf_NewMap (void)
CL_RegisterParticles();
Shader_DoReload();
if (cl.worldmodel)
{
if (cl.worldmodel->loadstate == MLS_LOADING)
COM_WorkerPartialSync(cl.worldmodel, &cl.worldmodel->loadstate, MLS_LOADING);
Mod_ParseInfoFromEntityLump(cl.worldmodel);
}
Shader_DoReload();
if (!pe)
Cvar_ForceCallback(&r_particlesystem);

View File

@ -51,7 +51,7 @@ void QDECL SCR_Fov_Callback (struct cvar_s *var, char *oldvalue);
void QDECL Image_TextureMode_Callback (struct cvar_s *var, char *oldvalue);
void QDECL R_SkyBox_Changed (struct cvar_s *var, char *oldvalue)
{
Shader_NeedReload(false);
// Shader_NeedReload(false);
}
void R_ForceSky_f(void)
{
@ -472,7 +472,7 @@ cvar_t gl_screenangle = CVAR("gl_screenangle", "0");
#endif
#ifdef VKQUAKE
cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u, e, v, 0.");
cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u(niform), e(lements), v(ertex), 0(none).");
cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers.");
cvar_t vk_debug = CVARFD("vk_debug", "0", CVAR_VIDEOLATCH, "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers.");
cvar_t vk_dualqueue = CVARFD("vk_dualqueue", "", CVAR_VIDEOLATCH, "Attempt to use a separate queue for presentation. Blank for default.");
@ -1795,9 +1795,6 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
// Skin_FlushAll();
Skin_FlushPlayers();
#ifdef CSQC_DAT
CSQC_RendererRestarted();
#endif
}
else
{
@ -1809,6 +1806,10 @@ TRACE(("dbg: R_ApplyRenderer: efrags\n"));
#ifdef SKELETALOBJECTS
skel_reload();
#endif
#ifdef CSQC_DAT
Shader_DoReload();
CSQC_RendererRestarted();
#endif
if (newr && qrenderer != QR_NONE)
{

View File

@ -16,17 +16,8 @@
#error ANDROID wasnt defined
#endif
#if 0
//FIXME: remove the nativeactivity shit. android's standard NativeActivity class is buggy and basically fucked.
#include <android/keycodes.h>
#include <android/native_window_jni.h>
// ANativeWindow_fromSurface((jobject)getSurfaceHolder().getSurface())
#else
//NOTE: This is apache 2.0, which means GPL3.0+ ONLY, no gpl2.
#include <../../../../../sources/android/native_app_glue/android_native_app_glue.h> //Fucking frameworks suck big hairy donkey balls.
JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize);
#include <../../../../../sources/android/native_app_glue/android_native_app_glue.c> //Fucking frameworks suck big hairy donkey balls.
#endif
#ifndef isDedicated
#ifdef SERVERONLY
@ -39,21 +30,29 @@ extern int r_blockvidrestart;
float sys_dpi_x, sys_dpi_y;
static void *sys_memheap;
//static unsigned int vibrateduration;
static char sys_binarydir[MAX_OSPATH];
static char sys_basedir[MAX_OSPATH];
static char sys_basepak[MAX_OSPATH];
extern jmp_buf host_abort;
extern qboolean r_forceheadless;
static qboolean r_forcevidrestart;
ANativeWindow *sys_nativewindow;
static struct android_app *android_app_state; //basically used only for errors.
//cvar_t sys_vibrate = CVARFD("sys_vibrate", "1", CVAR_ARCHIVE, "Enables the system vibrator for damage events and such things. The value provided is a duration scaler.");
cvar_t sys_osk = CVAR("sys_osk", "0"); //to be toggled
cvar_t sys_keepscreenon = CVARFD("sys_keepscreenon", "1", CVAR_ARCHIVE, "If set, the screen will never darken. This might cost some extra battery power, but then so will running a 3d engine."); //to be toggled
static cvar_t sys_osk = CVAR("sys_osk", "0"); //to be toggled
static cvar_t sys_keepscreenon = CVARFD("sys_keepscreenon", "1", CVAR_ARCHIVE, "If set, the screen will never darken. This might cost some extra battery power, but then so will running a 3d engine."); //to be toggled
cvar_t sys_orientation = CVARFD("sys_orientation", "landscape", CVAR_ARCHIVE, "Specifies what angle to render quake at.\nValid values are: sensor (autodetect), landscape, portrait, reverselandscape, reverseportrait");
extern cvar_t vid_conautoscale;
void VID_Register(void);
static qboolean sys_wantshutdown;
static JavaVM* sys_javavm;
static jobject *sys_activity;
static jobject *sys_cursurface; //surface we're currently trying to draw to
static jobject *sys_newsurface; //surface we're meant to be switching our gl context to
static void *sys_mainthread;
static void *sys_mainconditional;
#undef LOGI
#undef LOGW
#undef LOGE
@ -390,52 +389,12 @@ static int mapkey(int androidkey)
return 0;
}
static int32_t engine_handle_input(struct android_app *app, AInputEvent *event)
#if 0
static void run_intent_url(void)
{
switch(AInputEvent_getType(event))
{
case AINPUT_EVENT_TYPE_MOTION:
case AINPUT_EVENT_TYPE_KEY:
return 0; //we handle these in the java code, so shouldn't ever see them.
}
return 0; //no idea what sort of event it is.
}
static void engine_handle_cmd(struct android_app *app, int32_t cmd)
{
switch(cmd)
{
case APP_CMD_SAVE_STATE:
//FIXME: implement save-game-to-memory...
break;
case APP_CMD_INIT_WINDOW:
if (sys_nativewindow != app->window)
{
sys_nativewindow = app->window;
r_forceheadless = (sys_nativewindow==NULL);
r_forcevidrestart = true;
}
break;
case APP_CMD_TERM_WINDOW:
r_forceheadless = true;
if (qrenderer && !r_forcevidrestart && sys_nativewindow)
R_RestartRenderer_f();
sys_nativewindow = NULL;
break;
case APP_CMD_GAINED_FOCUS:
vid.activeapp = true;
break;
case APP_CMD_LOST_FOCUS:
vid.activeapp = false;
break;
}
}
static void run_intent_url(struct android_app *app)
{
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jobject intent = (*jni)->CallObjectMethod(jni, act, (*jni)->GetMethodID(jni, (*jni)->GetObjectClass(jni, act), "getIntent", "()Landroid/content/Intent;"));
if (intent)
@ -463,16 +422,17 @@ static void run_intent_url(struct android_app *app)
}
}
//FIXME: do we need to release methodids/objects?
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
}
#endif
static qboolean read_apk_path(struct android_app *app, char *out, size_t outsize)
static qboolean read_apk_path(char *out, size_t outsize)
{
qboolean res = false;
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jstring result = (*jni)->CallObjectMethod(jni, act, (*jni)->GetMethodID(jni, (*jni)->GetObjectClass(jni, act), "getPackageCodePath", "()Ljava/lang/String;"));
const char *tmp = (*jni)->GetStringUTFChars(jni, result, NULL);
@ -484,70 +444,70 @@ static qboolean read_apk_path(struct android_app *app, char *out, size_t outsize
}
//FIXME: do we need to release methodids/objects?
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
return res;
}
static void setsoftkeyboard(struct android_app *app, int flags)
static void setsoftkeyboard(int flags)
{ //the NDK is unusably buggy when it comes to keyboards, so call into java.
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jmethodID func = (*jni)->GetMethodID(jni, (*jni)->GetObjectClass(jni, act), "showKeyboard", "(I)V" );
if (func)
(*jni)->CallVoidMethod(jni, act, func, flags);
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
}
static void showMessageAndQuit(struct android_app *app, const char *errormsg)
static void showMessageAndQuit(const char *errormsg)
{ //no nice way to do this from native.
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jmethodID func = (*jni)->GetMethodID(jni, (*jni)->GetObjectClass(jni, act), "showMessageAndQuit", "(Ljava/lang/String;)V" );
if (func)
(*jni)->CallVoidMethod(jni, act, func, (*jni)->NewStringUTF(jni, errormsg));
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
}
static void updateOrientation(struct android_app *app, const char *neworientation)
static void updateOrientation(const char *neworientation)
{ //no nice way to do this from native.
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jmethodID func = (*jni)->GetMethodID(jni, (*jni)->GetObjectClass(jni, act), "updateOrientation", "(Ljava/lang/String;)V" );
if (func)
(*jni)->CallVoidMethod(jni, act, func, (*jni)->NewStringUTF(jni, neworientation));
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
}
static void updateScreenKeepOn(struct android_app *app, jboolean keepon)
static void updateScreenKeepOn(jboolean keepon)
{ //the NDK is unusably buggy when it comes to keyboards, so call into java.
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jmethodID func = (*jni)->GetMethodID(jni, (*jni)->GetObjectClass(jni, act), "updateScreenKeepOn", "(Z)V" );
if (func)
(*jni)->CallVoidMethod(jni, act, func, keepon);
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
}
static void setCursorVisibility(struct android_app *app, jboolean visible)
static void setCursorVisibility(jboolean visible)
{ //this is meant to use the nvidia-added setCursorVisibility function
//but its fatal if it doesn't exist, and it doesn't seem to exist.
#if 0
jobject act = app->activity->clazz;
jobject act = sys_activity;
JNIEnv *jni;
if (JNI_OK == (*app->activity->vm)->AttachCurrentThread(app->activity->vm, &jni, NULL))
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &jni, NULL))
{
jobject inputManager = NULL;
jmethodID setvis = NULL;
@ -559,7 +519,7 @@ static void setCursorVisibility(struct android_app *app, jboolean visible)
if (setvis)
(*jni)->CallVoidMethod(jni, inputManager, setvis, visible);
(*app->activity->vm)->DetachCurrentThread(app->activity->vm);
(*sys_javavm)->DetachCurrentThread(sys_javavm);
}
#endif
}
@ -634,42 +594,14 @@ static void FTENativeActivity_axis(JNIEnv *env, jobject this, jint devid, jint a
//{
// IN_Gyroscope(devid, pitch, yaw, roll);
//}
static JNINativeMethod methods[] = {
{"keypress", "(IZII)V", FTENativeActivity_keypress},
{"mousepress", "(II)V", FTENativeActivity_mousepress},
{"motion", "(IIFFFF)V", FTENativeActivity_motion},
{"wantrelative", "()Z", FTENativeActivity_wantrelative}, //so the java code knows if it should use (often buggy) relative mouse movement or (limited) abs cursor coords.
{"axis", "(IIF)V", FTENativeActivity_axis},
// {"accelerometer", "(IFFF)V", FTENativeActivity_accelerometer},
// {"gyroscope", "(IFFF)V", FTENativeActivity_gyroscope},
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *jni;
if (JNI_OK == (*vm)->GetEnv(vm, (void**)&jni, JNI_VERSION_1_2))
{
jclass naclass = (*jni)->FindClass(jni, "com/fteqw/FTENativeActivity");
if (naclass)
{
(*jni)->RegisterNatives(jni, naclass, methods, countof(methods));
return JNI_VERSION_1_2;
}
}
return -1;
}
void android_main(struct android_app *state)
static int FTEDroid_MainThread(void *arg)
{
static pthread_mutex_t onemainthread = PTHREAD_MUTEX_INITIALIZER; //android likes spawning multiple 'main' threads
int osk = 0, wantgrabs = 0, t;
double ltime,ctime,tdelta;
pthread_mutex_lock(&onemainthread);
android_app_state = state;
state->userData = NULL;
state->onAppCmd = engine_handle_cmd;
state->onInputEvent = engine_handle_input;
double newtime,oldtime=Sys_DoubleTime(), time, sleeptime;
r_forceheadless = true;
sys_nativewindow = NULL;
vid.activeapp = true;
if (!host_initialized)
{
@ -685,8 +617,9 @@ void android_main(struct android_app *state)
if (sys_memheap)
free(sys_memheap);
memset(&parms, 0, sizeof(parms));
parms.binarydir = sys_binarydir;
parms.basedir = sys_basedir; /*filled in later*/
parms.argc = read_apk_path(state, sys_basepak, sizeof(sys_basepak))?3:1;
parms.argc = read_apk_path(sys_basepak, sizeof(sys_basepak))?3:1;
parms.argv = args;
#ifdef CONFIG_MANIFEST_TEXT
parms.manifest = CONFIG_MANIFEST_TEXT;
@ -694,13 +627,6 @@ void android_main(struct android_app *state)
sys_dpi_x = 72; //no idea
sys_dpi_y = 72; //no idea
#if 0 //google made this a fucking pain.
Q_strncpyz(sys_basedir, getenv("EXTERNAL_STORAGE"), sizeof(sys_basedir));
Q_strncatz(sys_basedir, "/fte", sizeof(sys_basedir));
#else //so now users have to use some big long path to install stuff instead
Q_strncpyz(sys_basedir, state->activity->externalDataPath, sizeof(sys_basedir));
#endif
Sys_Printf("Starting up (apk=%s, usr=%s)\n", sys_basepak, parms.basedir);
VID_Register();
@ -712,89 +638,121 @@ void android_main(struct android_app *state)
}
else
Sys_Printf("Restarting up!\n");
ltime = Sys_DoubleTime();
sys_orientation.modified = false;
updateOrientation(state, sys_orientation.string);
updateOrientation(sys_orientation.string);
sys_keepscreenon.modified = false;
updateScreenKeepOn(state, sys_keepscreenon.ival);
updateScreenKeepOn(sys_keepscreenon.ival);
run_intent_url(state);
if (state->savedState != NULL)
// run_intent_url();
/*if (state->savedState != NULL)
{ //oh look, we're pretending to already be running...
//oh.
}
}*/
for(;;)
//we're sufficiently done loading. let the ui thread resume.
Sys_LockConditional(sys_mainconditional);
Sys_ConditionSignal(sys_mainconditional);
Sys_UnlockConditional(sys_mainconditional);
while (!sys_wantshutdown)
{
int ident, events;
struct android_poll_source *source;
while((ident=ALooper_pollAll(vid.activeapp?0:250, NULL, &events, (void**)&source)) >= 0)
//handle things if the UI thread is blocking for us (video restarts)
Sys_LockConditional(sys_mainconditional);
if (r_forcevidrestart)
{
if (source != NULL)
source->process(state, source);
ANativeWindow *oldwnd = NULL;
jobject oldsurf = NULL;
JNIEnv *env = NULL;
if (JNI_OK == (*sys_javavm)->AttachCurrentThread(sys_javavm, &env, NULL))
{
oldsurf = sys_cursurface;
sys_cursurface = (*env)->NewGlobalRef(env, sys_newsurface);
//FIXME: sensor crap
oldwnd = sys_nativewindow;
if (sys_cursurface)
sys_nativewindow = ANativeWindow_fromSurface(env, sys_cursurface);
else
sys_nativewindow = NULL;
ANativeWindow_acquire(sys_nativewindow);
}
if (state->destroyRequested != 0)
{
Sys_Printf("Shutdown requested\n");
Host_Shutdown ();
pthread_mutex_unlock(&onemainthread);
return;
}
}
if (host_initialized)
{
if (r_forcevidrestart)
{
if (qrenderer)
R_RestartRenderer_f();
r_forcevidrestart = false;
}
if (sys_nativewindow)
{
ctime = Sys_DoubleTime();
tdelta = ctime-ltime;
ltime = ctime;
Host_Frame(tdelta);
}
r_forceheadless = r_forcevidrestart&1;
r_forcevidrestart = 0;
Sys_ConditionSignal(sys_mainconditional); //let the java ui thread thread wake up now that we've got a handle to the new+old surfaces
Sys_UnlockConditional(sys_mainconditional);
LOGI("Video Restart...\n");
R_RestartRenderer_f();
LOGI("Video Restarted...\n");
//main thread can wake up now.
if (oldsurf)
(*env)->DeleteGlobalRef(env, oldsurf);
if (oldwnd)
ANativeWindow_release(oldwnd);
if (env)
(*sys_javavm)->DetachCurrentThread(sys_javavm);
continue;
}
if (sys_nativewindow && vid.activeapp && !r_forcevidrestart)
{
// find time spent rendering last frame
newtime = Sys_DoubleTime ();
time = newtime - oldtime;
sleeptime = Host_Frame(time);
oldtime = newtime;
if (sleeptime)
Sys_Sleep(sleeptime);
}
else
sleeptime = 0.25;
Sys_UnlockConditional(sys_mainconditional);
t = 0;
if (Key_Dest_Has(kdm_console|kdm_message))
t |= ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT;
if (!Key_Dest_Has(~kdm_game) && cls.state == ca_disconnected)
t |= ANATIVEACTIVITY_SHOW_SOFT_INPUT_IMPLICIT;
if (sys_osk.ival)
t |= ANATIVEACTIVITY_SHOW_SOFT_INPUT_FORCED;
if (sys_osk.ival >= 0)
{
if (Key_Dest_Has(kdm_console|kdm_message))
t |= 1;
if (!Key_Dest_Has(~kdm_game) && cls.state == ca_disconnected)
t |= 1;
if (sys_osk.ival)
t |= 2;
}
if (osk != t)
{
setsoftkeyboard(state, t);
setsoftkeyboard(t);
osk = t;
}
if (sys_orientation.modified)
{
sys_orientation.modified = false;
updateOrientation(state, sys_orientation.string);
updateOrientation(sys_orientation.string);
}
if (sys_keepscreenon.modified)
{
sys_keepscreenon.modified = false;
updateScreenKeepOn(state, sys_keepscreenon.ival);
updateScreenKeepOn(sys_keepscreenon.ival);
}
t = FTENativeActivity_wantrelative(NULL,NULL);
if (wantgrabs != t)
{
wantgrabs = t;
setCursorVisibility(state, wantgrabs);
setCursorVisibility(wantgrabs);
}
if (sleeptime)
Sys_Sleep(sleeptime);
}
return 0;
}
static int secbase;
@ -870,7 +828,7 @@ void Sys_Quit(void)
#endif
LOGI("%s", "quitting");
showMessageAndQuit(android_app_state, "");
showMessageAndQuit("");
longjmp(host_abort, 1);
exit(0);
@ -888,7 +846,7 @@ void Sys_Error (const char *error, ...)
strcpy(string, "no error");
LOGE("e: %s", string);
showMessageAndQuit(android_app_state, string);
showMessageAndQuit(string);
host_initialized = false; //don't keep calling Host_Frame, because it'll screw stuff up more. Can't trust Host_Shutdown either. :(
vid.activeapp = false; //make sure we don't busyloop.
@ -954,6 +912,11 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
h = dlopen(va("%s.so", name), RTLD_LAZY|RTLD_LOCAL);
if (!h)
h = dlopen(name, RTLD_LAZY|RTLD_LOCAL);
if (!h)
{
Con_DLPrintf(2,"%s\n", dlerror());
return NULL;
}
if (h && funcs)
{
@ -965,6 +928,7 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs)
}
if (funcs[i].name)
{
Con_DPrintf("Unable to find symbol \"%s\" in \"%s\"\n", funcs[i].name, name);
Sys_CloseLibrary(h);
h = NULL;
}
@ -1162,3 +1126,142 @@ int Sys_EnumerateFiles (const char *gpath, const char *match, int (*func)(const
return true;
}
static jboolean FTENativeActivity_startup(JNIEnv *jni, jobject this, jstring externalDataPath, jstring libraryPath)
{
const char *tmp;
if (sys_mainthread)
return false;
if (!sys_activity)
{
sys_activity = (*jni)->NewGlobalRef(jni, this);
tmp = (*jni)->GetStringUTFChars(jni, externalDataPath, NULL);
if (tmp)
{
Q_strncpyz(sys_basedir, tmp, sizeof(sys_basedir));
if (*sys_basedir && sys_basedir[strlen(sys_basedir)-1] != '/')
Q_strncatz(sys_basedir, "/", sizeof(sys_basedir));
(*jni)->ReleaseStringUTFChars(jni, externalDataPath, tmp);
}
else
*sys_basedir = 0;
tmp = (*jni)->GetStringUTFChars(jni, libraryPath, NULL);
if (tmp)
{
Q_strncpyz(sys_binarydir, tmp, sizeof(sys_binarydir));
if (*sys_binarydir && sys_binarydir[strlen(sys_binarydir)-1] != '/')
Q_strncatz(sys_binarydir, "/", sizeof(sys_binarydir));
(*jni)->ReleaseStringUTFChars(jni, libraryPath, tmp);
}
else
*sys_binarydir = 0;
LOGI("FTENativeActivity_startup: basedir=%s binarydir=%s\n", sys_basedir, sys_binarydir);
sys_wantshutdown = false;
sys_mainconditional = Sys_CreateConditional();
Sys_LockConditional(sys_mainconditional);
sys_mainthread = Sys_CreateThread("ftedroid", FTEDroid_MainThread, NULL, THREADP_NORMAL, -1);
if (sys_mainthread)
Sys_ConditionWait(sys_mainconditional);
Sys_UnlockConditional(sys_mainconditional);
return !!sys_mainthread;
}
LOGI("conflicting FTENativeActivity_startup. ignoring.\n");
return false;
}
static void FTENativeActivity_surfacechange(JNIEnv *env, jobject this, jboolean teardown, jboolean recreate, jobject surface)
{
if (this == sys_activity)
{
LOGI("FTENativeActivity_surfacechange: inactive %p, active %p\n", this, sys_activity);
return; //wasn't me...
}
LOGI("FTENativeActivity_surfacechange: %i %i %p\n", teardown, recreate, surface);
//FIXME: if teardown&&recreate then this is a window RESIZE.
//there shouldn't be a need to destroy the entire context but anbox crashes when simply moving the window if we early out here.
// if (teardown && recreate && (*env)->IsSameObject(env, surface, sys_newsurface))
// return;
// LOGI("FTENativeActivity_surfacechange: %i %i (%p==%p)==%i\n", teardown, recreate, surface, sys_newsurface, (*env)->IsSameObject(env, surface, sys_newsurface));
Sys_LockConditional(sys_mainconditional);
//get the main thread to let us know when its done...
if (qrenderer || (r_forceheadless && recreate))
r_forcevidrestart = recreate?2:1;
if (sys_newsurface)
(*env)->DeleteGlobalRef(env, sys_newsurface);
sys_newsurface = surface?(*env)->NewGlobalRef(env, surface):NULL;
//and wake up then
Sys_ConditionWait(sys_mainconditional);
//and we're done...
Sys_UnlockConditional(sys_mainconditional);
}
static void FTENativeActivity_shutdown(JNIEnv *env, jobject this)
{
if (this != sys_activity)
{
LOGI("FTENativeActivity_shutdown: inactive %p, active %p\n", this, sys_activity);
return; //wasn't me...
}
LOGI("FTENativeActivity_shutdown\n");
sys_wantshutdown = true;
if (sys_mainthread)
Sys_WaitOnThread(sys_mainthread);
sys_mainthread = NULL;
if (sys_mainconditional)
Sys_DestroyConditional(sys_mainconditional);
sys_mainconditional = NULL;
(*env)->DeleteGlobalRef(env, sys_newsurface);
sys_newsurface = NULL;
(*env)->DeleteGlobalRef(env, sys_activity);
sys_activity = NULL;
}
//FIXME: we need a version of this that takes a byte array instead of a filename, for android's content gibberish.
static void FTENativeActivity_openfile(JNIEnv *env, jobject this, jstring filename)
{
const char *tmp = (*env)->GetStringUTFChars(env, filename, NULL);
if (tmp)
{
Sys_Printf("FTENativeActivity_openfile: %s\n", tmp);
Host_RunFile(tmp, strlen(tmp), NULL);
(*env)->ReleaseStringUTFChars(env, filename, tmp);
}
}
static JNINativeMethod methods[] = {
//
{"startup", "(Ljava/lang/String;Ljava/lang/String;)Z", FTENativeActivity_startup}, //creates our 'main' thread too
{"surfacechange", "(ZZLandroid/view/Surface;)V", FTENativeActivity_surfacechange}, //syncs
{"shutdown", "()V", FTENativeActivity_shutdown}, //joins 'main' thread.
{"openfile", "(Ljava/lang/String;)V", FTENativeActivity_openfile},
//inputs. these use our in_generic.c ringbuffer so don't need to sync at all
{"keypress", "(IZII)V", FTENativeActivity_keypress},
{"mousepress", "(II)V", FTENativeActivity_mousepress},
{"motion", "(IIFFFF)V", FTENativeActivity_motion},
{"wantrelative", "()Z", FTENativeActivity_wantrelative}, //so the java code knows if it should use (often buggy) relative mouse movement or (limited) abs cursor coords.
{"axis", "(IIF)V", FTENativeActivity_axis},
// {"accelerometer", "(IFFF)V", FTENativeActivity_accelerometer},
// {"gyroscope", "(IFFF)V", FTENativeActivity_gyroscope},
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *jni;
sys_javavm = vm;
if (JNI_OK == (*vm)->GetEnv(vm, (void**)&jni, JNI_VERSION_1_2))
{
jclass naclass = (*jni)->FindClass(jni, "com/fteqw/FTENativeActivity");
if (naclass)
{
(*jni)->RegisterNatives(jni, naclass, methods, countof(methods));
return JNI_VERSION_1_2;
}
}
return -1;
}

View File

@ -174,7 +174,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define FULLENGINENAME "FTE Quake" //the posh name for the engine
#endif
#ifndef ENGINEWEBSITE
#define ENGINEWEBSITE "http://fte.triptohell.info" //url for program
#define ENGINEWEBSITE "^8http://^4fte.triptohell.info" //url for program
#endif
#if !defined(_WIN32) || defined(WINRT)

View File

@ -132,8 +132,11 @@ cvar_t ezcompat_markup = CVARD("ezcompat_markup", "1", "Attempt compatibility wi
cvar_t com_highlightcolor = CVARD("com_highlightcolor", STRINGIFY(COLOR_RED), "ANSI colour to be used for highlighted text, used when com_parseutf8 is active.");
cvar_t com_nogamedirnativecode = CVARFD("com_nogamedirnativecode", "1", CVAR_NOTFROMSERVER, FULLENGINENAME" blocks all downloads of files with a .dll or .so extension, however other engines (eg: ezquake and fodquake) do not - this omission can be used to trigger delayed eremote exploits in any engine (including "DISTRIBUTION") which is later run from the same gamedir.\nQuake2, Quake3(when debugging), and KTX typically run native gamecode from within gamedirs, so if you wish to run any of these games you will need to ensure this cvar is changed to 0, as well as ensure that you don't run unsafe clients.");
cvar_t sys_platform = CVAR("sys_platform", PLATFORM);
cvar_t pm_downloads_url = CVARFD("pm_downloads_url", NULL, CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "The URL of a package updates list."); //read from the default.fmf
cvar_t pm_autoupdate = CVARFD("pm_autoupdate", "1", CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "Controls autoupdates, can only be changed via the downloads menu.\n0: off.\n1: enabled (stable only).\n2: enabled (unstable).\nNote that autoupdate will still prompt the user to actually apply the changes."); //read from the package list only.
cvar_t pkg_downloads_url = CVARFD("pkg_downloads_url", NULL, CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "The URL of a package updates list."); //read from the default.fmf
cvar_t pkg_autoupdate = CVARFD("pkg_autoupdate", "1", CVAR_NOTFROMSERVER|CVAR_NOSAVE|CVAR_NOSET, "Controls autoupdates, can only be changed via the downloads menu.\n0: off.\n1: enabled (stable only).\n2: enabled (unstable).\nNote that autoupdate will still prompt the user to actually apply the changes."); //read from the package list only.
#ifdef HAVE_LEGACY
cvar_t pm_noround = CVARD("pm_noround", "0", "Disables player prediction snapping, in a way that cannot be reliably predicted but may be needed to avoid map bugs.");
#endif
qboolean com_modified; // set true if using non-id files
@ -4806,7 +4809,7 @@ static void COM_Version_f (void)
{
Con_Printf("\n");
Con_Printf("^&F0%s\n", FULLENGINENAME);
Con_Printf("^[%s\\url\\%s^]\n", ENGINEWEBSITE, ENGINEWEBSITE);
Con_Printf("^4"ENGINEWEBSITE"\n");
Con_Printf("%s\n", version_string());
Con_TPrintf ("Exe: %s %s\n", __DATE__, __TIME__);
@ -5819,6 +5822,7 @@ void COM_Init (void)
Cvar_Register (&com_parseutf8, "Internationalisation");
#ifdef HAVE_LEGACY
Cvar_Register (&ezcompat_markup, NULL);
Cvar_Register (&pm_noround, NULL);
#endif
Cvar_Register (&com_highlightcolor, "Internationalisation");
com_parseutf8.ival = 1;

View File

@ -1068,7 +1068,9 @@ static void QDECL FS_AddFileHash(int depth, const char *fname, fsbucket_t *fileh
if (!filehandle)
{
int nlen = strlen(fname)+1;
if (!fs_hash_filebuckets || fs_hash_filebuckets->used+sizeof(*filehandle)+nlen > fs_hash_filebuckets->total)
int plen = sizeof(*filehandle)+nlen;
plen = (plen+__alignof(*filehandle)-1) & ~(__alignof(*filehandle)-1);
if (!fs_hash_filebuckets || fs_hash_filebuckets->used+plen > fs_hash_filebuckets->total)
{
void *o = fs_hash_filebuckets;
fs_hash_filebuckets = Z_Malloc(65536);
@ -1076,7 +1078,7 @@ static void QDECL FS_AddFileHash(int depth, const char *fname, fsbucket_t *fileh
fs_hash_filebuckets->prev = o;
}
filehandle = (fsbucket_t*)(fs_hash_filebuckets->data+fs_hash_filebuckets->used);
fs_hash_filebuckets->used += sizeof(*filehandle)+nlen;
fs_hash_filebuckets->used += plen;
if (!filehandle)
return; //eep!
@ -4526,7 +4528,7 @@ void FS_Shutdown(void)
fs_thread_mutex = NULL;
Cvar_SetEngineDefault(&fs_gamename, NULL);
Cvar_SetEngineDefault(&pm_downloads_url, NULL);
Cvar_SetEngineDefault(&pkg_downloads_url, NULL);
Cvar_SetEngineDefault(&com_protocolname, NULL);
}
@ -5783,11 +5785,11 @@ qboolean FS_ChangeGame(ftemanifest_t *man, qboolean allowreloadconfigs, qboolean
if (reloadconfigs)
{
Cvar_SetEngineDefault(&fs_gamename, man->formalname?man->formalname:"FTE");
Cvar_SetEngineDefault(&pm_downloads_url, man->downloadsurl?man->downloadsurl:"");
Cvar_SetEngineDefault(&pkg_downloads_url, man->downloadsurl?man->downloadsurl:"");
Cvar_SetEngineDefault(&com_protocolname, man->protocolname?man->protocolname:"FTE");
//FIXME: flag this instead and do it after a delay?
Cvar_ForceSet(&fs_gamename, fs_gamename.enginevalue);
Cvar_ForceSet(&pm_downloads_url, pm_downloads_url.enginevalue);
Cvar_ForceSet(&pkg_downloads_url, pkg_downloads_url.enginevalue);
Cvar_ForceSet(&com_protocolname, com_protocolname.enginevalue);
#ifdef HAVE_CLIENT
vidrestart = false;
@ -6475,8 +6477,8 @@ void COM_InitFilesystem (void)
Cvar_Register(&cfg_reload_on_gamedir, "Filesystem");
Cvar_Register(&com_fs_cache, "Filesystem");
Cvar_Register(&fs_gamename, "Filesystem");
Cvar_Register(&pm_downloads_url, "Filesystem");
Cvar_Register(&pm_autoupdate, "Filesystem");
Cvar_Register(&pkg_downloads_url, "Filesystem");
Cvar_Register(&pkg_autoupdate, "Filesystem");
Cvar_Register(&com_protocolname, "Server Info");
Cvar_Register(&com_protocolversion, "Server Info");
Cvar_Register(&fs_game, "Filesystem");

View File

@ -316,7 +316,7 @@ static unsigned int QDECL FSSTDIO_FLocate(searchpathfuncs_t *handle, flocation_t
if ((unsigned int)snprintf (netpath, sizeof(netpath), "%s/%s", sp->rootpath, filename) > sizeof(netpath)-1)
return FF_NOTFOUND;
#ifdef ANDROID
#if 0//def ANDROID
{
vfsfile_t *f = VFSSTDIO_Open(netpath, "rb", NULL);
if (!f)

View File

@ -401,12 +401,12 @@ typedef unsigned char bool;
* NOTE: System headers on GNU/Linux may #define this macro already,
* so if you want to change it, you need to #undef it first.
*/
#ifndef __always_inline
#ifndef always_inline
# ifdef __GNUC__
# define __always_inline \
# define always_inline \
inline __attribute__((__always_inline__))
# else
# define __always_inline inline
# define always_inline inline
# endif
#endif
@ -2216,7 +2216,7 @@ static inline bool rc_is_finished(const struct rc_dec *rc)
}
/* Read the next input byte if needed. */
static __always_inline void rc_normalize(struct rc_dec *rc)
static always_inline void rc_normalize(struct rc_dec *rc)
{
if (rc->range < RC_TOP_VALUE) {
rc->range <<= RC_SHIFT_BITS;
@ -2235,7 +2235,7 @@ static __always_inline void rc_normalize(struct rc_dec *rc)
* of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care,
* and it generates 10-20 % faster code than GCC 3.x from this file anyway.)
*/
static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob)
static always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob)
{
uint32_t bound;
int bit;
@ -2257,7 +2257,7 @@ static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob)
}
/* Decode a bittree starting from the most significant bit. */
static __always_inline uint32_t rc_bittree(struct rc_dec *rc,
static always_inline uint32_t rc_bittree(struct rc_dec *rc,
uint16_t *probs, uint32_t limit)
{
uint32_t symbol = 1;
@ -2273,7 +2273,7 @@ static __always_inline uint32_t rc_bittree(struct rc_dec *rc,
}
/* Decode a bittree starting from the least significant bit. */
static __always_inline void rc_bittree_reverse(struct rc_dec *rc,
static always_inline void rc_bittree_reverse(struct rc_dec *rc,
uint16_t *probs,
uint32_t *dest, uint32_t limit)
{

View File

@ -1030,11 +1030,12 @@ size_t NET_StringToSockaddr2 (const char *s, int defaultport, netadrtype_t afhin
return result;
//EVIL HACK!
//updates.tth uses a known self-signed certificate. its not meant to be used for browsers etc, and I cba to register dns stuff for it.
//updates.tth uses a known self-signed certificate (to protect against dns hijacks like fteqw.com suffered).
//its not meant to be used for browsers etc, and I cba to register dns stuff for it.
//besides, browsers/etc would just bitch about its cert, so w/e.
//redirect the dns to the base host without affecting http(s) hosts/certificates.
if (!strcmp(s, "updates.triptohell.info"))
s = "triptohell.info";
s += 8;
memset (sadr, 0, sizeof(*sadr));

View File

@ -289,9 +289,15 @@ static plugin_t *Plug_Load(const char *file, int type)
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
if (!newplug->vm && (type & PLUG_NATIVE))
newplug->vm = VM_Create(va("fteplug_%s_", file), Plug_SystemCallsNative, NULL, NULL);
{
Q_snprintfz(temp, sizeof(temp), "fteplug_%s_", file);
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
if (!newplug->vm && (type & PLUG_NATIVE))
newplug->vm = VM_Create(va("fteplug_%s", file), Plug_SystemCallsNative, NULL, NULL);
{
Q_snprintfz(temp, sizeof(temp), "fteplug_%s", file);
newplug->vm = VM_Create(temp, Plug_SystemCallsNative, NULL, NULL);
}
if (!newplug->vm && (type & PLUG_QVM))
newplug->vm = VM_Create(NULL, NULL, file, Plug_SystemCallsVM);
if (!newplug->vm && (type & PLUG_NATIVE))

View File

@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
movevars_t movevars;
playermove_t pmove;
extern cvar_t pm_noround; //evile.
#define movevars_dpflags MOVEFLAG_QWCOMPAT
#define movevars_maxairspeed 30
@ -1227,8 +1228,14 @@ static void PM_NudgePosition (void)
//base[i] = MSG_FromCoord(MSG_ToCoord(pmove.origin[i], movevars.coordsize), movevars.coordsize);
//but it has overflow issues, so do things the painful way instead.
//this stuff is so annoying because we're trying to avoid biasing the position towards 0. you'll see the effects of that if you use a low forwardspeed or low sv_gamespeed etc, but its also noticable with default settings too.
if (movevars.coordsize == 4) //float precision on the network. no need to truncate.
if (
#ifdef HAVE_LEGACY
pm_noround.ival ||
#endif
movevars.coordsize == 4) //float precision on the network. no need to truncate.
{
VectorCopy (pmove.origin, base);
}
else if (movevars.coordsize) //1/8th precision, but don't truncate because that screws everything up.
{
for (i=0 ; i<3 ; i++)

View File

@ -477,6 +477,9 @@ void QCBUILTIN PF_cl_bprint (pubprogfuncs_t *prinst, struct globalvars_s *pr_glo
void QCBUILTIN PF_cl_clientcount (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_localsound(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_SendPacket(pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getlocaluserinfoblob (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_getlocaluserinfostring (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void QCBUILTIN PF_cl_setlocaluserinfo (pubprogfuncs_t *prinst, struct globalvars_s *pr_globals);
void search_close_progs(pubprogfuncs_t *prinst, qboolean complain);

View File

@ -79,11 +79,14 @@ void *Sys_CreateThread(char *name, int (*func)(void *), void *args, int priority
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
if (stacksize < PTHREAD_STACK_MIN*2)
stacksize = PTHREAD_STACK_MIN*2;
if (stacksize < PTHREAD_STACK_MIN+65536*16)
stacksize = PTHREAD_STACK_MIN+65536*16;
pthread_attr_setstacksize(&attr, stacksize);
if (stacksize != -1)
{
if (stacksize < PTHREAD_STACK_MIN*2)
stacksize = PTHREAD_STACK_MIN*2;
if (stacksize < PTHREAD_STACK_MIN+65536*16)
stacksize = PTHREAD_STACK_MIN+65536*16;
pthread_attr_setstacksize(&attr, stacksize);
}
if (pthread_create(thread, &attr, (pfunction_t)Sys_CreatedThread, qthread))
{
free(thread);

View File

@ -22,9 +22,6 @@
<activity android:name="com.fteqw.FTENativeActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation|screenLayout">
<meta-data android:name="android.app.lib_name"
android:value="ftedroid" />
<!-- -->
<!-- launcher icon -->

View File

@ -5,17 +5,147 @@ import android.view.MotionEvent;
import android.view.InputDevice;
import android.view.WindowManager;
public class FTENativeActivity extends android.app.NativeActivity
public class FTENativeActivity extends android.app.Activity implements android.view.SurfaceHolder.Callback2, android.view.ViewTreeObserver.OnGlobalLayoutListener
{
//Native functions and stuff
private native boolean startup(String externalDataPath, String libraryPath);
private native void openfile(String url);
private native void surfacechange(boolean teardown, boolean restart, android.view.Surface surface);
private native void shutdown();
private static native void keypress(int devid, boolean down, int androidkey, int unicode);
private static native void mousepress(int devid, int buttonbits);
private static native void motion(int devid, int action, float x, float y, float z, float size);
private static native boolean wantrelative();
private static native void axis(int devid, int axisid, float value);
// private static native void oncreate(String basedir, byte[] savedstate);
// private static native void oncreate(String bindir, String basedir, byte[] savedstate);
static
{
System.loadLibrary("ftedroid");
System.loadLibrary("ftedroid"); //registers the methods properly.
}
static class NativeContentView extends android.view.View
{
FTENativeActivity mActivity;
public NativeContentView(android.content.Context context)
{
super(context);
}
public NativeContentView(android.content.Context context, android.util.AttributeSet attrs)
{
super(context, attrs);
}
}
private NativeContentView mNativeContentView;
//SurfaceHolder.Callback2 methods
public void surfaceRedrawNeeded(android.view.SurfaceHolder holder)
{ //we constantly redraw.
}
public void surfaceCreated(android.view.SurfaceHolder holder)
{
// surfacechange(false, true, holder.getSurface());
}
public void surfaceChanged(android.view.SurfaceHolder holder, int format, int width, int height)
{
surfacechange(true, true, holder.getSurface());
}
public void surfaceDestroyed(android.view.SurfaceHolder holder)
{
surfacechange(true, false, null);
}
//OnGlobalLayoutListener methods
public void onGlobalLayout()
{
/* mNativeContentView.getLocationInWindow(mLocation);
int w = mNativeContentView.getWidth();
int h = mNativeContentView.getHeight();
if (mLocation[0] != mLastContentX || mLocation[1] != mLastContentY || w != mLastContentWidth || h != mLastContentHeight)
{
mLastContentX = mLocation[0];
mLastContentY = mLocation[1];
mLastContentWidth = w;
mLastContentHeight = h;
if (!mDestroyed) {
onContentRectChangedNative(mNativeHandle, mLastContentX,
mLastContentY, mLastContentWidth, mLastContentHeight);
}
}
*/ }
//Activity methods
@Override
protected void onCreate(android.os.Bundle savedInstanceState)
{
getWindow().takeSurface(this);
getWindow().setFormat(android.graphics.PixelFormat.RGB_565);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
mNativeContentView = new NativeContentView(this);
mNativeContentView.mActivity = this;
setContentView(mNativeContentView);
mNativeContentView.requestFocus();
mNativeContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
// byte[] nativeSavedState = savedInstanceState != null
// ? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
startup(getAbsolutePath(getExternalFilesDir(null)), getNativeLibraryDirectory());
handleIntent(getIntent());
// if (Build.VERSION.SDK_INT >= 19)
// {
// int flags = 0;
// flags |= 4096/*SYSTEM_UI_FLAG_IMMERSIVE_STICKY, api 19*/;
// flags |= 4/*SYSTEM_UI_FLAG_FULLSCREEN, api 16*/;
// flags |= 2/*SYSTEM_UI_FLAG_HIDE_NAVIGATION, api 14*/;
// mNativeContentView.setSystemUiVisibility(flags); /*api 11*/
// }
super.onCreate(savedInstanceState);
//Needed because the InputQueue stuff blocks dispatchKeyEvent
getWindow().takeInputQueue(null);
}
//random helpers
private void handleIntent(android.content.Intent intent)
{
String s = intent.getScheme();
if (s=="content")
{
android.database.Cursor cursor = this.getContentResolver().query(intent.getData(), null, null, null, null);
cursor.moveToFirst();
String myloc = cursor.getString(0);
cursor.close();
}
else
openfile(intent.getDataString());
}
private static String getAbsolutePath(java.io.File file)
{
return (file != null) ? file.getAbsolutePath() : null;
}
public String getNativeLibraryDirectory()
{
android.content.Context context = getApplicationContext();
int sdk_level = android.os.Build.VERSION.SDK_INT;
if (sdk_level >= android.os.Build.VERSION_CODES.GINGERBREAD)
{
try
{
String secondary = (String) android.content.pm.ApplicationInfo.class.getField("nativeLibraryRootDir").get(context.getApplicationInfo());
return secondary;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
if (sdk_level >= android.os.Build.VERSION_CODES.DONUT)
return context.getApplicationInfo().dataDir + "/lib";
return "/data/data/" + context.getPackageName() + "/lib";
}
//called by C code on errors / quitting.
@ -132,40 +262,6 @@ public class FTENativeActivity extends android.app.NativeActivity
});
}
@Override
protected void onCreate(android.os.Bundle savedInstanceState)
{
/* getWindow().takeSurface(this);
getWindow().setFormat(PixelFormat.RGB_565);
getWindow().setSoftInputMode(
WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
mNativeContentView = new NativeContentView(this);
mNativeContentView.mActivity = this;
setContentView(mNativeContentView);
mNativeContentView.requestFocus();
mNativeContentView.getViewTreeObserver().addOnGlobalLayoutListener(this);
byte[] nativeSavedState = savedInstanceState != null
? savedInstanceState.getByteArray(KEY_NATIVE_SAVED_STATE) : null;
mNativeHandle = oncreate(
getAbsolutePath(getFilesDir()), getAbsolutePath(getObbDir()),
getAbsolutePath(getExternalFilesDir(null)),
Build.VERSION.SDK_INT, getAssets(), nativeSavedState);
*/
// if (Build.VERSION.SDK_INT >= 19)
// {
// int flags = 0;
// flags |= 4096/*SYSTEM_UI_FLAG_IMMERSIVE_STICKY, api 19*/;
// flags |= 4/*SYSTEM_UI_FLAG_FULLSCREEN, api 16*/;
// flags |= 2/*SYSTEM_UI_FLAG_HIDE_NAVIGATION, api 14*/;
// mNativeContentView.setSystemUiVisibility(flags); /*api 11*/
// }
super.onCreate(savedInstanceState);
//Needed because the InputQueue stuff blocks dispatchKeyEvent
getWindow().takeInputQueue(null);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event)
{ //needed because AKeyEvent_getUnicode is missing completely.
@ -374,11 +470,12 @@ public class FTENativeActivity extends android.app.NativeActivity
//launching stuff
/*private static native int unicodeKeyPress(int unicode);
private static native int unicodeKeyPress(int unicode);
@Override
void onNewIntent(Intent intent)
protected void onNewIntent(android.content.Intent intent)
{
handleIntent(intent);
super.onNewIntent(intent);
}*/
}
}

View File

@ -1157,6 +1157,7 @@ static void T_Gen_CurrentRender(int tmu)
int vwidth, vheight;
int pwidth = vid.fbpwidth;
int pheight = vid.fbpheight;
GLenum fmt;
if (r_refdef.recurse)
return;
@ -1178,6 +1179,14 @@ static void T_Gen_CurrentRender(int tmu)
vheight *= 2;
}
}
if (vid.flags&VID_FP16)
fmt = GL_RGBA16F;
else if (vid.flags&VID_SRGB_CAPABLE)
fmt = GL_SRGB8;
else
fmt = GL_RGB;
// copy the scene to texture
if (!TEXVALID(shaderstate.temptexture))
{
@ -1185,12 +1194,7 @@ static void T_Gen_CurrentRender(int tmu)
qglGenTextures(1, &shaderstate.temptexture->num);
}
GL_MTBind(tmu, GL_TEXTURE_2D, shaderstate.temptexture);
if (vid.flags&VID_FP16)
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 0, 0, vwidth, vheight, 0);
else if (vid.flags&VID_SRGBAWARE)
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_SRGB_ALPHA_EXT, 0, 0, vwidth, vheight, 0);
else
qglCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, vwidth, vheight, 0);
qglCopyTexImage2D(GL_TEXTURE_2D, 0, fmt, 0, 0, vwidth, vheight, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

View File

@ -135,39 +135,39 @@ 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, 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);
glfmtc(PTI_RGB8, (ver>=3)?GL_RGB8:0, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, tc_rgb);
glfmtc(PTI_RGBA8, (ver>=3)?GL_RGBA8:0, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, tc_rgba8);
glfmt(PTI_L8A8, (ver>=3)?GL_LUMINANCE8_ALPHA8:0,GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE);
glfmt(PTI_L8, (ver>=3)?GL_LUMINANCE8:0, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE);
// glfmt(PTI_A8, (ver>=3)?GL_LUMINANCE8: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.
glfmtc(PTI_RGB565, GL_RGB, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, tc_rgb);
// glfmtc(PTI_RGBA4444,GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, tc_rgba8);
// glfmtc(PTI_RGBA5551,GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, tc_rgba1);
glfmtc(PTI_RGB565, (ver>=3)?GL_RGB565:0, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, tc_rgb);
// glfmtc(PTI_RGBA4444,(ver>=3)?GL_RGBA4:0, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, tc_rgba8);
// glfmtc(PTI_RGBA5551,(ver>=3)?GL_RGB555A1:0, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, tc_rgba1);
}
if (GL_CheckExtension("GL_OES_texture_half_float"))
glfmtc(PTI_RGBA16F, GL_RGBA, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, 0); //not to be confused with GL_HALF_FLOAT[_ARB] which has a different value
glfmtc(PTI_RGBA16F, (ver>=3)?GL_RGBA16F:0, GL_RGBA, GL_RGBA, GL_HALF_FLOAT_OES, 0); //not to be confused with GL_HALF_FLOAT[_ARB] which has a different value
if (GL_CheckExtension("GL_OES_texture_float"))
glfmtc(PTI_RGBA32F, GL_RGBA, GL_RGBA, GL_RGBA, GL_FLOAT, 0);
glfmtc(PTI_RGBA32F, (ver>=3)?GL_RGBA32F:0, GL_RGBA, GL_RGBA, GL_FLOAT, 0);
if (GL_CheckExtension("GL_WEBGL_depth_texture"))
{ //24bit is okay with this one.
glfmt(PTI_DEPTH16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
glfmt(PTI_DEPTH24, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8);
glfmt(PTI_DEPTH32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
glfmt(PTI_DEPTH16, (ver>=3)?GL_DEPTH_COMPONENT:0,GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
glfmt(PTI_DEPTH24, (ver>=3)?GL_DEPTH_COMPONENT:0,GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8);
glfmt(PTI_DEPTH32, (ver>=3)?GL_DEPTH_COMPONENT:0,GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
}
else if (GL_CheckExtension("GL_OES_depth_texture") || GL_CheckExtension("GL_ANGLE_depth_texture"))
{ //16+32, not 24.
glfmt(PTI_DEPTH16, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
glfmt(PTI_DEPTH32, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
glfmt(PTI_DEPTH16, (ver>=3)?GL_DEPTH_COMPONENT:0,GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT);
glfmt(PTI_DEPTH32, (ver>=3)?GL_DEPTH_COMPONENT:0,GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT);
}
if (GL_CheckExtension("GL_EXT_texture_format_BGRA8888"))
glfmtc(PTI_BGRA8, GL_BGRA_EXT, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_rgba8);
glfmtc(PTI_BGRA8, /*(ver>=3)?GL_BGRA8_EXT:*/0, GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE, tc_rgba8);
if (GL_CheckExtension("GL_EXT_texture_type_2_10_10_10_REV"))
glfmtc(PTI_BGRA8, GL_RGBA, GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, tc_rgba8);
glfmtc(PTI_A2BGR10, 0, GL_RGBA, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, tc_rgba8);
}
if (!gl_config_gles || ver >= 3.0)
{
@ -642,7 +642,8 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
int nummips = mips->mipcount;
uploadfmt_t encoding = mips->encoding;
qboolean compress;
qboolean storage = true;
unsigned int bb, bw, bh;
if (gl_config.gles)
{
@ -776,7 +777,12 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
ifmt = gl_config.formatinfo[encoding].sizedformat;
if (!ifmt)
return false;
{
ifmt = gl_config.formatinfo[encoding].internalformat;
if (!ifmt)
return false; //dude, everything bad is happening today.
storage = false; //no sized format means we can't use glTexStorageND
}
if (gl_config.formatinfo[encoding].swizzle_r != GL_RED || gl_config.formatinfo[encoding].swizzle_g != GL_GREEN ||
gl_config.formatinfo[encoding].swizzle_b != GL_BLUE || gl_config.formatinfo[encoding].swizzle_a != GL_ALPHA)
@ -787,10 +793,34 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
qglTexParameteri(targ, GL_TEXTURE_SWIZZLE_A, gl_config.formatinfo[encoding].swizzle_a);
}
Image_BlockSizeForEncoding(encoding, &bb, &bw, &bh);
switch(bb)
{
case 3:
default:
bb = 1; //rows are completely unaligned
break;
case 1:
case 2:
case 4:
case 8:
break; //rows are aligned naturally
case 16:
case 32:
case 64:
bb = 8; //row alignment is capped to 8 by opengl, for some reason.
break;
}
if (gl_config.unpackalignment != bb)
{
gl_config.unpackalignment = bb;
qglPixelStorei(GL_UNPACK_ALIGNMENT, bb);
}
if (targ == GL_TEXTURE_3D || targ == GL_TEXTURE_2D_ARRAY)
{
//FIXME: support array textures properly
if (qglTexStorage3D)
if (qglTexStorage3D && storage)
{
if (tex->flags & IF_TEXTYPE)
qglTexStorage3D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth);
@ -821,7 +851,7 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips)
}
else
{
if (qglTexStorage2D)
if (qglTexStorage2D && storage)
{ //FIXME: destroy the old texture
if (tex->flags & IF_TEXTYPE)
qglTexStorage2D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height);

View File

@ -1771,7 +1771,7 @@ static texid_t Font_LoadFallbackConchars(void)
Font_CopyGlyph('|', 131, lump);
Font_CopyGlyph('>', 13, lump);
}
tex = R_LoadTexture32("charset", width, height, (void*)lump, IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA);
tex = Image_GetTexture("charset", NULL, IF_PREMULTIPLYALPHA|IF_LOADNOW|IF_UIPIC|IF_NOMIPMAP|IF_NOGAMMA, (void*)lump, NULL, width, height, PTI_RGBA8);
BZ_Free(lump);
return tex;
}

View File

@ -57,6 +57,7 @@ void (APIENTRY *qglGetIntegerv) (GLenum pname, GLint *params);
const GLubyte * (APIENTRY *qglGetString) (GLenum name);
void (APIENTRY *qglHint) (GLenum target, GLenum mode);
GLboolean (APIENTRY *qglIsEnabled) (GLenum cap);
void (APIENTRY *qglPixelStorei) (GLenum pname, GLint param);
void (APIENTRY *qglPolygonOffset) (GLfloat factor, GLfloat units);
void (APIENTRY *qglLineWidth) (GLfloat width);
void (APIENTRY *qglReadPixels) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
@ -680,6 +681,15 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglGenProgramsARB = NULL;
*/
if (gl_config.glversion >= (gl_config.gles?3:1.2))
qglDrawRangeElements = (void *)getglext("glDrawRangeElements");
else if (GL_CheckExtension("GL_EXT_draw_range_elements"))
qglDrawRangeElements = (void *)getglext("glDrawRangeElementsEXT");
else
qglDrawRangeElements = NULL;
if (qglDrawRangeElements == NULL)
qglDrawRangeElements = GL_DrawRangeElementsEmul;
gl_config.ext_packed_depth_stencil = GL_CheckExtension("GL_EXT_packed_depth_stencil");
if (GL_CheckExtension("GL_EXT_texture_filter_anisotropic"))
@ -3259,6 +3269,7 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
qglFinish = (void *)getglcore("glFinish");
qglFlush = (void *)getglcore("glFlush");
qglGenTextures = (void *)getglcore("glGenTextures");
qglPixelStorei = (void *)getglcore("glPixelStorei");
qglGetFloatv = (void *)getglcore("glGetFloatv");
qglGetIntegerv = (void *)getglcore("glGetIntegerv");
qglGetString = (void *)getglcore("glGetString");
@ -3301,10 +3312,6 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name))
qglEnableClientState = (void *)getglcore("glEnableClientState");
qglDisableClientState = (void *)getglcore("glDisableClientState");
qglDrawRangeElements = (void *)getglext("glDrawRangeElements");
if (qglDrawRangeElements == 0)
qglDrawRangeElements = GL_DrawRangeElementsEmul;
qglMultiDrawElements = (void *)getglext("glMultiDrawElements"); //since gl2

View File

@ -76,7 +76,7 @@ void GLVID_DeInit(void)
Sys_Printf("GLVID_DeInited\n");
}
static void EGL_ShowConfig(EGLDisplay egldpy, EGLConfig cfg)
/*static void EGL_ShowConfig(EGLDisplay egldpy, EGLConfig cfg)
{
struct
{
@ -128,6 +128,7 @@ static void EGL_ShowConfig(EGLDisplay egldpy, EGLConfig cfg)
Sys_Printf("%i.%s: UNKNOWN\n", (int)cfg, eglattrs[i].attrname);
}
};
*/
qboolean GLVID_Init (rendererstate_t *info, unsigned char *palette)
{
@ -206,7 +207,7 @@ Sys_Printf("GLVID_Initing...\n");
Sys_Printf("Creating gles %i context\n", glesversion);
EGL_ShowConfig(sys_display, config);
// EGL_ShowConfig(sys_display, config);
sys_surface = eglCreateWindowSurface(sys_display, config, sys_nativewindow, NULL);
if (!sys_surface)
@ -233,7 +234,13 @@ Sys_Printf("GLVID_Initing...\n");
s++;
gl_major_version = atoi(s);
const char *driver;
if (gl_major_version>=3)
if ((glesversion<=1) != (gl_major_version<=1))
{
Con_Printf(CON_ERROR "Requested gles %i context, but got incompatible %i instead.\n", glesversion, gl_major_version);
GLVID_DeInit();
return false;
}
if (gl_major_version>=3)
driver = "libGLESv3.so";
else if (gl_major_version>=2)
driver = "libGLESv2.so";

View File

@ -2890,6 +2890,7 @@ static void GetEvent(void)
char *protname = x11.pXGetAtomName(vid_dpy, event.xclient.data.l[0]);
if (!strcmp(protname, "WM_DELETE_WINDOW"))
{
Key_Dest_Remove(kdm_console);
if (Cmd_Exists("menu_quit") || Cmd_AliasExist("menu_quit", RESTRICT_LOCAL))
Cmd_ExecuteString("menu_quit prompt", RESTRICT_LOCAL);
else if (Cmd_Exists("m_quit") || Cmd_AliasExist("m_quit", RESTRICT_LOCAL))

View File

@ -251,6 +251,7 @@ typedef struct {
int ext_texture_filter_anisotropic;
struct glfmt_s formatinfo[PTI_MAX];
int unpackalignment;
} gl_config_t;
extern gl_config_t gl_config;

View File

@ -10950,9 +10950,12 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"getplayerkeyvalue", PF_Fixme,0, 0, 0, 348, D("string(float playernum, string keyname)", "Look up a player's userinfo, to discover things like their name, topcolor, bottomcolor, skin, team, *ver.\nAlso includes scoreboard info like frags, ping, pl, userid, entertime, as well as voipspeaking and voiploudness.")},// (EXT_CSQC)
{"getplayerkeyfloat", PF_Fixme,0, 0, 0, 0, D("float(float playernum, string keyname, optional float assumevalue)", "Cheaper version of getplayerkeyvalue that avoids the need for so many tempstrings.")},
{"getplayerkeyblob", PF_Fixme,0, 0, 0, 0, D("int(float playernum, string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes but return the full size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")},
{"getlocalinfo", PF_getlocalinfo,0, 0, 0, 0, D("int(string keyname, optional void *outptr, int size)", "Obtains a copy of the full data blob. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")},
{"setlocalinfo", PF_setlocalinfo,0, 0, 0, 0, D("void(string keyname, optional void *outptr, int size)", "Changes the server's localinfo. This data will be available for the following map, and will *usually* reload with saved games.")},
{"setlocaluserinfo", PF_Fixme,0, 0, 0, 0, D("void(float seat, string keyname, string newvalue)", "Change a userinfo key for the local player, equivelent to the setinfo console command. The server will normally forward the setting to other clients.")},
{"getlocaluserinfo", PF_Fixme,0, 0, 0, 0, D("string(float seat, string keyname)", "Reads a local userinfo key for the active seat. This is not quite the same as getplayerkeyvalue, due to latency and possible serverside filtering.")},
{"setlocaluserinfoblob",PF_Fixme,0, 0, 0, 0, D("void(float seat, string keyname, void *outptr, int size)", "Sets the userinfo key to a blob that may contain nulls etc. Keys with a leading underscore will be visible to only the server (for user-specific binary settings).")},
{"getlocaluserinfoblob",PF_Fixme,0, 0, 0, 0, D("int(float seat, string keyname, void *outptr, int maxsize)", "Obtains a copy of the full data blob. Will write up to size bytes but return the full size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")},
{"getlocalinfo", PF_getlocalinfo,0, 0, 0, 0, D("int(string keyname, optional void *outptr, int size)", "Obtains a copy of a data blob (with spaces) from the server's private localinfo. Will write up to size bytes and return the actual size. Does not null terminate (but memalloc(ret+1) will, if you want to cast the buffer to a string), and the blob may contain embedded nulls. Ignores all special keys, returning only what is actually there.")},
{"setlocalinfo", PF_setlocalinfo,0, 0, 0, 0, D("void(string keyname, optional void *outptr, int size)", "Changes the server's private localinfo. This data will be available for the following map, and will *usually* reload with saved games.")},
{"isdemo", PF_Fixme, 0, 0, 0, 349, D("float()", "Returns if the client is currently playing a demo or not. Returns 2 when playing an mvd (where other player's stats can be queried, or the pov can be changed freely).")},// (EXT_CSQC)
{"isserver", PF_Fixme, 0, 0, 0, 350, D("float()", "Returns non-zero whenever the local console can directly affect the server (ie: listen servers or single-player). Compat note: DP returns 0 for single-player.")},//(EXT_CSQC)
@ -10960,10 +10963,10 @@ static BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs
{"setup_reverb", PF_Fixme, 0, 0, 0, 0, D("typedef struct {\n\tfloat flDensity;\n\tfloat flDiffusion;\n\tfloat flGain;\n\tfloat flGainHF;\n\tfloat flGainLF;\n\tfloat flDecayTime;\n\tfloat flDecayHFRatio;\n\tfloat flDecayLFRatio;\n\tfloat flReflectionsGain;\n\tfloat flReflectionsDelay;\n\tvector flReflectionsPan;\n\tfloat flLateReverbGain;\n\tfloat flLateReverbDelay;\n\tvector flLateReverbPan;\n\tfloat flEchoTime;\n\tfloat flEchoDepth;\n\tfloat flModulationTime;\n\tfloat flModulationDepth;\n\tfloat flAirAbsorptionGainHF;\n\tfloat flHFReference;\n\tfloat flLFReference;\n\tfloat flRoomRolloffFactor;\n\tint iDecayHFLimit;\n} reverbinfo_t;\nvoid(float reverbslot, reverbinfo_t *reverbinfo, int sizeofreverinfo_t)", "Reconfigures a reverb slot for weird effects. Slot 0 is reserved for no effects. Slot 1 is reserved for underwater effects. Reserved slots will be reinitialised on snd_restart, but can otherwise be changed. These reverb slots can be activated with SetListener. Note that reverb will currently only work when using OpenAL.")},
{"registercommand", PF_Fixme, 0, 0, 0, 352, D("void(string cmdname)", "Register the given console command, for easy console use.\nConsole commands that are later used will invoke CSQC_ConsoleCommand.")},//(EXT_CSQC)
{"wasfreed", PF_WasFreed,0, 0, 0, 353, D("float(entity ent)", "Quickly check to see if the entity is currently free. This function is only valid during the two-second non-reuse window, after that it may give bad results. Try one second to make it more robust.")},//(EXT_CSQC) (should be availabe on server too)
{"serverkey", PF_sv_serverkeystring,0,0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string")},//
{"serverkey", PF_sv_serverkeystring,0,0, 0, 354, D("string(string key)", "Look up a key in the server's public serverinfo string. If the key contains binary data then it will be truncated at the first null.")},//
{"serverkeyfloat", PF_sv_serverkeyfloat,0,0, 0, 0, D("float(string key, optional float assumevalue)", "Version of serverkey that returns the value as a float (which avoids tempstrings).")},//
{"serverkeyblob", PF_sv_serverkeyblob,0,0, 0, 0, D("int(int buf, string key, optional void *ptr, int size)", "Version of serverkey that can obtain entire serverinfo, localinfo, or (local)userinfo blobs. Returns blob size")},//
{"setserverkey", PF_setserverkey,0, 0, 0, 0, D("void(int buf, string key, void *ptr, optional int size)", "Changes the server's serverinfo.")},//
{"serverkeyblob", PF_sv_serverkeyblob,0,0, 0, 0, D("int(string key, optional void *ptr, int maxsize)", "Version of serverkey that returns data as a blob (ie: binary data that may contain nulls). Returns the full blob size, even if truncated (pass maxsize=0 to query required storage).")},//
{"setserverkey", PF_setserverkey,0, 0, 0, 0, D("void(string key, void *ptr, optional int size)", "Changes the server's serverinfo.")},//
{"getentitytoken", PF_Fixme, 0, 0, 0, 355, D("string(optional string resetstring)", "Grab the next token in the map's entity lump.\nIf resetstring is not specified, the next token will be returned with no other sideeffects.\nIf empty, will reset from the map before returning the first token, probably {.\nIf not empty, will tokenize from that string instead.\nAlways returns tempstrings.")},//;
{"findfont", PF_Fixme, 0, 0, 0, 356, D("float(string s)", "Looks up a named font slot. Matches the actual font name as a last resort.")},//;
{"loadfont", PF_Fixme, 0, 0, 0, 357, D("float(string fontname, string fontmaps, string sizes, float slot, optional float fix_scale, optional float fix_voffset)", "too convoluted for me to even try to explain correct usage. Try drawfont = loadfont(\"\", \"cour\", \"16\", -1, 0, 0); to switch to the courier font (optimised for 16 virtual pixels high), if you have the freetype2 library in windows..")},

View File

@ -1038,7 +1038,7 @@ void SV_FullClientUpdate (client_t *client, client_t *to)
MSG_WriteFloat(buf, realtime - client->connection_started);
ClientReliable_FinishWrite(to);
InfoBuf_ToString(&client->userinfo, info, (pext&PEXT_BIGUSERINFOS)?BASIC_INFO_STRING:sizeof(info), basicuserinfos, privateuserinfos, (pext&PEXT_BIGUSERINFOS)?NULL:basicuserinfos, NULL, NULL);
InfoBuf_ToString(&client->userinfo, info, (pext&PEXT_BIGUSERINFOS)?BASIC_INFO_STRING:sizeof(info), basicuserinfos, privateuserinfos, (pext&PEXT_BIGUSERINFOS)?NULL:basicuserinfos, &to->infosync, &client->userinfo);
buf = ClientReliable_StartWrite(to, 7 + strlen(info));
MSG_WriteByte(buf, svc_updateuserinfo);
MSG_WriteByte(buf, i);
@ -1372,6 +1372,12 @@ static void SVC_InfoQ2 (void)
}
#endif
#ifdef MVD_RECORDING
static void SVC_QTVUsers (void)
{
}
#endif
/*
===================
SV_CheckLog
@ -3927,12 +3933,14 @@ qboolean SV_ConnectionlessPacket (void)
if (SVC_ThrottleInfo())
SVC_DemoListRegex ();
}
*/
#ifdef MVD_RECORDING
else if (!strcmp(c,"qtvusers"))
{
if (SVC_ThrottleInfo())
SVC_QTVUsers ();
}
*/
#endif
else if (!PR_GameCodePacket(net_message.data+4))
{
static unsigned int lt;

View File

@ -2821,6 +2821,7 @@ static qboolean SV_SyncInfoBuf(client_t *client)
if (!blobdata)
blobdata = "";
Con_DLPrintf(2, "%s: info %u:%s\n", client->name, (info == &svs.info)?0:(unsigned int)((client_t*)((char*)info-(char*)&((client_t*)NULL)->userinfo)-svs.clients), key);
if (ISNQCLIENT(client))
{ //except that nq never had any userinfo
const char *s;
@ -2856,7 +2857,7 @@ static qboolean SV_SyncInfoBuf(client_t *client)
char enckey[2048];
unsigned int pl;
if (info == &svs.info)
pl = 0; //colourmaps being 1-based with these being 0-based means that only 0-254 are valid players, and 255 is unused, so lets use it for serverinfo blobs.
pl = 0; //players are 1-based. 0 is used for serverinfo.
else
pl = 1+((client_t*)((char*)info-(char*)&((client_t*)NULL)->userinfo)-svs.clients);
@ -2866,17 +2867,18 @@ static qboolean SV_SyncInfoBuf(client_t *client)
return false;
}
if (!blobdata)
bloboffset = 0; //wiped or something? I dunno, don't bug out though.y
bloboffset = 0; //wiped or something? I dunno, don't bug out though.
sendsize = blobsize - bloboffset;
bufferspace = MAX_BACKBUFLEN - client->netchan.message.cursize;
bufferspace -= 8 - strlen(enckey) - 1; //extra overhead
bufferspace -= 8 + strlen(enckey) + 1; //extra overhead
sendsize = min(bufferspace, sendsize);
final = (bloboffset+sendsize >= blobsize);
Con_DLPrintf(2, "%s: blob %u:%s@%u-%u\n", client->name, pl, key, (unsigned int)bloboffset, (unsigned int)(bloboffset+sendsize));
buf = ClientReliable_StartWrite(client, 8+strlen(enckey)+1+sendsize);
MSG_WriteByte(buf, svcfte_setinfoblob);
MSG_WriteByte(buf, pl); //special meaning to say that this is a partial update
MSG_WriteByte(buf, pl);
MSG_WriteString(buf, enckey);
MSG_WriteLong(buf, (final?0x80000000:0)|bloboffset);
MSG_WriteShort(buf, sendsize);
@ -3415,7 +3417,7 @@ void SV_SendClientMessages (void)
if (c->num_backbuf)
{
// will it fit?
if (c->netchan.message.cursize + c->backbuf_size[0] <
if (c->netchan.message.cursize + c->backbuf_size[0] <=
c->netchan.message.maxsize)
{

View File

@ -3903,6 +3903,10 @@ void VK_CheckTextureFormats(void)
{PTI_RG8, VK_FORMAT_R8G8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_R8_SNORM, VK_FORMAT_R8_SNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_RG8_SNORM, VK_FORMAT_R8G8_SNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_R16, VK_FORMAT_R16_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_RGBA16, VK_FORMAT_R16G16B16A16_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_R16F, VK_FORMAT_R16_SFLOAT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_R32F, VK_FORMAT_R32_SFLOAT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT},
{PTI_DEPTH16, VK_FORMAT_D16_UNORM, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
{PTI_DEPTH24, VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT},
@ -4566,7 +4570,12 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
Con_Printf("VK_ERROR_INCOMPATIBLE_DRIVER: please install an appropriate vulkan driver\n");
return false;
case VK_ERROR_EXTENSION_NOT_PRESENT:
Con_Printf("VK_ERROR_EXTENSION_NOT_PRESENT: something on a system level is probably misconfigured\n");
case VK_ERROR_FEATURE_NOT_PRESENT:
case VK_ERROR_INITIALIZATION_FAILED:
case VK_ERROR_DEVICE_LOST:
case VK_ERROR_OUT_OF_HOST_MEMORY:
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
Con_Printf("%s: something on a system level is probably misconfigured\n", VK_VKErrorToString(err));
return false;
default:
Con_Printf("Unknown vulkan device creation error: %x\n", err);
@ -4635,12 +4644,12 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre
sh_config.pValidateProgram = NULL;
sh_config.pProgAutoFields = NULL;
if (sh_config.texfmt[PTI_DEPTH32])
vk.depthformat = VK_FORMAT_D32_SFLOAT;
else if (sh_config.texfmt[PTI_DEPTH24])
if (sh_config.texfmt[PTI_DEPTH24])
vk.depthformat = VK_FORMAT_X8_D24_UNORM_PACK32;
else if (sh_config.texfmt[PTI_DEPTH24_8])
vk.depthformat = VK_FORMAT_D24_UNORM_S8_UINT;
else if (sh_config.texfmt[PTI_DEPTH32]) //nvidia recommend to de-prioritise 32bit (float) depth.
vk.depthformat = VK_FORMAT_D32_SFLOAT;
else //16bit depth is guarenteed in vulkan
vk.depthformat = VK_FORMAT_D16_UNORM;

View File

@ -950,6 +950,68 @@ static void magic_etghack(char *thestring)
}
static void IRC_TryNewNick(ircclient_t *irc, char *nickname)
{
char *seedednick;
IRC_CvarUpdate();
if (irc->tlsmode == TLS_STARTING)
{
//don't submit any of this info here.
return;
}
if (irc->connecting)
{
if (irc->nicktries == 0)
{
irc->nicktries++;
if (*irc->primarynick && strcmp(nickname, irc->primarynick))
{
IRC_SetNick(irc, irc->primarynick);
return;
}
}
if (irc->nicktries == 1)
{
irc->nicktries++;
if (*irc_nick.string && strcmp(nickname, irc_nick.string))
{
IRC_SetNick(irc, irc_nick.string);
return;
}
}
if (irc->nicktries == 2)
{
irc->nicktries++;
if (*irc_altnick.string && strcmp(nickname, irc_altnick.string))
{
IRC_SetNick(irc, irc_altnick.string);
return;
}
}
if (++irc->nicktries == 10)
{
IRC_Printf(irc, DEFAULTCONSOLE, COLOURRED "ERROR: Unable to obtain usable nickname\n");
return;
}
//panic and pick something at random
//IRC_Printf(irc, DEFAULTCONSOLE, COLOURRED "ERROR: primary nickname in use. Attempting random nickname.\n");
if (*irc->primarynick && irc->nicktries < 7)
seedednick = va("%.6s%i", irc->primarynick, rand());
else if (*irc_nick.string && irc->nicktries < 8)
seedednick = va("%.6s%i", irc_nick.string, rand());
else if (*irc_altnick.string && irc->nicktries < 9)
seedednick = va("%.6s%i", irc_altnick.string, rand());
else
seedednick = va("%.6s%i", "FTE", rand());
seedednick[9] = 0; //'Each client is distinguished from other clients by a unique nickname having a maximum length of nine (9) characters'
IRC_SetNick(irc, seedednick);
}
}
//==================================================
@ -1154,7 +1216,8 @@ static void numbered_command(int comm, char *msg, ircclient_t *irc) // move vars
case 432: /* #define ERR_ERRONEUSNICKNAME 432 */
{
IRC_Printf(irc, DEFAULTCONSOLE, "Erroneous/invalid nickname given\n");
goto trynewnick;
IRC_TryNewNick(irc, "FTEUser");
return;
}
case 433: /* #define ERR_NICKNAMEINUSE 433 */
case 438:
@ -1162,73 +1225,15 @@ static void numbered_command(int comm, char *msg, ircclient_t *irc) // move vars
{
char *nickname = strtok(casevar[4], " ");
char *badnickname = ":Nickname";
char *seedednick;
if ( !strcasecmp(nickname,badnickname) ) // bug with ircd, the nickname actually shifts position.
{
nickname = strtok(casevar[3], " ");
}
IRC_CvarUpdate();
// IRC_Printf(irc, DEFAULTCONSOLE, COLOURRED "ERROR: <%s> is already in use.\n",nickname);
trynewnick:
if (irc->tlsmode == TLS_STARTING)
{
//don't submit any of this info here.
return;
}
if (irc->connecting)
{
if (irc->nicktries == 0)
{
irc->nicktries++;
if (*irc->primarynick && strcmp(nickname, irc->primarynick))
{
IRC_SetNick(irc, irc->primarynick);
return;
}
}
if (irc->nicktries == 1)
{
irc->nicktries++;
if (*irc_nick.string && strcmp(nickname, irc_nick.string))
{
IRC_SetNick(irc, irc_nick.string);
return;
}
}
if (irc->nicktries == 2)
{
irc->nicktries++;
if (*irc_altnick.string && strcmp(nickname, irc_altnick.string))
{
IRC_SetNick(irc, irc_altnick.string);
return;
}
}
if (++irc->nicktries == 10)
{
IRC_Printf(irc, DEFAULTCONSOLE, COLOURRED "ERROR: Unable to obtain usable nickname\n");
return;
}
//panic and pick something at random
//IRC_Printf(irc, DEFAULTCONSOLE, COLOURRED "ERROR: primary nickname in use. Attempting random nickname.\n");
if (*irc->primarynick && irc->nicktries < 7)
seedednick = va("%.6s%i", irc->primarynick, rand());
else if (*irc_nick.string && irc->nicktries < 8)
seedednick = va("%.6s%i", irc_nick.string, rand());
else if (*irc_altnick.string && irc->nicktries < 9)
seedednick = va("%.6s%i", irc_altnick.string, rand());
else
seedednick = va("%.6s%i", "FTE", rand());
seedednick[9] = 0; //'Each client is distinguished from other clients by a unique nickname having a maximum length of nine (9) characters'
IRC_SetNick(irc, seedednick);
}
IRC_TryNewNick(irc, nickname);
return;
}
case 471: /* ERR_CHANNELISFULL */