mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-02-28 14:31:15 +00:00
Merge branch 'next' into extra-textures
This commit is contained in:
commit
722a3c3d48
13 changed files with 247 additions and 242 deletions
|
@ -55,7 +55,7 @@ static UINT8 *demobuffer = NULL;
|
||||||
static UINT8 *demo_p, *demotime_p;
|
static UINT8 *demo_p, *demotime_p;
|
||||||
static UINT8 *demoend;
|
static UINT8 *demoend;
|
||||||
static UINT8 demoflags;
|
static UINT8 demoflags;
|
||||||
static UINT16 demoversion;
|
UINT16 demoversion;
|
||||||
boolean singledemo; // quit after playing a demo from cmdline
|
boolean singledemo; // quit after playing a demo from cmdline
|
||||||
boolean demo_start; // don't start playing demo right away
|
boolean demo_start; // don't start playing demo right away
|
||||||
boolean demo_forwardmove_rng; // old demo backwards compatibility
|
boolean demo_forwardmove_rng; // old demo backwards compatibility
|
||||||
|
@ -98,7 +98,7 @@ demoghost *ghosts = NULL;
|
||||||
// DEMO RECORDING
|
// DEMO RECORDING
|
||||||
//
|
//
|
||||||
|
|
||||||
#define DEMOVERSION 0x0010
|
#define DEMOVERSION 0x0011
|
||||||
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
#define DEMOHEADER "\xF0" "SRB2Replay" "\x0F"
|
||||||
|
|
||||||
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
#define DF_GHOST 0x01 // This demo contains ghost data too!
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
// demoplaying back and demo recording
|
// demoplaying back and demo recording
|
||||||
extern boolean demoplayback, titledemo, demorecording, timingdemo;
|
extern boolean demoplayback, titledemo, demorecording, timingdemo;
|
||||||
extern tic_t demostarttime;
|
extern tic_t demostarttime;
|
||||||
|
extern UINT16 demoversion;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
|
|
|
@ -116,8 +116,36 @@ void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPt
|
||||||
polygonArray[polygonArraySize].texture = current_texture;
|
polygonArray[polygonArraySize].texture = current_texture;
|
||||||
polygonArray[polygonArraySize].shader = shader;
|
polygonArray[polygonArraySize].shader = shader;
|
||||||
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
polygonArray[polygonArraySize].horizonSpecial = horizonSpecial;
|
||||||
|
// default to polygonArraySize so we don't lose order on horizon lines
|
||||||
|
// (yes, it's supposed to be negative, since we're sorting in that direction)
|
||||||
|
polygonArray[polygonArraySize].hash = -polygonArraySize;
|
||||||
polygonArraySize++;
|
polygonArraySize++;
|
||||||
|
|
||||||
|
if (!(PolyFlags & PF_NoTexture) && !horizonSpecial)
|
||||||
|
{
|
||||||
|
// use FNV-1a to hash polygons for later sorting.
|
||||||
|
INT32 hash = 0x811c9dc5;
|
||||||
|
#define DIGEST(h, x) h ^= (x); h *= 0x01000193
|
||||||
|
if (current_texture)
|
||||||
|
{
|
||||||
|
DIGEST(hash, current_texture->downloaded);
|
||||||
|
}
|
||||||
|
DIGEST(hash, PolyFlags);
|
||||||
|
DIGEST(hash, pSurf->PolyColor.rgba);
|
||||||
|
if (cv_glshaders.value && gl_shadersavailable)
|
||||||
|
{
|
||||||
|
DIGEST(hash, shader);
|
||||||
|
DIGEST(hash, pSurf->TintColor.rgba);
|
||||||
|
DIGEST(hash, pSurf->FadeColor.rgba);
|
||||||
|
DIGEST(hash, pSurf->LightInfo.light_level);
|
||||||
|
DIGEST(hash, pSurf->LightInfo.fade_start);
|
||||||
|
DIGEST(hash, pSurf->LightInfo.fade_end);
|
||||||
|
}
|
||||||
|
#undef DIGEST
|
||||||
|
// remove the sign bit to ensure that skybox and horizon line comes first.
|
||||||
|
polygonArray[polygonArraySize-1].hash = (hash & INT32_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
|
memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector));
|
||||||
unsortedVertexArraySize += iNumPts;
|
unsortedVertexArraySize += iNumPts;
|
||||||
}
|
}
|
||||||
|
@ -135,84 +163,7 @@ static int comparePolygons(const void *p1, const void *p2)
|
||||||
unsigned int index2 = *(const unsigned int*)p2;
|
unsigned int index2 = *(const unsigned int*)p2;
|
||||||
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
||||||
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
||||||
int diff;
|
return poly1->hash - poly2->hash;
|
||||||
INT64 diff64;
|
|
||||||
UINT32 downloaded1 = 0;
|
|
||||||
UINT32 downloaded2 = 0;
|
|
||||||
|
|
||||||
int shader1 = poly1->shader;
|
|
||||||
int shader2 = poly2->shader;
|
|
||||||
// make skywalls and horizon lines first in order
|
|
||||||
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
|
||||||
shader1 = -1;
|
|
||||||
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
|
||||||
shader2 = -1;
|
|
||||||
diff = shader1 - shader2;
|
|
||||||
if (diff != 0) return diff;
|
|
||||||
|
|
||||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
|
||||||
if (shader1 == -1 && shader2 == -1)
|
|
||||||
return index1 - index2;
|
|
||||||
|
|
||||||
if (poly1->texture)
|
|
||||||
downloaded1 = poly1->texture->downloaded; // there should be a opengl texture name here, usable for comparisons
|
|
||||||
if (poly2->texture)
|
|
||||||
downloaded2 = poly2->texture->downloaded;
|
|
||||||
diff64 = downloaded1 - downloaded2;
|
|
||||||
if (diff64 != 0) return diff64;
|
|
||||||
|
|
||||||
diff = poly1->polyFlags - poly2->polyFlags;
|
|
||||||
if (diff != 0) return diff;
|
|
||||||
|
|
||||||
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
|
||||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
|
||||||
diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba;
|
|
||||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
|
||||||
diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba;
|
|
||||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
|
||||||
|
|
||||||
diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level;
|
|
||||||
if (diff != 0) return diff;
|
|
||||||
diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start;
|
|
||||||
if (diff != 0) return diff;
|
|
||||||
diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end;
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int comparePolygonsNoShaders(const void *p1, const void *p2)
|
|
||||||
{
|
|
||||||
unsigned int index1 = *(const unsigned int*)p1;
|
|
||||||
unsigned int index2 = *(const unsigned int*)p2;
|
|
||||||
PolygonArrayEntry* poly1 = &polygonArray[index1];
|
|
||||||
PolygonArrayEntry* poly2 = &polygonArray[index2];
|
|
||||||
int diff;
|
|
||||||
INT64 diff64;
|
|
||||||
|
|
||||||
GLMipmap_t *texture1 = poly1->texture;
|
|
||||||
GLMipmap_t *texture2 = poly2->texture;
|
|
||||||
UINT32 downloaded1 = 0;
|
|
||||||
UINT32 downloaded2 = 0;
|
|
||||||
if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial)
|
|
||||||
texture1 = NULL;
|
|
||||||
if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial)
|
|
||||||
texture2 = NULL;
|
|
||||||
if (texture1)
|
|
||||||
downloaded1 = texture1->downloaded; // there should be a opengl texture name here, usable for comparisons
|
|
||||||
if (texture2)
|
|
||||||
downloaded2 = texture2->downloaded;
|
|
||||||
// skywalls and horizon lines must retain their order for horizon lines to work
|
|
||||||
if (!texture1 && !texture2)
|
|
||||||
return index1 - index2;
|
|
||||||
diff64 = downloaded1 - downloaded2;
|
|
||||||
if (diff64 != 0) return diff64;
|
|
||||||
|
|
||||||
diff = poly1->polyFlags - poly2->polyFlags;
|
|
||||||
if (diff != 0) return diff;
|
|
||||||
|
|
||||||
diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba;
|
|
||||||
if (diff64 < 0) return -1; else if (diff64 > 0) return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses
|
// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses
|
||||||
|
@ -263,10 +214,7 @@ void HWR_RenderBatches(void)
|
||||||
|
|
||||||
// sort polygons
|
// sort polygons
|
||||||
PS_START_TIMING(ps_hw_batchsorttime);
|
PS_START_TIMING(ps_hw_batchsorttime);
|
||||||
if (cv_glshaders.value && gl_shadersavailable)
|
|
||||||
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
|
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons);
|
||||||
else
|
|
||||||
qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders);
|
|
||||||
PS_STOP_TIMING(ps_hw_batchsorttime);
|
PS_STOP_TIMING(ps_hw_batchsorttime);
|
||||||
// sort order
|
// sort order
|
||||||
// 1. shader
|
// 1. shader
|
||||||
|
@ -362,6 +310,9 @@ void HWR_RenderBatches(void)
|
||||||
{
|
{
|
||||||
// check if a state change is required, set the change bools and next vars
|
// check if a state change is required, set the change bools and next vars
|
||||||
int nextIndex = polygonIndexArray[polygonReadPos];
|
int nextIndex = polygonIndexArray[polygonReadPos];
|
||||||
|
if (polygonArray[index].hash != polygonArray[nextIndex].hash)
|
||||||
|
{
|
||||||
|
changeState = true;
|
||||||
nextShader = polygonArray[nextIndex].shader;
|
nextShader = polygonArray[nextIndex].shader;
|
||||||
nextTexture = polygonArray[nextIndex].texture;
|
nextTexture = polygonArray[nextIndex].texture;
|
||||||
nextPolyFlags = polygonArray[nextIndex].polyFlags;
|
nextPolyFlags = polygonArray[nextIndex].polyFlags;
|
||||||
|
@ -370,17 +321,14 @@ void HWR_RenderBatches(void)
|
||||||
nextTexture = 0;
|
nextTexture = 0;
|
||||||
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
|
if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable)
|
||||||
{
|
{
|
||||||
changeState = true;
|
|
||||||
changeShader = true;
|
changeShader = true;
|
||||||
}
|
}
|
||||||
if (currentTexture != nextTexture)
|
if (currentTexture != nextTexture)
|
||||||
{
|
{
|
||||||
changeState = true;
|
|
||||||
changeTexture = true;
|
changeTexture = true;
|
||||||
}
|
}
|
||||||
if (currentPolyFlags != nextPolyFlags)
|
if (currentPolyFlags != nextPolyFlags)
|
||||||
{
|
{
|
||||||
changeState = true;
|
|
||||||
changePolyFlags = true;
|
changePolyFlags = true;
|
||||||
}
|
}
|
||||||
if (cv_glshaders.value && gl_shadersavailable)
|
if (cv_glshaders.value && gl_shadersavailable)
|
||||||
|
@ -392,7 +340,6 @@ void HWR_RenderBatches(void)
|
||||||
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start ||
|
||||||
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
|
currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end)
|
||||||
{
|
{
|
||||||
changeState = true;
|
|
||||||
changeSurfaceInfo = true;
|
changeSurfaceInfo = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,11 +347,11 @@ void HWR_RenderBatches(void)
|
||||||
{
|
{
|
||||||
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
|
if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba)
|
||||||
{
|
{
|
||||||
changeState = true;
|
|
||||||
changeSurfaceInfo = true;
|
changeSurfaceInfo = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (changeState || stopFlag)
|
if (changeState || stopFlag)
|
||||||
{
|
{
|
||||||
|
@ -423,6 +370,8 @@ void HWR_RenderBatches(void)
|
||||||
if (stopFlag) break;
|
if (stopFlag) break;
|
||||||
|
|
||||||
// change state according to change bools and next vars, update current vars and reset bools
|
// change state according to change bools and next vars, update current vars and reset bools
|
||||||
|
if (changeState)
|
||||||
|
{
|
||||||
if (changeShader)
|
if (changeShader)
|
||||||
{
|
{
|
||||||
HWD.pfnSetShader(nextShader);
|
HWD.pfnSetShader(nextShader);
|
||||||
|
@ -454,6 +403,7 @@ void HWR_RenderBatches(void)
|
||||||
|
|
||||||
ps_hw_numcolors.value.i++;
|
ps_hw_numcolors.value.i++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// and that should be it?
|
// and that should be it?
|
||||||
}
|
}
|
||||||
// reset the arrays (set sizes to 0)
|
// reset the arrays (set sizes to 0)
|
||||||
|
|
|
@ -26,6 +26,7 @@ typedef struct
|
||||||
int shader;
|
int shader;
|
||||||
// this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls
|
// this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls
|
||||||
boolean horizonSpecial;
|
boolean horizonSpecial;
|
||||||
|
INT32 hash;
|
||||||
} PolygonArrayEntry;
|
} PolygonArrayEntry;
|
||||||
|
|
||||||
void HWR_StartBatching(void);
|
void HWR_StartBatching(void);
|
||||||
|
|
|
@ -2351,17 +2351,22 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
||||||
|
|
||||||
side_t *side = &sides[rover->master->sidenum[0]];
|
side_t *side = &sides[rover->master->sidenum[0]];
|
||||||
|
|
||||||
INT16 lineflags;
|
boolean do_texture_skew;
|
||||||
|
boolean dont_peg_bottom;
|
||||||
|
|
||||||
if (rover->master->flags & ML_TFERLINE)
|
if (rover->master->flags & ML_TFERLINE)
|
||||||
{
|
{
|
||||||
size_t linenum = gl_curline->linedef-gl_backsector->lines[0];
|
size_t linenum = gl_curline->linedef-gl_backsector->lines[0];
|
||||||
newline = rover->master->frontsector->lines[0] + linenum;
|
newline = rover->master->frontsector->lines[0] + linenum;
|
||||||
side = &sides[newline->sidenum[0]];
|
side = &sides[newline->sidenum[0]];
|
||||||
lineflags = newline->flags;
|
do_texture_skew = newline->flags & ML_SKEWTD;
|
||||||
|
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lineflags = gl_curline->linedef->flags;
|
{
|
||||||
|
do_texture_skew = rover->master->flags & ML_SKEWTD;
|
||||||
|
dont_peg_bottom = gl_curline->linedef->flags & ML_DONTPEGBOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
texnum = R_GetTextureNum(side->midtexture);
|
texnum = R_GetTextureNum(side->midtexture);
|
||||||
|
|
||||||
|
@ -2400,15 +2405,14 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
||||||
// ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software
|
// ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software
|
||||||
// -- Monster Iestyn 26/06/18
|
// -- Monster Iestyn 26/06/18
|
||||||
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
|
fixed_t texturevpeg = side->rowoffset + side->offsety_mid;
|
||||||
boolean attachtobottom = !!(lineflags & ML_DONTPEGBOTTOM);
|
|
||||||
|
|
||||||
grTex = HWR_GetTexture(texnum);
|
grTex = HWR_GetTexture(texnum);
|
||||||
xscale = FixedToFloat(side->scalex_mid);
|
xscale = FixedToFloat(side->scalex_mid);
|
||||||
yscale = FixedToFloat(side->scaley_mid);
|
yscale = FixedToFloat(side->scaley_mid);
|
||||||
|
|
||||||
if (!(lineflags & ML_SKEWTD)) // no skewing
|
if (!do_texture_skew) // no skewing
|
||||||
{
|
{
|
||||||
if (attachtobottom)
|
if (dont_peg_bottom)
|
||||||
texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale;
|
texturevpeg -= (*rover->topheight - *rover->bottomheight) * yscale;
|
||||||
|
|
||||||
wallVerts[3].t = (((*rover->topheight - h) * yscale) + texturevpeg) * grTex->scaleY;
|
wallVerts[3].t = (((*rover->topheight - h) * yscale) + texturevpeg) * grTex->scaleY;
|
||||||
|
@ -2418,7 +2422,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!attachtobottom) // skew by top
|
if (!dont_peg_bottom) // skew by top
|
||||||
{
|
{
|
||||||
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
|
wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY;
|
||||||
wallVerts[0].t = (((h - l) * yscale) + texturevpeg) * grTex->scaleY;
|
wallVerts[0].t = (((h - l) * yscale) + texturevpeg) * grTex->scaleY;
|
||||||
|
|
|
@ -415,16 +415,6 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
|
|
||||||
//CONS_Printf("\x82%s ", player_names[pnum]);
|
//CONS_Printf("\x82%s ", player_names[pnum]);
|
||||||
|
|
||||||
// If a verified admin banned someone, the server needs to know about it.
|
|
||||||
// If the playernum isn't zero (the server) then the server needs to record the ban.
|
|
||||||
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
|
|
||||||
{
|
|
||||||
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
|
|
||||||
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
|
|
||||||
else
|
|
||||||
Ban_Add(reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
case KICK_MSG_GO_AWAY:
|
case KICK_MSG_GO_AWAY:
|
||||||
|
@ -500,6 +490,16 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If a verified admin banned someone, the server needs to know about it.
|
||||||
|
// If the playernum isn't zero (the server) then the server needs to record the ban.
|
||||||
|
if (server && playernum && (msg == KICK_MSG_BANNED || msg == KICK_MSG_CUSTOM_BAN))
|
||||||
|
{
|
||||||
|
if (I_Ban && !I_Ban(playernode[(INT32)pnum]))
|
||||||
|
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
|
||||||
|
else
|
||||||
|
Ban_Add(msg == KICK_MSG_CUSTOM_BAN ? reason : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
if (pnum == consoleplayer)
|
if (pnum == consoleplayer)
|
||||||
{
|
{
|
||||||
LUA_HookBool(false, HOOK(GameQuit));
|
LUA_HookBool(false, HOOK(GameQuit));
|
||||||
|
|
|
@ -134,6 +134,7 @@ typedef union
|
||||||
#include "d_netfil.h"
|
#include "d_netfil.h"
|
||||||
#include "i_tcp.h"
|
#include "i_tcp.h"
|
||||||
#include "../m_argv.h"
|
#include "../m_argv.h"
|
||||||
|
#include "../i_threads.h"
|
||||||
|
|
||||||
#include "../doomstat.h"
|
#include "../doomstat.h"
|
||||||
|
|
||||||
|
@ -263,12 +264,33 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len
|
||||||
|
|
||||||
#ifdef HAVE_MINIUPNPC // based on old XChat patch
|
#ifdef HAVE_MINIUPNPC // based on old XChat patch
|
||||||
static void I_ShutdownUPnP(void);
|
static void I_ShutdownUPnP(void);
|
||||||
|
static void I_InitUPnP(void);
|
||||||
|
I_mutex upnp_mutex;
|
||||||
static struct UPNPUrls urls;
|
static struct UPNPUrls urls;
|
||||||
static struct IGDdatas data;
|
static struct IGDdatas data;
|
||||||
static char lanaddr[64];
|
static char lanaddr[64];
|
||||||
|
struct upnpdata
|
||||||
static inline void I_InitUPnP(void)
|
|
||||||
{
|
{
|
||||||
|
int upnpc_started;
|
||||||
|
};
|
||||||
|
static struct upnpdata *upnpuser;
|
||||||
|
static void init_upnpc_once(struct upnpdata *upnpdata);
|
||||||
|
|
||||||
|
static void I_InitUPnP(void)
|
||||||
|
{
|
||||||
|
upnpuser = malloc(sizeof *upnpuser);
|
||||||
|
upnpuser->upnpc_started = 0;
|
||||||
|
I_spawn_thread("init_upnpc_once", (I_thread_fn)init_upnpc_once, upnpuser);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_upnpc_once(struct upnpdata *upnpuserdata)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (upnpuserdata->upnpc_started != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
I_lock_mutex(&upnp_mutex);
|
||||||
const char * const deviceTypes[] = {
|
const char * const deviceTypes[] = {
|
||||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
|
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
|
||||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
|
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
|
||||||
|
@ -311,35 +333,43 @@ static inline void I_InitUPnP(void)
|
||||||
I_AddExitFunc(I_ShutdownUPnP);
|
I_AddExitFunc(I_ShutdownUPnP);
|
||||||
}
|
}
|
||||||
freeUPNPDevlist(devlist);
|
freeUPNPDevlist(devlist);
|
||||||
|
I_unlock_mutex(upnp_mutex);
|
||||||
}
|
}
|
||||||
else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR)
|
else if (upnp_error == UPNPDISCOVER_SOCKET_ERROR)
|
||||||
{
|
{
|
||||||
CONS_Printf(M_GetText("No UPnP devices discovered\n"));
|
CONS_Printf(M_GetText("No UPnP devices discovered\n"));
|
||||||
}
|
}
|
||||||
|
upnpuserdata->upnpc_started =1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
|
static inline void I_UPnP_add(const char * addr, const char *port, const char * servicetype)
|
||||||
{
|
{
|
||||||
|
I_lock_mutex(&upnp_mutex);
|
||||||
if (addr == NULL)
|
if (addr == NULL)
|
||||||
addr = lanaddr;
|
addr = lanaddr;
|
||||||
if (!urls.controlURL || urls.controlURL[0] == '\0')
|
if (!urls.controlURL || urls.controlURL[0] == '\0')
|
||||||
return;
|
return;
|
||||||
UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
|
UPNP_AddPortMapping(urls.controlURL, data.first.servicetype,
|
||||||
port, port, addr, "SRB2", servicetype, NULL, NULL);
|
port, port, addr, "SRB2", servicetype, NULL, NULL);
|
||||||
|
I_unlock_mutex(upnp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void I_UPnP_rem(const char *port, const char * servicetype)
|
static inline void I_UPnP_rem(const char *port, const char * servicetype)
|
||||||
{
|
{
|
||||||
|
I_lock_mutex(&upnp_mutex);
|
||||||
if (!urls.controlURL || urls.controlURL[0] == '\0')
|
if (!urls.controlURL || urls.controlURL[0] == '\0')
|
||||||
return;
|
return;
|
||||||
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
|
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
|
||||||
port, servicetype, NULL);
|
port, servicetype, NULL);
|
||||||
|
I_unlock_mutex(upnp_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void I_ShutdownUPnP(void)
|
static void I_ShutdownUPnP(void)
|
||||||
{
|
{
|
||||||
I_UPnP_rem(serverport_name, "UDP");
|
I_UPnP_rem(serverport_name, "UDP");
|
||||||
|
I_lock_mutex(&upnp_mutex);
|
||||||
FreeUPNPUrls(&urls);
|
FreeUPNPUrls(&urls);
|
||||||
|
I_unlock_mutex(upnp_mutex);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -8042,6 +8042,18 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
||||||
{
|
{
|
||||||
clientGamedata->mapvisited[gamemap-1] |= MV_VISITED;
|
clientGamedata->mapvisited[gamemap-1] |= MV_VISITED;
|
||||||
serverGamedata->mapvisited[gamemap-1] |= MV_VISITED;
|
serverGamedata->mapvisited[gamemap-1] |= MV_VISITED;
|
||||||
|
|
||||||
|
M_SilentUpdateUnlockablesAndEmblems(serverGamedata);
|
||||||
|
|
||||||
|
if (M_UpdateUnlockablesAndExtraEmblems(clientGamedata))
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_s3k68);
|
||||||
|
G_SaveGameData(clientGamedata);
|
||||||
|
}
|
||||||
|
else if (!reloadinggamestate)
|
||||||
|
{
|
||||||
|
G_SaveGameData(clientGamedata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
levelloading = false;
|
levelloading = false;
|
||||||
|
|
51
src/p_user.c
51
src/p_user.c
|
@ -19,6 +19,7 @@
|
||||||
#include "d_event.h"
|
#include "d_event.h"
|
||||||
#include "netcode/d_net.h"
|
#include "netcode/d_net.h"
|
||||||
#include "netcode/net_command.h"
|
#include "netcode/net_command.h"
|
||||||
|
#include "g_demo.h" // demoplayback, demoversion
|
||||||
#include "g_game.h"
|
#include "g_game.h"
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "r_fps.h"
|
#include "r_fps.h"
|
||||||
|
@ -7521,49 +7522,46 @@ static void P_NiGHTSMovement(player_t *player)
|
||||||
newangle = 270;
|
newangle = 270;
|
||||||
}
|
}
|
||||||
else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axises.
|
else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axises.
|
||||||
|
{
|
||||||
newangle = (INT16)FixedInt(AngleFixed(R_PointToAngle2(0,0, cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT)));
|
newangle = (INT16)FixedInt(AngleFixed(R_PointToAngle2(0,0, cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT)));
|
||||||
|
|
||||||
|
if (cmd->forwardmove == -36 && cmd->sidemove == 35 && !(demoplayback && demoversion < 0x0011))
|
||||||
|
newangle = 315; // Hack to compensate for directly down-right returning 314, not 315
|
||||||
|
}
|
||||||
|
|
||||||
newangle -= player->viewrollangle / ANG1;
|
newangle -= player->viewrollangle / ANG1;
|
||||||
|
|
||||||
if (newangle < 0 && moved)
|
if (newangle < 0 && moved)
|
||||||
newangle = (INT16)(360+newangle);
|
newangle = (INT16)(360+newangle);
|
||||||
}
|
|
||||||
|
|
||||||
|
if (moved && player->flyangle != newangle)
|
||||||
|
{
|
||||||
|
// "player->flyangle" is our current angle, "newangle" is where we want to go
|
||||||
|
INT32 anglediff = ((newangle - player->flyangle) + 360) % 360; // "+360" and then "%360" wraps it to 0-359
|
||||||
|
|
||||||
|
// How sharply can we turn?
|
||||||
if (player->pflags & PF_DRILLING)
|
if (player->pflags & PF_DRILLING)
|
||||||
thrustfactor = 2;
|
thrustfactor = 2;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
thrustfactor = 8;
|
thrustfactor = 8;
|
||||||
|
if (player->speed > 12000) // Decelerate while turning normally
|
||||||
// Decelerate while turning normally.
|
|
||||||
if (moved && player->flyangle != newangle && player->speed > 12000)
|
|
||||||
player->speed -= 60;
|
player->speed -= 60;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < thrustfactor; i++)
|
// Now, turn!
|
||||||
{
|
if (anglediff <= thrustfactor || anglediff >= (360-thrustfactor))
|
||||||
if (moved && player->flyangle != newangle)
|
player->flyangle = newangle;
|
||||||
{
|
else if (anglediff <= 180)
|
||||||
INT32 anglediff = (((newangle-player->flyangle)+360)%360);
|
player->flyangle += thrustfactor;
|
||||||
INT32 angledif2 = (((player->flyangle-newangle)+360)%360);
|
else
|
||||||
|
player->flyangle -= thrustfactor;
|
||||||
|
|
||||||
// player->flyangle is the one to move
|
player->flyangle = (player->flyangle + 360) % 360; // Buff out negatives, >360 angles...
|
||||||
// newangle is the "move to"
|
}
|
||||||
if (anglediff == 0 && angledif2 == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (anglediff>angledif2)
|
|
||||||
player->flyangle--;
|
|
||||||
else // if (anglediff<angledif2)
|
|
||||||
player->flyangle++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buff out negatives, >360 angles...
|
if (player->speed == 0 && cmd->forwardmove == 0 && (cmd->sidemove == 0 || (demoplayback && demoversion < 0x0011)))
|
||||||
player->flyangle = ((player->flyangle + 360) % 360);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(player->speed)
|
|
||||||
&& cmd->forwardmove == 0)
|
|
||||||
still = true;
|
still = true;
|
||||||
|
|
||||||
// No more bumper braking
|
// No more bumper braking
|
||||||
|
@ -7724,6 +7722,9 @@ static void P_NiGHTSMovement(player_t *player)
|
||||||
visangle += 180;
|
visangle += 180;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (player->mo->eflags & MFE_VERTICALFLIP) // Flip the roll angle in reverse gravity
|
||||||
|
visangle *= -1;
|
||||||
|
|
||||||
rollangle = FixedAngle(visangle<<FRACBITS);
|
rollangle = FixedAngle(visangle<<FRACBITS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1201,7 +1201,7 @@ void R_SetupFrame(player_t *player)
|
||||||
newview->x += quake.x;
|
newview->x += quake.x;
|
||||||
newview->y += quake.y;
|
newview->y += quake.y;
|
||||||
|
|
||||||
if (r_viewmobj->subsector)
|
if (!P_MobjWasRemoved(r_viewmobj) && r_viewmobj->subsector)
|
||||||
newview->sector = r_viewmobj->subsector->sector;
|
newview->sector = r_viewmobj->subsector->sector;
|
||||||
else
|
else
|
||||||
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
newview->sector = R_PointInSubsector(newview->x, newview->y)->sector;
|
||||||
|
|
19
src/r_segs.c
19
src/r_segs.c
|
@ -949,7 +949,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
||||||
lightlist_t *light;
|
lightlist_t *light;
|
||||||
r_lightlist_t *rlight;
|
r_lightlist_t *rlight;
|
||||||
INT32 range;
|
INT32 range;
|
||||||
line_t *newline = NULL;
|
|
||||||
// Render FOF sides kinda like normal sides, with the frac and step and everything
|
// Render FOF sides kinda like normal sides, with the frac and step and everything
|
||||||
// NOTE: INT64 instead of fixed_t because overflow concerns
|
// NOTE: INT64 instead of fixed_t because overflow concerns
|
||||||
INT64 top_frac, top_step, bottom_frac, bottom_step;
|
INT64 top_frac, top_step, bottom_frac, bottom_step;
|
||||||
|
@ -960,9 +959,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
||||||
fixed_t left_top, left_bottom; // needed here for slope skewing
|
fixed_t left_top, left_bottom; // needed here for slope skewing
|
||||||
pslope_t *skewslope = NULL;
|
pslope_t *skewslope = NULL;
|
||||||
boolean do_texture_skew;
|
boolean do_texture_skew;
|
||||||
INT16 lineflags;
|
boolean dont_peg_bottom;
|
||||||
INT32 blendlevel = 0;
|
|
||||||
fixed_t wall_scalex, wall_scaley;
|
fixed_t wall_scalex, wall_scaley;
|
||||||
|
INT32 blendlevel = 0;
|
||||||
UINT8 vertflip;
|
UINT8 vertflip;
|
||||||
|
|
||||||
void (*colfunc_2s) (column_t *);
|
void (*colfunc_2s) (column_t *);
|
||||||
|
@ -982,12 +981,16 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
||||||
if (pfloor->master->flags & ML_TFERLINE)
|
if (pfloor->master->flags & ML_TFERLINE)
|
||||||
{
|
{
|
||||||
size_t linenum = curline->linedef-pfloor->target->lines[0];
|
size_t linenum = curline->linedef-pfloor->target->lines[0];
|
||||||
newline = pfloor->master->frontsector->lines[0] + linenum;
|
line_t *newline = pfloor->master->frontsector->lines[0] + linenum;
|
||||||
sidedef = &sides[newline->sidenum[0]];
|
sidedef = &sides[newline->sidenum[0]];
|
||||||
lineflags = newline->flags;
|
do_texture_skew = newline->flags & ML_SKEWTD;
|
||||||
|
dont_peg_bottom = newline->flags & ML_DONTPEGBOTTOM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
lineflags = curline->linedef->flags;
|
{
|
||||||
|
do_texture_skew = pfloor->master->flags & ML_SKEWTD;
|
||||||
|
dont_peg_bottom = curline->linedef->flags & ML_DONTPEGBOTTOM;
|
||||||
|
}
|
||||||
|
|
||||||
texnum = R_GetTextureNum(sidedef->midtexture);
|
texnum = R_GetTextureNum(sidedef->midtexture);
|
||||||
vertflip = textures[texnum]->flip & 2;
|
vertflip = textures[texnum]->flip & 2;
|
||||||
|
@ -1169,8 +1172,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
||||||
left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
|
left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
|
||||||
left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
|
left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz;
|
||||||
|
|
||||||
do_texture_skew = lineflags & ML_SKEWTD;
|
|
||||||
|
|
||||||
if (do_texture_skew)
|
if (do_texture_skew)
|
||||||
{
|
{
|
||||||
skewslope = *pfloor->t_slope; // skew using top slope by default
|
skewslope = *pfloor->t_slope; // skew using top slope by default
|
||||||
|
@ -1181,7 +1182,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
||||||
|
|
||||||
offsetvalue = sidedef->rowoffset + sidedef->offsety_mid;
|
offsetvalue = sidedef->rowoffset + sidedef->offsety_mid;
|
||||||
|
|
||||||
if (lineflags & ML_DONTPEGBOTTOM)
|
if (dont_peg_bottom)
|
||||||
{
|
{
|
||||||
if (do_texture_skew)
|
if (do_texture_skew)
|
||||||
{
|
{
|
||||||
|
|
|
@ -3508,7 +3508,7 @@ boolean R_ThingVisible (mobj_t *thing)
|
||||||
(thing->sprite == SPR_NULL) || // Don't draw null-sprites
|
(thing->sprite == SPR_NULL) || // Don't draw null-sprites
|
||||||
(thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects
|
(thing->flags2 & MF2_DONTDRAW) || // Don't draw MF2_LINKDRAW objects
|
||||||
(thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects
|
(thing->drawonlyforplayer && thing->drawonlyforplayer != viewplayer) || // Don't draw other players' personal objects
|
||||||
(r_viewmobj && (
|
(!P_MobjWasRemoved(r_viewmobj) && (
|
||||||
(r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects
|
(r_viewmobj == thing) || // Don't draw first-person players or awayviewmobj objects
|
||||||
(r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj
|
(r_viewmobj->player && r_viewmobj->player->followmobj == thing) || // Don't draw first-person players' followmobj
|
||||||
(r_viewmobj == thing->dontdrawforviewmobj) // Don't draw objects that are hidden for the current view
|
(r_viewmobj == thing->dontdrawforviewmobj) // Don't draw objects that are hidden for the current view
|
||||||
|
|
|
@ -1785,6 +1785,8 @@ static void ST_drawNightsRecords(void)
|
||||||
|
|
||||||
static void ST_drawNiGHTSLink(void)
|
static void ST_drawNiGHTSLink(void)
|
||||||
{
|
{
|
||||||
|
if (stplyr->linkcount != 0) // Don't show a faint 4294967295 link, even when debugging
|
||||||
|
{
|
||||||
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0};
|
static INT32 prevsel[2] = {0, 0}, prevtime[2] = {0, 0};
|
||||||
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
|
const UINT8 q = ((splitscreen && stplyr == &players[secondarydisplayplayer]) ? 1 : 0);
|
||||||
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? (stplyr->linkcount-1 >= 600) ? 2 : 1 : 0);
|
INT32 sel = ((stplyr->linkcount-1) / 5) % NUMLINKCOLORS, aflag = V_PERPLAYER, mag = ((stplyr->linkcount-1 >= 300) ? (stplyr->linkcount-1 >= 600) ? 2 : 1 : 0);
|
||||||
|
@ -1824,6 +1826,7 @@ static void ST_drawNiGHTSLink(void)
|
||||||
ST_DrawNightsOverlayNum(x-(4*scale), y, scale, aflag, (stplyr->linkcount-1), nightsnum, colornum);
|
ST_DrawNightsOverlayNum(x-(4*scale), y, scale, aflag, (stplyr->linkcount-1), nightsnum, colornum);
|
||||||
V_DrawFixedPatch(x+(4*scale), y, scale, aflag, nightslink,
|
V_DrawFixedPatch(x+(4*scale), y, scale, aflag, nightslink,
|
||||||
colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE));
|
colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE));
|
||||||
|
}
|
||||||
|
|
||||||
// Show remaining link time left in debug
|
// Show remaining link time left in debug
|
||||||
if (cv_debug & DBG_NIGHTSBASIC)
|
if (cv_debug & DBG_NIGHTSBASIC)
|
||||||
|
@ -1854,13 +1857,15 @@ static void ST_drawNiGHTSHUD(void)
|
||||||
for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill)
|
for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill)
|
||||||
V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]);
|
V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_PERPLAYER|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]);
|
||||||
|
|
||||||
// Display actual drill amount and bumper time
|
// Display actual flyangle, drill amount, and bumper time
|
||||||
if (!splitscreen && (cv_debug & DBG_NIGHTSBASIC))
|
if (!splitscreen && (cv_debug & DBG_NIGHTSBASIC))
|
||||||
{
|
{
|
||||||
|
V_DrawString(locx, locy - 16, V_MONOSPACE, va("ANGLE: %3d", stplyr->flyangle));
|
||||||
|
|
||||||
if (stplyr->bumpertime)
|
if (stplyr->bumpertime)
|
||||||
V_DrawString(locx, locy - 8, V_REDMAP|V_MONOSPACE, va("BUMPER: 0.%02d", G_TicsToCentiseconds(stplyr->bumpertime)));
|
V_DrawString(locx, locy - 8, V_REDMAP|V_MONOSPACE, va("BUMPER: 0.%02d", G_TicsToCentiseconds(stplyr->bumpertime)));
|
||||||
else
|
else
|
||||||
V_DrawString(locx, locy - 8, V_MONOSPACE, va("Drill: %3d%%", (stplyr->drillmeter*100)/(96*20)));
|
V_DrawString(locx, locy - 8, V_MONOSPACE, va("DRILL: %3d%%", (stplyr->drillmeter*100)/(96*20)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue