mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-04-13 13:42:31 +00:00
Merge branch 'next' into ogl-palette-rendering
This commit is contained in:
commit
4523364a40
169 changed files with 14068 additions and 12173 deletions
|
@ -1,4 +1,4 @@
|
|||
version: 2.2.13.{branch}-{build}
|
||||
version: 2.2.14.{branch}-{build}
|
||||
os: MinGW
|
||||
|
||||
environment:
|
||||
|
|
|
@ -8,11 +8,7 @@ LOCAL_SRC_FILES := am_map.c \
|
|||
command.c \
|
||||
comptime.c \
|
||||
console.c \
|
||||
d_clisrv.c \
|
||||
d_main.c \
|
||||
d_net.c \
|
||||
d_netcmd.c \
|
||||
d_netfil.c \
|
||||
dehacked.c \
|
||||
f_finale.c \
|
||||
f_wipe.c \
|
||||
|
@ -20,7 +16,6 @@ LOCAL_SRC_FILES := am_map.c \
|
|||
g_game.c \
|
||||
g_input.c \
|
||||
hu_stuff.c \
|
||||
i_tcp.c \
|
||||
info.c \
|
||||
lzf.c \
|
||||
m_argv.c \
|
||||
|
@ -32,7 +27,6 @@ LOCAL_SRC_FILES := am_map.c \
|
|||
m_queue.c \
|
||||
m_random.c \
|
||||
md5.c \
|
||||
mserv.c \
|
||||
p_ceilng.c \
|
||||
p_enemy.c \
|
||||
p_fab.c \
|
||||
|
@ -61,6 +55,7 @@ LOCAL_SRC_FILES := am_map.c \
|
|||
r_things.c \
|
||||
s_sound.c \
|
||||
screen.c \
|
||||
snake.c \
|
||||
sounds.c \
|
||||
st_stuff.c \
|
||||
string.c \
|
||||
|
|
|
@ -6,10 +6,6 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
config.h.in
|
||||
string.c
|
||||
d_main.c
|
||||
d_clisrv.c
|
||||
d_net.c
|
||||
d_netfil.c
|
||||
d_netcmd.c
|
||||
dehacked.c
|
||||
deh_soc.c
|
||||
deh_lua.c
|
||||
|
@ -83,12 +79,10 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
sounds.c
|
||||
w_wad.c
|
||||
filesrch.c
|
||||
mserv.c
|
||||
http-mserv.c
|
||||
i_tcp.c
|
||||
lzf.c
|
||||
b_bot.c
|
||||
u_list.c
|
||||
snake.c
|
||||
lua_script.c
|
||||
lua_baselib.c
|
||||
lua_mathlib.c
|
||||
|
@ -105,6 +99,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
|
|||
lua_blockmaplib.c
|
||||
lua_hudlib.c
|
||||
lua_hudlib_drawlist.c
|
||||
lua_colorlib.c
|
||||
lua_inputlib.c
|
||||
)
|
||||
|
||||
|
@ -149,6 +144,7 @@ set(SRB2_CONFIG_DEV_BUILD OFF CACHE BOOL
|
|||
"Compile a development build of SRB2.")
|
||||
|
||||
add_subdirectory(blua)
|
||||
add_subdirectory(netcode)
|
||||
|
||||
# OS macros
|
||||
if (UNIX)
|
||||
|
@ -258,6 +254,7 @@ target_compile_options(SRB2SDL2 PRIVATE
|
|||
-Winline
|
||||
-Wformat-y2k
|
||||
-Wformat-security
|
||||
-fwrapv
|
||||
|
||||
$<$<VERSION_LESS:$<C_COMPILER_VERSION>,2.9.5>:
|
||||
-Wno-div-by-zero
|
||||
|
@ -327,6 +324,7 @@ target_compile_options(SRB2SDL2 PRIVATE
|
|||
-Wno-error=non-literal-null-conversion
|
||||
-Wno-error=constant-conversion
|
||||
-Wno-error=unused-but-set-variable
|
||||
-fwrapv
|
||||
>
|
||||
|
||||
# C, MSVC
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
#
|
||||
# Netplay incompatible
|
||||
# --------------------
|
||||
# NONET=1 - Disable online capability.
|
||||
# NOMD5=1 - Disable MD5 checksum (validation tool).
|
||||
# NOPOSTPROCESSING=1 - ?
|
||||
# MOBJCONSISTANCY=1 - ??
|
||||
|
@ -166,7 +165,7 @@ sources:=
|
|||
makedir:=../make
|
||||
|
||||
# -DCOMPVERSION: flag to use comptime.h
|
||||
opts:=-DCOMPVERSION -g
|
||||
opts:=-DCOMPVERSION -g -fwrapv
|
||||
libs:=
|
||||
|
||||
# This is a list of variables names, of which if defined,
|
||||
|
@ -188,6 +187,7 @@ objdir:=$(makedir)/objs
|
|||
sources+=\
|
||||
$(call List,Sourcefile)\
|
||||
$(call List,blua/Sourcefile)\
|
||||
$(call List,netcode/Sourcefile)\
|
||||
|
||||
depends:=$(basename $(filter %.c %.s,$(sources)))
|
||||
objects:=$(basename $(filter %.c %.s %.nas,$(sources)))
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#
|
||||
|
||||
passthru_opts+=\
|
||||
NONET NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
|
||||
NO_IPV6 NOHW NOMD5 NOPOSTPROCESSING\
|
||||
MOBJCONSISTANCY PACKETDROP ZDEBUG\
|
||||
NOUPNP NOEXECINFO\
|
||||
|
||||
|
@ -18,10 +18,6 @@ opts+=-DHWRENDER
|
|||
sources+=$(call List,hardware/Sourcefile)
|
||||
endif
|
||||
|
||||
ifdef NONET
|
||||
NOCURL=1
|
||||
endif
|
||||
|
||||
ifndef NOMD5
|
||||
sources+=md5.c
|
||||
endif
|
||||
|
@ -43,7 +39,6 @@ sources+=apng.c
|
|||
endif
|
||||
endif
|
||||
|
||||
ifndef NONET
|
||||
ifndef NOCURL
|
||||
CURLCONFIG?=curl-config
|
||||
$(eval $(call Configure,CURL,$(CURLCONFIG)))
|
||||
|
@ -56,7 +51,6 @@ $(eval $(call Use_pkg_config,MINIUPNPC))
|
|||
HAVE_MINIUPNPC=1
|
||||
opts+=-DHAVE_MINIUPNP
|
||||
endif
|
||||
endif
|
||||
|
||||
# (Valgrind is a memory debugger.)
|
||||
ifdef VALGRIND
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
string.c
|
||||
d_main.c
|
||||
d_clisrv.c
|
||||
d_net.c
|
||||
d_netfil.c
|
||||
d_netcmd.c
|
||||
dehacked.c
|
||||
deh_soc.c
|
||||
deh_lua.c
|
||||
|
@ -77,12 +73,10 @@ s_sound.c
|
|||
sounds.c
|
||||
w_wad.c
|
||||
filesrch.c
|
||||
mserv.c
|
||||
http-mserv.c
|
||||
i_tcp.c
|
||||
lzf.c
|
||||
b_bot.c
|
||||
u_list.c
|
||||
snake.c
|
||||
lua_script.c
|
||||
lua_baselib.c
|
||||
lua_mathlib.c
|
||||
|
@ -100,3 +94,4 @@ lua_blockmaplib.c
|
|||
lua_hudlib.c
|
||||
lua_hudlib_drawlist.c
|
||||
lua_inputlib.c
|
||||
lua_colorlib.c
|
||||
|
|
|
@ -1071,7 +1071,6 @@ static inline void AM_drawPlayers(void)
|
|||
return;
|
||||
}
|
||||
|
||||
// multiplayer (how??)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "../i_net.h"
|
||||
#include "../netcode/i_net.h"
|
||||
|
||||
boolean I_InitNetwork(void)
|
||||
{
|
||||
|
|
12
src/b_bot.c
12
src/b_bot.c
|
@ -239,7 +239,8 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
// SPINNING
|
||||
if (!(player->pflags & (PF_SPINNING|PF_STARTDASH)) && mem->thinkstate == AI_SPINFOLLOW)
|
||||
mem->thinkstate = AI_FOLLOW;
|
||||
else if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_SPINFOLLOW)
|
||||
else if ((mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_SPINFOLLOW)
|
||||
&& bot->charability2 == CA2_SPINDASH)
|
||||
{
|
||||
if (!_2d)
|
||||
{
|
||||
|
@ -329,7 +330,7 @@ static void B_BuildTailsTiccmd(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd)
|
|||
if (mem->thinkstate == AI_FOLLOW || mem->thinkstate == AI_CATCHUP || (mem->thinkstate == AI_SPINFOLLOW && player->pflags & PF_JUMPED))
|
||||
{
|
||||
// Flying catch-up
|
||||
if (bot->pflags & PF_THOKKED)
|
||||
if (bot->charability == CA_FLY && bot->pflags & PF_THOKKED)
|
||||
{
|
||||
cmd->forwardmove = min(MAXPLMOVE, (dist/scale)>>3);
|
||||
if (zdist < -64*scale)
|
||||
|
@ -583,11 +584,11 @@ void B_RespawnBot(INT32 playernum)
|
|||
P_SetOrigin(tails, x, y, z);
|
||||
if (player->charability == CA_FLY)
|
||||
{
|
||||
P_SetPlayerMobjState(tails, S_PLAY_FLY);
|
||||
P_SetMobjState(tails, S_PLAY_FLY);
|
||||
tails->player->powers[pw_tailsfly] = (UINT16)-1;
|
||||
}
|
||||
else
|
||||
P_SetPlayerMobjState(tails, S_PLAY_FALL);
|
||||
P_SetMobjState(tails, S_PLAY_FALL);
|
||||
P_SetScale(tails, sonic->scale);
|
||||
tails->destscale = sonic->destscale;
|
||||
}
|
||||
|
@ -613,6 +614,9 @@ void B_HandleFlightIndicator(player_t *player)
|
|||
|
||||
// otherwise, spawn it
|
||||
P_SetTarget(&tails->hnext, P_SpawnMobjFromMobj(tails, 0, 0, 0, MT_OVERLAY));
|
||||
if (P_MobjWasRemoved(tails->hnext))
|
||||
return; // we can't spawn one, so it can't exist
|
||||
|
||||
P_SetTarget(&tails->hnext->target, tails);
|
||||
P_SetTarget(&tails->hnext->hprev, tails);
|
||||
P_SetMobjState(tails->hnext, S_FLIGHTINDICATOR);
|
||||
|
|
|
@ -275,18 +275,36 @@ static int luaB_dofile (lua_State *L) {
|
|||
int n = lua_gettop(L);
|
||||
|
||||
if (!W_FileHasFolders(wadfiles[numwadfiles - 1]))
|
||||
luaL_error(L, "dofile() only works with PK3 files");
|
||||
luaL_error(L, "dofile() only works with PK3 files and folders");
|
||||
|
||||
snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename);
|
||||
lumpnum = W_CheckNumForFullNamePK3(fullfilename, numwadfiles - 1, 0);
|
||||
if (lumpnum == INT16_MAX)
|
||||
luaL_error(L, "can't find script " LUA_QS, fullfilename);
|
||||
|
||||
LUA_LoadLump(numwadfiles - 1, lumpnum, false);
|
||||
LUA_DoLump(numwadfiles - 1, lumpnum, false);
|
||||
|
||||
return lua_gettop(L) - n;
|
||||
}
|
||||
|
||||
// Edited to load PK3 entries instead
|
||||
static int luaB_loadfile (lua_State *L) {
|
||||
const char *filename = luaL_checkstring(L, 1);
|
||||
char fullfilename[256];
|
||||
UINT16 lumpnum;
|
||||
|
||||
if (!W_FileHasFolders(wadfiles[numwadfiles - 1]))
|
||||
luaL_error(L, "loadfile() only works with PK3 files and folders");
|
||||
|
||||
snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename);
|
||||
lumpnum = W_CheckNumForFullNamePK3(fullfilename, numwadfiles - 1, 0);
|
||||
if (lumpnum == INT16_MAX)
|
||||
luaL_error(L, "can't find script " LUA_QS, fullfilename);
|
||||
|
||||
LUA_LoadLump(numwadfiles - 1, lumpnum);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luaB_assert (lua_State *L) {
|
||||
luaL_checkany(L, 1);
|
||||
|
@ -406,6 +424,7 @@ static const luaL_Reg base_funcs[] = {
|
|||
{"collectgarbage", luaB_collectgarbage},
|
||||
{"error", luaB_error},
|
||||
{"dofile", luaB_dofile},
|
||||
{"loadfile", luaB_loadfile},
|
||||
{"gcinfo", luaB_gcinfo},
|
||||
{"getfenv", luaB_getfenv},
|
||||
{"getmetatable", luaB_getmetatable},
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
#include "lualib.h"
|
||||
#include "../i_system.h"
|
||||
#include "../g_game.h"
|
||||
#include "../d_netfil.h"
|
||||
#include "../netcode/d_netfil.h"
|
||||
#include "../netcode/net_command.h"
|
||||
#include "../lua_libs.h"
|
||||
#include "../byteptr.h"
|
||||
#include "../lua_script.h"
|
||||
|
|
107
src/command.c
107
src/command.c
|
@ -28,11 +28,12 @@
|
|||
#include "byteptr.h"
|
||||
#include "p_saveg.h"
|
||||
#include "g_game.h" // for player_names
|
||||
#include "d_netcmd.h"
|
||||
#include "netcode/d_netcmd.h"
|
||||
#include "netcode/net_command.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "p_setup.h"
|
||||
#include "lua_script.h"
|
||||
#include "d_netfil.h" // findfile
|
||||
#include "netcode/d_netfil.h" // findfile
|
||||
#include "r_data.h" // Color_cons_t
|
||||
#include "d_main.h" // D_IsPathAllowed
|
||||
|
||||
|
@ -50,9 +51,11 @@ static void COM_CEchoDuration_f(void);
|
|||
static void COM_Exec_f(void);
|
||||
static void COM_Wait_f(void);
|
||||
static void COM_Help_f(void);
|
||||
static void COM_Find_f(void);
|
||||
static void COM_Toggle_f(void);
|
||||
static void COM_Add_f(void);
|
||||
|
||||
|
||||
static void CV_EnforceExecVersion(void);
|
||||
static boolean CV_FilterVarByVersion(consvar_t *v, const char *valstr);
|
||||
static boolean CV_Command(void);
|
||||
|
@ -343,6 +346,7 @@ void COM_Init(void)
|
|||
COM_AddCommand("exec", COM_Exec_f, 0);
|
||||
COM_AddCommand("wait", COM_Wait_f, 0);
|
||||
COM_AddCommand("help", COM_Help_f, COM_LUA);
|
||||
COM_AddCommand("find", COM_Find_f, COM_LUA);
|
||||
COM_AddCommand("toggle", COM_Toggle_f, COM_LUA);
|
||||
COM_AddCommand("add", COM_Add_f, COM_LUA);
|
||||
RegisterNetXCmd(XD_NETVAR, Got_NetVar);
|
||||
|
@ -878,7 +882,7 @@ static void COM_Help_f(void)
|
|||
boolean floatmode = false;
|
||||
const char *cvalue = NULL;
|
||||
CONS_Printf("\x82""Variable %s:\n", cvar->name);
|
||||
CONS_Printf(M_GetText(" flags :"));
|
||||
CONS_Printf(M_GetText(" flags: "));
|
||||
if (cvar->flags & CV_SAVE)
|
||||
CONS_Printf("AUTOSAVE ");
|
||||
if (cvar->flags & CV_FLOAT)
|
||||
|
@ -975,31 +979,8 @@ static void COM_Help_f(void)
|
|||
return;
|
||||
}
|
||||
|
||||
CONS_Printf("No exact match, searching...\n");
|
||||
|
||||
// variables
|
||||
CONS_Printf("\x82""Variables:\n");
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
{
|
||||
if ((cvar->flags & CV_NOSHOWHELP) || (!strstr(cvar->name, help)))
|
||||
continue;
|
||||
CONS_Printf("%s ", cvar->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
// commands
|
||||
CONS_Printf("\x82""\nCommands:\n");
|
||||
for (cmd = com_commands; cmd; cmd = cmd->next)
|
||||
{
|
||||
if (!strstr(cmd->name, help))
|
||||
continue;
|
||||
CONS_Printf("%s ",cmd->name);
|
||||
i++;
|
||||
}
|
||||
|
||||
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or type help <command or variable>\n");
|
||||
|
||||
CONS_Debug(DBG_GAMELOGIC, "\x87Total : %d\n", i);
|
||||
CONS_Printf("No variable or command named %s", help);
|
||||
CONS_Printf("\x82""\nCheck wiki.srb2.org for more or try typing help without arguments\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -1029,6 +1010,76 @@ static void COM_Help_f(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void COM_Find_f(void)
|
||||
{
|
||||
static char prefix[80];
|
||||
xcommand_t *cmd;
|
||||
consvar_t *cvar;
|
||||
cmdalias_t *alias;
|
||||
const char *match;
|
||||
const char *help;
|
||||
size_t helplen;
|
||||
boolean matchesany;
|
||||
|
||||
if (COM_Argc() != 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("find <text>: Search for variables, commands and aliases containing <text>\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
help = COM_Argv(1);
|
||||
helplen = strlen(help);
|
||||
CONS_Printf("\x82""Variables:\n");
|
||||
matchesany = false;
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
{
|
||||
if (cvar->flags & CV_NOSHOWHELP)
|
||||
continue;
|
||||
match = strstr(cvar->name, help);
|
||||
if (match != NULL)
|
||||
{
|
||||
memcpy(prefix, cvar->name, match - cvar->name);
|
||||
prefix[match - cvar->name] = '\0';
|
||||
CONS_Printf(" %s\x83%s\x80%s\n", prefix, help, &match[helplen]);
|
||||
matchesany = true;
|
||||
}
|
||||
}
|
||||
if (!matchesany)
|
||||
CONS_Printf(" (none)\n");
|
||||
|
||||
CONS_Printf("\x82""Commands:\n");
|
||||
matchesany = false;
|
||||
for (cmd = com_commands; cmd; cmd = cmd->next)
|
||||
{
|
||||
match = strstr(cmd->name, help);
|
||||
if (match != NULL)
|
||||
{
|
||||
memcpy(prefix, cmd->name, match - cmd->name);
|
||||
prefix[match - cmd->name] = '\0';
|
||||
CONS_Printf(" %s\x83%s\x80%s\n", prefix, help, &match[helplen]);
|
||||
matchesany = true;
|
||||
}
|
||||
}
|
||||
if (!matchesany)
|
||||
CONS_Printf(" (none)\n");
|
||||
|
||||
CONS_Printf("\x82""Aliases:\n");
|
||||
matchesany = false;
|
||||
for (alias = com_alias; alias; alias = alias->next)
|
||||
{
|
||||
match = strstr(alias->name, help);
|
||||
if (match != NULL)
|
||||
{
|
||||
memcpy(prefix, alias->name, match - alias->name);
|
||||
prefix[match - alias->name] = '\0';
|
||||
CONS_Printf(" %s\x83%s\x80%s\n", prefix, help, &match[helplen]);
|
||||
matchesany = true;
|
||||
}
|
||||
}
|
||||
if (!matchesany)
|
||||
CONS_Printf(" (none)\n");
|
||||
}
|
||||
|
||||
/** Toggles a console variable. Useful for on/off values.
|
||||
*
|
||||
* This works on on/off, yes/no values only
|
||||
|
|
106
src/console.c
106
src/console.c
|
@ -220,13 +220,16 @@ static char *bindtable[NUMINPUTS];
|
|||
static void CONS_Bind_f(void)
|
||||
{
|
||||
size_t na;
|
||||
char *newcmd;
|
||||
//size_t newlen = 0;
|
||||
unsigned int i;
|
||||
INT32 key;
|
||||
|
||||
na = COM_Argc();
|
||||
|
||||
if (na != 2 && na != 3)
|
||||
if (na < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("bind <keyname> [<command>]: create shortcut keys to command(s)\n"));
|
||||
CONS_Printf(M_GetText("bind <keyname> [<command>] [<arg1>] [...]: create shortcut keys to command(s)\n"));
|
||||
CONS_Printf("\x82%s", M_GetText("Bind table :\n"));
|
||||
na = 0;
|
||||
for (key = 0; key < NUMINPUTS; key++)
|
||||
|
@ -250,8 +253,36 @@ static void CONS_Bind_f(void)
|
|||
Z_Free(bindtable[key]);
|
||||
bindtable[key] = NULL;
|
||||
|
||||
if (na == 3)
|
||||
bindtable[key] = Z_StrDup(COM_Argv(2));
|
||||
if (na < 3)
|
||||
return;
|
||||
|
||||
for (i = 2; i < na; ++i)
|
||||
{
|
||||
const char *arg = COM_Argv(i);
|
||||
|
||||
// on the second iteration, and after
|
||||
if (i > 2)
|
||||
{
|
||||
size_t newlen = strlen(bindtable[key]) + strlen(arg) + 1; // new length, allow space for ' ' and '\0'
|
||||
size_t curpos = newcmd - bindtable[key]; // offset from newcmd to original pointer
|
||||
|
||||
newcmd = bindtable[key] = Z_Realloc(bindtable[key], newlen, PU_STATIC, NULL);
|
||||
newcmd += curpos; // reapply offset
|
||||
|
||||
newcmd[0] = ' '; // replace previous '\0' w/ ' '
|
||||
++newcmd; // make sure later strcpy doesnt overwrite ' '
|
||||
}
|
||||
// first iteration
|
||||
else
|
||||
// allocate space for argument and a ' ' or '\0'
|
||||
newcmd = bindtable[key] = Z_Calloc(strlen(arg) + 1, PU_STATIC, NULL);
|
||||
|
||||
// the copy
|
||||
strcpy(newcmd, arg);
|
||||
|
||||
// move window past copied argument for next iteration
|
||||
newcmd += strlen(arg);
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================
|
||||
|
@ -543,13 +574,13 @@ static void CON_RecalcSize(void)
|
|||
con_scalefactor = 1;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
con_scalefactor = vid.smalldupx;
|
||||
con_scalefactor = vid.smalldup;
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
con_scalefactor = vid.meddupx;
|
||||
con_scalefactor = vid.meddup;
|
||||
break;
|
||||
default: // Full scaling
|
||||
con_scalefactor = vid.dupx;
|
||||
con_scalefactor = vid.dup;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -667,7 +698,7 @@ static void CON_MoveConsole(void)
|
|||
}
|
||||
|
||||
// Not instant - Increment fracmovement fractionally
|
||||
fracmovement += FixedMul(cons_speed.value*vid.fdupy, renderdeltatics);
|
||||
fracmovement += FixedMul(cons_speed.value*vid.fdup, renderdeltatics);
|
||||
|
||||
if (con_curlines < con_destlines) // Move the console downwards
|
||||
{
|
||||
|
@ -921,7 +952,8 @@ boolean CON_Responder(event_t *ev)
|
|||
static UINT8 consdown = false; // console is treated differently due to rare usage
|
||||
|
||||
// sequential completions a la 4dos
|
||||
static char completion[80];
|
||||
static char completioncmd[80 + sizeof("find ")] = "find ";
|
||||
static char *completion = &completioncmd[sizeof("find ")-1];
|
||||
|
||||
static INT32 skips;
|
||||
|
||||
|
@ -936,7 +968,7 @@ boolean CON_Responder(event_t *ev)
|
|||
return false;
|
||||
|
||||
// let go keyup events, don't eat them
|
||||
if (ev->type != ev_keydown && ev->type != ev_console)
|
||||
if (ev->type != ev_keydown && ev->type != ev_text && ev->type != ev_console)
|
||||
{
|
||||
if (ev->key == gamecontrol[GC_CONSOLE][0] || ev->key == gamecontrol[GC_CONSOLE][1])
|
||||
consdown = false;
|
||||
|
@ -951,7 +983,7 @@ boolean CON_Responder(event_t *ev)
|
|||
if (modeattacking || metalrecording || marathonmode)
|
||||
return false;
|
||||
|
||||
if (key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1])
|
||||
if ((key == gamecontrol[GC_CONSOLE][0] || key == gamecontrol[GC_CONSOLE][1]) && !shiftdown)
|
||||
{
|
||||
if (consdown) // ignore repeat
|
||||
return true;
|
||||
|
@ -963,7 +995,7 @@ boolean CON_Responder(event_t *ev)
|
|||
// check other keys only if console prompt is active
|
||||
if (!consoleready && key < NUMINPUTS) // metzgermeister: boundary check!!
|
||||
{
|
||||
if (! menuactive && bindtable[key])
|
||||
if (ev->type == ev_keydown && !menuactive && bindtable[key])
|
||||
{
|
||||
COM_BufAddText(bindtable[key]);
|
||||
COM_BufAddText("\n");
|
||||
|
@ -980,6 +1012,13 @@ boolean CON_Responder(event_t *ev)
|
|||
}
|
||||
}
|
||||
|
||||
if (ev->type == ev_text)
|
||||
{
|
||||
if (!consoletoggle)
|
||||
CON_InputAddChar(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Always eat ctrl/shift/alt if console open, so the menu doesn't get ideas
|
||||
if (key == KEY_LSHIFT || key == KEY_RSHIFT
|
||||
|| key == KEY_LCTRL || key == KEY_RCTRL
|
||||
|
@ -1057,36 +1096,14 @@ boolean CON_Responder(event_t *ev)
|
|||
// show all cvars/commands that match what we have inputted
|
||||
if (key == KEY_TAB)
|
||||
{
|
||||
size_t i, len;
|
||||
|
||||
if (!completion[0])
|
||||
{
|
||||
if (!input_len || input_len >= 40 || strchr(inputlines[inputline], ' '))
|
||||
return true;
|
||||
strcpy(completion, inputlines[inputline]);
|
||||
}
|
||||
len = strlen(completion);
|
||||
|
||||
//first check commands
|
||||
CONS_Printf("\nCommands:\n");
|
||||
for (i = 0, cmd = COM_CompleteCommand(completion, i); cmd; cmd = COM_CompleteCommand(completion, ++i))
|
||||
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
|
||||
if (i == 0) CONS_Printf(" (none)\n");
|
||||
|
||||
//now we move on to CVARs
|
||||
CONS_Printf("Variables:\n");
|
||||
for (i = 0, cmd = CV_CompleteVar(completion, i); cmd; cmd = CV_CompleteVar(completion, ++i))
|
||||
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
|
||||
if (i == 0) CONS_Printf(" (none)\n");
|
||||
|
||||
//and finally aliases
|
||||
CONS_Printf("Aliases:\n");
|
||||
for (i = 0, cmd = COM_CompleteAlias(completion, i); cmd; cmd = COM_CompleteAlias(completion, ++i))
|
||||
CONS_Printf(" \x83" "%s" "\x80" "%s\n", completion, cmd+len);
|
||||
if (i == 0) CONS_Printf(" (none)\n");
|
||||
|
||||
COM_BufInsertText(completioncmd);
|
||||
completion[0] = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
// ---
|
||||
|
@ -1316,21 +1333,12 @@ boolean CON_Responder(event_t *ev)
|
|||
else if (key == KEY_KPADSLASH)
|
||||
key = '/';
|
||||
|
||||
if (key >= 'a' && key <= 'z')
|
||||
{
|
||||
if (capslock ^ shiftdown)
|
||||
key = shiftxform[key];
|
||||
}
|
||||
else if (shiftdown)
|
||||
key = shiftxform[key];
|
||||
|
||||
// enter a char into the command prompt
|
||||
if (key < 32 || key > 127)
|
||||
return true;
|
||||
|
||||
if (input_sel != input_cur)
|
||||
CON_InputDelSelection();
|
||||
CON_InputAddChar(key);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1764,9 +1772,9 @@ static void CON_DrawBackpic(void)
|
|||
con_backpic = W_CachePatchNum(piclump, PU_PATCH);
|
||||
|
||||
// Center the backpic, and draw a vertically cropped patch.
|
||||
w = (con_backpic->width * vid.dupx);
|
||||
w = con_backpic->width * vid.dup;
|
||||
x = (vid.width / 2) - (w / 2);
|
||||
h = con_curlines/vid.dupy;
|
||||
h = con_curlines/vid.dup;
|
||||
|
||||
// If the patch doesn't fill the entire screen,
|
||||
// then fill the sides with a solid color.
|
||||
|
@ -1885,9 +1893,9 @@ void CON_Drawer(void)
|
|||
|
||||
if (con_curlines > 0)
|
||||
CON_DrawConsole();
|
||||
else if (gamestate == GS_LEVEL
|
||||
|| gamestate == GS_INTERMISSION || gamestate == GS_ENDING || gamestate == GS_CUTSCENE
|
||||
|| gamestate == GS_CREDITS || gamestate == GS_EVALUATION || gamestate == GS_WAITINGPLAYERS)
|
||||
else if (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_CREDITS
|
||||
|| gamestate == GS_EVALUATION || gamestate == GS_ENDING || gamestate == GS_CUTSCENE
|
||||
|| gamestate == GS_WAITINGPLAYERS || cv_debug)
|
||||
CON_DrawHudlines();
|
||||
|
||||
Unlock_state();
|
||||
|
|
5840
src/d_clisrv.c
5840
src/d_clisrv.c
File diff suppressed because it is too large
Load diff
|
@ -22,6 +22,7 @@ typedef enum
|
|||
{
|
||||
ev_keydown,
|
||||
ev_keyup,
|
||||
ev_text,
|
||||
ev_console,
|
||||
ev_mouse,
|
||||
ev_joystick,
|
||||
|
|
16
src/d_main.c
16
src/d_main.c
|
@ -34,7 +34,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "am_map.h"
|
||||
#include "console.h"
|
||||
#include "d_net.h"
|
||||
#include "netcode/d_net.h"
|
||||
#include "f_finale.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
|
@ -56,11 +56,11 @@
|
|||
#include "w_wad.h"
|
||||
#include "z_zone.h"
|
||||
#include "d_main.h"
|
||||
#include "d_netfil.h"
|
||||
#include "netcode/d_netfil.h"
|
||||
#include "m_cheat.h"
|
||||
#include "y_inter.h"
|
||||
#include "p_local.h" // chasecam
|
||||
#include "mserv.h" // ms_RoomId
|
||||
#include "netcode/mserv.h" // ms_RoomId
|
||||
#include "m_misc.h" // screenshot functionality
|
||||
#include "deh_tables.h" // Dehacked list test
|
||||
#include "m_cond.h" // condition initialization
|
||||
|
@ -192,19 +192,19 @@ void D_ProcessEvents(void)
|
|||
ev = &events[eventtail];
|
||||
|
||||
// Set mouse buttons early in case event is eaten later
|
||||
if (ev->type == ev_keydown || ev->type == ev_keyup)
|
||||
if (ev->type == ev_keydown || ev->type == ev_keyup || ev->type == ev_text)
|
||||
{
|
||||
// Mouse buttons
|
||||
if ((UINT32)(ev->key - KEY_MOUSE1) < MOUSEBUTTONS)
|
||||
{
|
||||
if (ev->type == ev_keydown)
|
||||
if (ev->type == ev_keydown || ev->type == ev_text)
|
||||
mouse.buttons |= 1 << (ev->key - KEY_MOUSE1);
|
||||
else
|
||||
mouse.buttons &= ~(1 << (ev->key - KEY_MOUSE1));
|
||||
}
|
||||
else if ((UINT32)(ev->key - KEY_2MOUSE1) < MOUSEBUTTONS)
|
||||
{
|
||||
if (ev->type == ev_keydown)
|
||||
if (ev->type == ev_keydown || ev->type == ev_text)
|
||||
mouse2.buttons |= 1 << (ev->key - KEY_2MOUSE1);
|
||||
else
|
||||
mouse2.buttons &= ~(1 << (ev->key - KEY_2MOUSE1));
|
||||
|
@ -981,6 +981,7 @@ void D_StartTitle(void)
|
|||
emeralds = 0;
|
||||
memset(&luabanks, 0, sizeof(luabanks));
|
||||
lastmaploaded = 0;
|
||||
pickedchar = R_SkinAvailable(cv_defaultskin.string);
|
||||
|
||||
// In case someone exits out at the same time they start a time attack run,
|
||||
// reset modeattacking
|
||||
|
@ -1613,6 +1614,9 @@ void D_SRB2Main(void)
|
|||
if (D_CheckNetGame())
|
||||
autostart = true;
|
||||
|
||||
if (!dedicated)
|
||||
pickedchar = R_SkinAvailable(cv_defaultskin.string);
|
||||
|
||||
// check for a driver that wants intermission stats
|
||||
// start the apropriate game based on parms
|
||||
if (M_CheckParm("-metal"))
|
||||
|
|
|
@ -158,6 +158,10 @@ typedef enum
|
|||
PF_FORCESTRAFE = 1<<28, // Turning inputs are translated into strafing inputs
|
||||
PF_CANCARRY = 1<<29, // Can carry another player?
|
||||
PF_FINISHED = 1<<30, // The player finished the level. NOT the same as exiting
|
||||
|
||||
// True if shield button down last tic
|
||||
// This may be the final flag, but 2.3 could free up the others
|
||||
PF_SHIELDDOWN = 1<<31,
|
||||
|
||||
// up to 1<<31 is free
|
||||
} pflags_t;
|
||||
|
@ -607,6 +611,7 @@ typedef struct player_s
|
|||
|
||||
tic_t jointime; // Timer when player joins game to change skin/color
|
||||
tic_t quittime; // Time elapsed since user disconnected, zero if connected
|
||||
tic_t lastinputtime; // the last tic the player has made any input
|
||||
#ifdef HWRENDER
|
||||
fixed_t fovadd; // adjust FOV for hw rendering
|
||||
#endif
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef struct thinker_s
|
|||
// killough 11/98: count of how many other objects reference
|
||||
// this one using pointers. Used for garbage collection.
|
||||
INT32 references;
|
||||
boolean cachable;
|
||||
|
||||
#ifdef PARANOIA
|
||||
INT32 debug_mobjtype;
|
||||
|
|
|
@ -26,20 +26,23 @@
|
|||
// Button/action code definitions.
|
||||
typedef enum
|
||||
{
|
||||
// First 4 bits are weapon change info, DO NOT USE!
|
||||
BT_WEAPONMASK = 0x0F, //our first four bits.
|
||||
// First 3 bits are weapon change info, DO NOT USE!
|
||||
BT_WEAPONMASK = 0x07, //our first three bits.
|
||||
|
||||
BT_SHIELD = 1<<3, // shield or super action
|
||||
|
||||
BT_WEAPONNEXT = 1<<4,
|
||||
BT_WEAPONPREV = 1<<5,
|
||||
|
||||
BT_ATTACK = 1<<6, // shoot rings
|
||||
BT_SPIN = 1<<7,
|
||||
BT_CAMLEFT = 1<<8, // turn camera left
|
||||
BT_CAMRIGHT = 1<<9, // turn camera right
|
||||
BT_TOSSFLAG = 1<<10,
|
||||
BT_JUMP = 1<<11,
|
||||
BT_FIRENORMAL = 1<<12, // Fire a normal ring no matter what
|
||||
BT_WEAPONNEXT = 1<<4, // select next weapon
|
||||
BT_WEAPONPREV = 1<<5, // select previous weapon
|
||||
|
||||
BT_ATTACK = 1<<6, // shoot rings
|
||||
BT_SPIN = 1<<7, // spin action
|
||||
BT_CAMLEFT = 1<<8, // turn camera left
|
||||
BT_CAMRIGHT = 1<<9, // turn camera right
|
||||
BT_TOSSFLAG = 1<<10, // toss flag or emeralds
|
||||
BT_JUMP = 1<<11, // jump action
|
||||
BT_FIRENORMAL = 1<<12, // fire a normal ring no matter what
|
||||
|
||||
// custom lua buttons
|
||||
BT_CUSTOM1 = 1<<13,
|
||||
BT_CUSTOM2 = 1<<14,
|
||||
BT_CUSTOM3 = 1<<15,
|
||||
|
|
|
@ -297,7 +297,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
|
|||
CacheAndPushConstant(L, word, (lua_Integer)PF_FULLSTASIS);
|
||||
return 1;
|
||||
}
|
||||
else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release...
|
||||
// TODO: 2.3: Delete this alias
|
||||
else if (fastcmp(p, "USEDOWN"))
|
||||
{
|
||||
CacheAndPushConstant(L, word, (lua_Integer)PF_SPINDOWN);
|
||||
return 1;
|
||||
|
@ -583,11 +584,12 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release...
|
||||
// TODO: 2.3: Delete this alias
|
||||
if (fastcmp(word, "BT_USE"))
|
||||
{
|
||||
CacheAndPushConstant(L, word, (lua_Integer)BT_SPIN);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; INT_CONST[i].n; i++)
|
||||
if (fastcmp(word,INT_CONST[i].n)) {
|
||||
|
@ -598,14 +600,9 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int lib_getenum(lua_State *L)
|
||||
static inline int getEnum(lua_State *L, boolean mathlib, const char *word)
|
||||
{
|
||||
const char *word;
|
||||
fixed_t i;
|
||||
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
|
||||
if (lua_type(L,2) != LUA_TSTRING)
|
||||
return 0;
|
||||
word = lua_tostring(L,2);
|
||||
|
||||
// check actions, super and globals first, as they don't have _G caching implemented
|
||||
// so they benefit from being checked first
|
||||
|
@ -672,6 +669,46 @@ static inline int lib_getenum(lua_State *L)
|
|||
else if ((!mathlib && LUA_PushGlobals(L, word)) || ScanConstants(L, mathlib, word))
|
||||
return 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int constants_get(lua_State *L)
|
||||
{
|
||||
const char *key;
|
||||
int ret;
|
||||
|
||||
if (!lua_isstring(L, 2))
|
||||
return 0;
|
||||
|
||||
key = luaL_checkstring(L, 2);
|
||||
|
||||
// In Lua, mathlib is never there
|
||||
ret = getEnum(L, false, key);
|
||||
|
||||
if (ret != -1)
|
||||
// Don't allow A_* or super.
|
||||
// All userdata is meant to be considered global variables,
|
||||
// so no need to get more specific than "is it userdata?"
|
||||
if (!lua_isuserdata(L, -1) && !lua_isfunction(L, -1))
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lib_getenum(lua_State *L)
|
||||
{
|
||||
const char *word;
|
||||
int ret;
|
||||
boolean mathlib = lua_toboolean(L, lua_upvalueindex(1));
|
||||
if (lua_type(L,2) != LUA_TSTRING)
|
||||
return 0;
|
||||
word = lua_tostring(L,2);
|
||||
|
||||
ret = getEnum(L, mathlib, word);
|
||||
|
||||
if (ret != -1)
|
||||
return ret;
|
||||
|
||||
if (mathlib) return luaL_error(L, "constant '%s' could not be parsed.\n", word);
|
||||
|
||||
return 0;
|
||||
|
@ -771,10 +808,18 @@ int LUA_SOCLib(lua_State *L)
|
|||
lua_register(L,"getActionName",lib_getActionName);
|
||||
|
||||
luaL_newmetatable(L, META_ACTION);
|
||||
lua_pushcfunction(L, action_call);
|
||||
lua_setfield(L, -2, "__call");
|
||||
LUA_SetCFunctionField(L, "__call", action_call);
|
||||
lua_pop(L, 1);
|
||||
|
||||
// Allow access to constants without forcing the use of name comparison checks Lua-side
|
||||
// This table will not access global variables, only constants
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, constants_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "constants");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
#include "r_sky.h"
|
||||
#include "fastcmp.h"
|
||||
#include "lua_script.h" // Reluctantly included for LUA_EvalMath
|
||||
#include "d_clisrv.h"
|
||||
#include "netcode/d_clisrv.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_light.h"
|
||||
|
@ -911,6 +911,7 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame)
|
|||
sprinfo->pivot[frame].x = value;
|
||||
else if (fastcmp(word, "YPIVOT"))
|
||||
sprinfo->pivot[frame].y = value;
|
||||
// TODO: 2.3: Delete
|
||||
else if (fastcmp(word, "ROTAXIS"))
|
||||
deh_warning("SpriteInfo: ROTAXIS is deprecated and will be removed.");
|
||||
else
|
||||
|
@ -1617,6 +1618,7 @@ void readlevelheader(MYFILE *f, INT32 num)
|
|||
sizeof(mapheaderinfo[num-1]->musname), va("Level header %d: music", num));
|
||||
}
|
||||
}
|
||||
// TODO: 2.3: Delete
|
||||
else if (fastcmp(word, "MUSICSLOT"))
|
||||
deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num);
|
||||
else if (fastcmp(word, "MUSICTRACK"))
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
#include "r_sky.h"
|
||||
#include "fastcmp.h"
|
||||
#include "lua_script.h" // Reluctantly included for LUA_EvalMath
|
||||
#include "d_clisrv.h"
|
||||
#include "netcode/d_clisrv.h"
|
||||
|
||||
#ifdef HWRENDER
|
||||
#include "hardware/hw_light.h"
|
||||
|
|
|
@ -370,8 +370,9 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_XDEATHSTATE",
|
||||
"S_RAISESTATE",
|
||||
|
||||
// Thok
|
||||
// Thok effect and spin trail
|
||||
"S_THOK",
|
||||
"S_THOKEFFECT",
|
||||
|
||||
// Player
|
||||
"S_PLAY_STND",
|
||||
|
@ -1933,6 +1934,13 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_SMALLGRABCHAIN",
|
||||
"S_BIGGRABCHAIN",
|
||||
|
||||
// Blue spring on a ball
|
||||
"S_BLUESPRINGBALL",
|
||||
"S_BLUESPRINGBALL2",
|
||||
"S_BLUESPRINGBALL3",
|
||||
"S_BLUESPRINGBALL4",
|
||||
"S_BLUESPRINGBALL5",
|
||||
|
||||
// Yellow spring on a ball
|
||||
"S_YELLOWSPRINGBALL",
|
||||
"S_YELLOWSPRINGBALL2",
|
||||
|
@ -3553,7 +3561,8 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_NULL",
|
||||
"MT_UNKNOWN",
|
||||
|
||||
"MT_THOK", // Thok! mobj
|
||||
"MT_THOK", // Spin trail mobj
|
||||
"MT_THOKEFFECT", // Thok boom effect
|
||||
"MT_PLAYER",
|
||||
"MT_TAILSOVERLAY", // c:
|
||||
"MT_METALJETFUME",
|
||||
|
@ -3891,6 +3900,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_BIGMACE", // Big Mace
|
||||
"MT_SMALLGRABCHAIN", // Small Grab Chain
|
||||
"MT_BIGGRABCHAIN", // Big Grab Chain
|
||||
"MT_BLUESPRINGBALL", // Blue spring on a ball
|
||||
"MT_YELLOWSPRINGBALL", // Yellow spring on a ball
|
||||
"MT_REDSPRINGBALL", // Red spring on a ball
|
||||
"MT_SMALLFIREBAR", // Small Firebar
|
||||
|
@ -4883,7 +4893,7 @@ const char *const MENUTYPES_LIST[] = {
|
|||
"MP_SERVER",
|
||||
"MP_CONNECT",
|
||||
"MP_ROOM",
|
||||
"MP_PLAYERSETUP", // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
|
||||
"MP_PLAYERSETUP",
|
||||
"MP_SERVER_OPTIONS",
|
||||
|
||||
// Options
|
||||
|
@ -5568,7 +5578,8 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"ROTAXIS_Z",ROTAXIS_Z},
|
||||
|
||||
// Buttons (ticcmd_t)
|
||||
{"BT_WEAPONMASK",BT_WEAPONMASK}, //our first four bits.
|
||||
{"BT_WEAPONMASK",BT_WEAPONMASK}, //our first three bits.
|
||||
{"BT_SHIELD",BT_SHIELD},
|
||||
{"BT_WEAPONNEXT",BT_WEAPONNEXT},
|
||||
{"BT_WEAPONPREV",BT_WEAPONPREV},
|
||||
{"BT_ATTACK",BT_ATTACK}, // shoot rings
|
||||
|
@ -5748,9 +5759,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"GC_WEPSLOT5",GC_WEPSLOT5},
|
||||
{"GC_WEPSLOT6",GC_WEPSLOT6},
|
||||
{"GC_WEPSLOT7",GC_WEPSLOT7},
|
||||
{"GC_WEPSLOT8",GC_WEPSLOT8},
|
||||
{"GC_WEPSLOT9",GC_WEPSLOT9},
|
||||
{"GC_WEPSLOT10",GC_WEPSLOT10},
|
||||
{"GC_SHIELD",GC_SHIELD},
|
||||
{"GC_FIRE",GC_FIRE},
|
||||
{"GC_FIRENORMAL",GC_FIRENORMAL},
|
||||
{"GC_TOSSFLAG",GC_TOSSFLAG},
|
||||
|
|
|
@ -56,7 +56,6 @@
|
|||
#endif
|
||||
|
||||
#ifdef _WINDOWS
|
||||
#define NONET
|
||||
#if !defined (HWRENDER) && !defined (NOHW)
|
||||
#define HWRENDER
|
||||
#endif
|
||||
|
@ -534,7 +533,7 @@ extern char liveeventbackup[256];
|
|||
#define M_GetText(x) (x)
|
||||
#endif
|
||||
void M_StartupLocale(void);
|
||||
extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL;
|
||||
void *M_Memcpy(void* dest, const void* src, size_t n);
|
||||
char *va(const char *format, ...) FUNCPRINTF;
|
||||
char *M_GetToken(const char *inputString);
|
||||
void M_UnGetToken(void);
|
||||
|
@ -724,7 +723,7 @@ extern int
|
|||
/// Maintain compatibility with older 2.2 demos
|
||||
#define OLD22DEMOCOMPAT
|
||||
|
||||
#if defined (HAVE_CURL) && ! defined (NONET)
|
||||
#ifdef HAVE_CURL
|
||||
#define MASTERSERVER
|
||||
#else
|
||||
#undef UPDATE_ALERT
|
||||
|
|
|
@ -634,7 +634,7 @@ extern boolean singletics;
|
|||
// Netgame stuff
|
||||
// =============
|
||||
|
||||
#include "d_clisrv.h"
|
||||
#include "netcode/d_clisrv.h"
|
||||
|
||||
extern consvar_t cv_timetic; // display high resolution timer
|
||||
extern consvar_t cv_powerupdisplay; // display powerups
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "../i_net.h"
|
||||
#include "../netcode/i_net.h"
|
||||
|
||||
boolean I_InitNetwork(void)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "../doomdef.h"
|
||||
#include "../doomtype.h"
|
||||
#include "../i_system.h"
|
||||
#include "../i_time.h"
|
||||
|
||||
FILE *logstream = NULL;
|
||||
|
||||
|
@ -19,6 +20,11 @@ void I_Sleep(UINT32 ms)
|
|||
(void)ms;
|
||||
}
|
||||
|
||||
void I_SleepDuration(precise_t duration)
|
||||
{
|
||||
(void)duration;
|
||||
}
|
||||
|
||||
precise_t I_GetPreciseTime(void)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_main.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "netcode/d_netcmd.h"
|
||||
#include "f_finale.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
|
@ -1327,7 +1327,7 @@ void F_CreditDrawer(void)
|
|||
y += 12<<FRACBITS;
|
||||
break;
|
||||
}
|
||||
if (FixedMul(y,vid.dupy) > vid.height)
|
||||
if (FixedMul(y,vid.dup) > vid.height)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1362,7 +1362,7 @@ void F_CreditTicker(void)
|
|||
case 1: y += 30<<FRACBITS; break;
|
||||
default: y += 12<<FRACBITS; break;
|
||||
}
|
||||
if (FixedMul(y,vid.dupy) > vid.height)
|
||||
if (FixedMul(y,vid.dup) > vid.height)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2082,7 +2082,7 @@ void F_EndingDrawer(void)
|
|||
if (goodending && finalecount >= TICRATE && finalecount < INFLECTIONPOINT)
|
||||
{
|
||||
INT32 workingtime = finalecount - TICRATE;
|
||||
fixed_t radius = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE);
|
||||
fixed_t radius = ((vid.width/vid.dup)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE);
|
||||
angle_t fa;
|
||||
INT32 eemeralds_cur[4];
|
||||
char patchname[7] = "CEMGx0";
|
||||
|
@ -2287,7 +2287,6 @@ void F_InitMenuPresValues(void)
|
|||
void F_SkyScroll(const char *patchname)
|
||||
{
|
||||
INT32 x, basey = 0;
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
patch_t *pat;
|
||||
|
||||
if (rendermode == render_none)
|
||||
|
@ -2315,17 +2314,17 @@ void F_SkyScroll(const char *patchname)
|
|||
curbgy %= pat->height * 16;
|
||||
|
||||
// Ooh, fancy frame interpolation
|
||||
x = ((curbgx*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*dupz)) / 16;
|
||||
basey = ((curbgy*dupz) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*dupz)) / 16;
|
||||
x = ((curbgx*vid.dup) + FixedInt((rendertimefrac-FRACUNIT) * curbgxspeed*vid.dup)) / 16;
|
||||
basey = ((curbgy*vid.dup) + FixedInt((rendertimefrac-FRACUNIT) * curbgyspeed*vid.dup)) / 16;
|
||||
|
||||
if (x > 0) // Make sure that we don't leave the left or top sides empty
|
||||
x -= pat->width * dupz;
|
||||
x -= pat->width * vid.dup;
|
||||
if (basey > 0)
|
||||
basey -= pat->height * dupz;
|
||||
basey -= pat->height * vid.dup;
|
||||
|
||||
for (; x < vid.width; x += pat->width * dupz)
|
||||
for (; x < vid.width; x += pat->width * vid.dup)
|
||||
{
|
||||
for (INT32 y = basey; y < vid.height; y += pat->height * dupz)
|
||||
for (INT32 y = basey; y < vid.height; y += pat->height * vid.dup)
|
||||
V_DrawScaledPatch(x, y, V_NOSCALESTART, pat);
|
||||
}
|
||||
|
||||
|
@ -2603,7 +2602,7 @@ static void F_LoadAlacroixGraphics(SINT8 newttscale)
|
|||
|
||||
static void F_FigureActiveTtScale(void)
|
||||
{
|
||||
SINT8 newttscale = max(1, min(6, vid.dupx));
|
||||
SINT8 newttscale = max(1, min(6, vid.dup));
|
||||
SINT8 oldttscale = activettscale;
|
||||
|
||||
if (newttscale == testttscale)
|
||||
|
@ -4095,7 +4094,7 @@ static fixed_t F_GetPromptHideHudBound(void)
|
|||
F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr);
|
||||
|
||||
// calc boxheight (see V_DrawPromptBack)
|
||||
boxh *= vid.dupy;
|
||||
boxh *= vid.dup;
|
||||
boxh = (boxh * 4) + (boxh/2)*5; // 4 lines of space plus gaps between and some leeway
|
||||
|
||||
// return a coordinate to check
|
||||
|
@ -4525,7 +4524,7 @@ void F_TextPromptDrawer(void)
|
|||
if (players[j].mo->state == states+S_PLAY_STND && players[j].mo->tics != -1)\
|
||||
players[j].mo->tics++;\
|
||||
else if (players[j].mo->state == states+S_PLAY_WAIT)\
|
||||
P_SetPlayerMobjState(players[j].mo, S_PLAY_STND);\
|
||||
P_SetMobjState(players[j].mo, S_PLAY_STND);\
|
||||
}\
|
||||
}
|
||||
|
||||
|
|
|
@ -23,10 +23,20 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef S_ISLNK
|
||||
#define IGNORE_SYMLINKS
|
||||
#endif
|
||||
|
||||
#ifndef IGNORE_SYMLINKS
|
||||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
#include "filesrch.h"
|
||||
#include "d_netfil.h"
|
||||
#include "netcode/d_netfil.h"
|
||||
#include "m_misc.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_menu.h" // Addons_option_Onchange
|
||||
|
@ -433,9 +443,19 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
// okay, now we actually want searchpath to incorporate d_name
|
||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (dent->d_type == DT_UNKNOWN)
|
||||
if (lstat(searchpath,&fsstat) == 0 && S_ISDIR(fsstat.st_mode))
|
||||
dent->d_type = DT_DIR;
|
||||
|
||||
// Linux and FreeBSD has a special field for file type on dirent, so use that to speed up lookups.
|
||||
// FIXME: should we also follow symlinks?
|
||||
if (dent->d_type == DT_DIR && depthleft)
|
||||
#else
|
||||
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||
; // was the file (re)moved? can't stat it
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
#endif
|
||||
{
|
||||
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
||||
dirhandle[depthleft] = opendir(searchpath);
|
||||
|
@ -451,6 +471,9 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
}
|
||||
else if (!strcasecmp(searchname, dent->d_name))
|
||||
{
|
||||
#ifndef IGNORE_SYMLINKS
|
||||
struct stat statbuf;
|
||||
#endif
|
||||
switch (checkfilemd5(searchpath, wantedmd5sum))
|
||||
{
|
||||
case FS_FOUND:
|
||||
|
@ -458,6 +481,19 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
strcpy(filename,searchpath);
|
||||
else
|
||||
strcpy(filename,dent->d_name);
|
||||
#ifndef IGNORE_SYMLINKS
|
||||
if (lstat(filename, &statbuf) != -1)
|
||||
{
|
||||
if (S_ISLNK(statbuf.st_mode))
|
||||
{
|
||||
char *tempbuf = realpath(filename, NULL);
|
||||
if (!tempbuf)
|
||||
I_Error("Error parsing link %s: %s", filename, strerror(errno));
|
||||
strncpy(filename, tempbuf, MAX_WADPATH);
|
||||
free(tempbuf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
retval = FS_FOUND;
|
||||
found = 1;
|
||||
break;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#define __FILESRCH_H__
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "netcode/d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
#include "w_wad.h"
|
||||
|
||||
|
|
275
src/g_demo.c
275
src/g_demo.c
|
@ -15,7 +15,7 @@
|
|||
#include "console.h"
|
||||
#include "d_main.h"
|
||||
#include "d_player.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "netcode/d_clisrv.h"
|
||||
#include "p_setup.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
|
@ -39,7 +39,7 @@
|
|||
#include "v_video.h"
|
||||
#include "lua_hook.h"
|
||||
#include "md5.h" // demo checksums
|
||||
#include "d_netfil.h" // G_CheckDemoExtraFiles
|
||||
#include "netcode/d_netfil.h" // G_CheckDemoExtraFiles
|
||||
|
||||
boolean timingdemo; // if true, exit with report on completion
|
||||
boolean nodrawers; // for comparative timing purposes
|
||||
|
@ -798,32 +798,53 @@ void G_GhostTicker(void)
|
|||
if (type == MT_GHOST)
|
||||
{
|
||||
mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us
|
||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<<FF_TRANSSHIFT; // P_SpawnGhostMobj sets trans50, we want trans60
|
||||
}
|
||||
else if (type == MT_THOKEFFECT)
|
||||
{
|
||||
mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, FixedDiv(g->mo->height, g->mo->scale)*3/4, type);
|
||||
mobj->angle = g->mo->angle + ANGLE_90;
|
||||
mobj->fuse = 7;
|
||||
mobj->scale = g->mo->scale / 3;
|
||||
mobj->destscale = 10 * g->mo->scale;
|
||||
mobj->colorized = true;
|
||||
mobj->color = g->mo->color;
|
||||
mobj->momx = -g->mo->momx / 2;
|
||||
mobj->momy = -g->mo->momy / 2;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
mobj = P_SpawnMobjFromMobj(g->mo, 0, 0, -FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK);
|
||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
|
||||
mobj->color = g->mo->color;
|
||||
mobj->skin = g->mo->skin;
|
||||
P_SetScale(mobj, (mobj->destscale = g->mo->scale));
|
||||
|
||||
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
{
|
||||
mobj->frame = FF_TRANS80;
|
||||
mobj->fuse = mobj->tics;
|
||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||
mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<<FF_TRANSSHIFT;
|
||||
mobj->color = g->mo->color;
|
||||
mobj->skin = g->mo->skin;
|
||||
P_SetScale(mobj, (mobj->destscale = g->mo->scale));
|
||||
|
||||
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||
{
|
||||
mobj->frame = FF_TRANS80;
|
||||
mobj->fuse = mobj->tics;
|
||||
}
|
||||
mobj->tics = -1; // nope.
|
||||
}
|
||||
mobj->tics = -1; // nope.
|
||||
}
|
||||
mobj->floorz = mobj->z;
|
||||
mobj->ceilingz = mobj->z+mobj->height;
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
P_SetThingPosition(mobj);
|
||||
if (!mobj->fuse)
|
||||
mobj->fuse = 8;
|
||||
P_SetTarget(&mobj->target, g->mo);
|
||||
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
{
|
||||
mobj->floorz = mobj->z;
|
||||
mobj->ceilingz = mobj->z+mobj->height;
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
P_SetThingPosition(mobj);
|
||||
if (!mobj->fuse)
|
||||
mobj->fuse = 8;
|
||||
P_SetTarget(&mobj->target, g->mo);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xziptic & EZT_HIT)
|
||||
|
@ -847,6 +868,8 @@ void G_GhostTicker(void)
|
|||
|| health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad.
|
||||
continue;
|
||||
poof = P_SpawnMobj(x, y, z, MT_GHOST);
|
||||
if (P_MobjWasRemoved(poof))
|
||||
continue;
|
||||
poof->angle = angle;
|
||||
poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
poof->health = 0;
|
||||
|
@ -892,19 +915,22 @@ void G_GhostTicker(void)
|
|||
if (follow)
|
||||
P_RemoveMobj(follow);
|
||||
P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST));
|
||||
P_SetTarget(&follow->tracer, g->mo);
|
||||
follow->tics = -1;
|
||||
temp = READINT16(g->p)<<FRACBITS;
|
||||
follow->height = FixedMul(follow->scale, temp);
|
||||
if (!P_MobjWasRemoved(follow))
|
||||
{
|
||||
P_SetTarget(&follow->tracer, g->mo);
|
||||
follow->tics = -1;
|
||||
temp = READINT16(g->p)<<FRACBITS;
|
||||
follow->height = FixedMul(follow->scale, temp);
|
||||
|
||||
if (followtic & FZT_LINKDRAW)
|
||||
follow->flags2 |= MF2_LINKDRAW;
|
||||
if (followtic & FZT_LINKDRAW)
|
||||
follow->flags2 |= MF2_LINKDRAW;
|
||||
|
||||
if (followtic & FZT_COLORIZED)
|
||||
follow->colorized = true;
|
||||
if (followtic & FZT_COLORIZED)
|
||||
follow->colorized = true;
|
||||
|
||||
if (followtic & FZT_SKIN)
|
||||
follow->skin = &skins[READUINT8(g->p)];
|
||||
if (followtic & FZT_SKIN)
|
||||
follow->skin = &skins[READUINT8(g->p)];
|
||||
}
|
||||
}
|
||||
if (follow)
|
||||
{
|
||||
|
@ -1094,31 +1120,50 @@ void G_ReadMetalTic(mobj_t *metal)
|
|||
{
|
||||
mobj = P_SpawnGhostMobj(metal); // does a large portion of the work for us
|
||||
}
|
||||
else if (type == MT_THOKEFFECT)
|
||||
{
|
||||
mobj = P_SpawnMobjFromMobj(metal, 0, 0, FixedDiv(metal->height, metal->scale)*3/4, type);
|
||||
mobj->angle = metal->angle + ANGLE_90;
|
||||
mobj->fuse = 7;
|
||||
mobj->scale = metal->scale / 3;
|
||||
mobj->destscale = 10 * metal->scale;
|
||||
mobj->colorized = true;
|
||||
mobj->color = metal->color;
|
||||
mobj->momx = -metal->momx / 2;
|
||||
mobj->momy = -metal->momy / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj = P_SpawnMobjFromMobj(metal, 0, 0, -FixedDiv(FixedMul(metal->info->height, metal->scale) - metal->height,3*FRACUNIT), MT_THOK);
|
||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||
mobj->frame = states[mobjinfo[type].spawnstate].frame;
|
||||
mobj->angle = metal->angle;
|
||||
mobj->color = metal->color;
|
||||
mobj->skin = metal->skin;
|
||||
P_SetScale(mobj, (mobj->destscale = metal->scale));
|
||||
|
||||
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
{
|
||||
mobj->frame = FF_TRANS70;
|
||||
mobj->fuse = mobj->tics;
|
||||
mobj->sprite = states[mobjinfo[type].spawnstate].sprite;
|
||||
mobj->frame = states[mobjinfo[type].spawnstate].frame;
|
||||
mobj->angle = metal->angle;
|
||||
mobj->color = metal->color;
|
||||
mobj->skin = metal->skin;
|
||||
P_SetScale(mobj, (mobj->destscale = metal->scale));
|
||||
|
||||
if (type == MT_THOK) // spintrail-specific modification for MT_THOK
|
||||
{
|
||||
mobj->frame = FF_TRANS70;
|
||||
mobj->fuse = mobj->tics;
|
||||
}
|
||||
mobj->tics = -1; // nope.
|
||||
}
|
||||
mobj->tics = -1; // nope.
|
||||
}
|
||||
mobj->floorz = mobj->z;
|
||||
mobj->ceilingz = mobj->z+mobj->height;
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
P_SetThingPosition(mobj);
|
||||
if (!mobj->fuse)
|
||||
mobj->fuse = 8;
|
||||
P_SetTarget(&mobj->target, metal);
|
||||
|
||||
if (!P_MobjWasRemoved(mobj))
|
||||
{
|
||||
mobj->floorz = mobj->z;
|
||||
mobj->ceilingz = mobj->z+mobj->height;
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up...
|
||||
P_SetThingPosition(mobj);
|
||||
if (!mobj->fuse)
|
||||
mobj->fuse = 8;
|
||||
P_SetTarget(&mobj->target, metal);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (xziptic & EZT_SPRITE)
|
||||
|
@ -1140,19 +1185,22 @@ void G_ReadMetalTic(mobj_t *metal)
|
|||
if (follow)
|
||||
P_RemoveMobj(follow);
|
||||
P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST));
|
||||
P_SetTarget(&follow->tracer, metal);
|
||||
follow->tics = -1;
|
||||
temp = READINT16(metal_p)<<FRACBITS;
|
||||
follow->height = FixedMul(follow->scale, temp);
|
||||
if (!P_MobjWasRemoved(follow))
|
||||
{
|
||||
P_SetTarget(&follow->tracer, metal);
|
||||
follow->tics = -1;
|
||||
temp = READINT16(metal_p)<<FRACBITS;
|
||||
follow->height = FixedMul(follow->scale, temp);
|
||||
|
||||
if (followtic & FZT_LINKDRAW)
|
||||
follow->flags2 |= MF2_LINKDRAW;
|
||||
if (followtic & FZT_LINKDRAW)
|
||||
follow->flags2 |= MF2_LINKDRAW;
|
||||
|
||||
if (followtic & FZT_COLORIZED)
|
||||
follow->colorized = true;
|
||||
if (followtic & FZT_COLORIZED)
|
||||
follow->colorized = true;
|
||||
|
||||
if (followtic & FZT_SKIN)
|
||||
follow->skin = &skins[READUINT8(metal_p)];
|
||||
if (followtic & FZT_SKIN)
|
||||
follow->skin = &skins[READUINT8(metal_p)];
|
||||
}
|
||||
}
|
||||
if (follow)
|
||||
{
|
||||
|
@ -1492,16 +1540,21 @@ void G_BeginRecording(void)
|
|||
demo_p += 16;
|
||||
|
||||
// Skin
|
||||
for (i = 0; i < 16 && cv_skin.string[i]; i++)
|
||||
name[i] = cv_skin.string[i];
|
||||
const char *skinname = skins[players[0].skin].name;
|
||||
for (i = 0; i < 16 && skinname[i]; i++)
|
||||
name[i] = skinname[i];
|
||||
for (; i < 16; i++)
|
||||
name[i] = '\0';
|
||||
M_Memcpy(demo_p,name,16);
|
||||
demo_p += 16;
|
||||
|
||||
// Color
|
||||
for (i = 0; i < MAXCOLORNAME && cv_playercolor.string[i]; i++)
|
||||
name[i] = cv_playercolor.string[i];
|
||||
UINT16 skincolor = players[0].skincolor;
|
||||
if (skincolor >= numskincolors)
|
||||
skincolor = SKINCOLOR_NONE;
|
||||
const char *skincolor_name = skincolors[skincolor].name;
|
||||
for (i = 0; i < MAXCOLORNAME && skincolor_name[i]; i++)
|
||||
name[i] = skincolor_name[i];
|
||||
for (; i < MAXCOLORNAME; i++)
|
||||
name[i] = '\0';
|
||||
M_Memcpy(demo_p,name,MAXCOLORNAME);
|
||||
|
@ -1887,16 +1940,9 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p++; // VERSION
|
||||
p++; // SUBVERSION
|
||||
oldversion = READUINT16(p);
|
||||
switch(oldversion) // demoversion
|
||||
if (oldversion < 0x000c || oldversion > DEMOVERSION)
|
||||
{
|
||||
case DEMOVERSION: // latest always supported
|
||||
case 0x000f: // The previous demoversions also supported
|
||||
case 0x000e:
|
||||
case 0x000d: // all that changed between then and now was longer color name
|
||||
case 0x000c:
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
// too old (or new), cannot support
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname);
|
||||
Z_Free(buffer);
|
||||
return UINT8_MAX;
|
||||
|
@ -1969,14 +2015,11 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
UINT8 i;
|
||||
lumpnum_t l;
|
||||
char skin[17],color[MAXCOLORNAME+1],*n,*pdemoname;
|
||||
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration,cnamelen;
|
||||
UINT8 version,subversion,charability,charability2,thrustfactor,accelstart,acceleration;
|
||||
pflags_t pflags;
|
||||
UINT32 randseed, followitem;
|
||||
fixed_t camerascale,shieldscale,actionspd,mindash,maxdash,normalspeed,runspeed,jumpfactor,height,spinheight;
|
||||
char msg[1024];
|
||||
#ifdef OLD22DEMOCOMPAT
|
||||
boolean use_old_demo_vars = false;
|
||||
#endif
|
||||
|
||||
skin[16] = '\0';
|
||||
color[MAXCOLORNAME] = '\0';
|
||||
|
@ -2035,23 +2078,13 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
subversion = READUINT8(demo_p);
|
||||
demoversion = READUINT16(demo_p);
|
||||
demo_forwardmove_rng = (demoversion < 0x0010);
|
||||
switch(demoversion)
|
||||
{
|
||||
case 0x000f:
|
||||
case 0x000d:
|
||||
case 0x000e:
|
||||
case DEMOVERSION: // latest always supported
|
||||
cnamelen = MAXCOLORNAME;
|
||||
break;
|
||||
#ifdef OLD22DEMOCOMPAT
|
||||
// all that changed between then and now was longer color name
|
||||
case 0x000c:
|
||||
cnamelen = 16;
|
||||
use_old_demo_vars = true;
|
||||
break;
|
||||
if (demoversion < 0x000c || demoversion > DEMOVERSION)
|
||||
#else
|
||||
if (demoversion < 0x000d || demoversion > DEMOVERSION)
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
{
|
||||
// too old (or new), cannot support
|
||||
snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname);
|
||||
CONS_Alert(CONS_ERROR, "%s", msg);
|
||||
M_StartMessage(msg, NULL, MM_NOTHING);
|
||||
|
@ -2178,8 +2211,8 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demo_p += 16;
|
||||
|
||||
// Color
|
||||
M_Memcpy(color,demo_p,cnamelen);
|
||||
demo_p += cnamelen;
|
||||
M_Memcpy(color, demo_p, (demoversion < 0x000d) ? 16 : MAXCOLORNAME);
|
||||
demo_p += (demoversion < 0x000d) ? 16 : MAXCOLORNAME;
|
||||
|
||||
charability = READUINT8(demo_p);
|
||||
charability2 = READUINT8(demo_p);
|
||||
|
@ -2215,7 +2248,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
|
||||
// net var data
|
||||
#ifdef OLD22DEMOCOMPAT
|
||||
if (use_old_demo_vars)
|
||||
if (demoversion < 0x000d)
|
||||
CV_LoadOldDemoVars(&demo_p);
|
||||
else
|
||||
#endif
|
||||
|
@ -2263,7 +2296,6 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
players[0].skincolor = i;
|
||||
break;
|
||||
}
|
||||
CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
|
||||
if (players[0].mo)
|
||||
{
|
||||
players[0].mo->color = players[0].skincolor;
|
||||
|
@ -2349,19 +2381,13 @@ UINT8 G_CheckDemoForError(char *defdemoname)
|
|||
demo_p++; // version
|
||||
demo_p++; // subversion
|
||||
our_demo_version = READUINT16(demo_p);
|
||||
switch(our_demo_version)
|
||||
{
|
||||
case 0x000d:
|
||||
case 0x000e:
|
||||
case 0x000f:
|
||||
case DEMOVERSION: // latest always supported
|
||||
break;
|
||||
#ifdef OLD22DEMOCOMPAT
|
||||
case 0x000c:
|
||||
break;
|
||||
if (our_demo_version < 0x000c || our_demo_version > DEMOVERSION)
|
||||
#else
|
||||
if (our_demo_version < 0x000d || our_demo_version > DEMOVERSION)
|
||||
#endif
|
||||
// too old, cannot support.
|
||||
default:
|
||||
{
|
||||
// too old (or new), cannot support
|
||||
return DFILE_ERROR_NOTDEMO;
|
||||
}
|
||||
demo_p += 16; // demo checksum
|
||||
|
@ -2383,7 +2409,6 @@ void G_AddGhost(char *defdemoname)
|
|||
INT32 i;
|
||||
lumpnum_t l;
|
||||
char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16];
|
||||
UINT8 cnamelen;
|
||||
demoghost *gh;
|
||||
UINT8 flags, subversion;
|
||||
UINT8 *buffer,*p;
|
||||
|
@ -2435,20 +2460,9 @@ void G_AddGhost(char *defdemoname)
|
|||
p++; // VERSION
|
||||
subversion = READUINT8(p); // SUBVERSION
|
||||
ghostversion = READUINT16(p);
|
||||
switch(ghostversion)
|
||||
if (ghostversion < 0x000c || ghostversion > DEMOVERSION)
|
||||
{
|
||||
case 0x000f:
|
||||
case 0x000d:
|
||||
case 0x000e:
|
||||
case DEMOVERSION: // latest always supported
|
||||
cnamelen = MAXCOLORNAME;
|
||||
break;
|
||||
// all that changed between then and now was longer color name
|
||||
case 0x000c:
|
||||
cnamelen = 16;
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
// too old (or new), cannot support
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname);
|
||||
Z_Free(pdemoname);
|
||||
Z_Free(buffer);
|
||||
|
@ -2511,8 +2525,8 @@ void G_AddGhost(char *defdemoname)
|
|||
p += 16;
|
||||
|
||||
// Color
|
||||
M_Memcpy(color, p,cnamelen);
|
||||
p += cnamelen;
|
||||
M_Memcpy(color, p, (ghostversion < 0x000d) ? 16 : MAXCOLORNAME);
|
||||
p += (ghostversion < 0x000d) ? 16 : MAXCOLORNAME;
|
||||
|
||||
// Ghosts do not have a player structure to put this in.
|
||||
p++; // charability
|
||||
|
@ -2569,7 +2583,9 @@ void G_AddGhost(char *defdemoname)
|
|||
{ // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling.
|
||||
fixed_t z,f,c;
|
||||
fixed_t offset = mthing->z << FRACBITS;
|
||||
gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST);
|
||||
P_SetTarget(&gh->mo, P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST));
|
||||
if (P_MobjWasRemoved(gh->mo))
|
||||
return;
|
||||
gh->mo->angle = FixedAngle(mthing->angle << FRACBITS);
|
||||
f = gh->mo->floorz;
|
||||
c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height;
|
||||
|
@ -2695,16 +2711,9 @@ void G_DoPlayMetal(void)
|
|||
metal_p++; // VERSION
|
||||
metal_p++; // SUBVERSION
|
||||
metalversion = READUINT16(metal_p);
|
||||
switch(metalversion)
|
||||
if (metalversion < 0x000c || metalversion > DEMOVERSION)
|
||||
{
|
||||
case DEMOVERSION: // latest always supported
|
||||
case 0x000f:
|
||||
case 0x000e: // There are checks wheter the momentum is from older demo versions or not
|
||||
case 0x000d: // all that changed between then and now was longer color name
|
||||
case 0x000c:
|
||||
break;
|
||||
// too old, cannot support.
|
||||
default:
|
||||
// too old (or new), cannot support
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n"));
|
||||
Z_Free(metalbuffer);
|
||||
return;
|
||||
|
|
89
src/g_game.c
89
src/g_game.c
|
@ -15,7 +15,8 @@
|
|||
#include "console.h"
|
||||
#include "d_main.h"
|
||||
#include "d_player.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "netcode/d_clisrv.h"
|
||||
#include "netcode/net_command.h"
|
||||
#include "f_finale.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_saveg.h"
|
||||
|
@ -50,11 +51,14 @@
|
|||
#include "r_fps.h" // frame interpolation/uncapped
|
||||
|
||||
#include "lua_hud.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
gameaction_t gameaction;
|
||||
gamestate_t gamestate = GS_NULL;
|
||||
UINT8 ultimatemode = false;
|
||||
|
||||
INT32 pickedchar;
|
||||
|
||||
boolean botingame;
|
||||
UINT8 botskin;
|
||||
UINT16 botcolor;
|
||||
|
@ -304,7 +308,9 @@ consvar_t cv_chatheight= CVAR_INIT ("chatheight", "8", CV_SAVE, chatheight_cons_
|
|||
consvar_t cv_chatnotifications= CVAR_INIT ("chatnotifications", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
// chat spam protection (why would you want to disable that???)
|
||||
consvar_t cv_chatspamprotection= CVAR_INIT ("chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_chatspamprotection= CVAR_INIT ("chatspamprotection", "On", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
|
||||
consvar_t cv_chatspamspeed= CVAR_INIT ("chatspamspeed", "35", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL);
|
||||
consvar_t cv_chatspamburst= CVAR_INIT ("chatspamburst", "3", CV_SAVE|CV_NETVAR, CV_Unsigned, NULL);
|
||||
|
||||
// minichat text background
|
||||
consvar_t cv_chatbacktint = CVAR_INIT ("chatbacktint", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
|
@ -1167,7 +1173,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
// why build a ticcmd if we're paused?
|
||||
// Or, for that matter, if we're being reborn.
|
||||
// ...OR if we're blindfolded. No looking into the floor.
|
||||
if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
|
||||
if (ignoregameinputs || paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG)
|
||||
&& (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT)))))
|
||||
{//@TODO splitscreen player
|
||||
cmd->angleturn = ticcmd_oldangleturn[forplayer];
|
||||
|
@ -1331,7 +1337,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
#if NUM_WEAPONS > 10
|
||||
"Add extra inputs to g_input.h/gamecontrols_e"
|
||||
#endif
|
||||
//use the four avaliable bits to determine the weapon.
|
||||
//use the three avaliable bits to determine the weapon.
|
||||
cmd->buttons &= ~BT_WEAPONMASK;
|
||||
for (i = 0; i < NUM_WEAPONS; ++i)
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_WEPSLOT1 + i))
|
||||
|
@ -1349,9 +1355,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
axis = PlayerJoyAxis(ssplayer, JA_FIRENORMAL);
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_FIRENORMAL) || (usejoystick && axis > 0))
|
||||
cmd->buttons |= BT_FIRENORMAL;
|
||||
|
||||
|
||||
// Toss flag button
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_TOSSFLAG))
|
||||
cmd->buttons |= BT_TOSSFLAG;
|
||||
|
||||
// Shield button
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_SHIELD))
|
||||
cmd->buttons |= BT_SHIELD;
|
||||
|
||||
// Lua scriptable buttons
|
||||
if (PLAYERINPUTDOWN(ssplayer, GC_CUSTOM1))
|
||||
|
@ -2744,6 +2755,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->pflags |= PF_SPINDOWN;
|
||||
p->pflags |= PF_ATTACKDOWN;
|
||||
p->pflags |= PF_JUMPDOWN;
|
||||
p->pflags |= PF_SHIELDDOWN;
|
||||
|
||||
p->playerstate = PST_LIVE;
|
||||
p->panim = PA_IDLE; // standing animation
|
||||
|
@ -2751,25 +2763,6 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
//if ((netgame || multiplayer) && !p->spectator) -- moved into P_SpawnPlayer to account for forced changes there
|
||||
//p->powers[pw_flashing] = flashingtics-1; // Babysitting deterrent
|
||||
|
||||
// Check to make sure their color didn't change somehow...
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
if (p->ctfteam == 1 && p->skincolor != skincolor_redteam)
|
||||
{
|
||||
if (p == &players[consoleplayer])
|
||||
CV_SetValue(&cv_playercolor, skincolor_redteam);
|
||||
else if (p == &players[secondarydisplayplayer])
|
||||
CV_SetValue(&cv_playercolor2, skincolor_redteam);
|
||||
}
|
||||
else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam)
|
||||
{
|
||||
if (p == &players[consoleplayer])
|
||||
CV_SetValue(&cv_playercolor, skincolor_blueteam);
|
||||
else if (p == &players[secondarydisplayplayer])
|
||||
CV_SetValue(&cv_playercolor2, skincolor_blueteam);
|
||||
}
|
||||
}
|
||||
|
||||
if (betweenmaps)
|
||||
return;
|
||||
|
||||
|
@ -4362,7 +4355,7 @@ void G_LoadGameSettings(void)
|
|||
}
|
||||
|
||||
#define GAMEDATA_ID 0x86E4A27C // Change every major version, as usual
|
||||
#define COMPAT_GAMEDATA_ID 0xFCAFE211 // Can be removed entirely for 2.3
|
||||
#define COMPAT_GAMEDATA_ID 0xFCAFE211 // TODO: 2.3: Delete
|
||||
|
||||
// G_LoadGameData
|
||||
// Loads the main data file, which stores information such as emblems found, etc.
|
||||
|
@ -4805,12 +4798,9 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride)
|
|||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = NULL;
|
||||
|
||||
// gameaction = ga_nothing;
|
||||
// G_SetGamestate(GS_LEVEL);
|
||||
displayplayer = consoleplayer;
|
||||
multiplayer = splitscreen = false;
|
||||
|
||||
// G_DeferedInitNew(sk_medium, G_BuildMapName(1), 0, 0, 1);
|
||||
if (setsizeneeded)
|
||||
R_ExecuteSetViewSize();
|
||||
|
||||
|
@ -5003,9 +4993,9 @@ cleanup:
|
|||
// Can be called by the startup code or the menu task,
|
||||
// consoleplayer, displayplayer, playeringame[] should be set.
|
||||
//
|
||||
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, boolean SSSG, boolean FLS)
|
||||
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS)
|
||||
{
|
||||
UINT16 color = skins[pickedchar].prefcolor;
|
||||
pickedchar = character;
|
||||
paused = false;
|
||||
|
||||
if (demoplayback)
|
||||
|
@ -5026,10 +5016,7 @@ void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar, b
|
|||
SplitScreen_OnChange();
|
||||
}
|
||||
|
||||
color = skins[pickedchar].prefcolor;
|
||||
SetPlayerSkinByNum(consoleplayer, pickedchar);
|
||||
CV_StealthSet(&cv_skin, skins[pickedchar].name);
|
||||
CV_StealthSetValue(&cv_playercolor, color);
|
||||
SetPlayerSkinByNum(consoleplayer, character);
|
||||
|
||||
if (mapname)
|
||||
D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pultmode, true, 1, false, FLS);
|
||||
|
@ -5109,6 +5096,10 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
CV_StealthSetValue(&cv_itemfinder, 0);
|
||||
}
|
||||
|
||||
// Restore each player's skin if it was previously forced to be a specific one
|
||||
// (Looks a bit silly, but it works.)
|
||||
boolean reset_skin = netgame && mapheaderinfo[gamemap-1] && mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0';
|
||||
|
||||
// internal game map
|
||||
// well this check is useless because it is done before (d_netcmd.c::command_map_f)
|
||||
// but in case of for demos....
|
||||
|
@ -5136,6 +5127,9 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
|
|||
automapactive = false;
|
||||
imcontinuing = false;
|
||||
|
||||
if (reset_skin)
|
||||
D_SendPlayerConfig();
|
||||
|
||||
// fetch saved data if available
|
||||
if (savedata.lives > 0)
|
||||
{
|
||||
|
@ -5388,16 +5382,29 @@ void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc)
|
|||
INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep)
|
||||
{
|
||||
boolean usemapcode = false;
|
||||
|
||||
INT32 newmapnum;
|
||||
|
||||
size_t mapnamelen;
|
||||
|
||||
size_t mapnamelen = strlen(mapname);
|
||||
char *p;
|
||||
|
||||
mapnamelen = strlen(mapname);
|
||||
|
||||
if (mapnamelen == 2)/* maybe two digit code */
|
||||
if (mapnamelen == 1)
|
||||
{
|
||||
if (mapname[0] == '*') // current map
|
||||
{
|
||||
usemapcode = true;
|
||||
newmapnum = gamemap;
|
||||
}
|
||||
else if (mapname[0] == '+' && mapheaderinfo[gamemap-1]) // next map
|
||||
{
|
||||
usemapcode = true;
|
||||
newmapnum = mapheaderinfo[gamemap-1]->nextlevel;
|
||||
if (newmapnum < 1 || newmapnum > NUMMAPS)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("NextLevel (%d) is not a valid map.\n"), newmapnum);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mapnamelen == 2)/* maybe two digit code */
|
||||
{
|
||||
if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) ))
|
||||
usemapcode = true;
|
||||
|
|
|
@ -53,7 +53,7 @@ extern consvar_t cv_instantretry;
|
|||
|
||||
// used in game menu
|
||||
extern consvar_t cv_tutorialprompt;
|
||||
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_compactscoreboard;
|
||||
extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection, cv_chatspamspeed, cv_chatspamburst, cv_compactscoreboard;
|
||||
extern consvar_t cv_crosshair, cv_crosshair2;
|
||||
extern consvar_t cv_invertmouse, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove;
|
||||
extern consvar_t cv_invertmouse2, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2;
|
||||
|
@ -176,8 +176,7 @@ void G_SpawnPlayer(INT32 playernum);
|
|||
|
||||
// Can be called by the startup code or M_Responder.
|
||||
// A normal game starts at map 1, but a warp test can start elsewhere
|
||||
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 pickedchar,
|
||||
boolean SSSG, boolean FLS);
|
||||
void G_DeferedInitNew(boolean pultmode, const char *mapname, INT32 character, boolean SSSG, boolean FLS);
|
||||
void G_DoLoadLevel(boolean resetplayer);
|
||||
void G_StartTitleCard(void);
|
||||
void G_PreLevelTitleCard(void);
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
#include "g_input.h"
|
||||
#include "keys.h"
|
||||
#include "hu_stuff.h" // need HUFONT start & end
|
||||
#include "d_net.h"
|
||||
#include "netcode/d_net.h"
|
||||
#include "console.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
|
||||
|
||||
|
@ -116,7 +118,10 @@ void G_MapEventsToControls(event_t *ev)
|
|||
{
|
||||
case ev_keydown:
|
||||
if (ev->key < NUMINPUTS)
|
||||
gamekeydown[ev->key] = 1;
|
||||
{
|
||||
if (!ignoregameinputs)
|
||||
gamekeydown[ev->key] = 1;
|
||||
}
|
||||
#ifdef PARANOIA
|
||||
else
|
||||
{
|
||||
|
@ -144,7 +149,7 @@ void G_MapEventsToControls(event_t *ev)
|
|||
|
||||
case ev_joystick: // buttons are virtual keys
|
||||
i = ev->key;
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on || ignoregameinputs)
|
||||
break;
|
||||
if (ev->x != INT32_MAX) joyxmove[i] = ev->x;
|
||||
if (ev->y != INT32_MAX) joyymove[i] = ev->y;
|
||||
|
@ -152,7 +157,7 @@ void G_MapEventsToControls(event_t *ev)
|
|||
|
||||
case ev_joystick2: // buttons are virtual keys
|
||||
i = ev->key;
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on)
|
||||
if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on || ignoregameinputs)
|
||||
break;
|
||||
if (ev->x != INT32_MAX) joy2xmove[i] = ev->x;
|
||||
if (ev->y != INT32_MAX) joy2ymove[i] = ev->y;
|
||||
|
@ -571,9 +576,7 @@ static const char *gamecontrolname[NUM_GAMECONTROLS] =
|
|||
"weapon5",
|
||||
"weapon6",
|
||||
"weapon7",
|
||||
"weapon8",
|
||||
"weapon9",
|
||||
"weapon10",
|
||||
"shield",
|
||||
"fire",
|
||||
"firenormal",
|
||||
"tossflag",
|
||||
|
@ -688,6 +691,7 @@ void G_DefineDefaultControls(void)
|
|||
gamecontroldefault[gcs_fps][GC_CENTERVIEW ][0] = KEY_LCTRL;
|
||||
gamecontroldefault[gcs_fps][GC_JUMP ][0] = KEY_SPACE;
|
||||
gamecontroldefault[gcs_fps][GC_SPIN ][0] = KEY_LSHIFT;
|
||||
gamecontroldefault[gcs_fps][GC_SHIELD ][0] = KEY_LALT;
|
||||
gamecontroldefault[gcs_fps][GC_FIRE ][0] = KEY_RCTRL;
|
||||
gamecontroldefault[gcs_fps][GC_FIRE ][1] = KEY_MOUSE1+0;
|
||||
gamecontroldefault[gcs_fps][GC_FIRENORMAL ][0] = KEY_RALT;
|
||||
|
@ -708,6 +712,7 @@ void G_DefineDefaultControls(void)
|
|||
gamecontroldefault[gcs_platform][GC_CENTERVIEW ][0] = KEY_END;
|
||||
gamecontroldefault[gcs_platform][GC_JUMP ][0] = KEY_SPACE;
|
||||
gamecontroldefault[gcs_platform][GC_SPIN ][0] = KEY_LSHIFT;
|
||||
gamecontroldefault[gcs_platform][GC_SHIELD ][0] = KEY_LALT;
|
||||
gamecontroldefault[gcs_platform][GC_FIRE ][0] = 's';
|
||||
gamecontroldefault[gcs_platform][GC_FIRE ][1] = KEY_MOUSE1+0;
|
||||
gamecontroldefault[gcs_platform][GC_FIRENORMAL ][0] = 'w';
|
||||
|
@ -723,9 +728,6 @@ void G_DefineDefaultControls(void)
|
|||
gamecontroldefault[i][GC_WEPSLOT5 ][0] = '5';
|
||||
gamecontroldefault[i][GC_WEPSLOT6 ][0] = '6';
|
||||
gamecontroldefault[i][GC_WEPSLOT7 ][0] = '7';
|
||||
gamecontroldefault[i][GC_WEPSLOT8 ][0] = '8';
|
||||
gamecontroldefault[i][GC_WEPSLOT9 ][0] = '9';
|
||||
gamecontroldefault[i][GC_WEPSLOT10 ][0] = '0';
|
||||
gamecontroldefault[i][GC_TOSSFLAG ][0] = '\'';
|
||||
gamecontroldefault[i][GC_CAMTOGGLE ][0] = 'v';
|
||||
gamecontroldefault[i][GC_CAMRESET ][0] = 'r';
|
||||
|
@ -744,15 +746,15 @@ void G_DefineDefaultControls(void)
|
|||
gamecontroldefault[i][GC_CUSTOM1 ][1] = KEY_JOY1+1; // B
|
||||
gamecontroldefault[i][GC_CUSTOM2 ][1] = KEY_JOY1+3; // Y
|
||||
gamecontroldefault[i][GC_CUSTOM3 ][1] = KEY_JOY1+8; // Left Stick
|
||||
gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_JOY1+4; // LB
|
||||
gamecontroldefault[i][GC_SHIELD ][1] = KEY_JOY1+4; // LB
|
||||
gamecontroldefault[i][GC_CENTERVIEW ][1] = KEY_JOY1+5; // RB
|
||||
gamecontroldefault[i][GC_SCREENSHOT ][1] = KEY_JOY1+6; // Back
|
||||
gamecontroldefault[i][GC_SCORES ][1] = KEY_JOY1+6; // Back
|
||||
gamecontroldefault[i][GC_SYSTEMMENU ][0] = KEY_JOY1+7; // Start
|
||||
gamecontroldefault[i][GC_WEAPONPREV ][1] = KEY_HAT1+2; // D-Pad Left
|
||||
gamecontroldefault[i][GC_WEAPONNEXT ][1] = KEY_HAT1+3; // D-Pad Right
|
||||
gamecontroldefault[i][GC_VIEWPOINTNEXT][1] = KEY_JOY1+9; // Right Stick
|
||||
gamecontroldefault[i][GC_TOSSFLAG ][1] = KEY_HAT1+0; // D-Pad Up
|
||||
gamecontroldefault[i][GC_SCORES ][1] = KEY_HAT1+1; // D-Pad Down
|
||||
gamecontroldefault[i][GC_CAMTOGGLE ][1] = KEY_HAT1+1; // D-Pad Down
|
||||
|
||||
// Second player controls only have joypad defaults
|
||||
gamecontrolbisdefault[i][GC_JUMP ][1] = KEY_2JOY1+0; // A
|
||||
|
@ -760,15 +762,15 @@ void G_DefineDefaultControls(void)
|
|||
gamecontrolbisdefault[i][GC_CUSTOM1 ][1] = KEY_2JOY1+1; // B
|
||||
gamecontrolbisdefault[i][GC_CUSTOM2 ][1] = KEY_2JOY1+3; // Y
|
||||
gamecontrolbisdefault[i][GC_CUSTOM3 ][1] = KEY_2JOY1+8; // Left Stick
|
||||
gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbisdefault[i][GC_SHIELD ][1] = KEY_2JOY1+4; // LB
|
||||
gamecontrolbisdefault[i][GC_CENTERVIEW ][1] = KEY_2JOY1+5; // RB
|
||||
gamecontrolbisdefault[i][GC_SCREENSHOT ][1] = KEY_2JOY1+6; // Back
|
||||
//gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2JOY1+6; // Back
|
||||
//gamecontrolbisdefault[i][GC_SYSTEMMENU ][0] = KEY_2JOY1+7; // Start
|
||||
gamecontrolbisdefault[i][GC_WEAPONPREV ][1] = KEY_2HAT1+2; // D-Pad Left
|
||||
gamecontrolbisdefault[i][GC_WEAPONNEXT ][1] = KEY_2HAT1+3; // D-Pad Right
|
||||
gamecontrolbisdefault[i][GC_VIEWPOINTNEXT][1] = KEY_2JOY1+9; // Right Stick
|
||||
gamecontrolbisdefault[i][GC_TOSSFLAG ][1] = KEY_2HAT1+0; // D-Pad Up
|
||||
//gamecontrolbisdefault[i][GC_SCORES ][1] = KEY_2HAT1+1; // D-Pad Down
|
||||
gamecontrolbisdefault[i][GC_CAMTOGGLE ][1] = KEY_2HAT1+1; // D-Pad Down
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -997,8 +999,9 @@ static void setcontrol(INT32 (*gc)[2])
|
|||
INT32 player = ((void*)gc == (void*)&gamecontrolbis ? 1 : 0);
|
||||
boolean nestedoverride = false;
|
||||
|
||||
// Update me for 2.3
|
||||
// TODO: 2.3: Delete the "use" alias
|
||||
namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin";
|
||||
|
||||
|
||||
for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]);
|
||||
numctrl++)
|
||||
|
|
|
@ -74,9 +74,7 @@ typedef enum
|
|||
GC_WEPSLOT5,
|
||||
GC_WEPSLOT6,
|
||||
GC_WEPSLOT7,
|
||||
GC_WEPSLOT8,
|
||||
GC_WEPSLOT9,
|
||||
GC_WEPSLOT10,
|
||||
GC_SHIELD,
|
||||
GC_FIRE,
|
||||
GC_FIRENORMAL,
|
||||
GC_TOSSFLAG,
|
||||
|
|
|
@ -53,9 +53,11 @@ typedef enum
|
|||
|
||||
extern gamestate_t gamestate;
|
||||
extern UINT8 titlemapinaction;
|
||||
extern UINT8 ultimatemode; // was sk_insane
|
||||
extern UINT8 ultimatemode;
|
||||
extern gameaction_t gameaction;
|
||||
|
||||
extern INT32 pickedchar;
|
||||
|
||||
extern boolean botingame;
|
||||
extern UINT8 botskin;
|
||||
extern UINT16 botcolor;
|
||||
|
|
|
@ -291,6 +291,7 @@ enum hwdsetspecialstate
|
|||
HWD_SET_SHADERS,
|
||||
HWD_SET_TEXTUREFILTERMODE,
|
||||
HWD_SET_TEXTUREANISOTROPICMODE,
|
||||
HWD_SET_WIREFRAME,
|
||||
HWD_NUMSTATE
|
||||
};
|
||||
|
||||
|
|
|
@ -79,10 +79,8 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
|||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
float sdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
|
||||
float sdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
|
||||
float pdupx = FIXED_TO_FLOAT(vid.fdupx)*2.0f;
|
||||
float pdupy = FIXED_TO_FLOAT(vid.fdupy)*2.0f;
|
||||
float sdup = FIXED_TO_FLOAT(vid.fdup)*2.0f;
|
||||
float pdup = FIXED_TO_FLOAT(vid.fdup)*2.0f;
|
||||
|
||||
// make patch ready in hardware cache
|
||||
HWR_GetPatch(gpatch);
|
||||
|
@ -91,25 +89,23 @@ void HWR_DrawPatch(patch_t *gpatch, INT32 x, INT32 y, INT32 option)
|
|||
switch (option & V_SCALEPATCHMASK)
|
||||
{
|
||||
case V_NOSCALEPATCH:
|
||||
pdupx = pdupy = 2.0f;
|
||||
pdup = 2.0f;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fsmalldupy);
|
||||
pdup = 2.0f * FIXED_TO_FLOAT(vid.fsmalldup);
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
pdupx = 2.0f * FIXED_TO_FLOAT(vid.fmeddupx);
|
||||
pdupy = 2.0f * FIXED_TO_FLOAT(vid.fmeddupy);
|
||||
pdup = 2.0f * FIXED_TO_FLOAT(vid.fmeddup);
|
||||
break;
|
||||
}
|
||||
|
||||
if (option & V_NOSCALESTART)
|
||||
sdupx = sdupy = 2.0f;
|
||||
sdup = 2.0f;
|
||||
|
||||
v[0].x = v[3].x = (x*sdupx-(gpatch->leftoffset)*pdupx)/vid.width - 1;
|
||||
v[2].x = v[1].x = (x*sdupx+(gpatch->width-gpatch->leftoffset)*pdupx)/vid.width - 1;
|
||||
v[0].y = v[1].y = 1-(y*sdupy-(gpatch->topoffset)*pdupy)/vid.height;
|
||||
v[2].y = v[3].y = 1-(y*sdupy+(gpatch->height-gpatch->topoffset)*pdupy)/vid.height;
|
||||
v[0].x = v[3].x = (x*sdup-(gpatch->leftoffset)*pdup)/vid.width - 1;
|
||||
v[2].x = v[1].x = (x*sdup+(gpatch->width-gpatch->leftoffset)*pdup)/vid.width - 1;
|
||||
v[0].y = v[1].y = 1-(y*sdup-(gpatch->topoffset)*pdup)/vid.height;
|
||||
v[2].y = v[3].y = 1-(y*sdup+(gpatch->height-gpatch->topoffset)*pdup)/vid.height;
|
||||
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
|
@ -138,7 +134,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
float dupx, dupy, fscalew, fscaleh, fwidth, fheight;
|
||||
float dup, fscalew, fscaleh, fwidth, fheight;
|
||||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
|
@ -150,25 +146,21 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
|
||||
hwrPatch = ((GLPatch_t *)gpatch->hardware);
|
||||
|
||||
dupx = (float)vid.dupx;
|
||||
dupy = (float)vid.dupy;
|
||||
dup = (float)vid.dup;
|
||||
|
||||
switch (option & V_SCALEPATCHMASK)
|
||||
{
|
||||
case V_NOSCALEPATCH:
|
||||
dupx = dupy = 1.0f;
|
||||
dup = 1.0f;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
dupx = (float)vid.smalldupx;
|
||||
dupy = (float)vid.smalldupy;
|
||||
dup = (float)vid.smalldup;
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
dupx = (float)vid.meddupx;
|
||||
dupy = (float)vid.meddupy;
|
||||
dup = (float)vid.meddup;
|
||||
break;
|
||||
}
|
||||
|
||||
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
||||
fscalew = fscaleh = FIXED_TO_FLOAT(pscale);
|
||||
if (vscale != pscale)
|
||||
fscaleh = FIXED_TO_FLOAT(vscale);
|
||||
|
@ -262,8 +254,8 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
|
||||
if (!(option & V_NOSCALESTART))
|
||||
{
|
||||
cx = cx * dupx;
|
||||
cy = cy * dupy;
|
||||
cx = cx * dup;
|
||||
cy = cy * dup;
|
||||
|
||||
if (!(option & V_SCALEPATCHMASK))
|
||||
{
|
||||
|
@ -280,40 +272,40 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p
|
|||
}
|
||||
}
|
||||
// centre screen
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/2;
|
||||
if (perplayershuffle & 4)
|
||||
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4;
|
||||
else if (perplayershuffle & 8)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTOBOTTOM)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/2;
|
||||
if (perplayershuffle & 1)
|
||||
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4;
|
||||
else if (perplayershuffle & 2)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
|
||||
{
|
||||
fwidth = (float)(gpatch->width) * fscalew * dupx;
|
||||
fheight = (float)(gpatch->height) * fscaleh * dupy;
|
||||
fwidth = (float)(gpatch->width) * fscalew * dup;
|
||||
fheight = (float)(gpatch->height) * fscaleh * dup;
|
||||
}
|
||||
else
|
||||
{
|
||||
fwidth = (float)(gpatch->width) * dupx;
|
||||
fheight = (float)(gpatch->height) * dupy;
|
||||
fwidth = (float)(gpatch->width) * dup;
|
||||
fheight = (float)(gpatch->height) * dup;
|
||||
}
|
||||
|
||||
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
|
||||
|
@ -380,7 +372,7 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
// | /|
|
||||
// |/ |
|
||||
// 0--1
|
||||
float dupx, dupy, fscalew, fscaleh, fwidth, fheight;
|
||||
float dup, fscalew, fscaleh, fwidth, fheight;
|
||||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
|
@ -392,25 +384,21 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
|
||||
hwrPatch = ((GLPatch_t *)gpatch->hardware);
|
||||
|
||||
dupx = (float)vid.dupx;
|
||||
dupy = (float)vid.dupy;
|
||||
dup = (float)vid.dup;
|
||||
|
||||
switch (option & V_SCALEPATCHMASK)
|
||||
{
|
||||
case V_NOSCALEPATCH:
|
||||
dupx = dupy = 1.0f;
|
||||
dup = 1.0f;
|
||||
break;
|
||||
case V_SMALLSCALEPATCH:
|
||||
dupx = (float)vid.smalldupx;
|
||||
dupy = (float)vid.smalldupy;
|
||||
dup = (float)vid.smalldup;
|
||||
break;
|
||||
case V_MEDSCALEPATCH:
|
||||
dupx = (float)vid.meddupx;
|
||||
dupy = (float)vid.meddupy;
|
||||
dup = (float)vid.meddup;
|
||||
break;
|
||||
}
|
||||
|
||||
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
||||
fscalew = fscaleh = FIXED_TO_FLOAT(pscale);
|
||||
if (vscale != pscale)
|
||||
fscaleh = FIXED_TO_FLOAT(vscale);
|
||||
|
@ -488,8 +476,8 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
|
||||
if (!(option & V_NOSCALESTART))
|
||||
{
|
||||
cx = cx * dupx;
|
||||
cy = cy * dupy;
|
||||
cx = cx * dup;
|
||||
cy = cy * dup;
|
||||
|
||||
if (!(option & V_SCALEPATCHMASK))
|
||||
{
|
||||
|
@ -497,27 +485,27 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
// no the patch is cropped do not do this ever
|
||||
|
||||
// centre screen
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTORIGHT)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup));
|
||||
else if (!(option & V_SNAPTOLEFT))
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/2;
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/2;
|
||||
if (perplayershuffle & 4)
|
||||
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
cx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4;
|
||||
else if (perplayershuffle & 8)
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx))/4;
|
||||
cx += ((float)vid.width - ((float)BASEVIDWIDTH * dup))/4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f)
|
||||
{
|
||||
if (option & V_SNAPTOBOTTOM)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup));
|
||||
else if (!(option & V_SNAPTOTOP))
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2;
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/2;
|
||||
if (perplayershuffle & 1)
|
||||
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
cy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4;
|
||||
else if (perplayershuffle & 2)
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/4;
|
||||
cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup))/4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -533,13 +521,13 @@ void HWR_DrawCroppedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale,
|
|||
|
||||
if (pscale != FRACUNIT || vscale != FRACUNIT || (splitscreen && option & V_PERPLAYER))
|
||||
{
|
||||
fwidth *= fscalew * dupx;
|
||||
fheight *= fscaleh * dupy;
|
||||
fwidth *= fscalew * dup;
|
||||
fheight *= fscaleh * dup;
|
||||
}
|
||||
else
|
||||
{
|
||||
fwidth *= dupx;
|
||||
fheight *= dupy;
|
||||
fwidth *= dup;
|
||||
fheight *= dup;
|
||||
}
|
||||
|
||||
// positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1
|
||||
|
@ -675,9 +663,9 @@ void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum)
|
|||
// 0--1
|
||||
|
||||
v[0].x = v[3].x = 2.0f * (float)x/vid.width - 1;
|
||||
v[2].x = v[1].x = 2.0f * (float)(x + patch->width*FIXED_TO_FLOAT(vid.fdupx))/vid.width - 1;
|
||||
v[2].x = v[1].x = 2.0f * (float)(x + patch->width*FIXED_TO_FLOAT(vid.fdup))/vid.width - 1;
|
||||
v[0].y = v[1].y = 1.0f - 2.0f * (float)y/vid.height;
|
||||
v[2].y = v[3].y = 1.0f - 2.0f * (float)(y + patch->height*FIXED_TO_FLOAT(vid.fdupy))/vid.height;
|
||||
v[2].y = v[3].y = 1.0f - 2.0f * (float)(y + patch->height*FIXED_TO_FLOAT(vid.fdup))/vid.height;
|
||||
|
||||
v[0].z = v[1].z = v[2].z = v[3].z = 1.0f;
|
||||
|
||||
|
@ -910,35 +898,33 @@ void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 ac
|
|||
|
||||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
fx *= vid.dup;
|
||||
fy *= vid.dup;
|
||||
fw *= vid.dup;
|
||||
fh *= vid.dup;
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * vid.dup) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * vid.dup) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1077,10 +1063,10 @@ void HWR_DrawViewBorder(INT32 clearlines)
|
|||
clearlines = BASEVIDHEIGHT; // refresh all
|
||||
|
||||
// calc view size based on original game resolution
|
||||
baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdupx)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7;
|
||||
baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdupy));
|
||||
top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdupy));
|
||||
side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdupx));
|
||||
baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdup)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7;
|
||||
baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdup));
|
||||
top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdup));
|
||||
side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdup));
|
||||
|
||||
// top
|
||||
HWR_DrawFlatFill(0, 0,
|
||||
|
@ -1296,35 +1282,35 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32
|
|||
|
||||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
float dup = (float)vid.dup;
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
fx *= dup;
|
||||
fy *= dup;
|
||||
fw *= dup;
|
||||
fh *= dup;
|
||||
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dup) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dup));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dup)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dup)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dup) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dup)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dup)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1380,6 +1366,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
FSurfaceInfo Surf;
|
||||
float fx, fy, fw, fh;
|
||||
RGBA_t *palette = HWR_GetTexturePalette();
|
||||
UINT8 alphalevel = ((color & V_ALPHAMASK) >> V_ALPHASHIFT);
|
||||
|
||||
UINT8 perplayershuffle = 0;
|
||||
|
||||
|
@ -1463,8 +1450,6 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
|
||||
if (!(color & V_NOSCALESTART))
|
||||
{
|
||||
float dupx = (float)vid.dupx, dupy = (float)vid.dupy;
|
||||
|
||||
if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT)
|
||||
{
|
||||
RGBA_t rgbaColour = palette[color&0xFF];
|
||||
|
@ -1477,33 +1462,33 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
return;
|
||||
}
|
||||
|
||||
fx *= dupx;
|
||||
fy *= dupy;
|
||||
fw *= dupx;
|
||||
fh *= dupy;
|
||||
fx *= vid.dup;
|
||||
fy *= vid.dup;
|
||||
fw *= vid.dup;
|
||||
fh *= vid.dup;
|
||||
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * dupx) > 1.0E-36f)
|
||||
if (fabsf((float)vid.width - (float)BASEVIDWIDTH * vid.dup) > 1.0E-36f)
|
||||
{
|
||||
if (color & V_SNAPTORIGHT)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx));
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup));
|
||||
else if (!(color & V_SNAPTOLEFT))
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 2;
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 2;
|
||||
if (perplayershuffle & 4)
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
fx -= ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4;
|
||||
else if (perplayershuffle & 8)
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * dupx)) / 4;
|
||||
fx += ((float)vid.width - ((float)BASEVIDWIDTH * vid.dup)) / 4;
|
||||
}
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f)
|
||||
if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * vid.dup) > 1.0E-36f)
|
||||
{
|
||||
// same thing here
|
||||
if (color & V_SNAPTOBOTTOM)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy));
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup));
|
||||
else if (!(color & V_SNAPTOTOP))
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 2;
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 2;
|
||||
if (perplayershuffle & 1)
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
fy -= ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4;
|
||||
else if (perplayershuffle & 2)
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)) / 4;
|
||||
fy += ((float)vid.height - ((float)BASEVIDHEIGHT * vid.dup)) / 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1546,8 +1531,16 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color)
|
|||
|
||||
Surf.PolyColor = palette[color&0xFF];
|
||||
|
||||
if (alphalevel)
|
||||
{
|
||||
if (alphalevel == 10) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; // V_HUDTRANSHALF
|
||||
else if (alphalevel == 11) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; // V_HUDTRANS
|
||||
else if (alphalevel == 12) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; // V_HUDTRANSDOUBLE
|
||||
else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel];
|
||||
}
|
||||
|
||||
HWD.pfnDrawPolygon(&Surf, v, 4,
|
||||
PF_Modulated|PF_NoTexture|PF_NoDepthTest);
|
||||
PF_Modulated|PF_NoTexture|PF_NoDepthTest|PF_Translucent);
|
||||
}
|
||||
|
||||
#ifdef HAVE_PNG
|
||||
|
|
|
@ -138,6 +138,7 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_UNKN
|
||||
|
||||
&lspr[NOLIGHT], // SPR_THOK
|
||||
&lspr[NOLIGHT], // SPR_THKE
|
||||
&lspr[SUPERSONIC_L],// SPR_PLAY
|
||||
|
||||
// Enemies
|
||||
|
@ -341,6 +342,7 @@ light_t *t_lspr[NUMSPRITES] =
|
|||
&lspr[NOLIGHT], // SPR_BMCH
|
||||
&lspr[NOLIGHT], // SPR_SMCE
|
||||
&lspr[NOLIGHT], // SPR_BMCE
|
||||
&lspr[NOLIGHT], // SPR_BSPB
|
||||
&lspr[NOLIGHT], // SPR_YSPB
|
||||
&lspr[NOLIGHT], // SPR_RSPB
|
||||
&lspr[REDBALL_L], // SPR_SFBR
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -54,7 +54,6 @@ UINT8 *HWR_GetScreenshot(void);
|
|||
boolean HWR_Screenshot(const char *pathname);
|
||||
|
||||
void HWR_AddCommands(void);
|
||||
void HWR_AddSessionCommands(void);
|
||||
void transform(float *cx, float *cy, float *cz);
|
||||
INT32 HWR_GetTextureUsed(void);
|
||||
void HWR_DoPostProcessor(player_t *player);
|
||||
|
@ -103,6 +102,8 @@ extern consvar_t cv_glbatching;
|
|||
extern consvar_t cv_glpaletterendering;
|
||||
extern consvar_t cv_glpalettedepth;
|
||||
|
||||
extern consvar_t cv_glwireframe;
|
||||
|
||||
extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowy;
|
||||
|
||||
extern float gl_viewwindowx, gl_basewindowcentery;
|
||||
|
|
|
@ -1144,9 +1144,6 @@ static void HWR_GetBlendedTexture(patch_t *patch, patch_t *blendpatch, INT32 ski
|
|||
Z_ChangeTag(newMipmap->data, PU_HWRMODELTEXTURE_UNLOCKED);
|
||||
}
|
||||
|
||||
#define NORMALFOG 0x00000000
|
||||
#define FADEFOG 0x19000000
|
||||
|
||||
static boolean HWR_AllowModel(mobj_t *mobj)
|
||||
{
|
||||
// Signpost overlay. Not needed.
|
||||
|
@ -1584,6 +1581,8 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
#undef INTERPOLERATION_LIMIT
|
||||
#endif
|
||||
|
||||
if (spr->mobj->type == MT_OVERLAY) // Handle overlays
|
||||
R_ThingOffsetOverlay(spr->mobj, &interp.x, &interp.y);
|
||||
//Hurdler: it seems there is still a small problem with mobj angle
|
||||
p.x = FIXED_TO_FLOAT(interp.x);
|
||||
p.y = FIXED_TO_FLOAT(interp.y)+md2->offset;
|
||||
|
|
|
@ -6,350 +6,16 @@
|
|||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hw_shaders.h
|
||||
/// \file hw_shaders.c
|
||||
/// \brief Handles the shaders used by the game.
|
||||
|
||||
#ifdef HWRENDER
|
||||
|
||||
#include "hw_glob.h"
|
||||
#include "hw_drv.h"
|
||||
#include "hw_shaders.h"
|
||||
#include "../z_zone.h"
|
||||
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// replicates the way fixed function lighting is used by the model lighting option,
|
||||
// stores the lighting result to gl_Color
|
||||
// (ambient lighting of 0.75 and diffuse lighting from above)
|
||||
#define GLSL_MODEL_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
|
||||
"float light = min(0.75 + max(nDotVP, 0.0), 1.0);\n" \
|
||||
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
|
||||
"#else\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// ==================
|
||||
// Fragment shaders
|
||||
// ==================
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
|
||||
#define GLSL_DOOM_COLORMAP \
|
||||
"float R_DoomColormap(float light, float z)\n" \
|
||||
"{\n" \
|
||||
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
|
||||
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
|
||||
"float startmap = (15.0 - lightnum) * 4.0;\n" \
|
||||
"float scale = 160.0 / (lightz + 1.0);\n" \
|
||||
"float cap = (155.0 - light) * 0.26;\n" \
|
||||
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
|
||||
"}\n"
|
||||
// lighting cap adjustment:
|
||||
// first num (155.0), increase to make it start to go dark sooner
|
||||
// second num (0.26), increase to make it go dark faster
|
||||
|
||||
#define GLSL_DOOM_LIGHT_EQUATION \
|
||||
"float R_DoomLightingEquation(float light)\n" \
|
||||
"{\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
|
||||
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_TINT_EQUATION \
|
||||
"if (tint_color.a > 0.0) {\n" \
|
||||
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
|
||||
"float strength = sqrt(9.0 * tint_color.a);\n" \
|
||||
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
#define GLSL_PALETTE_RENDERING \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \
|
||||
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
|
||||
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
// hand tuned adjustments for light level calculation
|
||||
#define GLSL_FLOOR_FUDGES \
|
||||
"#define STARTMAP_FUDGE 1.06\n" \
|
||||
"#define SCALE_FUDGE 1.15\n"
|
||||
|
||||
#define GLSL_WALL_FUDGES \
|
||||
"#define STARTMAP_FUDGE 1.05\n" \
|
||||
"#define SCALE_FUDGE 2.2\n"
|
||||
|
||||
#define GLSL_FLOOR_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER
|
||||
|
||||
#define GLSL_WALL_FRAGMENT_SHADER \
|
||||
GLSL_WALL_FUDGES \
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color) if model lighting is enabled
|
||||
#define GLSL_MODEL_FRAGMENT_SHADER \
|
||||
GLSL_WALL_FUDGES \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"texel *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
//
|
||||
// Water surface shader
|
||||
//
|
||||
// Mostly guesstimated, rather than the rest being built off Software science.
|
||||
// Still needs to distort things underneath/around the water...
|
||||
//
|
||||
|
||||
#define GLSL_WATER_TEXEL \
|
||||
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
|
||||
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
|
||||
"float sdistort = sin(a) * amp;\n" \
|
||||
"float cdistort = cos(a) * amp;\n" \
|
||||
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
|
||||
|
||||
#define GLSL_WATER_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
"const float freq = 0.025;\n" \
|
||||
"const float amp = 0.025;\n" \
|
||||
"const float speed = 2.0;\n" \
|
||||
"const float pi = 3.14159;\n" \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
GLSL_WATER_TEXEL \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
GLSL_WATER_TEXEL \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
//
|
||||
// Fog block shader
|
||||
//
|
||||
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
|
||||
//
|
||||
|
||||
// The floor fudges are used, but should the wall fudges be used instead? or something inbetween?
|
||||
// or separate values for floors and walls? (need to change more than this shader for that)
|
||||
#define GLSL_FOG_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 base_color = gl_Color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// Shader for the palette rendering postprocess step
|
||||
#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler1D palette_tex;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \
|
||||
"vec4 final_color = texture1D(palette_tex, palette_coord);\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// Applies a palettized colormap fade to tex
|
||||
#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \
|
||||
"gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \
|
||||
"}\0"
|
||||
|
||||
// For wipes that use additive and subtractive blending.
|
||||
// alpha_factor = 31 * 8 / 10 = 24.8
|
||||
// Calculated based on the use of the "fade" variable from the GETCOLOR macro
|
||||
// in r_data.c:R_CreateFadeColormaps.
|
||||
// However this value created some ugliness in fades to white (special stage entry)
|
||||
// while palette rendering is enabled, so I raised the value just a bit.
|
||||
#define GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"const float alpha_factor = 24.875;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 final_color = poly_color;\n" \
|
||||
"float alpha = texel.a;\n" \
|
||||
"if (final_color.a >= 0.5)\n" \
|
||||
"alpha = 1.0 - alpha;\n" \
|
||||
"alpha *= alpha_factor;\n" \
|
||||
"final_color *= alpha;\n" \
|
||||
"final_color.a = 1.0;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// ================
|
||||
// Shader sources
|
||||
// ================
|
||||
|
|
424
src/hardware/hw_shaders.h
Normal file
424
src/hardware/hw_shaders.h
Normal file
|
@ -0,0 +1,424 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file hw_shaders.h
|
||||
/// \brief Handles the shaders used by the game.
|
||||
|
||||
#ifndef _HW_SHADERS_H_
|
||||
#define _HW_SHADERS_H_
|
||||
|
||||
#include "../doomtype.h"
|
||||
|
||||
// ================
|
||||
// Vertex shaders
|
||||
// ================
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// replicates the way fixed function lighting is used by the model lighting option,
|
||||
// stores the lighting result to gl_Color
|
||||
// (ambient lighting of 0.75 and diffuse lighting from above)
|
||||
#define GLSL_MODEL_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \
|
||||
"float light = min(0.75 + max(nDotVP, 0.0), 1.0);\n" \
|
||||
"gl_FrontColor = vec4(light, light, light, 1.0);\n" \
|
||||
"#else\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
// ==================
|
||||
// Fragment shaders
|
||||
// ==================
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_DEFAULT_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
// Include GLSL_FLOOR_FUDGES or GLSL_WALL_FUDGES or define the fudges in shaders that use this macro.
|
||||
#define GLSL_DOOM_COLORMAP \
|
||||
"float R_DoomColormap(float light, float z)\n" \
|
||||
"{\n" \
|
||||
"float lightnum = clamp(light / 17.0, 0.0, 15.0);\n" \
|
||||
"float lightz = clamp(z / 16.0, 0.0, 127.0);\n" \
|
||||
"float startmap = (15.0 - lightnum) * 4.0;\n" \
|
||||
"float scale = 160.0 / (lightz + 1.0);\n" \
|
||||
"float cap = (155.0 - light) * 0.26;\n" \
|
||||
"return max(startmap * STARTMAP_FUDGE - scale * 0.5 * SCALE_FUDGE, cap);\n" \
|
||||
"}\n"
|
||||
// lighting cap adjustment:
|
||||
// first num (155.0), increase to make it start to go dark sooner
|
||||
// second num (0.26), increase to make it go dark faster
|
||||
|
||||
#define GLSL_DOOM_LIGHT_EQUATION \
|
||||
"float R_DoomLightingEquation(float light)\n" \
|
||||
"{\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float colormap = floor(R_DoomColormap(light, z)) + 0.5;\n" \
|
||||
"return clamp(colormap, 0.0, 31.0) / 32.0;\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_TINT_EQUATION \
|
||||
"if (tint_color.a > 0.0) {\n" \
|
||||
"float color_bright = sqrt((base_color.r * base_color.r) + (base_color.g * base_color.g) + (base_color.b * base_color.b));\n" \
|
||||
"float strength = sqrt(9.0 * tint_color.a);\n" \
|
||||
"final_color.r = clamp((color_bright * (tint_color.r * strength)) + (base_color.r * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.g = clamp((color_bright * (tint_color.g * strength)) + (base_color.g * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"final_color.b = clamp((color_bright * (tint_color.b * strength)) + (base_color.b * (1.0 - strength)), 0.0, 1.0);\n" \
|
||||
"}\n"
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
#define GLSL_PALETTE_RENDERING \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"float z = gl_FragCoord.z / gl_FragCoord.w;\n" \
|
||||
"float light_y = clamp(floor(R_DoomColormap(lighting, z)), 0.0, 31.0);\n" \
|
||||
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (light_y + 0.5) / 32.0);\n" \
|
||||
"vec4 final_color = texture2D(lighttable_tex, lighttable_coord);\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
|
||||
#define GLSL_SOFTWARE_FRAGMENT_SHADER \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
// hand tuned adjustments for light level calculation
|
||||
#define GLSL_FLOOR_FUDGES \
|
||||
"#define STARTMAP_FUDGE 1.06\n" \
|
||||
"#define SCALE_FUDGE 1.15\n"
|
||||
|
||||
#define GLSL_WALL_FUDGES \
|
||||
"#define STARTMAP_FUDGE 1.05\n" \
|
||||
"#define SCALE_FUDGE 2.2\n"
|
||||
|
||||
#define GLSL_FLOOR_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER
|
||||
|
||||
#define GLSL_WALL_FRAGMENT_SHADER \
|
||||
GLSL_WALL_FUDGES \
|
||||
GLSL_SOFTWARE_FRAGMENT_SHADER
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color) if model lighting is enabled
|
||||
#define GLSL_MODEL_FRAGMENT_SHADER \
|
||||
GLSL_WALL_FUDGES \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"texel *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"#ifdef SRB2_MODEL_LIGHTING\n" \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"#endif\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
//
|
||||
// Water surface shader
|
||||
//
|
||||
// Mostly guesstimated, rather than the rest being built off Software science.
|
||||
// Still needs to distort things underneath/around the water...
|
||||
//
|
||||
|
||||
#define GLSL_WATER_TEXEL \
|
||||
"float water_z = (gl_FragCoord.z / gl_FragCoord.w) / 2.0;\n" \
|
||||
"float a = -pi * (water_z * freq) + (leveltime * speed);\n" \
|
||||
"float sdistort = sin(a) * amp;\n" \
|
||||
"float cdistort = cos(a) * amp;\n" \
|
||||
"vec4 texel = texture2D(tex, vec2(gl_TexCoord[0].s - sdistort, gl_TexCoord[0].t - cdistort));\n"
|
||||
|
||||
#define GLSL_WATER_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
"const float freq = 0.025;\n" \
|
||||
"const float amp = 0.025;\n" \
|
||||
"const float speed = 2.0;\n" \
|
||||
"const float pi = 3.14159;\n" \
|
||||
"#ifdef SRB2_PALETTE_RENDERING\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
"void main(void) {\n" \
|
||||
GLSL_WATER_TEXEL \
|
||||
GLSL_PALETTE_RENDERING \
|
||||
"}\n" \
|
||||
"#else\n" \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
"uniform float leveltime;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
GLSL_WATER_TEXEL \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\n" \
|
||||
"#endif\0"
|
||||
|
||||
//
|
||||
// Fog block shader
|
||||
//
|
||||
// Alpha of the planes themselves are still slightly off -- see HWR_FogBlockAlpha
|
||||
//
|
||||
|
||||
// The floor fudges are used, but should the wall fudges be used instead? or something inbetween?
|
||||
// or separate values for floors and walls? (need to change more than this shader for that)
|
||||
#define GLSL_FOG_FRAGMENT_SHADER \
|
||||
GLSL_FLOOR_FUDGES \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 base_color = gl_Color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// Shader for the palette rendering postprocess step
|
||||
#define GLSL_PALETTE_POSTPROCESS_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler1D palette_tex;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"float palette_coord = (tex_pal_idx + 0.5) / 256.0;\n" \
|
||||
"vec4 final_color = texture1D(palette_tex, palette_coord);\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
// Applies a palettized colormap fade to tex
|
||||
#define GLSL_UI_COLORMAP_FADE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform sampler3D palette_lookup_tex;\n" \
|
||||
"uniform sampler2D lighttable_tex;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"float tex_pal_idx = texture3D(palette_lookup_tex, vec3((texel * 63.0 + 0.5) / 64.0))[0] * 255.0;\n" \
|
||||
"vec2 lighttable_coord = vec2((tex_pal_idx + 0.5) / 256.0, (lighting + 0.5) / 32.0);\n" \
|
||||
"gl_FragColor = texture2D(lighttable_tex, lighttable_coord);\n" \
|
||||
"}\0"
|
||||
|
||||
// For wipes that use additive and subtractive blending.
|
||||
// alpha_factor = 31 * 8 / 10 = 24.8
|
||||
// Calculated based on the use of the "fade" variable from the GETCOLOR macro
|
||||
// in r_data.c:R_CreateFadeColormaps.
|
||||
// However this value created some ugliness in fades to white (special stage entry)
|
||||
// while palette rendering is enabled, so I raised the value just a bit.
|
||||
#define GLSL_UI_TINTED_WIPE_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"const float alpha_factor = 24.875;\n" \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 final_color = poly_color;\n" \
|
||||
"float alpha = texel.a;\n" \
|
||||
"if (final_color.a >= 0.5)\n" \
|
||||
"alpha = 1.0 - alpha;\n" \
|
||||
"alpha *= alpha_factor;\n" \
|
||||
"final_color *= alpha;\n" \
|
||||
"final_color.a = 1.0;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_FALLBACK_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_FALLBACK_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Software fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"float darkness = R_DoomLightingEquation(lighting);\n" \
|
||||
"if (fade_start != 0.0 || fade_end != 31.0) {\n" \
|
||||
"float fs = fade_start / 31.0;\n" \
|
||||
"float fe = fade_end / 31.0;\n" \
|
||||
"float fd = fe - fs;\n" \
|
||||
"darkness = clamp((darkness - fs) * (1.0 / fd), 0.0, 1.0);\n" \
|
||||
"}\n" \
|
||||
"final_color = mix(final_color, fade_color, darkness);\n"
|
||||
|
||||
// same as above but multiplies results with the lighting value from the
|
||||
// accompanying vertex shader (stored in gl_Color)
|
||||
#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"uniform vec4 tint_color;\n" \
|
||||
"uniform vec4 fade_color;\n" \
|
||||
"uniform float lighting;\n" \
|
||||
"uniform float fade_start;\n" \
|
||||
"uniform float fade_end;\n" \
|
||||
GLSL_DOOM_COLORMAP \
|
||||
GLSL_DOOM_LIGHT_EQUATION \
|
||||
"void main(void) {\n" \
|
||||
"vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \
|
||||
"vec4 base_color = texel * poly_color;\n" \
|
||||
"vec4 final_color = base_color;\n" \
|
||||
GLSL_SOFTWARE_TINT_EQUATION \
|
||||
GLSL_SOFTWARE_FADE_EQUATION \
|
||||
"final_color *= gl_Color;\n" \
|
||||
"final_color.a = texel.a * poly_color.a;\n" \
|
||||
"gl_FragColor = final_color;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Sky fragment shader
|
||||
// Modulates poly_color with gl_Color
|
||||
//
|
||||
#define GLSL_SKY_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
#endif
|
|
@ -24,6 +24,7 @@
|
|||
#include "../../r_local.h" // For rendertimefrac, used for the leveltime shader uniform
|
||||
#include "r_opengl.h"
|
||||
#include "r_vbo.h"
|
||||
#include "../hw_shaders.h"
|
||||
|
||||
#if defined (HWRENDER) && !defined (NOROPENGL)
|
||||
|
||||
|
@ -317,6 +318,8 @@ typedef void (APIENTRY * PFNglDisable) (GLenum cap);
|
|||
static PFNglDisable pglDisable;
|
||||
typedef void (APIENTRY * PFNglGetFloatv) (GLenum pname, GLfloat *params);
|
||||
static PFNglGetFloatv pglGetFloatv;
|
||||
typedef void (APIENTRY * PFNglPolygonMode) (GLenum, GLenum);
|
||||
static PFNglPolygonMode pglPolygonMode;
|
||||
|
||||
/* Depth Buffer */
|
||||
typedef void (APIENTRY * PFNglClearDepth) (GLclampd depth);
|
||||
|
@ -502,6 +505,7 @@ boolean SetupGLfunc(void)
|
|||
GETOPENGLFUNC(pglGetFloatv, glGetFloatv)
|
||||
GETOPENGLFUNC(pglGetIntegerv, glGetIntegerv)
|
||||
GETOPENGLFUNC(pglGetString, glGetString)
|
||||
GETOPENGLFUNC(pglPolygonMode, glPolygonMode)
|
||||
|
||||
GETOPENGLFUNC(pglClearDepth, glClearDepth)
|
||||
GETOPENGLFUNC(pglDepthFunc, glDepthFunc)
|
||||
|
@ -660,30 +664,6 @@ static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAF
|
|||
|
||||
static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
|
||||
//
|
||||
// Generic vertex shader
|
||||
//
|
||||
|
||||
#define GLSL_FALLBACK_VERTEX_SHADER \
|
||||
"void main()\n" \
|
||||
"{\n" \
|
||||
"gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"gl_FrontColor = gl_Color;\n" \
|
||||
"gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \
|
||||
"gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \
|
||||
"}\0"
|
||||
|
||||
//
|
||||
// Generic fragment shader
|
||||
//
|
||||
|
||||
#define GLSL_FALLBACK_FRAGMENT_SHADER \
|
||||
"uniform sampler2D tex;\n" \
|
||||
"uniform vec4 poly_color;\n" \
|
||||
"void main(void) {\n" \
|
||||
"gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \
|
||||
"}\0"
|
||||
|
||||
#endif // GL_SHADERS
|
||||
|
||||
void SetupGLFunc4(void)
|
||||
|
@ -2275,6 +2255,10 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value)
|
|||
Flush(); //??? if we want to change filter mode by texture, remove this
|
||||
break;
|
||||
|
||||
case HWD_SET_WIREFRAME:
|
||||
pglPolygonMode(GL_FRONT_AND_BACK, Value ? GL_LINE : GL_FILL);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
131
src/hu_stuff.c
131
src/hu_stuff.c
|
@ -19,7 +19,9 @@
|
|||
#include "m_cond.h" // emblems
|
||||
#include "m_misc.h" // word jumping
|
||||
|
||||
#include "d_clisrv.h"
|
||||
#include "netcode/d_clisrv.h"
|
||||
#include "netcode/net_command.h"
|
||||
#include "netcode/gamestate.h"
|
||||
|
||||
#include "g_game.h"
|
||||
#include "g_input.h"
|
||||
|
@ -77,6 +79,7 @@ patch_t *nto_font[NT_FONTSIZE];
|
|||
|
||||
static player_t *plr;
|
||||
boolean chat_on; // entering a chat message?
|
||||
boolean chat_on_first_event; // blocker for first chat input event
|
||||
static char w_chat[HU_MAXMSGLEN + 1];
|
||||
static size_t c_input = 0; // let's try to make the chat input less shitty.
|
||||
static boolean headsupactive = false;
|
||||
|
@ -175,14 +178,12 @@ static huddrawlist_h luahuddrawlist_scores;
|
|||
|
||||
static tic_t resynch_ticker = 0;
|
||||
|
||||
#ifndef NONET
|
||||
// just after
|
||||
static void Command_Say_f(void);
|
||||
static void Command_Sayto_f(void);
|
||||
static void Command_Sayteam_f(void);
|
||||
static void Command_CSay_f(void);
|
||||
static void Got_Saycmd(UINT8 **p, INT32 playernum);
|
||||
#endif
|
||||
|
||||
void HU_LoadGraphics(void)
|
||||
{
|
||||
|
@ -327,13 +328,11 @@ void HU_LoadGraphics(void)
|
|||
//
|
||||
void HU_Init(void)
|
||||
{
|
||||
#ifndef NONET
|
||||
COM_AddCommand("say", Command_Say_f, COM_LUA);
|
||||
COM_AddCommand("sayto", Command_Sayto_f, COM_LUA);
|
||||
COM_AddCommand("sayteam", Command_Sayteam_f, COM_LUA);
|
||||
COM_AddCommand("csay", Command_CSay_f, COM_LUA);
|
||||
RegisterNetXCmd(XD_SAY, Got_Saycmd);
|
||||
#endif
|
||||
|
||||
// set shift translation table
|
||||
shiftxform = english_shiftxform;
|
||||
|
@ -363,8 +362,6 @@ void HU_Start(void)
|
|||
// EXECUTION
|
||||
//======================================================================
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
// EVERY CHANGE IN THIS SCRIPT IS LOL XD! BY VINCYTM
|
||||
|
||||
static UINT32 chat_nummsg_log = 0;
|
||||
|
@ -412,11 +409,9 @@ static void HU_removeChatText_Log(void)
|
|||
}
|
||||
chat_nummsg_log--; // lost 1 msg.
|
||||
}
|
||||
#endif
|
||||
|
||||
void HU_AddChatText(const char *text, boolean playsound)
|
||||
{
|
||||
#ifndef NONET
|
||||
if (playsound && cv_consolechat.value != 2) // Don't play the sound if we're using hidden chat.
|
||||
S_StartSound(NULL, sfx_radio);
|
||||
// reguardless of our preferences, put all of this in the chat buffer in case we decide to change from oldchat mid-game.
|
||||
|
@ -438,14 +433,8 @@ void HU_AddChatText(const char *text, boolean playsound)
|
|||
CONS_Printf("%s\n", text);
|
||||
else // if we aren't, still save the message to log.txt
|
||||
CON_LogMessage(va("%s\n", text));
|
||||
#else
|
||||
(void)playsound;
|
||||
CONS_Printf("%s\n", text);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
/** Runs a say command, sending an ::XD_SAY message.
|
||||
* A say command consists of a signed 8-bit integer for the target, an
|
||||
* unsigned 8-bit flag variable, and then the message itself.
|
||||
|
@ -630,7 +619,9 @@ static void Command_CSay_f(void)
|
|||
|
||||
DoSayCommand(0, 1, HU_CSAY);
|
||||
}
|
||||
static tic_t stop_spamming[MAXPLAYERS];
|
||||
|
||||
static tic_t spam_tokens[MAXPLAYERS];
|
||||
static tic_t spam_tics[MAXPLAYERS];
|
||||
|
||||
/** Receives a message, processing an ::XD_SAY command.
|
||||
* \sa DoSayCommand
|
||||
|
@ -682,14 +673,14 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
// before we do anything, let's verify the guy isn't spamming, get this easier on us.
|
||||
|
||||
//if (stop_spamming[playernum] != 0 && cv_chatspamprotection.value && !(flags & HU_CSAY))
|
||||
if (stop_spamming[playernum] != 0 && consoleplayer != playernum && cv_chatspamprotection.value && !(flags & HU_CSAY))
|
||||
if (spam_tokens[playernum] <= 0 && cv_chatspamprotection.value && !(flags & HU_CSAY))
|
||||
{
|
||||
CONS_Debug(DBG_NETPLAY,"Received SAY cmd too quickly from Player %d (%s), assuming as spam and blocking message.\n", playernum+1, player_names[playernum]);
|
||||
stop_spamming[playernum] = 4;
|
||||
spam_tics[playernum] = 0;
|
||||
spam_eatmsg = 1;
|
||||
}
|
||||
else
|
||||
stop_spamming[playernum] = 4; // you can hold off for 4 tics, can you?
|
||||
spam_tokens[playernum] -= 1;
|
||||
|
||||
// run the lua hook even if we were supposed to eat the msg, netgame consistency goes first.
|
||||
|
||||
|
@ -865,12 +856,29 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum)
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
//
|
||||
void HU_Ticker(void)
|
||||
{
|
||||
// do this server-side, too
|
||||
if (netgame)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
// handle spam while we're at it:
|
||||
for(; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
if (spam_tokens[i] < (tic_t)cv_chatspamburst.value)
|
||||
{
|
||||
if (++spam_tics[i] >= (tic_t)cv_chatspamspeed.value)
|
||||
{
|
||||
spam_tokens[i]++;
|
||||
spam_tics[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dedicated)
|
||||
return;
|
||||
|
||||
|
@ -882,7 +890,6 @@ void HU_Ticker(void)
|
|||
else
|
||||
hu_showscores = false;
|
||||
|
||||
#ifndef NONET
|
||||
if (chat_on)
|
||||
{
|
||||
// count down the scroll timer.
|
||||
|
@ -894,13 +901,6 @@ void HU_Ticker(void)
|
|||
{
|
||||
size_t i = 0;
|
||||
|
||||
// handle spam while we're at it:
|
||||
for(; (i<MAXPLAYERS); i++)
|
||||
{
|
||||
if (stop_spamming[i] > 0)
|
||||
stop_spamming[i]--;
|
||||
}
|
||||
|
||||
// handle chat timers
|
||||
for (i=0; (i<chat_nummsg_min); i++)
|
||||
{
|
||||
|
@ -910,7 +910,6 @@ void HU_Ticker(void)
|
|||
HU_removeChatText_Mini();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cechotimer > 0) --cechotimer;
|
||||
|
||||
|
@ -918,8 +917,6 @@ void HU_Ticker(void)
|
|||
resynch_ticker++;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
static boolean teamtalk = false;
|
||||
static boolean justscrolleddown;
|
||||
static boolean justscrolledup;
|
||||
|
@ -1027,8 +1024,6 @@ static void HU_sendChatMessage(void)
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void HU_clearChatChars(void)
|
||||
{
|
||||
memset(w_chat, '\0', sizeof(w_chat));
|
||||
|
@ -1043,11 +1038,9 @@ void HU_clearChatChars(void)
|
|||
//
|
||||
boolean HU_Responder(event_t *ev)
|
||||
{
|
||||
#ifndef NONET
|
||||
INT32 c=0;
|
||||
#endif
|
||||
|
||||
if (ev->type != ev_keydown)
|
||||
if (ev->type != ev_keydown && ev->type != ev_text)
|
||||
return false;
|
||||
|
||||
// only KeyDown events now...
|
||||
|
@ -1072,16 +1065,19 @@ boolean HU_Responder(event_t *ev)
|
|||
return false;
|
||||
}*/ //We don't actually care about that unless we get splitscreen netgames. :V
|
||||
|
||||
#ifndef NONET
|
||||
c = (INT32)ev->key;
|
||||
|
||||
if (!chat_on)
|
||||
{
|
||||
if (ev->type == ev_text)
|
||||
return false;
|
||||
|
||||
// enter chat mode
|
||||
if ((ev->key == gamecontrol[GC_TALKKEY][0] || ev->key == gamecontrol[GC_TALKKEY][1])
|
||||
&& netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise.
|
||||
{
|
||||
chat_on = true;
|
||||
chat_on_first_event = false;
|
||||
w_chat[0] = 0;
|
||||
teamtalk = false;
|
||||
chat_scrollmedown = true;
|
||||
|
@ -1092,6 +1088,7 @@ boolean HU_Responder(event_t *ev)
|
|||
&& netgame && !OLD_MUTE)
|
||||
{
|
||||
chat_on = true;
|
||||
chat_on_first_event = false;
|
||||
w_chat[0] = 0;
|
||||
teamtalk = G_GametypeHasTeams(); // Don't teamtalk if we don't have teams.
|
||||
chat_scrollmedown = true;
|
||||
|
@ -1101,6 +1098,31 @@ boolean HU_Responder(event_t *ev)
|
|||
}
|
||||
else // if chat_on
|
||||
{
|
||||
if (!chat_on_first_event)
|
||||
{
|
||||
// since the text event is sent immediately after the keydown event,
|
||||
// we need to make sure that nothing is displayed once the chat
|
||||
// opens, otherwise a 't' would be outputted.
|
||||
chat_on_first_event = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ev->type == ev_text)
|
||||
{
|
||||
if ((c < HU_FONTSTART || c > HU_FONTEND || !hu_font[c-HU_FONTSTART])
|
||||
&& c != ' ') // Allow spaces, of course
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CHAT_MUTE || strlen(w_chat) >= HU_MAXMSGLEN)
|
||||
return true;
|
||||
|
||||
memmove(&w_chat[c_input + 1], &w_chat[c_input], strlen(w_chat) - c_input + 1);
|
||||
w_chat[c_input] = c;
|
||||
c_input++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ignore modifier keys
|
||||
// Note that we do this here so users can still set
|
||||
|
@ -1110,23 +1132,8 @@ boolean HU_Responder(event_t *ev)
|
|||
|| ev->key == KEY_LALT || ev->key == KEY_RALT)
|
||||
return true;
|
||||
|
||||
c = (INT32)ev->key;
|
||||
|
||||
// I know this looks very messy but this works. If it ain't broke, don't fix it!
|
||||
// shift LETTERS to uppercase if we have capslock or are holding shift
|
||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
|
||||
{
|
||||
if (shiftdown ^ capslock)
|
||||
c = shiftxform[c];
|
||||
}
|
||||
else // if we're holding shift we should still shift non letter symbols
|
||||
{
|
||||
if (shiftdown)
|
||||
c = shiftxform[c];
|
||||
}
|
||||
|
||||
// pasting. pasting is cool. chat is a bit limited, though :(
|
||||
if ((c == 'v' || c == 'V') && ctrldown)
|
||||
if (c == 'v' && ctrldown)
|
||||
{
|
||||
const char *paste;
|
||||
size_t chatlen;
|
||||
|
@ -1194,16 +1201,6 @@ boolean HU_Responder(event_t *ev)
|
|||
else
|
||||
c_input++;
|
||||
}
|
||||
else if ((c >= HU_FONTSTART && c <= HU_FONTEND && hu_font[c-HU_FONTSTART])
|
||||
|| c == ' ') // Allow spaces, of course
|
||||
{
|
||||
if (CHAT_MUTE || strlen(w_chat) >= HU_MAXMSGLEN)
|
||||
return true;
|
||||
|
||||
memmove(&w_chat[c_input + 1], &w_chat[c_input], strlen(w_chat) - c_input + 1);
|
||||
w_chat[c_input] = c;
|
||||
c_input++;
|
||||
}
|
||||
else if (c == KEY_BACKSPACE)
|
||||
{
|
||||
if (CHAT_MUTE || c_input <= 0)
|
||||
|
@ -1222,7 +1219,6 @@ boolean HU_Responder(event_t *ev)
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1232,8 +1228,6 @@ boolean HU_Responder(event_t *ev)
|
|||
// HEADS UP DRAWING
|
||||
//======================================================================
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
// Precompile a wordwrapped string to any given width.
|
||||
// This is a muuuch better method than V_WORDWRAP.
|
||||
// again stolen and modified a bit from video.c, don't mind me, will need to rearrange this one day.
|
||||
|
@ -1813,7 +1807,6 @@ static void HU_DrawChat_Old(void)
|
|||
if (hu_tick < 4)
|
||||
V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Draw crosshairs at the exact center of the view.
|
||||
// In splitscreen, crosshairs are stretched vertically to compensate for V_PERPLAYER squishing them.
|
||||
|
@ -1953,7 +1946,6 @@ static void HU_DrawDemoInfo(void)
|
|||
//
|
||||
void HU_Drawer(void)
|
||||
{
|
||||
#ifndef NONET
|
||||
// draw chat string plus cursor
|
||||
if (chat_on)
|
||||
{
|
||||
|
@ -1970,7 +1962,6 @@ void HU_Drawer(void)
|
|||
if (!OLDCHAT && cv_consolechat.value < 2 && netgame) // Don't display minimized chat if you set the mode to Window (Hidden)
|
||||
HU_drawMiniChat(); // draw messages in a cool fashion.
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cechotimer)
|
||||
HU_DrawCEcho();
|
||||
|
|
43
src/i_time.c
43
src/i_time.c
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include "command.h"
|
||||
#include "doomtype.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "netcode/d_netcmd.h"
|
||||
#include "m_fixed.h"
|
||||
#include "i_system.h"
|
||||
|
||||
|
@ -30,12 +30,6 @@ static precise_t enterprecise, oldenterprecise;
|
|||
static fixed_t entertic, oldentertics;
|
||||
static double tictimer;
|
||||
|
||||
// A little more than the minimum sleep duration on Windows.
|
||||
// May be incorrect for other platforms, but we don't currently have a way to
|
||||
// query the scheduler granularity. SDL will do what's needed to make this as
|
||||
// low as possible though.
|
||||
#define MIN_SLEEP_DURATION_MS 2.1
|
||||
|
||||
tic_t I_GetTime(void)
|
||||
{
|
||||
return g_time.time;
|
||||
|
@ -88,38 +82,3 @@ void I_UpdateTime(fixed_t timescale)
|
|||
g_time.timefrac = FLOAT_TO_FIXED(fractional);
|
||||
}
|
||||
}
|
||||
|
||||
void I_SleepDuration(precise_t duration)
|
||||
{
|
||||
UINT64 precision = I_GetPrecisePrecision();
|
||||
INT32 sleepvalue = cv_sleep.value;
|
||||
UINT64 delaygranularity;
|
||||
precise_t cur;
|
||||
precise_t dest;
|
||||
|
||||
{
|
||||
double gran = round(((double)(precision / 1000) * sleepvalue * MIN_SLEEP_DURATION_MS));
|
||||
delaygranularity = (UINT64)gran;
|
||||
}
|
||||
|
||||
cur = I_GetPreciseTime();
|
||||
dest = cur + duration;
|
||||
|
||||
// the reason this is not dest > cur is because the precise counter may wrap
|
||||
// two's complement arithmetic is our friend here, though!
|
||||
// e.g. cur 0xFFFFFFFFFFFFFFFE = -2, dest 0x0000000000000001 = 1
|
||||
// 0x0000000000000001 - 0xFFFFFFFFFFFFFFFE = 3
|
||||
while ((INT64)(dest - cur) > 0)
|
||||
{
|
||||
// If our cv_sleep value exceeds the remaining sleep duration, use the
|
||||
// hard sleep function.
|
||||
if (sleepvalue > 0 && (dest - cur) > delaygranularity)
|
||||
{
|
||||
I_Sleep(sleepvalue);
|
||||
}
|
||||
|
||||
// Otherwise, this is a spinloop.
|
||||
|
||||
cur = I_GetPreciseTime();
|
||||
}
|
||||
}
|
||||
|
|
68
src/info.c
68
src/info.c
|
@ -33,7 +33,8 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"NULL", // invisible object
|
||||
"UNKN",
|
||||
|
||||
"THOK", // Thok! mobj
|
||||
"THOK", // Spin trail mobj
|
||||
"THKE", // Thok boom effect
|
||||
"PLAY",
|
||||
|
||||
// Enemies
|
||||
|
@ -250,6 +251,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"BMCH", // Big Mace Chain
|
||||
"SMCE", // Small Mace
|
||||
"BMCE", // Big Mace
|
||||
"BSPB", // Blue spring on a ball
|
||||
"YSPB", // Yellow spring on a ball
|
||||
"RSPB", // Red spring on a ball
|
||||
"SFBR", // Small Firebar
|
||||
|
@ -702,8 +704,9 @@ state_t states[NUMSTATES] =
|
|||
{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 5, 0, S_NULL}, // S_XDEATHSTATE
|
||||
{SPR_UNKN, FF_FULLBRIGHT, -1, {A_InfoState}, 6, 0, S_NULL}, // S_RAISESTATE
|
||||
|
||||
// Thok
|
||||
// Spin trail and thok boom effect
|
||||
{SPR_THOK, FF_TRANS50, 8, {NULL}, 0, 0, S_NULL}, // S_THOK
|
||||
{SPR_THKE, FF_TRANS50|FF_PAPERSPRITE, 8, {NULL}, 0, 0, S_NULL}, // S_THOKEFFECT
|
||||
|
||||
// Player
|
||||
{SPR_PLAY, SPR2_STND|FF_ANIMATE, 105, {NULL}, 0, 7, S_PLAY_WAIT}, // S_PLAY_STND
|
||||
|
@ -2297,6 +2300,13 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SMALLGRABCHAIN
|
||||
{SPR_BMCH, 1, -1, {NULL}, 0, 0, S_NULL}, // S_BIGGRABCHAIN
|
||||
|
||||
// Blue spring on a ball
|
||||
{SPR_BSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUESPRINGBALL
|
||||
{SPR_BSPB, 4, 4, {A_Pain}, 0, 0, S_BLUESPRINGBALL3}, // S_BLUESPRINGBALL2
|
||||
{SPR_BSPB, 3, 1, {NULL}, 0, 0, S_BLUESPRINGBALL4}, // S_BLUESPRINGBALL3
|
||||
{SPR_BSPB, 2, 1, {NULL}, 0, 0, S_BLUESPRINGBALL5}, // S_BLUESPRINGBALL4
|
||||
{SPR_BSPB, 1, 1, {NULL}, 0, 0, S_BLUESPRINGBALL}, // S_BLUESPRINGBALL5
|
||||
|
||||
// Yellow spring on a ball
|
||||
{SPR_YSPB, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YELLOWSPRINGBALL
|
||||
{SPR_YSPB, 4, 4, {A_Pain}, 0, 0, S_YELLOWSPRINGBALL3}, // S_YELLOWSPRINGBALL2
|
||||
|
@ -4070,6 +4080,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_THOKEFFECT
|
||||
-1, // doomednum
|
||||
S_THOKEFFECT, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
8, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
8, // speed
|
||||
32*FRACUNIT, // radius
|
||||
64*FRACUNIT, // height
|
||||
0, // display offset
|
||||
16, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_PLAYER
|
||||
-1, // doomednum
|
||||
|
@ -11679,6 +11716,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BLUESPRINGBALL
|
||||
1133, // doomednum
|
||||
S_BLUESPRINGBALL, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_BLUESPRINGBALL2, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_spring, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
24*FRACUNIT, // speed
|
||||
17*FRACUNIT, // radius
|
||||
34*FRACUNIT, // height
|
||||
1, // display offset
|
||||
11*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_mswing, // activesound
|
||||
MF_SCENERY|MF_SPRING|MF_NOGRAVITY, // flags
|
||||
S_BLUESPRINGBALL2 // raisestate
|
||||
},
|
||||
|
||||
{ // MT_YELLOWSPRINGBALL
|
||||
1134, // doomednum
|
||||
S_YELLOWSPRINGBALL, // spawnstate
|
||||
|
|
18
src/info.h
18
src/info.h
|
@ -580,7 +580,8 @@ typedef enum sprite
|
|||
SPR_NULL, // invisible object
|
||||
SPR_UNKN,
|
||||
|
||||
SPR_THOK, // Thok! mobj
|
||||
SPR_THOK, // Spin trail mobj
|
||||
SPR_THKE, // Thok boom effect
|
||||
SPR_PLAY,
|
||||
|
||||
// Enemies
|
||||
|
@ -797,6 +798,7 @@ typedef enum sprite
|
|||
SPR_BMCH, // Big Mace Chain
|
||||
SPR_SMCE, // Small Mace
|
||||
SPR_BMCE, // Big Mace
|
||||
SPR_BSPB, // Blue spring on a ball
|
||||
SPR_YSPB, // Yellow spring on a ball
|
||||
SPR_RSPB, // Red spring on a ball
|
||||
SPR_SFBR, // Small Firebar
|
||||
|
@ -1181,8 +1183,9 @@ typedef enum state
|
|||
S_XDEATHSTATE,
|
||||
S_RAISESTATE,
|
||||
|
||||
// Thok
|
||||
// Thok boom effect and spin trail
|
||||
S_THOK,
|
||||
S_THOKEFFECT,
|
||||
|
||||
// Player
|
||||
S_PLAY_STND,
|
||||
|
@ -2744,6 +2747,13 @@ typedef enum state
|
|||
S_SMALLGRABCHAIN,
|
||||
S_BIGGRABCHAIN,
|
||||
|
||||
// Blue spring on a ball
|
||||
S_BLUESPRINGBALL,
|
||||
S_BLUESPRINGBALL2,
|
||||
S_BLUESPRINGBALL3,
|
||||
S_BLUESPRINGBALL4,
|
||||
S_BLUESPRINGBALL5,
|
||||
|
||||
// Yellow spring on a ball
|
||||
S_YELLOWSPRINGBALL,
|
||||
S_YELLOWSPRINGBALL2,
|
||||
|
@ -4384,7 +4394,8 @@ typedef enum mobj_type
|
|||
MT_NULL,
|
||||
MT_UNKNOWN,
|
||||
|
||||
MT_THOK, // Thok! mobj
|
||||
MT_THOK, // Spin trail mobj
|
||||
MT_THOKEFFECT, // Thok boom effect
|
||||
MT_PLAYER,
|
||||
MT_TAILSOVERLAY, // c:
|
||||
MT_METALJETFUME,
|
||||
|
@ -4722,6 +4733,7 @@ typedef enum mobj_type
|
|||
MT_BIGMACE, // Big Mace
|
||||
MT_SMALLGRABCHAIN, // Small Grab Chain
|
||||
MT_BIGGRABCHAIN, // Big Grab Chain
|
||||
MT_BLUESPRINGBALL, // Blue spring on a ball
|
||||
MT_YELLOWSPRINGBALL, // Yellow spring on a ball
|
||||
MT_REDSPRINGBALL, // Red spring on a ball
|
||||
MT_SMALLFIREBAR, // Small Firebar
|
||||
|
|
|
@ -26,11 +26,11 @@
|
|||
#include "y_inter.h"
|
||||
#include "hu_stuff.h" // HU_AddChatText
|
||||
#include "console.h"
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
#include "netcode/d_netcmd.h" // IsPlayerAdmin
|
||||
#include "m_menu.h" // Player Setup menu color stuff
|
||||
#include "m_misc.h" // M_MapNumber
|
||||
#include "b_bot.h" // B_UpdateBotleader
|
||||
#include "d_clisrv.h" // CL_RemovePlayer
|
||||
#include "netcode/d_clisrv.h" // CL_RemovePlayer
|
||||
#include "i_system.h" // I_GetPreciseTime, I_GetPrecisePrecision
|
||||
|
||||
#include "lua_script.h"
|
||||
|
@ -213,6 +213,8 @@ static const struct {
|
|||
{META_HUDINFO, "hudinfo_t"},
|
||||
{META_PATCH, "patch_t"},
|
||||
{META_COLORMAP, "colormap"},
|
||||
{META_EXTRACOLORMAP,"extracolormap_t"},
|
||||
{META_LIGHTTABLE, "lighttable_t"},
|
||||
{META_CAMERA, "camera_t"},
|
||||
|
||||
{META_ACTION, "action"},
|
||||
|
@ -1031,6 +1033,20 @@ static int lib_pRailThinker(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pCheckSkyHit(lua_State *L)
|
||||
{
|
||||
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
line_t *line = *((line_t **)luaL_checkudata(L, 2, META_LINE));
|
||||
//HUDSAFE
|
||||
INLEVEL
|
||||
if (!mobj)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
if (!line)
|
||||
return LUA_ErrInvalid(L, "line_t");
|
||||
lua_pushboolean(L, P_CheckSkyHit(mobj, line));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pXYMovement(lua_State *L)
|
||||
{
|
||||
mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -1330,6 +1346,17 @@ static int lib_pSetObjectMomZ(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pIsLocalPlayer(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
//NOHUD
|
||||
//INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushboolean(L, P_IsLocalPlayer(player));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pPlayJingle(lua_State *L)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
|
@ -1425,6 +1452,18 @@ static int lib_pGivePlayerRings(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pGivePlayerSpheres(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
INT32 num_spheres = (INT32)luaL_checkinteger(L, 2);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
P_GivePlayerSpheres(player, num_spheres);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pGivePlayerLives(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -1567,6 +1606,19 @@ static int lib_pInstaThrust(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pInstaThrustEvenIn2D(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
angle_t angle = luaL_checkangle(L, 2);
|
||||
fixed_t move = luaL_checkfixed(L, 3);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_InstaThrustEvenIn2D(mo, angle, move);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pReturnThrustX(lua_State *L)
|
||||
{
|
||||
angle_t angle;
|
||||
|
@ -1647,11 +1699,12 @@ static int lib_pHomingAttack(lua_State *L)
|
|||
static int lib_pSuperReady(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
boolean transform = (boolean)lua_opttrueboolean(L, 2);
|
||||
//HUDSAFE
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushboolean(L, P_SuperReady(player));
|
||||
lua_pushboolean(L, P_SuperReady(player, transform));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1667,6 +1720,17 @@ static int lib_pDoJump(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pDoSpinDashDust(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
P_DoSpinDashDust(player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pSpawnThokMobj(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -1717,6 +1781,48 @@ static int lib_pSwitchShield(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pDoTailsOverlay(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
mobj_t *tails = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!tails)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_DoTailsOverlay(player, tails);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pDoMetalJetFume(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
mobj_t *fume = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!fume)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_DoMetalJetFume(player, fume);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pDoFollowMobj(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
mobj_t *followmobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
if (!followmobj)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_DoFollowMobj(player, followmobj);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pPlayerCanEnterSpinGaps(lua_State *L)
|
||||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
|
@ -1788,6 +1894,7 @@ static int lib_pMove(lua_State *L)
|
|||
return 2;
|
||||
}
|
||||
|
||||
// TODO: 2.3: Delete
|
||||
static int lib_pTeleportMove(lua_State *L)
|
||||
{
|
||||
mobj_t *ptmthing = tmthing;
|
||||
|
@ -1928,6 +2035,30 @@ static int lib_pCeilingzAtPos(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pGetSectorColormapAt(lua_State *L)
|
||||
{
|
||||
boolean has_sector = false;
|
||||
sector_t *sector = NULL;
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
{
|
||||
has_sector = true;
|
||||
sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
|
||||
}
|
||||
fixed_t x = luaL_checkfixed(L, 2);
|
||||
fixed_t y = luaL_checkfixed(L, 3);
|
||||
fixed_t z = luaL_checkfixed(L, 4);
|
||||
INLEVEL
|
||||
if (has_sector && !sector)
|
||||
return LUA_ErrInvalid(L, "sector_t");
|
||||
extracolormap_t *exc;
|
||||
if (sector)
|
||||
exc = P_GetColormapFromSectorAt(sector, x, y, z);
|
||||
else
|
||||
exc = P_GetSectorColormapAt(x, y, z);
|
||||
LUA_PushUserdata(L, exc, META_EXTRACOLORMAP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lib_pDoSpring(lua_State *L)
|
||||
{
|
||||
mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -2198,6 +2329,21 @@ static int lib_pDoMatchSuper(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pTouchSpecialThing(lua_State *L)
|
||||
{
|
||||
mobj_t *special = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
mobj_t *toucher = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ));
|
||||
boolean heightcheck = lua_optboolean(L, 3);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!special || !toucher)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
if (!toucher->player)
|
||||
return luaL_error(L, "P_TouchSpecialThing requires a valid toucher.player.");
|
||||
P_TouchSpecialThing(special, toucher, heightcheck);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// P_SPEC
|
||||
////////////
|
||||
|
||||
|
@ -2214,6 +2360,40 @@ static int lib_pThrust(lua_State *L)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pThrustEvenIn2D(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
angle_t angle = luaL_checkangle(L, 2);
|
||||
fixed_t move = luaL_checkfixed(L, 3);
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_ThrustEvenIn2D(mo, angle, move);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pVectorInstaThrust(lua_State *L)
|
||||
{
|
||||
fixed_t xa = luaL_checkfixed(L, 1);
|
||||
fixed_t xb = luaL_checkfixed(L, 2);
|
||||
fixed_t xc = luaL_checkfixed(L, 3);
|
||||
fixed_t ya = luaL_checkfixed(L, 4);
|
||||
fixed_t yb = luaL_checkfixed(L, 5);
|
||||
fixed_t yc = luaL_checkfixed(L, 6);
|
||||
fixed_t za = luaL_checkfixed(L, 7);
|
||||
fixed_t zb = luaL_checkfixed(L, 8);
|
||||
fixed_t zc = luaL_checkfixed(L, 9);
|
||||
fixed_t momentum = luaL_checkfixed(L, 10);
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 11, META_MOBJ));
|
||||
NOHUD
|
||||
INLEVEL
|
||||
if (!mo)
|
||||
return LUA_ErrInvalid(L, "mobj_t");
|
||||
P_VectorInstaThrust(xa, xb, xc, ya, yb, yc, za, zb, zc, momentum, mo);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_pSetMobjStateNF(lua_State *L)
|
||||
{
|
||||
mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -2266,6 +2446,7 @@ static int lib_pMobjTouchingSectorSpecial(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// TODO: 2.3: Delete
|
||||
static int lib_pThingOnSpecial3DFloor(lua_State *L)
|
||||
{
|
||||
mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ));
|
||||
|
@ -3570,6 +3751,7 @@ static int lib_gAddPlayer(lua_State *L)
|
|||
|
||||
newplayer->jointime = 0;
|
||||
newplayer->quittime = 0;
|
||||
newplayer->lastinputtime = 0;
|
||||
|
||||
// Read the skin argument (defaults to Sonic)
|
||||
if (!lua_isnoneornil(L, 1))
|
||||
|
@ -4079,6 +4261,7 @@ static luaL_Reg lib[] = {
|
|||
{"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope},
|
||||
{"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope},
|
||||
{"P_RailThinker",lib_pRailThinker},
|
||||
{"P_CheckSkyHit",lib_pCheckSkyHit},
|
||||
{"P_XYMovement",lib_pXYMovement},
|
||||
{"P_RingXYMovement",lib_pRingXYMovement},
|
||||
{"P_SceneryXYMovement",lib_pSceneryXYMovement},
|
||||
|
@ -4105,12 +4288,14 @@ static luaL_Reg lib[] = {
|
|||
{"P_InQuicksand",lib_pInQuicksand},
|
||||
{"P_InJumpFlipSector",lib_pInJumpFlipSector},
|
||||
{"P_SetObjectMomZ",lib_pSetObjectMomZ},
|
||||
{"P_IsLocalPlayer",lib_pIsLocalPlayer},
|
||||
{"P_PlayJingle",lib_pPlayJingle},
|
||||
{"P_PlayJingleMusic",lib_pPlayJingleMusic},
|
||||
{"P_RestoreMusic",lib_pRestoreMusic},
|
||||
{"P_SpawnShieldOrb",lib_pSpawnShieldOrb},
|
||||
{"P_SpawnGhostMobj",lib_pSpawnGhostMobj},
|
||||
{"P_GivePlayerRings",lib_pGivePlayerRings},
|
||||
{"P_GivePlayerSpheres",lib_pGivePlayerSpheres},
|
||||
{"P_GivePlayerLives",lib_pGivePlayerLives},
|
||||
{"P_GiveCoopLives",lib_pGiveCoopLives},
|
||||
{"P_ResetScore",lib_pResetScore},
|
||||
|
@ -4123,6 +4308,7 @@ static luaL_Reg lib[] = {
|
|||
{"P_DoPlayerFinish",lib_pDoPlayerFinish},
|
||||
{"P_DoPlayerExit",lib_pDoPlayerExit},
|
||||
{"P_InstaThrust",lib_pInstaThrust},
|
||||
{"P_InstaThrustEvenIn2D",lib_pInstaThrustEvenIn2D},
|
||||
{"P_ReturnThrustX",lib_pReturnThrustX},
|
||||
{"P_ReturnThrustY",lib_pReturnThrustY},
|
||||
{"P_LookForEnemies",lib_pLookForEnemies},
|
||||
|
@ -4131,10 +4317,14 @@ static luaL_Reg lib[] = {
|
|||
{"P_HomingAttack",lib_pHomingAttack},
|
||||
{"P_SuperReady",lib_pSuperReady},
|
||||
{"P_DoJump",lib_pDoJump},
|
||||
{"P_DoSpinDashDust",lib_pDoSpinDashDust},
|
||||
{"P_SpawnThokMobj",lib_pSpawnThokMobj},
|
||||
{"P_SpawnSpinMobj",lib_pSpawnSpinMobj},
|
||||
{"P_Telekinesis",lib_pTelekinesis},
|
||||
{"P_SwitchShield",lib_pSwitchShield},
|
||||
{"P_DoTailsOverlay",lib_pDoTailsOverlay},
|
||||
{"P_DoMetalJetFume",lib_pDoMetalJetFume},
|
||||
{"P_DoFollowMobj",lib_pDoFollowMobj},
|
||||
{"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps},
|
||||
{"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight},
|
||||
|
||||
|
@ -4152,7 +4342,9 @@ static luaL_Reg lib[] = {
|
|||
{"P_RadiusAttack",lib_pRadiusAttack},
|
||||
{"P_FloorzAtPos",lib_pFloorzAtPos},
|
||||
{"P_CeilingzAtPos",lib_pCeilingzAtPos},
|
||||
{"P_GetSectorColormapAt",lib_pGetSectorColormapAt},
|
||||
{"P_DoSpring",lib_pDoSpring},
|
||||
{"P_TouchSpecialThing",lib_pTouchSpecialThing},
|
||||
{"P_TryCameraMove", lib_pTryCameraMove},
|
||||
{"P_TeleportCameraMove", lib_pTeleportCameraMove},
|
||||
|
||||
|
@ -4176,6 +4368,8 @@ static luaL_Reg lib[] = {
|
|||
|
||||
// p_spec
|
||||
{"P_Thrust",lib_pThrust},
|
||||
{"P_ThrustEvenIn2D",lib_pThrustEvenIn2D},
|
||||
{"P_VectorInstaThrust",lib_pVectorInstaThrust},
|
||||
{"P_SetMobjStateNF",lib_pSetMobjStateNF},
|
||||
{"P_DoSuperTransformation",lib_pDoSuperTransformation},
|
||||
{"P_ExplodeMissile",lib_pExplodeMissile},
|
||||
|
@ -4300,8 +4494,7 @@ int LUA_BaseLib(lua_State *L)
|
|||
// Set metatable for string
|
||||
lua_pushliteral(L, ""); // dummy string
|
||||
lua_getmetatable(L, -1); // get string metatable
|
||||
lua_pushcfunction(L,lib_concat); // push concatination function
|
||||
lua_setfield(L,-2,"__add"); // ... store it as mathematical addition
|
||||
LUA_SetCFunctionField(L, "__add", lib_concat);
|
||||
lua_pop(L, 2); // pop metatable and dummy string
|
||||
|
||||
lua_newtable(L);
|
||||
|
|
332
src/lua_colorlib.c
Normal file
332
src/lua_colorlib.c
Normal file
|
@ -0,0 +1,332 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2021-2022 by "Lactozilla".
|
||||
// Copyright (C) 2014-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file lua_colorlib.c
|
||||
/// \brief color and colormap libraries for Lua scripting
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "fastcmp.h"
|
||||
#include "r_data.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
||||
#define IS_HEX_CHAR(x) ((x >= '0' && x <= '9') || (x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F'))
|
||||
#define ARE_HEX_CHARS(str, i) IS_HEX_CHAR(str[i]) && IS_HEX_CHAR(str[i + 1])
|
||||
|
||||
static UINT32 hex2int(char x)
|
||||
{
|
||||
if (x >= '0' && x <= '9')
|
||||
return x - '0';
|
||||
else if (x >= 'a' && x <= 'f')
|
||||
return x - 'a' + 10;
|
||||
else if (x >= 'A' && x <= 'F')
|
||||
return x - 'A' + 10;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static UINT8 ParseHTMLColor(const char *str, UINT8 *rgba, size_t numc)
|
||||
{
|
||||
const char *hex = str;
|
||||
|
||||
if (hex[0] == '#')
|
||||
hex++;
|
||||
else if (!IS_HEX_CHAR(hex[0]))
|
||||
return 0;
|
||||
|
||||
size_t len = strlen(hex);
|
||||
|
||||
if (len == 3)
|
||||
{
|
||||
// Shorthand like #09C
|
||||
for (unsigned i = 0; i < 3; i++)
|
||||
{
|
||||
if (!IS_HEX_CHAR(hex[i]))
|
||||
return 0;
|
||||
|
||||
UINT32 hx = hex2int(hex[i]);
|
||||
*rgba++ = (hx * 16) + hx;
|
||||
}
|
||||
|
||||
return 3;
|
||||
}
|
||||
else if (len == 6 || len == 8)
|
||||
{
|
||||
if (numc != 4)
|
||||
len = 6;
|
||||
|
||||
// A triplet like #0099CC
|
||||
for (unsigned i = 0; i < len; i += 2)
|
||||
{
|
||||
if (!ARE_HEX_CHARS(hex, i))
|
||||
return false;
|
||||
|
||||
*rgba++ = (hex2int(hex[i]) * 16) + hex2int(hex[i + 1]);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/////////////////////////
|
||||
// extracolormap userdata
|
||||
/////////////////////////
|
||||
|
||||
enum extracolormap_e {
|
||||
extracolormap_red = 0,
|
||||
extracolormap_green,
|
||||
extracolormap_blue,
|
||||
extracolormap_alpha,
|
||||
extracolormap_color,
|
||||
extracolormap_fade_red,
|
||||
extracolormap_fade_green,
|
||||
extracolormap_fade_blue,
|
||||
extracolormap_fade_alpha,
|
||||
extracolormap_fade_color,
|
||||
extracolormap_fade_start,
|
||||
extracolormap_fade_end,
|
||||
extracolormap_colormap
|
||||
};
|
||||
|
||||
static const char *const extracolormap_opt[] = {
|
||||
"red",
|
||||
"green",
|
||||
"blue",
|
||||
"alpha",
|
||||
"color",
|
||||
"fade_red",
|
||||
"fade_green",
|
||||
"fade_blue",
|
||||
"fade_alpha",
|
||||
"fade_color",
|
||||
"fade_start",
|
||||
"fade_end",
|
||||
"colormap",
|
||||
NULL};
|
||||
|
||||
static int extracolormap_get(lua_State *L)
|
||||
{
|
||||
extracolormap_t *exc = *((extracolormap_t **)luaL_checkudata(L, 1, META_EXTRACOLORMAP));
|
||||
enum extracolormap_e field = luaL_checkoption(L, 2, NULL, extracolormap_opt);
|
||||
|
||||
switch (field)
|
||||
{
|
||||
case extracolormap_red:
|
||||
lua_pushinteger(L, R_GetRgbaR(exc->rgba));
|
||||
break;
|
||||
case extracolormap_green:
|
||||
lua_pushinteger(L, R_GetRgbaG(exc->rgba));
|
||||
break;
|
||||
case extracolormap_blue:
|
||||
lua_pushinteger(L, R_GetRgbaB(exc->rgba));
|
||||
break;
|
||||
case extracolormap_alpha:
|
||||
lua_pushinteger(L, R_GetRgbaA(exc->rgba));
|
||||
break;
|
||||
case extracolormap_color:
|
||||
lua_pushinteger(L, R_GetRgbaR(exc->rgba));
|
||||
lua_pushinteger(L, R_GetRgbaG(exc->rgba));
|
||||
lua_pushinteger(L, R_GetRgbaB(exc->rgba));
|
||||
lua_pushinteger(L, R_GetRgbaA(exc->rgba));
|
||||
return 4;
|
||||
case extracolormap_fade_red:
|
||||
lua_pushinteger(L, R_GetRgbaR(exc->fadergba));
|
||||
break;
|
||||
case extracolormap_fade_green:
|
||||
lua_pushinteger(L, R_GetRgbaG(exc->fadergba));
|
||||
break;
|
||||
case extracolormap_fade_blue:
|
||||
lua_pushinteger(L, R_GetRgbaB(exc->fadergba));
|
||||
break;
|
||||
case extracolormap_fade_alpha:
|
||||
lua_pushinteger(L, R_GetRgbaA(exc->fadergba));
|
||||
break;
|
||||
case extracolormap_fade_color:
|
||||
lua_pushinteger(L, R_GetRgbaR(exc->fadergba));
|
||||
lua_pushinteger(L, R_GetRgbaG(exc->fadergba));
|
||||
lua_pushinteger(L, R_GetRgbaB(exc->fadergba));
|
||||
lua_pushinteger(L, R_GetRgbaA(exc->fadergba));
|
||||
return 4;
|
||||
case extracolormap_fade_start:
|
||||
lua_pushinteger(L, exc->fadestart);
|
||||
break;
|
||||
case extracolormap_fade_end:
|
||||
lua_pushinteger(L, exc->fadeend);
|
||||
break;
|
||||
case extracolormap_colormap:
|
||||
LUA_PushUserdata(L, exc->colormap, META_LIGHTTABLE);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void GetExtraColormapRGBA(lua_State *L, UINT8 *rgba, int arg)
|
||||
{
|
||||
if (lua_type(L, arg) == LUA_TSTRING)
|
||||
{
|
||||
const char *str = lua_tostring(L, arg);
|
||||
UINT8 parsed = ParseHTMLColor(str, rgba, 4);
|
||||
if (!parsed)
|
||||
luaL_error(L, "Malformed HTML color '%s'", str);
|
||||
}
|
||||
else
|
||||
{
|
||||
UINT32 colors = lua_tointeger(L, arg);
|
||||
if (colors > 0xFFFFFF)
|
||||
{
|
||||
rgba[0] = (colors >> 24) & 0xFF;
|
||||
rgba[1] = (colors >> 16) & 0xFF;
|
||||
rgba[2] = (colors >> 8) & 0xFF;
|
||||
rgba[3] = colors & 0xFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
rgba[0] = (colors >> 16) & 0xFF;
|
||||
rgba[1] = (colors >> 8) & 0xFF;
|
||||
rgba[2] = colors & 0xFF;
|
||||
rgba[3] = 0xFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int extracolormap_set(lua_State *L)
|
||||
{
|
||||
extracolormap_t *exc = *((extracolormap_t **)luaL_checkudata(L, 1, META_EXTRACOLORMAP));
|
||||
enum extracolormap_e field = luaL_checkoption(L, 2, NULL, extracolormap_opt);
|
||||
|
||||
UINT8 r = R_GetRgbaR(exc->rgba);
|
||||
UINT8 g = R_GetRgbaG(exc->rgba);
|
||||
UINT8 b = R_GetRgbaB(exc->rgba);
|
||||
UINT8 a = R_GetRgbaA(exc->rgba);
|
||||
|
||||
UINT8 fr = R_GetRgbaR(exc->fadergba);
|
||||
UINT8 fg = R_GetRgbaG(exc->fadergba);
|
||||
UINT8 fb = R_GetRgbaB(exc->fadergba);
|
||||
UINT8 fa = R_GetRgbaA(exc->fadergba);
|
||||
|
||||
UINT8 rgba[4];
|
||||
|
||||
INT32 old_rgba = exc->rgba, old_fade_rgba = exc->fadergba; // It's not unsigned?
|
||||
UINT8 old_fade_start = exc->fadestart, old_fade_end = exc->fadeend;
|
||||
|
||||
#define val luaL_checkinteger(L, 3)
|
||||
|
||||
switch(field)
|
||||
{
|
||||
case extracolormap_red:
|
||||
exc->rgba = R_PutRgbaRGBA(val, g, b, a);
|
||||
break;
|
||||
case extracolormap_green:
|
||||
exc->rgba = R_PutRgbaRGBA(r, val, b, a);
|
||||
break;
|
||||
case extracolormap_blue:
|
||||
exc->rgba = R_PutRgbaRGBA(r, g, val, a);
|
||||
break;
|
||||
case extracolormap_alpha:
|
||||
exc->rgba = R_PutRgbaRGBA(r, g, b, val);
|
||||
break;
|
||||
case extracolormap_color:
|
||||
rgba[0] = r;
|
||||
rgba[1] = g;
|
||||
rgba[2] = b;
|
||||
rgba[3] = a;
|
||||
GetExtraColormapRGBA(L, rgba, 3);
|
||||
exc->rgba = R_PutRgbaRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
break;
|
||||
case extracolormap_fade_red:
|
||||
exc->fadergba = R_PutRgbaRGBA(val, fg, fb, fa);
|
||||
break;
|
||||
case extracolormap_fade_green:
|
||||
exc->fadergba = R_PutRgbaRGBA(fr, val, fb, fa);
|
||||
break;
|
||||
case extracolormap_fade_blue:
|
||||
exc->fadergba = R_PutRgbaRGBA(fr, fg, val, fa);
|
||||
break;
|
||||
case extracolormap_fade_alpha:
|
||||
exc->fadergba = R_PutRgbaRGBA(fr, fg, fb, val);
|
||||
break;
|
||||
case extracolormap_fade_color:
|
||||
rgba[0] = fr;
|
||||
rgba[1] = fg;
|
||||
rgba[2] = fb;
|
||||
rgba[3] = fa;
|
||||
GetExtraColormapRGBA(L, rgba, 3);
|
||||
exc->fadergba = R_PutRgbaRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||
break;
|
||||
case extracolormap_fade_start:
|
||||
if (val > 31)
|
||||
return luaL_error(L, "fade start %d out of range (0 - 31)", val);
|
||||
exc->fadestart = val;
|
||||
break;
|
||||
case extracolormap_fade_end:
|
||||
if (val > 31)
|
||||
return luaL_error(L, "fade end %d out of range (0 - 31)", val);
|
||||
exc->fadeend = val;
|
||||
break;
|
||||
case extracolormap_colormap:
|
||||
return luaL_error(L, LUA_QL("extracolormap_t") " field " LUA_QS " should not be set directly.", extracolormap_opt[field]);
|
||||
}
|
||||
|
||||
#undef val
|
||||
|
||||
if (exc->rgba != old_rgba
|
||||
|| exc->fadergba != old_fade_rgba
|
||||
|| exc->fadestart != old_fade_start
|
||||
|| exc->fadeend != old_fade_end)
|
||||
R_GenerateLightTable(exc, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lighttable_get(lua_State *L)
|
||||
{
|
||||
void **userdata;
|
||||
|
||||
lighttable_t *table = *((lighttable_t **)luaL_checkudata(L, 1, META_LIGHTTABLE));
|
||||
UINT32 row = luaL_checkinteger(L, 2);
|
||||
if (row < 1 || row > 34)
|
||||
return luaL_error(L, "lighttable row %d out of range (1 - %d)", row, 34);
|
||||
|
||||
userdata = lua_newuserdata(L, sizeof(void *));
|
||||
*userdata = &table[256 * (row - 1)];
|
||||
luaL_getmetatable(L, META_COLORMAP);
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int lighttable_len(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, NUM_PALETTE_ENTRIES);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LUA_ColorLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_EXTRACOLORMAP);
|
||||
lua_pushcfunction(L, extracolormap_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, extracolormap_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_LIGHTTABLE);
|
||||
lua_pushcfunction(L, lighttable_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lighttable_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -16,6 +16,7 @@
|
|||
#include "g_game.h"
|
||||
#include "byteptr.h"
|
||||
#include "z_zone.h"
|
||||
#include "netcode/net_command.h"
|
||||
|
||||
#include "lua_script.h"
|
||||
#include "lua_libs.h"
|
||||
|
@ -193,6 +194,7 @@ static int lib_comAddCommand(lua_State *L)
|
|||
if (lua_gettop(L) >= 3)
|
||||
{ // For the third argument, only take a boolean or a number.
|
||||
lua_settop(L, 3);
|
||||
// TODO: 2.3: Remove boolean option
|
||||
if (lua_type(L, 3) == LUA_TBOOLEAN)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
|
@ -373,6 +375,9 @@ static int lib_cvRegisterVar(lua_State *L)
|
|||
size_t count = 0;
|
||||
CV_PossibleValue_t *cvpv;
|
||||
|
||||
const char * const MINMAX[2] = {"MIN", "MAX"};
|
||||
int minmax_unset = 3;
|
||||
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 4))
|
||||
{
|
||||
|
@ -391,16 +396,45 @@ static int lib_cvRegisterVar(lua_State *L)
|
|||
lua_pushnil(L);
|
||||
while (lua_next(L, 4))
|
||||
{
|
||||
INT32 n;
|
||||
const char * strval;
|
||||
|
||||
// stack: [...] PossibleValue table, index, value
|
||||
// 4 5 6
|
||||
if (lua_type(L, 5) != LUA_TSTRING
|
||||
|| lua_type(L, 6) != LUA_TNUMBER)
|
||||
FIELDERROR("PossibleValue", "custom PossibleValue table requires a format of string=integer, i.e. {MIN=0, MAX=9999}");
|
||||
cvpv[i].strvalue = Z_StrDup(lua_tostring(L, 5));
|
||||
cvpv[i].value = (INT32)lua_tonumber(L, 6);
|
||||
i++;
|
||||
|
||||
strval = lua_tostring(L, 5);
|
||||
|
||||
if (
|
||||
stricmp(strval, MINMAX[n=0]) == 0 ||
|
||||
stricmp(strval, MINMAX[n=1]) == 0
|
||||
){
|
||||
/* need to shift forward */
|
||||
if (minmax_unset == 3)
|
||||
{
|
||||
memmove(&cvpv[2], &cvpv[0],
|
||||
i * sizeof *cvpv);
|
||||
i += 2;
|
||||
}
|
||||
cvpv[n].strvalue = MINMAX[n];
|
||||
minmax_unset &= ~(1 << n);
|
||||
}
|
||||
else
|
||||
{
|
||||
n = i++;
|
||||
cvpv[n].strvalue = Z_StrDup(strval);
|
||||
}
|
||||
|
||||
cvpv[n].value = (INT32)lua_tonumber(L, 6);
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
if (minmax_unset && minmax_unset != 3)
|
||||
FIELDERROR("PossibleValue", "custom PossibleValue table requires requires both MIN and MAX keys if one is present");
|
||||
|
||||
cvpv[i].value = 0;
|
||||
cvpv[i].strvalue = NULL;
|
||||
cvar->PossibleValue = cvpv;
|
||||
|
@ -625,10 +659,7 @@ static int cvar_get(lua_State *L)
|
|||
int LUA_ConsoleLib(lua_State *L)
|
||||
{
|
||||
// Metatable for consvar_t
|
||||
luaL_newmetatable(L, META_CVAR);
|
||||
lua_pushcfunction(L, cvar_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L,1);
|
||||
LUA_RegisterUserdataMetatable(L, META_CVAR, cvar_get, NULL, NULL);
|
||||
|
||||
cvar_fields_ref = Lua_CreateFieldTable(L, cvar_opt);
|
||||
|
||||
|
|
|
@ -126,7 +126,9 @@ int LUA_HookPlayer(player_t *, int hook);
|
|||
int LUA_HookTiccmd(player_t *, ticcmd_t *, int hook);
|
||||
int LUA_HookKey(event_t *event, int hook); // Hooks for key events
|
||||
|
||||
void LUA_HookPreThinkFrame(void);
|
||||
void LUA_HookThinkFrame(void);
|
||||
void LUA_HookPostThinkFrame(void);
|
||||
int LUA_HookMobjLineCollide(mobj_t *, line_t *);
|
||||
int LUA_HookTouchSpecial(mobj_t *special, mobj_t *toucher);
|
||||
int LUA_HookShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "lua_hud.h" // hud_running errors
|
||||
|
||||
#include "m_perfstats.h"
|
||||
#include "d_netcmd.h" // for cv_perfstats
|
||||
#include "netcode/d_netcmd.h" // for cv_perfstats
|
||||
#include "i_system.h" // I_GetPreciseTime
|
||||
|
||||
/* =========================================================================
|
||||
|
@ -76,12 +76,12 @@ static boolean mobj_hook_available(int hook_type, mobjtype_t mobj_type)
|
|||
);
|
||||
}
|
||||
|
||||
static int hook_in_list
|
||||
static unsigned hook_in_list
|
||||
(
|
||||
const char * const name,
|
||||
const char * const * const list
|
||||
){
|
||||
int type;
|
||||
unsigned type;
|
||||
|
||||
for (type = 0; list[type] != NULL; ++type)
|
||||
{
|
||||
|
@ -200,7 +200,7 @@ static void add_hook_ref(lua_State *L, int idx)
|
|||
static int lib_addHook(lua_State *L)
|
||||
{
|
||||
const char * name;
|
||||
int type;
|
||||
unsigned type;
|
||||
|
||||
if (!lua_lumploading)
|
||||
return luaL_error(L, "This function cannot be called from within a hook or coroutine!");
|
||||
|
@ -671,10 +671,8 @@ void LUA_HookHUD(int hook_type, huddrawlist_h list)
|
|||
SPECIALIZED HOOKS
|
||||
========================================================================= */
|
||||
|
||||
void LUA_HookThinkFrame(void)
|
||||
static void hook_think_frame(int type)
|
||||
{
|
||||
const int type = HOOK(ThinkFrame);
|
||||
|
||||
// variables used by perf stats
|
||||
int hook_index = 0;
|
||||
precise_t time_taken = 0;
|
||||
|
@ -692,7 +690,7 @@ void LUA_HookThinkFrame(void)
|
|||
{
|
||||
get_hook(&hook, map->ids, k);
|
||||
|
||||
if (cv_perfstats.value == 3)
|
||||
if (cv_perfstats.value >= 3)
|
||||
{
|
||||
lua_pushvalue(gL, -1);/* need the function again */
|
||||
time_taken = I_GetPreciseTime();
|
||||
|
@ -700,12 +698,18 @@ void LUA_HookThinkFrame(void)
|
|||
|
||||
call_single_hook(&hook);
|
||||
|
||||
if (cv_perfstats.value == 3)
|
||||
if (cv_perfstats.value >= 3)
|
||||
{
|
||||
lua_Debug ar;
|
||||
time_taken = I_GetPreciseTime() - time_taken;
|
||||
lua_getinfo(gL, ">S", &ar);
|
||||
PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
|
||||
if (type == 4) // sorry for magic numbers
|
||||
PS_SetPreThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
|
||||
else if (type == 5)
|
||||
PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
|
||||
else if (type == 6)
|
||||
PS_SetPostThinkFrameHookInfo(hook_index, time_taken, ar.short_src);
|
||||
|
||||
hook_index++;
|
||||
}
|
||||
}
|
||||
|
@ -714,6 +718,21 @@ void LUA_HookThinkFrame(void)
|
|||
}
|
||||
}
|
||||
|
||||
void LUA_HookPreThinkFrame(void)
|
||||
{
|
||||
hook_think_frame(HOOK(PreThinkFrame));
|
||||
}
|
||||
|
||||
void LUA_HookThinkFrame(void)
|
||||
{
|
||||
hook_think_frame(HOOK(ThinkFrame));
|
||||
}
|
||||
|
||||
void LUA_HookPostThinkFrame(void)
|
||||
{
|
||||
hook_think_frame(HOOK(PostThinkFrame));
|
||||
}
|
||||
|
||||
int LUA_HookMobjLineCollide(mobj_t *mobj, line_t *line)
|
||||
{
|
||||
Hook_State hook;
|
||||
|
|
|
@ -517,7 +517,7 @@ static int libd_getSpritePatch(lua_State *L)
|
|||
INT32 rot = R_GetRollAngle(rollangle);
|
||||
|
||||
if (rot) {
|
||||
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &spriteinfo[i], rot);
|
||||
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &spriteinfo[i], rot);
|
||||
LUA_PushUserdata(L, rotsprite, META_PATCH);
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushboolean(L, true);
|
||||
|
@ -629,7 +629,7 @@ static int libd_getSprite2Patch(lua_State *L)
|
|||
INT32 rot = R_GetRollAngle(rollangle);
|
||||
|
||||
if (rot) {
|
||||
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), true, &skins[i].sprinfo[j], rot);
|
||||
patch_t *rotsprite = Patch_GetRotatedSprite(sprframe, frame, angle, sprframe->flip & (1<<angle), &skins[i].sprinfo[j], rot);
|
||||
LUA_PushUserdata(L, rotsprite, META_PATCH);
|
||||
lua_pushboolean(L, false);
|
||||
lua_pushboolean(L, true);
|
||||
|
@ -1206,19 +1206,11 @@ static int libd_height(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int libd_dupx(lua_State *L)
|
||||
static int libd_dup(lua_State *L)
|
||||
{
|
||||
HUDONLY
|
||||
lua_pushinteger(L, vid.dupx); // push integral scale (patch scale)
|
||||
lua_pushfixed(L, vid.fdupx); // push fixed point scale (position scale)
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int libd_dupy(lua_State *L)
|
||||
{
|
||||
HUDONLY
|
||||
lua_pushinteger(L, vid.dupy); // push integral scale (patch scale)
|
||||
lua_pushfixed(L, vid.fdupy); // push fixed point scale (position scale)
|
||||
lua_pushinteger(L, vid.dup); // push integral scale (patch scale)
|
||||
lua_pushfixed(L, vid.fdup); // push fixed point scale (position scale)
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
@ -1338,8 +1330,8 @@ static luaL_Reg lib_draw[] = {
|
|||
// properties
|
||||
{"width", libd_width},
|
||||
{"height", libd_height},
|
||||
{"dupx", libd_dupx},
|
||||
{"dupy", libd_dupy},
|
||||
{"dupx", libd_dup},
|
||||
{"dupy", libd_dup},
|
||||
{"renderer", libd_renderer},
|
||||
{"localTransFlag", libd_getlocaltransflag},
|
||||
{"userTransFlag", libd_getusertransflag},
|
||||
|
@ -1404,52 +1396,16 @@ int LUA_HudLib(lua_State *L)
|
|||
luaL_register(L, NULL, lib_draw);
|
||||
lib_draw_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
|
||||
luaL_newmetatable(L, META_HUDINFO);
|
||||
lua_pushcfunction(L, hudinfo_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, hudinfo_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, hudinfo_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getHudInfo);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_hudinfolen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "hudinfo");
|
||||
|
||||
luaL_newmetatable(L, META_COLORMAP);
|
||||
lua_pushcfunction(L, colormap_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_PATCH);
|
||||
lua_pushcfunction(L, patch_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, patch_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
LUA_RegisterUserdataMetatable(L, META_HUDINFO, hudinfo_get, hudinfo_set, hudinfo_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_COLORMAP, colormap_get, NULL, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_PATCH, patch_get, patch_set, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_CAMERA, camera_get, camera_set, NULL);
|
||||
|
||||
patch_fields_ref = Lua_CreateFieldTable(L, patch_opt);
|
||||
|
||||
luaL_newmetatable(L, META_CAMERA);
|
||||
lua_pushcfunction(L, camera_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, camera_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
camera_fields_ref = Lua_CreateFieldTable(L, camera_opt);
|
||||
|
||||
LUA_RegisterGlobalUserdata(L, "hudinfo", lib_getHudInfo, NULL, lib_hudinfolen);
|
||||
|
||||
luaL_register(L, "hud", lib_hud);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -318,6 +318,7 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in
|
|||
pivot[idx].x = (INT32)value;
|
||||
else if (ikey == 2 || (key && fastcmp(key, "y")))
|
||||
pivot[idx].y = (INT32)value;
|
||||
// TODO: 2.3: Delete
|
||||
else if (ikey == 3 || (key && fastcmp(key, "rotaxis")))
|
||||
LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.")
|
||||
else if (ikey == -1 && (key != NULL))
|
||||
|
@ -571,6 +572,7 @@ static int framepivot_get(lua_State *L)
|
|||
lua_pushinteger(L, framepivot->x);
|
||||
else if (fastcmp("y", field))
|
||||
lua_pushinteger(L, framepivot->y);
|
||||
// TODO: 2.3: Delete
|
||||
else if (fastcmp("rotaxis", field))
|
||||
{
|
||||
LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.");
|
||||
|
@ -600,6 +602,7 @@ static int framepivot_set(lua_State *L)
|
|||
framepivot->x = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp("y", field))
|
||||
framepivot->y = luaL_checkinteger(L, 3);
|
||||
// TODO: 2.3: delete
|
||||
else if (fastcmp("rotaxis", field))
|
||||
LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.")
|
||||
else
|
||||
|
@ -1914,206 +1917,28 @@ int LUA_InfoLib(lua_State *L)
|
|||
lua_newtable(L);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS);
|
||||
|
||||
luaL_newmetatable(L, META_STATE);
|
||||
lua_pushcfunction(L, state_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, state_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, state_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_MOBJINFO);
|
||||
lua_pushcfunction(L, mobjinfo_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, mobjinfo_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, mobjinfo_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
LUA_RegisterUserdataMetatable(L, META_STATE, state_get, state_set, state_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_MOBJINFO, mobjinfo_get, mobjinfo_set, mobjinfo_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_SKINCOLOR, skincolor_get, skincolor_set, skincolor_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_COLORRAMP, colorramp_get, colorramp_set, colorramp_len);
|
||||
LUA_RegisterUserdataMetatable(L, META_SFXINFO, sfxinfo_get, sfxinfo_set, sfxinfo_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_SPRITEINFO, spriteinfo_get, spriteinfo_set, spriteinfo_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_PIVOTLIST, pivotlist_get, pivotlist_set, pivotlist_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_FRAMEPIVOT, framepivot_get, framepivot_set, framepivot_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_LUABANKS, lib_getluabanks, lib_setluabanks, lib_luabankslen);
|
||||
|
||||
mobjinfo_fields_ref = Lua_CreateFieldTable(L, mobjinfo_opt);
|
||||
|
||||
luaL_newmetatable(L, META_SKINCOLOR);
|
||||
lua_pushcfunction(L, skincolor_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, skincolor_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, skincolor_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_COLORRAMP);
|
||||
lua_pushcfunction(L, colorramp_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, colorramp_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, colorramp_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_SFXINFO);
|
||||
lua_pushcfunction(L, sfxinfo_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, sfxinfo_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, sfxinfo_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_SPRITEINFO);
|
||||
lua_pushcfunction(L, spriteinfo_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, spriteinfo_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, spriteinfo_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_PIVOTLIST);
|
||||
lua_pushcfunction(L, pivotlist_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, pivotlist_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, pivotlist_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_FRAMEPIVOT);
|
||||
lua_pushcfunction(L, framepivot_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, framepivot_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, framepivot_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSprname);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_sprnamelen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "sprnames");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSpr2name);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_spr2namelen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "spr2names");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSpr2default);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setSpr2default);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_spr2namelen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "spr2defaults");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getState);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setState);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_statelen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "states");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getMobjInfo);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setMobjInfo);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_mobjinfolen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "mobjinfo");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSkinColor);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setSkinColor);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_skincolorslen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "skincolors");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSfxInfo);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setSfxInfo);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_sfxlen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setglobal(L, "S_sfx");
|
||||
lua_setglobal(L, "sfxinfo");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSpriteInfo);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setSpriteInfo);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_spriteinfolen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "spriteinfo");
|
||||
|
||||
luaL_newmetatable(L, META_LUABANKS);
|
||||
lua_pushcfunction(L, lib_getluabanks);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setluabanks);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_luabankslen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
LUA_RegisterGlobalUserdata(L, "sprnames", lib_getSprname, NULL, lib_sprnamelen);
|
||||
LUA_RegisterGlobalUserdata(L, "spr2names", lib_getSpr2name, NULL, lib_spr2namelen);
|
||||
LUA_RegisterGlobalUserdata(L, "spr2defaults", lib_getSpr2default, lib_setSpr2default, lib_spr2namelen);
|
||||
LUA_RegisterGlobalUserdata(L, "states", lib_getState, lib_setState, lib_statelen);
|
||||
LUA_RegisterGlobalUserdata(L, "mobjinfo", lib_getMobjInfo, lib_setMobjInfo, lib_mobjinfolen);
|
||||
LUA_RegisterGlobalUserdata(L, "skincolors", lib_getSkinColor, lib_setSkinColor, lib_skincolorslen);
|
||||
LUA_RegisterGlobalUserdata(L, "spriteinfo", lib_getSpriteInfo, lib_setSpriteInfo, lib_spriteinfolen);
|
||||
LUA_RegisterGlobalUserdata(L, "sfxinfo", lib_getSfxInfo, lib_setSfxInfo, lib_sfxlen);
|
||||
// TODO: 2.3: Delete this alias
|
||||
LUA_RegisterGlobalUserdata(L, "S_sfx", lib_getSfxInfo, lib_setSfxInfo, lib_sfxlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "lua_libs.h"
|
||||
|
||||
boolean mousegrabbedbylua = true;
|
||||
boolean ignoregameinputs = false;
|
||||
|
||||
///////////////
|
||||
// FUNCTIONS //
|
||||
|
@ -145,6 +146,51 @@ static luaL_Reg lib[] = {
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
///////////////
|
||||
// VARIABLES //
|
||||
///////////////
|
||||
|
||||
static int lib_get(lua_State *L)
|
||||
{
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
|
||||
if (fastcmp(field, "mouse"))
|
||||
{
|
||||
LUA_PushUserdata(L, &mouse, META_MOUSE);
|
||||
return 1;
|
||||
}
|
||||
else if (fastcmp(field, "mouse2"))
|
||||
{
|
||||
LUA_PushUserdata(L, &mouse2, META_MOUSE);
|
||||
return 1;
|
||||
}
|
||||
else if (fastcmp(field, "ignoregameinputs"))
|
||||
{
|
||||
lua_pushboolean(L, ignoregameinputs);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int lib_set(lua_State *L)
|
||||
{
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
|
||||
if (fastcmp(field, "ignoregameinputs"))
|
||||
{
|
||||
ignoregameinputs = luaL_checkboolean(L, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
lua_rawset(L, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// gamekeydown[] //
|
||||
///////////////////
|
||||
|
@ -239,32 +285,18 @@ static int mouse_num(lua_State *L)
|
|||
|
||||
int LUA_InputLib(lua_State *L)
|
||||
{
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getGameKeyDown);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setGameKeyDown);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_lenGameKeyDown);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "gamekeydown");
|
||||
|
||||
luaL_newmetatable(L, META_KEYEVENT);
|
||||
lua_pushcfunction(L, keyevent_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_MOUSE);
|
||||
lua_pushcfunction(L, mouse_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, mouse_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
LUA_RegisterUserdataMetatable(L, META_KEYEVENT, keyevent_get, NULL, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_MOUSE, mouse_get, NULL, mouse_num);
|
||||
|
||||
// Register the library, then add __index and __newindex
|
||||
// metamethods to it to allow global variables
|
||||
luaL_register(L, "input", lib);
|
||||
LUA_CreateAndSetMetatable(L, lib_get, lib_set, NULL, false);
|
||||
|
||||
LUA_CreateAndSetUserdataField(L, -1, "gamekeydown", lib_getGameKeyDown, lib_setGameKeyDown, lib_lenGameKeyDown, false);
|
||||
// TODO: 2.3: Delete this alias (moved to input library)
|
||||
LUA_RegisterGlobalUserdata(L, "gamekeydown", lib_getGameKeyDown, lib_setGameKeyDown, lib_lenGameKeyDown);
|
||||
lua_pop(L, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
extern lua_State *gL;
|
||||
|
||||
extern boolean mousegrabbedbylua;
|
||||
extern boolean ignoregameinputs;
|
||||
|
||||
#define MUTABLE_TAGS
|
||||
|
||||
|
@ -84,6 +85,8 @@ extern boolean mousegrabbedbylua;
|
|||
#define META_HUDINFO "HUDINFO_T*"
|
||||
#define META_PATCH "PATCH_T*"
|
||||
#define META_COLORMAP "COLORMAP"
|
||||
#define META_EXTRACOLORMAP "EXTRACOLORMAP_T*"
|
||||
#define META_LIGHTTABLE "LIGHTTABLE_T*"
|
||||
#define META_CAMERA "CAMERA_T*"
|
||||
|
||||
#define META_ACTION "ACTIONF_T*"
|
||||
|
@ -111,4 +114,5 @@ int LUA_TagLib(lua_State *L);
|
|||
int LUA_PolyObjLib(lua_State *L);
|
||||
int LUA_BlockmapLib(lua_State *L);
|
||||
int LUA_HudLib(lua_State *L);
|
||||
int LUA_ColorLib(lua_State *L);
|
||||
int LUA_InputLib(lua_State *L);
|
||||
|
|
460
src/lua_maplib.c
460
src/lua_maplib.c
|
@ -35,15 +35,19 @@ enum sector_e {
|
|||
sector_floorpic,
|
||||
sector_floorxoffset,
|
||||
sector_flooryoffset,
|
||||
sector_floorangle,
|
||||
sector_floorxscale,
|
||||
sector_flooryscale,
|
||||
sector_floorangle,
|
||||
sector_ceilingpic,
|
||||
sector_ceilingxoffset,
|
||||
sector_ceilingyoffset,
|
||||
sector_ceilingxscale,
|
||||
sector_ceilingyscale,
|
||||
sector_ceilingangle,
|
||||
sector_lightlevel,
|
||||
sector_floorlightlevel,
|
||||
sector_floorlightabsolute,
|
||||
sector_floorlightsec,
|
||||
sector_floorlightsec,
|
||||
sector_ceilinglightlevel,
|
||||
sector_ceilinglightabsolute,
|
||||
sector_ceilinglightsec,
|
||||
|
@ -57,6 +61,7 @@ enum sector_e {
|
|||
sector_ffloors,
|
||||
sector_fslope,
|
||||
sector_cslope,
|
||||
sector_colormap,
|
||||
sector_flags,
|
||||
sector_specialflags,
|
||||
sector_damagetype,
|
||||
|
@ -73,18 +78,22 @@ static const char *const sector_opt[] = {
|
|||
"floorpic",
|
||||
"floorxoffset",
|
||||
"flooryoffset",
|
||||
"floorxscale",
|
||||
"flooryscale",
|
||||
"floorangle",
|
||||
"ceilingpic",
|
||||
"ceilingxoffset",
|
||||
"ceilingyoffset",
|
||||
"ceilingangle",
|
||||
"ceilingxscale",
|
||||
"ceilingyscale",
|
||||
"ceilingangle",
|
||||
"lightlevel",
|
||||
"floorlightlevel",
|
||||
"floorlightabsolute",
|
||||
"floorlightsec",
|
||||
"ceilinglightlevel",
|
||||
"ceilinglightabsolute",
|
||||
"ceilinglightsec",
|
||||
"ceilinglightsec",
|
||||
"special",
|
||||
"tag",
|
||||
"taglist",
|
||||
|
@ -95,6 +104,7 @@ static const char *const sector_opt[] = {
|
|||
"ffloors",
|
||||
"f_slope",
|
||||
"c_slope",
|
||||
"colormap",
|
||||
"flags",
|
||||
"specialflags",
|
||||
"damagetype",
|
||||
|
@ -186,8 +196,16 @@ enum side_e {
|
|||
side_offsety_top,
|
||||
side_offsetx_mid,
|
||||
side_offsety_mid,
|
||||
side_offsetx_bottom,
|
||||
side_offsetx_bot,
|
||||
side_offsety_bottom,
|
||||
side_offsety_bot,
|
||||
side_scalex_top,
|
||||
side_scaley_top,
|
||||
side_scalex_mid,
|
||||
side_scaley_mid,
|
||||
side_scalex_bottom,
|
||||
side_scaley_bottom,
|
||||
side_toptexture,
|
||||
side_bottomtexture,
|
||||
side_midtexture,
|
||||
|
@ -206,8 +224,16 @@ static const char *const side_opt[] = {
|
|||
"offsety_top",
|
||||
"offsetx_mid",
|
||||
"offsety_mid",
|
||||
"offsetx_bottom",
|
||||
"offsetx_bot",
|
||||
"offsety_bottom",
|
||||
"offsety_bot",
|
||||
"scalex_top",
|
||||
"scaley_top",
|
||||
"scalex_mid",
|
||||
"scaley_mid",
|
||||
"scalex_bottom",
|
||||
"scaley_bottom",
|
||||
"toptexture",
|
||||
"bottomtexture",
|
||||
"midtexture",
|
||||
|
@ -247,8 +273,16 @@ enum ffloor_e {
|
|||
ffloor_topheight,
|
||||
ffloor_toppic,
|
||||
ffloor_toplightlevel,
|
||||
ffloor_topxoffs,
|
||||
ffloor_topyoffs,
|
||||
ffloor_topxscale,
|
||||
ffloor_topyscale,
|
||||
ffloor_bottomheight,
|
||||
ffloor_bottompic,
|
||||
ffloor_bottomxoffs,
|
||||
ffloor_bottomyoffs,
|
||||
ffloor_bottomxscale,
|
||||
ffloor_bottomyscale,
|
||||
ffloor_tslope,
|
||||
ffloor_bslope,
|
||||
ffloor_sector,
|
||||
|
@ -273,8 +307,16 @@ static const char *const ffloor_opt[] = {
|
|||
"topheight",
|
||||
"toppic",
|
||||
"toplightlevel",
|
||||
"topxoffs",
|
||||
"topyoffs",
|
||||
"topxscale",
|
||||
"topyscale",
|
||||
"bottomheight",
|
||||
"bottompic",
|
||||
"bottomxoffs",
|
||||
"bottomyoffs",
|
||||
"bottomxscale",
|
||||
"bottomyscale",
|
||||
"t_slope",
|
||||
"b_slope",
|
||||
"sector", // secnum pushed as control sector userdata
|
||||
|
@ -654,20 +696,20 @@ static int sector_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
case sector_floorxoffset:
|
||||
{
|
||||
lua_pushfixed(L, sector->floorxoffset);
|
||||
return 1;
|
||||
}
|
||||
case sector_flooryoffset:
|
||||
{
|
||||
lua_pushfixed(L, sector->flooryoffset);
|
||||
return 1;
|
||||
}
|
||||
case sector_floorangle:
|
||||
{
|
||||
case sector_floorxscale:
|
||||
lua_pushfixed(L, sector->floorxscale);
|
||||
return 1;
|
||||
case sector_flooryscale:
|
||||
lua_pushfixed(L, sector->flooryscale);
|
||||
return 1;
|
||||
case sector_floorangle:
|
||||
lua_pushangle(L, sector->floorangle);
|
||||
return 1;
|
||||
}
|
||||
case sector_ceilingpic: // ceilingpic
|
||||
{
|
||||
levelflat_t *levelflat = &levelflats[sector->ceilingpic];
|
||||
|
@ -678,20 +720,20 @@ static int sector_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
case sector_ceilingxoffset:
|
||||
{
|
||||
lua_pushfixed(L, sector->ceilingxoffset);
|
||||
return 1;
|
||||
}
|
||||
case sector_ceilingyoffset:
|
||||
{
|
||||
lua_pushfixed(L, sector->ceilingyoffset);
|
||||
return 1;
|
||||
}
|
||||
case sector_ceilingxscale:
|
||||
lua_pushfixed(L, sector->ceilingxscale);
|
||||
return 1;
|
||||
case sector_ceilingyscale:
|
||||
lua_pushfixed(L, sector->ceilingyscale);
|
||||
return 1;
|
||||
case sector_ceilingangle:
|
||||
{
|
||||
lua_pushangle(L, sector->ceilingangle);
|
||||
return 1;
|
||||
}
|
||||
case sector_lightlevel:
|
||||
lua_pushinteger(L, sector->lightlevel);
|
||||
return 1;
|
||||
|
@ -703,7 +745,7 @@ static int sector_get(lua_State *L)
|
|||
return 1;
|
||||
case sector_floorlightsec:
|
||||
lua_pushinteger(L, sector->floorlightsec);
|
||||
return 1;
|
||||
return 1;
|
||||
case sector_ceilinglightlevel:
|
||||
lua_pushinteger(L, sector->ceilinglightlevel);
|
||||
return 1;
|
||||
|
@ -712,7 +754,7 @@ static int sector_get(lua_State *L)
|
|||
return 1;
|
||||
case sector_ceilinglightsec:
|
||||
lua_pushinteger(L, sector->ceilinglightsec);
|
||||
return 1;
|
||||
return 1;
|
||||
case sector_special:
|
||||
lua_pushinteger(L, sector->special);
|
||||
return 1;
|
||||
|
@ -751,6 +793,9 @@ static int sector_get(lua_State *L)
|
|||
case sector_cslope: // c_slope
|
||||
LUA_PushUserdata(L, sector->c_slope, META_SLOPE);
|
||||
return 1;
|
||||
case sector_colormap: // extra_colormap
|
||||
LUA_PushUserdata(L, sector->extra_colormap, META_EXTRACOLORMAP);
|
||||
return 1;
|
||||
case sector_flags: // flags
|
||||
lua_pushinteger(L, sector->flags);
|
||||
return 1;
|
||||
|
@ -840,9 +885,15 @@ static int sector_set(lua_State *L)
|
|||
case sector_flooryoffset:
|
||||
sector->flooryoffset = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case sector_floorxscale:
|
||||
sector->floorxscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case sector_flooryscale:
|
||||
sector->flooryscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case sector_floorangle:
|
||||
sector->floorangle = luaL_checkangle(L, 3);
|
||||
break;
|
||||
break;
|
||||
case sector_ceilingpic:
|
||||
sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
|
||||
break;
|
||||
|
@ -852,6 +903,12 @@ static int sector_set(lua_State *L)
|
|||
case sector_ceilingyoffset:
|
||||
sector->ceilingyoffset = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case sector_ceilingxscale:
|
||||
sector->ceilingxscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case sector_ceilingyscale:
|
||||
sector->ceilingyscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case sector_ceilingangle:
|
||||
sector->ceilingangle = luaL_checkangle(L, 3);
|
||||
break;
|
||||
|
@ -866,7 +923,7 @@ static int sector_set(lua_State *L)
|
|||
break;
|
||||
case sector_floorlightsec:
|
||||
sector->floorlightsec = (INT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
break;
|
||||
case sector_ceilinglightlevel:
|
||||
sector->ceilinglightlevel = (INT16)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
@ -875,7 +932,7 @@ static int sector_set(lua_State *L)
|
|||
break;
|
||||
case sector_ceilinglightsec:
|
||||
sector->ceilinglightsec = (INT32)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
break;
|
||||
case sector_special:
|
||||
sector->special = (INT16)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
@ -1043,17 +1100,7 @@ static int line_get(lua_State *L)
|
|||
lua_pushinteger(L, line->special);
|
||||
return 1;
|
||||
case line_tag:
|
||||
// HELLO
|
||||
// THIS IS LJ SONIC
|
||||
// HOW IS YOUR DAY?
|
||||
// BY THE WAY WHEN 2.3 OR 3.0 OR 4.0 OR SRB3 OR SRB4 OR WHATEVER IS OUT
|
||||
// YOU SHOULD REMEMBER TO CHANGE THIS SO IT ALWAYS RETURNS A UNSIGNED VALUE
|
||||
// HAVE A NICE DAY
|
||||
//
|
||||
//
|
||||
//
|
||||
//
|
||||
// you are ugly
|
||||
// TODO: 2.3: Always return a unsigned value
|
||||
lua_pushinteger(L, Tag_FGet(&line->tags));
|
||||
return 1;
|
||||
case line_taglist:
|
||||
|
@ -1072,7 +1119,7 @@ static int line_get(lua_State *L)
|
|||
LUA_PushUserdata(L, &sides[line->sidenum[0]], META_SIDE);
|
||||
return 1;
|
||||
case line_backside: // backside
|
||||
if (line->sidenum[1] == 0xffff)
|
||||
if (line->sidenum[1] == NO_SIDEDEF)
|
||||
return 0;
|
||||
LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE);
|
||||
return 1;
|
||||
|
@ -1108,6 +1155,7 @@ static int line_get(lua_State *L)
|
|||
case line_polyobj:
|
||||
LUA_PushUserdata(L, line->polyobj, META_POLYOBJ);
|
||||
return 1;
|
||||
// TODO: 2.3: Delete
|
||||
case line_text:
|
||||
{
|
||||
if (udmf)
|
||||
|
@ -1147,7 +1195,7 @@ static int line_num(lua_State *L)
|
|||
|
||||
static int sidenum_get(lua_State *L)
|
||||
{
|
||||
UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM));
|
||||
UINT32 *sidenum = *((UINT32 **)luaL_checkudata(L, 1, META_SIDENUM));
|
||||
int i;
|
||||
lua_settop(L, 2);
|
||||
if (!lua_isnumber(L, 2))
|
||||
|
@ -1214,11 +1262,31 @@ static int side_get(lua_State *L)
|
|||
case side_offsety_mid:
|
||||
lua_pushfixed(L, side->offsety_mid);
|
||||
return 1;
|
||||
case side_offsetx_bottom:
|
||||
case side_offsetx_bot:
|
||||
lua_pushfixed(L, side->offsetx_bot);
|
||||
lua_pushfixed(L, side->offsetx_bottom);
|
||||
return 1;
|
||||
case side_offsety_bottom:
|
||||
case side_offsety_bot:
|
||||
lua_pushfixed(L, side->offsety_bot);
|
||||
lua_pushfixed(L, side->offsety_bottom);
|
||||
return 1;
|
||||
case side_scalex_top:
|
||||
lua_pushfixed(L, side->scalex_top);
|
||||
return 1;
|
||||
case side_scaley_top:
|
||||
lua_pushfixed(L, side->scaley_top);
|
||||
return 1;
|
||||
case side_scalex_mid:
|
||||
lua_pushfixed(L, side->scalex_mid);
|
||||
return 1;
|
||||
case side_scaley_mid:
|
||||
lua_pushfixed(L, side->scaley_mid);
|
||||
return 1;
|
||||
case side_scalex_bottom:
|
||||
lua_pushfixed(L, side->scalex_bottom);
|
||||
return 1;
|
||||
case side_scaley_bottom:
|
||||
lua_pushfixed(L, side->scaley_bottom);
|
||||
return 1;
|
||||
case side_toptexture:
|
||||
lua_pushinteger(L, side->toptexture);
|
||||
|
@ -1241,8 +1309,12 @@ static int side_get(lua_State *L)
|
|||
case side_repeatcnt:
|
||||
lua_pushinteger(L, side->repeatcnt);
|
||||
return 1;
|
||||
// TODO: 2.3: Delete
|
||||
case side_text:
|
||||
{
|
||||
boolean isfrontside;
|
||||
size_t sidei = side-sides;
|
||||
|
||||
if (udmf)
|
||||
{
|
||||
LUA_Deprecated(L, "(sidedef_t).text", "(sidedef_t).line.stringargs");
|
||||
|
@ -1250,7 +1322,7 @@ static int side_get(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
boolean isfrontside = side->line->sidenum[0] == side-sides;
|
||||
isfrontside = side->line->sidenum[0] == sidei;
|
||||
|
||||
lua_pushstring(L, side->line->stringargs[isfrontside ? 0 : 1]);
|
||||
return 1;
|
||||
|
@ -1302,10 +1374,30 @@ static int side_set(lua_State *L)
|
|||
side->offsety_mid = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_offsetx_bot:
|
||||
side->offsetx_bot = luaL_checkfixed(L, 3);
|
||||
case side_offsetx_bottom:
|
||||
side->offsetx_bottom = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_offsety_bot:
|
||||
side->offsety_bot = luaL_checkfixed(L, 3);
|
||||
case side_offsety_bottom:
|
||||
side->offsety_bottom = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_scalex_top:
|
||||
side->scalex_top = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_scaley_top:
|
||||
side->scaley_top = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_scalex_mid:
|
||||
side->scalex_mid = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_scaley_mid:
|
||||
side->scaley_mid = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_scalex_bottom:
|
||||
side->scalex_bottom = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_scaley_bottom:
|
||||
side->scaley_bottom = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case side_toptexture:
|
||||
side->toptexture = luaL_checkinteger(L, 3);
|
||||
|
@ -2122,6 +2214,18 @@ static int ffloor_get(lua_State *L)
|
|||
case ffloor_toplightlevel:
|
||||
lua_pushinteger(L, *ffloor->toplightlevel);
|
||||
return 1;
|
||||
case ffloor_topxoffs:
|
||||
lua_pushfixed(L, *ffloor->topxoffs);
|
||||
return 1;
|
||||
case ffloor_topyoffs:
|
||||
lua_pushfixed(L, *ffloor->topyoffs);
|
||||
return 1;
|
||||
case ffloor_topxscale:
|
||||
lua_pushfixed(L, *ffloor->topxscale);
|
||||
return 1;
|
||||
case ffloor_topyscale:
|
||||
lua_pushfixed(L, *ffloor->topyscale);
|
||||
return 1;
|
||||
case ffloor_bottomheight:
|
||||
lua_pushfixed(L, *ffloor->bottomheight);
|
||||
return 1;
|
||||
|
@ -2133,6 +2237,18 @@ static int ffloor_get(lua_State *L)
|
|||
lua_pushlstring(L, levelflat->name, i);
|
||||
return 1;
|
||||
}
|
||||
case ffloor_bottomxoffs:
|
||||
lua_pushfixed(L, *ffloor->bottomxoffs);
|
||||
return 1;
|
||||
case ffloor_bottomyoffs:
|
||||
lua_pushfixed(L, *ffloor->bottomyoffs);
|
||||
return 1;
|
||||
case ffloor_bottomxscale:
|
||||
lua_pushfixed(L, *ffloor->bottomxscale);
|
||||
return 1;
|
||||
case ffloor_bottomyscale:
|
||||
lua_pushfixed(L, *ffloor->bottomyscale);
|
||||
return 1;
|
||||
case ffloor_tslope:
|
||||
LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE);
|
||||
return 1;
|
||||
|
@ -2317,6 +2433,18 @@ static int ffloor_set(lua_State *L)
|
|||
case ffloor_toplightlevel:
|
||||
*ffloor->toplightlevel = (INT16)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case ffloor_topxoffs:
|
||||
*ffloor->topxoffs = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_topyoffs:
|
||||
*ffloor->topyoffs = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_topxscale:
|
||||
*ffloor->topxscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_topyscale:
|
||||
*ffloor->topyscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_bottomheight: { // bottomheight
|
||||
boolean flag;
|
||||
fixed_t lastpos = *ffloor->bottomheight;
|
||||
|
@ -2335,6 +2463,18 @@ static int ffloor_set(lua_State *L)
|
|||
case ffloor_bottompic:
|
||||
*ffloor->bottompic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
|
||||
break;
|
||||
case ffloor_bottomxoffs:
|
||||
*ffloor->bottomxoffs = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_bottomyoffs:
|
||||
*ffloor->bottomyoffs = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_bottomxscale:
|
||||
*ffloor->bottomxscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_bottomyscale:
|
||||
*ffloor->bottomyscale = luaL_checkfixed(L, 3);
|
||||
break;
|
||||
case ffloor_fofflags: {
|
||||
ffloortype_e oldflags = ffloor->fofflags; // store FOF's old flags
|
||||
ffloor->fofflags = luaL_checkinteger(L, 3);
|
||||
|
@ -2843,170 +2983,36 @@ static int mapheaderinfo_get(lua_State *L)
|
|||
|
||||
int LUA_MapLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_SECTORLINES);
|
||||
lua_pushcfunction(L, sectorlines_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, sectorlines_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_SECTOR);
|
||||
lua_pushcfunction(L, sector_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, sector_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, sector_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
LUA_RegisterUserdataMetatable(L, META_SECTORLINES, sectorlines_get, NULL, sectorlines_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_SECTOR, sector_get, sector_set, sector_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_SUBSECTOR, subsector_get, NULL, subsector_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_LINE, line_get, NULL, line_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_LINEARGS, lineargs_get, NULL, lineargs_len);
|
||||
LUA_RegisterUserdataMetatable(L, META_LINESTRINGARGS, linestringargs_get, NULL, linestringargs_len);
|
||||
LUA_RegisterUserdataMetatable(L, META_SIDENUM, sidenum_get, NULL, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_SIDE, side_get, side_set, side_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_VERTEX, vertex_get, NULL, vertex_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_FFLOOR, ffloor_get, ffloor_set, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_BBOX, bbox_get, NULL, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_SLOPE, slope_get, slope_set, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_VECTOR2, vector2_get, NULL, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_VECTOR3, vector3_get, NULL, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_MAPHEADER, mapheaderinfo_get, NULL, NULL);
|
||||
|
||||
sector_fields_ref = Lua_CreateFieldTable(L, sector_opt);
|
||||
|
||||
luaL_newmetatable(L, META_SUBSECTOR);
|
||||
lua_pushcfunction(L, subsector_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, subsector_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
subsector_fields_ref = Lua_CreateFieldTable(L, subsector_opt);
|
||||
|
||||
luaL_newmetatable(L, META_LINE);
|
||||
lua_pushcfunction(L, line_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, line_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
line_fields_ref = Lua_CreateFieldTable(L, line_opt);
|
||||
|
||||
luaL_newmetatable(L, META_LINEARGS);
|
||||
lua_pushcfunction(L, lineargs_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lineargs_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_LINESTRINGARGS);
|
||||
lua_pushcfunction(L, linestringargs_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, linestringargs_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_SIDENUM);
|
||||
lua_pushcfunction(L, sidenum_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_SIDE);
|
||||
lua_pushcfunction(L, side_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, side_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, side_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
side_fields_ref = Lua_CreateFieldTable(L, side_opt);
|
||||
|
||||
luaL_newmetatable(L, META_VERTEX);
|
||||
lua_pushcfunction(L, vertex_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, vertex_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
vertex_fields_ref = Lua_CreateFieldTable(L, vertex_opt);
|
||||
|
||||
luaL_newmetatable(L, META_FFLOOR);
|
||||
lua_pushcfunction(L, ffloor_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, ffloor_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L, 1);
|
||||
|
||||
ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt);
|
||||
|
||||
#ifdef HAVE_LUA_SEGS
|
||||
luaL_newmetatable(L, META_SEG);
|
||||
lua_pushcfunction(L, seg_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, seg_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
seg_fields_ref = Lua_CreateFieldTable(L, seg_opt);
|
||||
|
||||
luaL_newmetatable(L, META_NODE);
|
||||
lua_pushcfunction(L, node_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, node_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
node_fields_ref = Lua_CreateFieldTable(L, node_opt);
|
||||
|
||||
luaL_newmetatable(L, META_NODEBBOX);
|
||||
//lua_pushcfunction(L, nodebbox_get);
|
||||
//lua_setfield(L, -2, "__index");
|
||||
lua_pushcfunction(L, nodebbox_call);
|
||||
lua_setfield(L, -2, "__call");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_NODECHILDREN);
|
||||
lua_pushcfunction(L, nodechildren_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
#endif
|
||||
|
||||
luaL_newmetatable(L, META_BBOX);
|
||||
lua_pushcfunction(L, bbox_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_SLOPE);
|
||||
lua_pushcfunction(L, slope_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, slope_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L, 1);
|
||||
|
||||
slope_fields_ref = Lua_CreateFieldTable(L, slope_opt);
|
||||
|
||||
luaL_newmetatable(L, META_VECTOR2);
|
||||
lua_pushcfunction(L, vector2_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_VECTOR3);
|
||||
lua_pushcfunction(L, vector3_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_MAPHEADER);
|
||||
lua_pushcfunction(L, mapheaderinfo_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
//lua_pushcfunction(L, mapheaderinfo_num);
|
||||
//lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
mapheaderinfo_fields_ref = Lua_CreateFieldTable(L, mapheaderinfo_opt);
|
||||
|
||||
LUA_RegisterGlobalUserdata(L, "subsectors", lib_getSubsector, NULL, lib_numsubsectors);
|
||||
LUA_RegisterGlobalUserdata(L, "sides", lib_getSide, NULL, lib_numsides);
|
||||
LUA_RegisterGlobalUserdata(L, "vertexes", lib_getVertex, NULL, lib_numvertexes);
|
||||
LUA_RegisterGlobalUserdata(L, "mapheaderinfo", lib_getMapheaderinfo, NULL, lib_nummapheaders);
|
||||
|
||||
LUA_PushTaggableObjectArray(L, "sectors",
|
||||
lib_iterateSectors,
|
||||
lib_getSector,
|
||||
|
@ -3015,16 +3021,6 @@ int LUA_MapLib(lua_State *L)
|
|||
&numsectors, §ors,
|
||||
sizeof (sector_t), META_SECTOR);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSubsector);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numsubsectors);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "subsectors");
|
||||
|
||||
LUA_PushTaggableObjectArray(L, "lines",
|
||||
lib_iterateLines,
|
||||
lib_getLine,
|
||||
|
@ -3033,56 +3029,22 @@ int LUA_MapLib(lua_State *L)
|
|||
&numlines, &lines,
|
||||
sizeof (line_t), META_LINE);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSide);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numsides);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "sides");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getVertex);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numvertexes);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "vertexes");
|
||||
|
||||
#ifdef HAVE_LUA_SEGS
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSeg);
|
||||
lua_setfield(L, -2, "__index");
|
||||
LUA_RegisterUserdataMetatable(L, META_SEG, seg_get, NULL, seg_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_NODE, node_get, NULL, node_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_NODECHILDREN, nodechildren_get, NULL, NULL);
|
||||
|
||||
lua_pushcfunction(L, lib_numsegs);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "segs");
|
||||
seg_fields_ref = Lua_CreateFieldTable(L, seg_opt);
|
||||
node_fields_ref = Lua_CreateFieldTable(L, node_opt);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getNode);
|
||||
lua_setfield(L, -2, "__index");
|
||||
luaL_newmetatable(L, META_NODEBBOX);
|
||||
//LUA_SetCFunctionField(L, "__index", nodebbox_get);
|
||||
LUA_SetCFunctionField(L, "__call", nodebbox_call);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_pushcfunction(L, lib_numnodes);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "nodes");
|
||||
LUA_RegisterGlobalUserdata(L, "segs", lib_getSeg, NULL, lib_numsegs);
|
||||
LUA_RegisterGlobalUserdata(L, "nodes", lib_getNode, NULL, lib_numnodes);
|
||||
#endif
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getMapheaderinfo);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_nummapheaders);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "mapheaderinfo");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ static int lib_fixeddiv(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// TODO: 2.3: Delete
|
||||
static int lib_fixedrem(lua_State *L)
|
||||
{
|
||||
LUA_Deprecated(L, "FixedRem(a, b)", "a % b");
|
||||
|
|
|
@ -641,10 +641,7 @@ static int mobj_set(lua_State *L)
|
|||
mo->tics = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case mobj_state: // set state by enum
|
||||
if (mo->player)
|
||||
P_SetPlayerMobjState(mo, luaL_checkinteger(L, 3));
|
||||
else
|
||||
P_SetMobjState(mo, luaL_checkinteger(L, 3));
|
||||
P_SetMobjState(mo, luaL_checkinteger(L, 3));
|
||||
break;
|
||||
case mobj_flags: // special handling for MF_NOBLOCKMAP and MF_NOSECTOR
|
||||
{
|
||||
|
@ -1163,43 +1160,12 @@ static int lib_nummapthings(lua_State *L)
|
|||
|
||||
int LUA_MobjLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_MOBJ);
|
||||
lua_pushcfunction(L, mobj_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, mobj_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
LUA_RegisterUserdataMetatable(L, META_MOBJ, mobj_get, mobj_set, NULL);
|
||||
LUA_RegisterUserdataMetatable(L, META_THINGARGS, thingargs_get, NULL, thingargs_len);
|
||||
LUA_RegisterUserdataMetatable(L, META_THINGSTRINGARGS, thingstringargs_get, NULL, thingstringargs_len);
|
||||
LUA_RegisterUserdataMetatable(L, META_MAPTHING, mapthing_get, mapthing_set, mapthing_num);
|
||||
|
||||
mobj_fields_ref = Lua_CreateFieldTable(L, mobj_opt);
|
||||
|
||||
luaL_newmetatable(L, META_THINGARGS);
|
||||
lua_pushcfunction(L, thingargs_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, thingargs_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_THINGSTRINGARGS);
|
||||
lua_pushcfunction(L, thingstringargs_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, thingstringargs_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_MAPTHING);
|
||||
lua_pushcfunction(L, mapthing_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, mapthing_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, mapthing_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt);
|
||||
|
||||
LUA_PushTaggableObjectArray(L, "mapthings",
|
||||
|
|
|
@ -223,6 +223,7 @@ enum player_e
|
|||
player_blocked,
|
||||
player_jointime,
|
||||
player_quittime,
|
||||
player_lastinputtime,
|
||||
player_ping,
|
||||
#ifdef HWRENDER
|
||||
player_fovadd,
|
||||
|
@ -371,6 +372,7 @@ static const char *const player_opt[] = {
|
|||
"blocked",
|
||||
"jointime",
|
||||
"quittime",
|
||||
"lastinputtime",
|
||||
"ping",
|
||||
#ifdef HWRENDER
|
||||
"fovadd",
|
||||
|
@ -407,7 +409,7 @@ static int player_get(lua_State *L)
|
|||
case player_realmo:
|
||||
LUA_PushUserdata(L, plr->mo, META_MOBJ);
|
||||
break;
|
||||
// Kept for backward-compatibility
|
||||
// TODO: 2.3: Kept for backward-compatibility
|
||||
// Should be fixed to work like "realmo" later
|
||||
case player_mo:
|
||||
if (plr->spectator)
|
||||
|
@ -826,6 +828,9 @@ static int player_get(lua_State *L)
|
|||
case player_quittime:
|
||||
lua_pushinteger(L, plr->quittime);
|
||||
break;
|
||||
case player_lastinputtime:
|
||||
lua_pushinteger(L, plr->lastinputtime);
|
||||
break;
|
||||
case player_ping:
|
||||
lua_pushinteger(L, playerpingtable[plr - players]);
|
||||
break;
|
||||
|
@ -1349,6 +1354,9 @@ static int player_set(lua_State *L)
|
|||
case player_quittime:
|
||||
plr->quittime = (tic_t)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_lastinputtime:
|
||||
plr->lastinputtime = (tic_t)luaL_checkinteger(L, 3);
|
||||
break;
|
||||
#ifdef HWRENDER
|
||||
case player_fovadd:
|
||||
plr->fovadd = luaL_checkfixed(L, 3);
|
||||
|
@ -1523,48 +1531,13 @@ static int ticcmd_set(lua_State *L)
|
|||
|
||||
int LUA_PlayerLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_PLAYER);
|
||||
lua_pushcfunction(L, player_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, player_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, player_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
LUA_RegisterUserdataMetatable(L, META_PLAYER, player_get, player_set, player_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_POWERS, power_get, power_set, power_len);
|
||||
LUA_RegisterUserdataMetatable(L, META_TICCMD, ticcmd_get, ticcmd_set, NULL);
|
||||
|
||||
player_fields_ref = Lua_CreateFieldTable(L, player_opt);
|
||||
|
||||
luaL_newmetatable(L, META_POWERS);
|
||||
lua_pushcfunction(L, power_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, power_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, power_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_TICCMD);
|
||||
lua_pushcfunction(L, ticcmd_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, ticcmd_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
lua_pop(L,1);
|
||||
|
||||
ticcmd_fields_ref = Lua_CreateFieldTable(L, ticcmd_opt);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getPlayer);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_lenPlayer);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "players");
|
||||
LUA_RegisterGlobalUserdata(L, "players", lib_getPlayer, NULL, lib_lenPlayer);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -447,41 +447,10 @@ static int lib_numPolyObjects(lua_State *L)
|
|||
|
||||
int LUA_PolyObjLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_POLYOBJVERTICES);
|
||||
lua_pushcfunction(L, polyobjvertices_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
LUA_RegisterUserdataMetatable(L, META_POLYOBJVERTICES, polyobjvertices_get, NULL, polyobjvertices_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_POLYOBJLINES, polyobjlines_get, NULL, polyobjlines_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_POLYOBJ, polyobj_get, polyobj_set, polyobj_num);
|
||||
|
||||
lua_pushcfunction(L, polyobjvertices_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_POLYOBJLINES);
|
||||
lua_pushcfunction(L, polyobjlines_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, polyobjlines_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_POLYOBJ);
|
||||
lua_pushcfunction(L, polyobj_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, polyobj_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, polyobj_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getPolyObject);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numPolyObjects);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "polyobjects");
|
||||
LUA_RegisterGlobalUserdata(L, "polyobjects", lib_getPolyObject, NULL, lib_numPolyObjects);
|
||||
return 0;
|
||||
}
|
||||
|
|
195
src/lua_script.c
195
src/lua_script.c
|
@ -28,7 +28,7 @@
|
|||
#include "p_slopes.h" // for P_SlopeById and slopelist
|
||||
#include "p_polyobj.h" // polyobj_t, PolyObjects
|
||||
#ifdef LUA_ALLOW_BYTECODE
|
||||
#include "d_netfil.h" // for LUA_DumpFile
|
||||
#include "netcode/d_netfil.h" // for LUA_DumpFile
|
||||
#endif
|
||||
|
||||
#include "lua_script.h"
|
||||
|
@ -58,6 +58,7 @@ static lua_CFunction liblist[] = {
|
|||
LUA_PolyObjLib, // polyobj_t
|
||||
LUA_BlockmapLib, // blockmap stuff
|
||||
LUA_HudLib, // HUD stuff
|
||||
LUA_ColorLib, // general color functions
|
||||
LUA_InputLib, // inputs
|
||||
NULL
|
||||
};
|
||||
|
@ -415,9 +416,11 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word, "stagefailed")) {
|
||||
lua_pushboolean(L, stagefailed);
|
||||
return 1;
|
||||
// TODO: 2.3: Deprecated (moved to the input library)
|
||||
} else if (fastcmp(word, "mouse")) {
|
||||
LUA_PushUserdata(L, &mouse, META_MOUSE);
|
||||
return 1;
|
||||
// TODO: 2.3: Deprecated (moved to the input library)
|
||||
} else if (fastcmp(word, "mouse2")) {
|
||||
LUA_PushUserdata(L, &mouse2, META_MOUSE);
|
||||
return 1;
|
||||
|
@ -576,8 +579,7 @@ static void LUA_ClearState(void)
|
|||
|
||||
// lock the global namespace
|
||||
lua_getmetatable(L, LUA_GLOBALSINDEX);
|
||||
lua_pushcfunction(L, setglobals);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
LUA_SetCFunctionField(L, "__newindex", setglobals);
|
||||
lua_newtable(L);
|
||||
lua_setfield(L, -2, "__metatable");
|
||||
lua_pop(L, 1);
|
||||
|
@ -602,64 +604,114 @@ void LUA_ClearExtVars(void)
|
|||
INT32 lua_lumploading = 0;
|
||||
|
||||
// Load a script from a MYFILE
|
||||
static inline void LUA_LoadFile(MYFILE *f, char *name, boolean noresults)
|
||||
static inline boolean LUA_LoadFile(MYFILE *f, char *name)
|
||||
{
|
||||
int errorhandlerindex;
|
||||
boolean success;
|
||||
|
||||
if (!name)
|
||||
name = wadfiles[f->wad]->filename;
|
||||
|
||||
CONS_Printf("Loading Lua script from %s\n", name);
|
||||
|
||||
if (!gL) // Lua needs to be initialized
|
||||
LUA_ClearState();
|
||||
|
||||
lua_pushinteger(gL, f->wad);
|
||||
lua_setfield(gL, LUA_REGISTRYINDEX, "WAD");
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
errorhandlerindex = lua_gettop(gL);
|
||||
|
||||
success = !luaL_loadbuffer(gL, f->data, f->size, va("@%s",name));
|
||||
|
||||
if (!success) {
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
||||
lua_pop(gL,1);
|
||||
}
|
||||
|
||||
lua_gc(gL, LUA_GCCOLLECT, 0);
|
||||
lua_remove(gL, errorhandlerindex);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Runs a script loaded by LUA_LoadFile.
|
||||
static inline void LUA_DoFile(boolean noresults)
|
||||
{
|
||||
int errorhandlerindex;
|
||||
|
||||
if (!gL) // LUA_LoadFile should've allocated gL for us!
|
||||
return;
|
||||
|
||||
lua_lumploading++; // turn on loading flag
|
||||
|
||||
lua_pushcfunction(gL, LUA_GetErrorMessage);
|
||||
errorhandlerindex = lua_gettop(gL);
|
||||
if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, noresults ? 0 : LUA_MULTRET, lua_gettop(gL) - 1)) {
|
||||
lua_insert(gL, -2); // move the function we're calling to the top.
|
||||
errorhandlerindex = lua_gettop(gL) - 1;
|
||||
|
||||
if (lua_pcall(gL, 0, noresults ? 0 : LUA_MULTRET, lua_gettop(gL) - 1)) {
|
||||
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
|
||||
lua_pop(gL,1);
|
||||
}
|
||||
|
||||
lua_gc(gL, LUA_GCCOLLECT, 0);
|
||||
lua_remove(gL, errorhandlerindex);
|
||||
|
||||
lua_lumploading--; // turn off again
|
||||
}
|
||||
|
||||
// Load a script from a lump
|
||||
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults)
|
||||
static inline MYFILE *LUA_GetFile(UINT16 wad, UINT16 lump, char **name)
|
||||
{
|
||||
MYFILE f;
|
||||
char *name;
|
||||
MYFILE *f = Z_Malloc(sizeof(MYFILE), PU_LUA, NULL);
|
||||
size_t len;
|
||||
f.wad = wad;
|
||||
f.size = W_LumpLengthPwad(wad, lump);
|
||||
f.data = Z_Malloc(f.size, PU_LUA, NULL);
|
||||
W_ReadLumpPwad(wad, lump, f.data);
|
||||
f.curpos = f.data;
|
||||
|
||||
f->wad = wad;
|
||||
f->size = W_LumpLengthPwad(wad, lump);
|
||||
f->data = Z_Malloc(f->size, PU_LUA, NULL);
|
||||
W_ReadLumpPwad(wad, lump, f->data);
|
||||
f->curpos = f->data;
|
||||
|
||||
len = strlen(wadfiles[wad]->filename); // length of file name
|
||||
|
||||
if (wadfiles[wad]->type == RET_LUA)
|
||||
{
|
||||
name = malloc(len+1);
|
||||
strcpy(name, wadfiles[wad]->filename);
|
||||
*name = malloc(len+1);
|
||||
strcpy(*name, wadfiles[wad]->filename);
|
||||
}
|
||||
else // If it's not a .lua file, copy the lump name in too.
|
||||
{
|
||||
lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump];
|
||||
len += 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
|
||||
name = malloc(len+1);
|
||||
sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname);
|
||||
name[len] = '\0';
|
||||
*name = malloc(len+1);
|
||||
sprintf(*name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname);
|
||||
(*name)[len] = '\0'; // annoying that index takes priority over dereference, but w/e
|
||||
}
|
||||
|
||||
LUA_LoadFile(&f, name, noresults); // actually load file!
|
||||
return f;
|
||||
}
|
||||
|
||||
// Load a script from a lump
|
||||
boolean LUA_LoadLump(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
char *name = NULL;
|
||||
MYFILE *f = LUA_GetFile(wad, lump, &name);
|
||||
boolean success = LUA_LoadFile(f, name); // actually load file!
|
||||
|
||||
free(name);
|
||||
Z_Free(f.data);
|
||||
|
||||
Z_Free(f->data);
|
||||
Z_Free(f);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void LUA_DoLump(UINT16 wad, UINT16 lump, boolean noresults)
|
||||
{
|
||||
boolean success = LUA_LoadLump(wad, lump);
|
||||
|
||||
if (success)
|
||||
LUA_DoFile(noresults); // run it
|
||||
}
|
||||
|
||||
#ifdef LUA_ALLOW_BYTECODE
|
||||
|
@ -1813,20 +1865,107 @@ void LUA_PushTaggableObjectArray
|
|||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, iterator);
|
||||
lua_setfield(L, -2, "iterate");
|
||||
LUA_SetCFunctionField(L, "iterate", iterator);
|
||||
|
||||
LUA_InsertTaggroupIterator(L, garray,
|
||||
max_elements, element_array, sizeof_element, meta);
|
||||
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushcfunction(L, indexer);
|
||||
lua_setfield(L, -2, "__index");
|
||||
LUA_SetCFunctionField(L, "__index", indexer);
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, counter);
|
||||
lua_setfield(L, -2, "__len");
|
||||
LUA_SetCFunctionField(L, "__len", counter);
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, field);
|
||||
}
|
||||
|
||||
static void SetBasicMetamethods(
|
||||
lua_State *L,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
)
|
||||
{
|
||||
if (get)
|
||||
LUA_SetCFunctionField(L, "__index", get);
|
||||
if (set)
|
||||
LUA_SetCFunctionField(L, "__newindex", set);
|
||||
if (len)
|
||||
LUA_SetCFunctionField(L, "__len", len);
|
||||
}
|
||||
|
||||
void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value)
|
||||
{
|
||||
lua_pushcfunction(L, value);
|
||||
lua_setfield(L, -2, name);
|
||||
}
|
||||
|
||||
void LUA_RegisterUserdataMetatable(
|
||||
lua_State *L,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
)
|
||||
{
|
||||
luaL_newmetatable(L, name);
|
||||
SetBasicMetamethods(L, get, set, len);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// If keep is true, leaves the metatable on the stack.
|
||||
// Otherwise, the stack size remains unchanged.
|
||||
void LUA_CreateAndSetMetatable(
|
||||
lua_State *L,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len,
|
||||
boolean keep
|
||||
)
|
||||
{
|
||||
lua_newtable(L);
|
||||
SetBasicMetamethods(L, get, set, len);
|
||||
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setmetatable(L, -3);
|
||||
|
||||
if (!keep)
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
// If keep is true, leaves the userdata and metatable on the stack.
|
||||
// Otherwise, the stack size remains unchanged.
|
||||
void LUA_CreateAndSetUserdataField(
|
||||
lua_State *L,
|
||||
int index,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len,
|
||||
boolean keep
|
||||
)
|
||||
{
|
||||
if (index < 0 && index > LUA_REGISTRYINDEX)
|
||||
index -= 3;
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
LUA_CreateAndSetMetatable(L, get, set, len, true);
|
||||
|
||||
lua_pushvalue(L, -2);
|
||||
lua_setfield(L, index, name);
|
||||
|
||||
if (!keep)
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
|
||||
void LUA_RegisterGlobalUserdata(
|
||||
lua_State *L,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
)
|
||||
{
|
||||
LUA_CreateAndSetUserdataField(L, LUA_GLOBALSINDEX, name, get, set, len, false);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ extern INT32 lua_lumploading; // is LUA_LoadLump being called?
|
|||
|
||||
int LUA_GetErrorMessage(lua_State *L);
|
||||
int LUA_Call(lua_State *L, int nargs, int nresults, int errorhandlerindex);
|
||||
void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults);
|
||||
boolean LUA_LoadLump(UINT16 wad, UINT16 lump);
|
||||
void LUA_DoLump(UINT16 wad, UINT16 lump, boolean noresults);
|
||||
#ifdef LUA_ALLOW_BYTECODE
|
||||
void LUA_DumpFile(const char *filename);
|
||||
#endif
|
||||
|
@ -73,6 +74,42 @@ void LUA_PushTaggableObjectArray
|
|||
size_t sizeof_element,
|
||||
const char *meta);
|
||||
|
||||
void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value);
|
||||
|
||||
void LUA_RegisterUserdataMetatable(
|
||||
lua_State *L,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
);
|
||||
|
||||
void LUA_CreateAndSetMetatable(
|
||||
lua_State *L,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len,
|
||||
boolean keep
|
||||
);
|
||||
|
||||
void LUA_CreateAndSetUserdataField(
|
||||
lua_State *L,
|
||||
int index,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len,
|
||||
boolean keep
|
||||
);
|
||||
|
||||
void LUA_RegisterGlobalUserdata(
|
||||
lua_State *L,
|
||||
const char *name,
|
||||
lua_CFunction get,
|
||||
lua_CFunction set,
|
||||
lua_CFunction len
|
||||
);
|
||||
|
||||
void LUA_InsertTaggroupIterator
|
||||
( lua_State *L,
|
||||
taggroup_t *garray[],
|
||||
|
|
|
@ -373,49 +373,14 @@ static int sprite_get(lua_State *L)
|
|||
|
||||
int LUA_SkinLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_SKIN);
|
||||
lua_pushcfunction(L, skin_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, skin_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, skin_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
LUA_RegisterUserdataMetatable(L, META_SKIN, skin_get, skin_set, skin_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_SOUNDSID, soundsid_get, NULL, soundsid_num);
|
||||
LUA_RegisterUserdataMetatable(L, META_SKINSPRITES, lib_getSkinSprite, NULL, lib_numSkinsSprites);
|
||||
LUA_RegisterUserdataMetatable(L, META_SKINSPRITESLIST, sprite_get, NULL, NULL);
|
||||
|
||||
skin_fields_ref = Lua_CreateFieldTable(L, skin_opt);
|
||||
|
||||
luaL_newmetatable(L, META_SOUNDSID);
|
||||
lua_pushcfunction(L, soundsid_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, soundsid_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_SKINSPRITES);
|
||||
lua_pushcfunction(L, lib_getSkinSprite);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numSkinsSprites);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L,1);
|
||||
|
||||
luaL_newmetatable(L, META_SKINSPRITESLIST);
|
||||
lua_pushcfunction(L, sprite_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L,1);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSkin);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numSkins);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "skins");
|
||||
LUA_RegisterGlobalUserdata(L, "skins", lib_getSkin, NULL, lib_numSkins);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -228,7 +228,7 @@ static int taglist_get(lua_State *L)
|
|||
}
|
||||
else
|
||||
{
|
||||
lua_getmetatable(L, 1);
|
||||
lua_getglobal(L, "taglist");
|
||||
lua_replace(L, 1);
|
||||
lua_rawget(L, 1);
|
||||
return 1;
|
||||
|
@ -372,8 +372,7 @@ void LUA_InsertTaggroupIterator
|
|||
lua_pushcclosure(L, lib_numTaggroupElements, 2);
|
||||
lua_setfield(L, -2, "__len");
|
||||
|
||||
lua_pushcfunction(L, element_iterator);
|
||||
lua_setfield(L, -2, "__call");
|
||||
LUA_SetCFunctionField(L, "__call", element_iterator);
|
||||
lua_pushcclosure(L, lib_getTaggroup, 1);
|
||||
lua_setfield(L, -2, "tagged");
|
||||
}
|
||||
|
@ -414,11 +413,9 @@ set_taglist_metatable(lua_State *L, const char *meta)
|
|||
lua_setfenv(L, -2);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, taglist_len);
|
||||
lua_setfield(L, -2, "__len");
|
||||
LUA_SetCFunctionField(L, "__len", taglist_len);
|
||||
|
||||
lua_pushcfunction(L, taglist_equal);
|
||||
lua_setfield(L, -2, "__eq");
|
||||
LUA_SetCFunctionField(L, "__eq", taglist_equal);
|
||||
#ifdef MUTABLE_TAGS
|
||||
return luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
#endif
|
||||
|
@ -426,17 +423,11 @@ set_taglist_metatable(lua_State *L, const char *meta)
|
|||
|
||||
int LUA_TagLib(lua_State *L)
|
||||
{
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_createtable(L, 0, 1);
|
||||
lua_pushcfunction(L, lib_iterateTags);
|
||||
lua_setfield(L, -2, "iterate");
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_numTags);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "tags");
|
||||
LUA_CreateAndSetUserdataField(L, LUA_GLOBALSINDEX, "tags", NULL, NULL, lib_numTags, true);
|
||||
lua_createtable(L, 0, 1);
|
||||
LUA_SetCFunctionField(L, "iterate", lib_iterateTags);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 2);
|
||||
|
||||
open_taglist(L);
|
||||
|
||||
|
|
|
@ -127,8 +127,7 @@ static int lib_startIterate(lua_State *L)
|
|||
int LUA_ThinkerLib(lua_State *L)
|
||||
{
|
||||
luaL_newmetatable(L, META_ITERATIONSTATE);
|
||||
lua_pushcfunction(L, iterationState_gc);
|
||||
lua_setfield(L, -2, "__gc");
|
||||
LUA_SetCFunctionField(L, "__gc", iterationState_gc);
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_createtable(L, 0, 1);
|
||||
|
|
|
@ -463,7 +463,7 @@ static void GIF_headwrite(void)
|
|||
// Image width/height
|
||||
if (gif_downscale)
|
||||
{
|
||||
scrbuf_downscaleamt = vid.dupx;
|
||||
scrbuf_downscaleamt = vid.dup;
|
||||
rwidth = (vid.width / scrbuf_downscaleamt);
|
||||
rheight = (vid.height / scrbuf_downscaleamt);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "r_local.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "d_net.h"
|
||||
#include "netcode/d_net.h"
|
||||
|
||||
#include "m_cheat.h"
|
||||
#include "m_menu.h"
|
||||
|
@ -1019,7 +1019,7 @@ static void OP_CycleThings(INT32 amt)
|
|||
if (players[0].mo->eflags & MFE_VERTICALFLIP) // correct z when flipped
|
||||
players[0].mo->z += players[0].mo->height - FixedMul(mobjinfo[op_currentthing].height, players[0].mo->scale);
|
||||
players[0].mo->height = FixedMul(mobjinfo[op_currentthing].height, players[0].mo->scale);
|
||||
P_SetPlayerMobjState(players[0].mo, S_OBJPLACE_DUMMY);
|
||||
P_SetMobjState(players[0].mo, S_OBJPLACE_DUMMY);
|
||||
|
||||
op_currentdoomednum = mobjinfo[op_currentthing].doomednum;
|
||||
}
|
||||
|
@ -1528,7 +1528,7 @@ void Command_ObjectPlace_f(void)
|
|||
else
|
||||
OP_CycleThings(0); // sets all necessary height values without cycling op_currentthing
|
||||
|
||||
P_SetPlayerMobjState(players[0].mo, S_OBJPLACE_DUMMY);
|
||||
P_SetMobjState(players[0].mo, S_OBJPLACE_DUMMY);
|
||||
}
|
||||
// Or are we leaving it instead?
|
||||
else
|
||||
|
@ -1542,7 +1542,7 @@ void Command_ObjectPlace_f(void)
|
|||
|
||||
// If still in dummy state, get out of it.
|
||||
if (players[0].mo->state == &states[S_OBJPLACE_DUMMY])
|
||||
P_SetPlayerMobjState(players[0].mo, op_oldstate);
|
||||
P_SetMobjState(players[0].mo, op_oldstate);
|
||||
|
||||
// Reset everything back to how it was before we entered objectplace.
|
||||
P_UnsetThingPosition(players[0].mo);
|
||||
|
|
|
@ -509,7 +509,7 @@ UINT8 M_CampaignWarpIsCheat(INT32 gt, INT32 mapnum, gamedata_t *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
if (mapheaderinfo[mapnum-1]->menuflags & LF2_HIDEINMENU)
|
||||
if (!mapheaderinfo[mapnum-1] || mapheaderinfo[mapnum-1]->menuflags & LF2_HIDEINMENU)
|
||||
{
|
||||
// You're never allowed to warp to this level.
|
||||
return true;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
*/
|
||||
|
||||
typedef INT32 fixed_t;
|
||||
typedef UINT32 ufixed_t;
|
||||
|
||||
/*!
|
||||
\brief convert fixed_t into floating number
|
||||
|
@ -106,7 +107,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedInt(fixed_t a)
|
|||
*/
|
||||
FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedDiv(fixed_t a, fixed_t b)
|
||||
{
|
||||
if ((abs(a) >> (FRACBITS-2)) >= abs(b))
|
||||
if (((ufixed_t)abs(a) >> (FRACBITS-2)) >= (ufixed_t)abs(b))
|
||||
return (a^b) < 0 ? INT32_MIN : INT32_MAX;
|
||||
|
||||
return FixedDiv2(a, b);
|
||||
|
|
372
src/m_menu.c
372
src/m_menu.c
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "doomdef.h"
|
||||
#include "d_main.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "netcode/d_netcmd.h"
|
||||
#include "console.h"
|
||||
#include "r_fps.h"
|
||||
#include "r_local.h"
|
||||
|
@ -53,8 +53,10 @@
|
|||
#include "hardware/hw_main.h"
|
||||
#endif
|
||||
|
||||
#include "d_net.h"
|
||||
#include "mserv.h"
|
||||
#include "netcode/d_net.h"
|
||||
#include "netcode/mserv.h"
|
||||
#include "netcode/server_connection.h"
|
||||
#include "netcode/client_connection.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_anigif.h"
|
||||
#include "byteptr.h"
|
||||
|
@ -149,9 +151,7 @@ levellist_mode_t levellistmode = LLM_CREATESERVER;
|
|||
UINT8 maplistoption = 0;
|
||||
|
||||
static char joystickInfo[MAX_JOYSTICKS+1][29];
|
||||
#ifndef NONET
|
||||
static UINT32 serverlistpage;
|
||||
#endif
|
||||
|
||||
static UINT8 numsaves = 0;
|
||||
static saveinfo_t* savegameinfo = NULL; // Extra info about the save games.
|
||||
|
@ -190,10 +190,8 @@ static void M_GoBack(INT32 choice);
|
|||
static void M_StopMessage(INT32 choice);
|
||||
static boolean stopstopmessage = false;
|
||||
|
||||
#ifndef NONET
|
||||
static void M_HandleServerPage(INT32 choice);
|
||||
static void M_RoomMenu(INT32 choice);
|
||||
#endif
|
||||
|
||||
// Prototyping is fun, innit?
|
||||
// ==========================================================================
|
||||
|
@ -216,7 +214,7 @@ static fixed_t lsoffs[2];
|
|||
#define lshli levelselectselect[2]
|
||||
|
||||
#define lshseperation 101
|
||||
#define lsbasevseperation ((62*vid.height)/(BASEVIDHEIGHT*vid.dupy)) //62
|
||||
#define lsbasevseperation ((62*vid.height)/(BASEVIDHEIGHT*vid.dup)) //62
|
||||
#define lsheadingheight 16
|
||||
#define getheadingoffset(row) (levelselect.rows[row].header[0] ? lsheadingheight : 0)
|
||||
#define lsvseperation(row) (lsbasevseperation + getheadingoffset(row))
|
||||
|
@ -296,7 +294,6 @@ static void M_SetupMultiPlayer2(INT32 choice);
|
|||
static void M_StartSplitServerMenu(INT32 choice);
|
||||
static void M_StartServer(INT32 choice);
|
||||
static void M_ServerOptions(INT32 choice);
|
||||
#ifndef NONET
|
||||
static void M_StartServerMenu(INT32 choice);
|
||||
static void M_ConnectMenu(INT32 choice);
|
||||
static void M_ConnectMenuModChecks(INT32 choice);
|
||||
|
@ -304,7 +301,6 @@ static void M_Refresh(INT32 choice);
|
|||
static void M_Connect(INT32 choice);
|
||||
static void M_ChooseRoom(INT32 choice);
|
||||
menu_t MP_MainDef;
|
||||
#endif
|
||||
|
||||
// Options
|
||||
// Split into multiple parts due to size
|
||||
|
@ -382,11 +378,9 @@ static void M_DrawVideoMode(void);
|
|||
static void M_DrawColorMenu(void);
|
||||
static void M_DrawScreenshotMenu(void);
|
||||
static void M_DrawMonitorToggles(void);
|
||||
#ifndef NONET
|
||||
static void M_DrawConnectMenu(void);
|
||||
static void M_DrawMPMainMenu(void);
|
||||
static void M_DrawRoomMenu(void);
|
||||
#endif
|
||||
static void M_DrawJoystick(void);
|
||||
static void M_DrawSetupMultiPlayerMenu(void);
|
||||
static void M_DrawColorRamp(INT32 x, INT32 y, INT32 w, INT32 h, skincolor_t color);
|
||||
|
@ -401,10 +395,8 @@ static void M_HandleImageDef(INT32 choice);
|
|||
static void M_HandleLoadSave(INT32 choice);
|
||||
static void M_HandleLevelStats(INT32 choice);
|
||||
static void M_HandlePlaystyleMenu(INT32 choice);
|
||||
#ifndef NONET
|
||||
static boolean M_CancelConnect(void);
|
||||
static void M_HandleConnectIP(INT32 choice);
|
||||
#endif
|
||||
static void M_HandleSetupMultiPlayer(INT32 choice);
|
||||
static void M_HandleVideoMode(INT32 choice);
|
||||
|
||||
|
@ -503,11 +495,7 @@ consvar_t cv_dummyloadless = CVAR_INIT ("dummyloadless", "In-game", CV_HIDEN, lo
|
|||
static menuitem_t MainMenu[] =
|
||||
{
|
||||
{IT_STRING|IT_CALL, NULL, "1 Player", M_SinglePlayerMenu, 76},
|
||||
#ifndef NONET
|
||||
{IT_STRING|IT_SUBMENU, NULL, "Multiplayer", &MP_MainDef, 84},
|
||||
#else
|
||||
{IT_STRING|IT_CALL, NULL, "Multiplayer", M_StartSplitServerMenu, 84},
|
||||
#endif
|
||||
{IT_STRING|IT_CALL, NULL, "Extras", M_SecretsMenu, 92},
|
||||
{IT_CALL |IT_STRING, NULL, "Addons", M_Addons, 100},
|
||||
{IT_STRING|IT_CALL, NULL, "Options", M_Options, 108},
|
||||
|
@ -930,16 +918,10 @@ static menuitem_t SP_PlayerMenu[] =
|
|||
static menuitem_t MP_SplitServerMenu[] =
|
||||
{
|
||||
{IT_STRING|IT_CALL, NULL, "Select Gametype/Level...", M_MapChange, 100},
|
||||
#ifdef NONET // In order to keep player setup accessible.
|
||||
{IT_STRING|IT_CALL, NULL, "Player 1 setup...", M_SetupMultiPlayer, 110},
|
||||
{IT_STRING|IT_CALL, NULL, "Player 2 setup...", M_SetupMultiPlayer2, 120},
|
||||
#endif
|
||||
{IT_STRING|IT_CALL, NULL, "More Options...", M_ServerOptions, 130},
|
||||
{IT_WHITESTRING|IT_CALL, NULL, "Start", M_StartServer, 140},
|
||||
};
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
static menuitem_t MP_MainMenu[] =
|
||||
{
|
||||
{IT_HEADER, NULL, "Join a game", NULL, 0},
|
||||
|
@ -1026,8 +1008,6 @@ menuitem_t MP_RoomMenu[] =
|
|||
{IT_DISABLED, NULL, "", M_ChooseRoom, 162},
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
static menuitem_t MP_PlayerSetupMenu[] =
|
||||
{
|
||||
{IT_KEYHANDLER, NULL, "", M_HandleSetupMultiPlayer, 0}, // name
|
||||
|
@ -1088,6 +1068,7 @@ static menuitem_t OP_ChangeControlsMenu[] =
|
|||
{IT_CALL | IT_STRING2, NULL, "Move Right", M_ChangeControl, GC_STRAFERIGHT },
|
||||
{IT_CALL | IT_STRING2, NULL, "Jump", M_ChangeControl, GC_JUMP },
|
||||
{IT_CALL | IT_STRING2, NULL, "Spin", M_ChangeControl, GC_SPIN },
|
||||
{IT_CALL | IT_STRING2, NULL, "Shield", M_ChangeControl, GC_SHIELD },
|
||||
{IT_HEADER, NULL, "Camera", NULL, 0},
|
||||
{IT_SPACE, NULL, NULL, NULL, 0}, // padding
|
||||
{IT_CALL | IT_STRING2, NULL, "Look Up", M_ChangeControl, GC_LOOKUP },
|
||||
|
@ -1587,14 +1568,12 @@ enum
|
|||
static menuitem_t OP_ServerOptionsMenu[] =
|
||||
{
|
||||
{IT_HEADER, NULL, "General", NULL, 0},
|
||||
#ifndef NONET
|
||||
{IT_STRING | IT_CVAR | IT_CV_STRING,
|
||||
NULL, "Server name", &cv_servername, 7},
|
||||
{IT_STRING | IT_CVAR, NULL, "Max Players", &cv_maxplayers, 21},
|
||||
{IT_STRING | IT_CVAR, NULL, "Allow Add-on Downloading", &cv_downloading, 26},
|
||||
{IT_STRING | IT_CVAR, NULL, "Allow players to join", &cv_allownewplayer, 31},
|
||||
{IT_STRING | IT_CVAR, NULL, "Minutes for reconnecting", &cv_rejointimeout, 36},
|
||||
#endif
|
||||
{IT_STRING | IT_CVAR, NULL, "Map progression", &cv_advancemap, 41},
|
||||
{IT_STRING | IT_CVAR, NULL, "Intermission Timer", &cv_inttime, 46},
|
||||
|
||||
|
@ -1633,7 +1612,6 @@ static menuitem_t OP_ServerOptionsMenu[] =
|
|||
{IT_STRING | IT_CVAR, NULL, "Autobalance sizes", &cv_autobalance, 216},
|
||||
{IT_STRING | IT_CVAR, NULL, "Scramble on Map Change", &cv_scrambleonchange, 221},
|
||||
|
||||
#ifndef NONET
|
||||
{IT_HEADER, NULL, "Advanced", NULL, 230},
|
||||
{IT_STRING | IT_CVAR | IT_CV_STRING, NULL, "Master server", &cv_masterserver, 236},
|
||||
|
||||
|
@ -1641,7 +1619,6 @@ static menuitem_t OP_ServerOptionsMenu[] =
|
|||
{IT_STRING | IT_CVAR, NULL, "Attempts to resynchronise", &cv_resynchattempts, 256},
|
||||
|
||||
{IT_STRING | IT_CVAR, NULL, "Show IP Address of Joiners", &cv_showjoinaddress, 261},
|
||||
#endif
|
||||
};
|
||||
|
||||
static menuitem_t OP_MonitorToggleMenu[] =
|
||||
|
@ -1955,11 +1932,7 @@ menu_t MP_SplitServerDef =
|
|||
MTREE2(MN_MP_MAIN, MN_MP_SPLITSCREEN),
|
||||
"M_MULTI",
|
||||
sizeof (MP_SplitServerMenu)/sizeof (menuitem_t),
|
||||
#ifndef NONET
|
||||
&MP_MainDef,
|
||||
#else
|
||||
&MainDef,
|
||||
#endif
|
||||
MP_SplitServerMenu,
|
||||
M_DrawServerMenu,
|
||||
27, 30 - 50,
|
||||
|
@ -1967,8 +1940,6 @@ menu_t MP_SplitServerDef =
|
|||
NULL
|
||||
};
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
menu_t MP_MainDef =
|
||||
{
|
||||
MN_MP_MAIN,
|
||||
|
@ -2020,15 +1991,10 @@ menu_t MP_RoomDef =
|
|||
0,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
menu_t MP_PlayerSetupDef =
|
||||
{
|
||||
#ifdef NONET
|
||||
MTREE2(MN_MP_MAIN, MN_MP_PLAYERSETUP),
|
||||
#else
|
||||
MTREE3(MN_MP_MAIN, MN_MP_SPLITSCREEN, MN_MP_PLAYERSETUP),
|
||||
#endif
|
||||
"M_SPLAYR",
|
||||
sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t),
|
||||
&MainDef, // doesn't matter
|
||||
|
@ -2788,6 +2754,7 @@ void M_SetMenuCurBackground(const char *defaultname)
|
|||
{
|
||||
char name[9];
|
||||
strncpy(name, defaultname, 8);
|
||||
name[8] = '\0';
|
||||
M_IterateMenuTree(MIT_SetCurBackground, &name);
|
||||
}
|
||||
|
||||
|
@ -3211,40 +3178,42 @@ boolean M_Responder(event_t *ev)
|
|||
}
|
||||
else if (menuactive)
|
||||
{
|
||||
if (ev->type == ev_keydown)
|
||||
if (ev->type == ev_keydown || ev->type == ev_text)
|
||||
{
|
||||
keydown++;
|
||||
ch = ev->key;
|
||||
|
||||
// added 5-2-98 remap virtual keys (mouse & joystick buttons)
|
||||
switch (ch)
|
||||
if (ev->type == ev_keydown)
|
||||
{
|
||||
case KEY_MOUSE1:
|
||||
case KEY_JOY1:
|
||||
ch = KEY_ENTER;
|
||||
break;
|
||||
case KEY_JOY1 + 3:
|
||||
ch = 'n';
|
||||
break;
|
||||
case KEY_MOUSE1 + 1:
|
||||
case KEY_JOY1 + 1:
|
||||
ch = KEY_ESCAPE;
|
||||
break;
|
||||
case KEY_JOY1 + 2:
|
||||
ch = KEY_BACKSPACE;
|
||||
break;
|
||||
case KEY_HAT1:
|
||||
ch = KEY_UPARROW;
|
||||
break;
|
||||
case KEY_HAT1 + 1:
|
||||
ch = KEY_DOWNARROW;
|
||||
break;
|
||||
case KEY_HAT1 + 2:
|
||||
ch = KEY_LEFTARROW;
|
||||
break;
|
||||
case KEY_HAT1 + 3:
|
||||
ch = KEY_RIGHTARROW;
|
||||
break;
|
||||
keydown++;
|
||||
// added 5-2-98 remap virtual keys (mouse & joystick buttons)
|
||||
switch (ch)
|
||||
{
|
||||
case KEY_MOUSE1:
|
||||
case KEY_JOY1:
|
||||
ch = KEY_ENTER;
|
||||
break;
|
||||
case KEY_JOY1 + 3:
|
||||
ch = 'n';
|
||||
break;
|
||||
case KEY_MOUSE1 + 1:
|
||||
case KEY_JOY1 + 1:
|
||||
ch = KEY_ESCAPE;
|
||||
break;
|
||||
case KEY_JOY1 + 2:
|
||||
ch = KEY_BACKSPACE;
|
||||
break;
|
||||
case KEY_HAT1:
|
||||
ch = KEY_UPARROW;
|
||||
break;
|
||||
case KEY_HAT1 + 1:
|
||||
ch = KEY_DOWNARROW;
|
||||
break;
|
||||
case KEY_HAT1 + 2:
|
||||
ch = KEY_LEFTARROW;
|
||||
break;
|
||||
case KEY_HAT1 + 3:
|
||||
ch = KEY_RIGHTARROW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (ev->type == ev_joystick && ev->key == 0 && joywait < I_GetTime())
|
||||
|
@ -3406,8 +3375,11 @@ boolean M_Responder(event_t *ev)
|
|||
// Handle menuitems which need a specific key handling
|
||||
if (routine && (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_KEYHANDLER)
|
||||
{
|
||||
if (shiftdown && ch >= 32 && ch <= 127)
|
||||
ch = shiftxform[ch];
|
||||
// ignore ev_keydown events if the key maps to a character, since
|
||||
// the ev_text event will follow immediately after in that case.
|
||||
if (ev->type == ev_keydown && ch >= 32 && ch <= 127)
|
||||
return true;
|
||||
|
||||
routine(ch);
|
||||
return true;
|
||||
}
|
||||
|
@ -3449,6 +3421,11 @@ boolean M_Responder(event_t *ev)
|
|||
{
|
||||
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
|
||||
{
|
||||
// ignore ev_keydown events if the key maps to a character, since
|
||||
// the ev_text event will follow immediately after in that case.
|
||||
if (ev->type == ev_keydown && ch >= 32 && ch <= 127)
|
||||
return false;
|
||||
|
||||
if (M_ChangeStringCvar(ch))
|
||||
return true;
|
||||
else
|
||||
|
@ -3609,16 +3586,16 @@ void M_Drawer(void)
|
|||
{
|
||||
if (customversionstring[0] != '\0')
|
||||
{
|
||||
V_DrawThinString(vid.dupx, vid.height - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:");
|
||||
V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
|
||||
V_DrawThinString(vid.dup, vid.height - 17*vid.dup, V_NOSCALESTART|V_TRANSLUCENT, "Mod version:");
|
||||
V_DrawThinString(vid.dup, vid.height - 9*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, customversionstring);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEVELOP // Development -- show revision / branch info
|
||||
V_DrawThinString(vid.dupx, vid.height - 17*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch);
|
||||
V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision);
|
||||
V_DrawThinString(vid.dup, vid.height - 17*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, compbranch);
|
||||
V_DrawThinString(vid.dup, vid.height - 9*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, comprevision);
|
||||
#else // Regular build
|
||||
V_DrawThinString(vid.dupx, vid.height - 9*vid.dupy, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING));
|
||||
V_DrawThinString(vid.dup, vid.height - 9*vid.dup, V_NOSCALESTART|V_TRANSLUCENT|V_ALLOWLOWERCASE, va("%s", VERSIONSTRING));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -3957,9 +3934,7 @@ void M_Init(void)
|
|||
OP_JoystickSetMenu[i].itemaction = M_AssignJoystick;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
CV_RegisterVar(&cv_serversort);
|
||||
#endif
|
||||
}
|
||||
|
||||
void M_InitCharacterTables(void)
|
||||
|
@ -4156,31 +4131,97 @@ void M_DrawTextBox(INT32 x, INT32 y, INT32 width, INT32 boxlines)
|
|||
*/
|
||||
}
|
||||
|
||||
static fixed_t staticalong = 0;
|
||||
|
||||
//
|
||||
// Draw the TV static effect on unavailable map icons
|
||||
//
|
||||
static void M_DrawStaticBox(fixed_t x, fixed_t y, INT32 flags, fixed_t w, fixed_t h)
|
||||
{
|
||||
patch_t *patch;
|
||||
fixed_t sw, pw;
|
||||
patch_t *patch = W_CachePatchName("LSSTATIC", PU_PATCH);
|
||||
static fixed_t staticx = 0, staticy = 0; // Keep track of where we are across function calls
|
||||
|
||||
patch = W_CachePatchName("LSSTATIC", PU_PATCH);
|
||||
pw = patch->width - (sw = w*2); //FixedDiv(w, scale); -- for scale FRACUNIT/2
|
||||
|
||||
/*if (pw > 0) -- model code for modders providing weird LSSTATIC
|
||||
if (!patch->width || !patch->height) // Shouldn't be necessary, but I don't want to get in trouble!
|
||||
{
|
||||
if (staticalong > pw)
|
||||
staticalong -= pw;
|
||||
W_UnlockCachedPatch(patch);
|
||||
return;
|
||||
}
|
||||
else
|
||||
staticalong = 0;*/
|
||||
if (patch->width == 1) // Nothing to randomise or tile
|
||||
{
|
||||
// Just stretch the patch over the whole box - no need to draw it 160 times over
|
||||
// Technically, we should crop and maybe tile and randomise the Y axis, but... it's not worth it here
|
||||
V_DrawStretchyFixedPatch(x*FRACUNIT, y*FRACUNIT, (w*FRACUNIT) / patch->width, (h*FRACUNIT) / patch->height, flags, patch, NULL);
|
||||
W_UnlockCachedPatch(patch);
|
||||
return;
|
||||
}
|
||||
if (patch->width == 160) // Something to randomise or tile - but don't!
|
||||
{
|
||||
// If it's 160 pixels wide, the modder probably wants the patch fixed in place
|
||||
// But instead of "just drawing" it, why not allow sequential frames of animation on the Y axis?
|
||||
// For example, this could be used to make a vignette effect, whether animated or not
|
||||
// This function is primarily called with a patch region of 160x100, so the frames must be 160x100 too
|
||||
fixed_t temp = patch->height / 100; // Amount of 160x100 frames in the patch
|
||||
if (temp) // Don't modulo by zero
|
||||
temp = (gametic % temp) * h*2*FRACUNIT; // Which frame to draw
|
||||
|
||||
if (staticalong > pw) // simplified for base LSSTATIC
|
||||
staticalong -= pw;
|
||||
V_DrawCroppedPatch(x*FRACUNIT, y*FRACUNIT, (w*FRACUNIT) / 160, (h*FRACUNIT) / 100, flags, patch, NULL, 0, temp, w*2*FRACUNIT, h*2*FRACUNIT);
|
||||
|
||||
W_UnlockCachedPatch(patch);
|
||||
return;
|
||||
}
|
||||
|
||||
V_DrawCroppedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT/2, FRACUNIT/2, flags, patch, NULL, staticalong<<FRACBITS, 0, sw<<FRACBITS, h*2<<FRACBITS); // FixedDiv(h, scale)); -- for scale FRACUNIT/2
|
||||
|
||||
staticalong += sw; //M_RandomRange(sw/2, 2*sw); -- turns out less randomisation looks better because immediately adjacent frames can't end up close to each other
|
||||
// If the patch isn't 1 or 160 pixels wide, that means that it's time for randomised static!
|
||||
|
||||
// First, randomise the static patch's offset - It's largely just based on "w", but there's...
|
||||
// ...the tiniest bit of randomisation, to keep it animated even when the patch width is 160 x [static boxes on-screen]
|
||||
// Making it TOO randomised could make it randomise to the almost-same position multiple frames in a row - that's bad
|
||||
staticx = (staticx + (w*4) + (M_RandomByte() % 4)) % (patch->width*2);
|
||||
|
||||
if (patch->height == h*2) // Is the patch 100 pixels tall? If so, reset "staticy"...
|
||||
staticy = 0; // ...in case that one add-on would randomise it and a later add-on wouldn't
|
||||
else // Otherwise, as we already make "staticx" near-sequential, I think that making "staticy"...
|
||||
staticy = M_RandomRange(0, (patch->height*2) - 1); // ...fully random instead of sequential increases the... randomness
|
||||
|
||||
// The drawing function calls can get a bit lengthy, so let's make a little shortcut
|
||||
#define DRAWSTATIC(_x,_y,_sx,_sy,_w,_h) V_DrawCroppedPatch((x*FRACUNIT)+((_x)*FRACUNIT/4), (y*FRACUNIT)+((_y)*FRACUNIT/4),\
|
||||
FRACUNIT/2, FRACUNIT/2, flags, patch, NULL, (_sx)*FRACUNIT/2, (_sy)*FRACUNIT/2, (w*2*FRACUNIT)+((_w)*FRACUNIT/2), (h*2*FRACUNIT)+((_h)*FRACUNIT/2))
|
||||
|
||||
// And finally, let's draw it! Don't worry about "staticx" plus "w*2" potentially going off-patch
|
||||
DRAWSTATIC(0, 0, staticx, staticy, 0, 0); // This gets drawn in all cases
|
||||
|
||||
if ((patch->width*2) - staticx >= w*4) // No horizontal tiling
|
||||
{
|
||||
if ((patch->height*2) - staticy >= h*4) // Simplest-case scenario, no tiling at all
|
||||
{}
|
||||
else // Vertical tiling only
|
||||
{
|
||||
for (INT16 j = 2; ((patch->height*j) - staticy) < h*4; j += 2)
|
||||
DRAWSTATIC(0, (patch->height*j) - staticy, staticx, 0, 0, staticy - (patch->height*j));
|
||||
}
|
||||
}
|
||||
else // Horizontal tiling
|
||||
{
|
||||
if ((patch->height*2) - staticy >= h*4) // Horizontal tiling only
|
||||
{
|
||||
for (INT16 i = 2; ((patch->width*i) - staticx) < w*4; i += 2)
|
||||
DRAWSTATIC((patch->width*i) - staticx, 0, 0, staticy, staticx - (patch->width*i), 0);
|
||||
}
|
||||
else // Horizontal and vertical tiling
|
||||
{
|
||||
for (INT16 j = 2; ((patch->height*j) - staticy) < h*4; j += 2)
|
||||
DRAWSTATIC(0, (patch->height*j) - staticy, staticx, 0, 0, staticy - (patch->height*j));
|
||||
|
||||
for (INT16 i = 2; ((patch->width*i) - staticx) < w*4; i += 2)
|
||||
{
|
||||
DRAWSTATIC((patch->width*i) - staticx, 0, 0, staticy, staticx - (patch->width*i), 0);
|
||||
for (INT16 j = 2; ((patch->height*j) - staticy) < h*4; j += 2)
|
||||
DRAWSTATIC((patch->width*i) - staticx, (patch->height*j) - staticy, 0, 0, staticx - (patch->width*i), staticy - (patch->height*j));
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef DRAWSTATIC
|
||||
|
||||
// Now that we're done with the patch, it's time to say our goodbyes. Until next time, patch!
|
||||
W_UnlockCachedPatch(patch);
|
||||
}
|
||||
|
||||
|
@ -5794,16 +5835,15 @@ static void M_DrawRecordAttackForeground(void)
|
|||
|
||||
INT32 i;
|
||||
INT32 height = (fg->height / 2);
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
|
||||
for (i = -12; i < (BASEVIDHEIGHT/height) + 12; i++)
|
||||
{
|
||||
INT32 y = ((i*height) - (height - ((FixedInt(recatkdrawtimer*2))%height)));
|
||||
// don't draw above the screen
|
||||
{
|
||||
INT32 sy = FixedMul(y, dupz<<FRACBITS) >> FRACBITS;
|
||||
if (vid.height != BASEVIDHEIGHT * dupz)
|
||||
sy += (vid.height - (BASEVIDHEIGHT * dupz)) / 2;
|
||||
INT32 sy = FixedMul(y, vid.dup<<FRACBITS) >> FRACBITS;
|
||||
if (vid.height != BASEVIDHEIGHT * vid.dup)
|
||||
sy += (vid.height - (BASEVIDHEIGHT * vid.dup)) / 2;
|
||||
if ((sy+height) < 0)
|
||||
continue;
|
||||
}
|
||||
|
@ -5827,13 +5867,12 @@ static void M_DrawRecordAttackForeground(void)
|
|||
static void M_DrawNightsAttackMountains(void)
|
||||
{
|
||||
static fixed_t bgscrollx;
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy);
|
||||
patch_t *background = W_CachePatchName(curbgname, PU_PATCH);
|
||||
INT16 w = background->width;
|
||||
INT32 x = FixedInt(-bgscrollx) % w;
|
||||
INT32 y = BASEVIDHEIGHT - (background->height * 2);
|
||||
|
||||
if (vid.height != BASEVIDHEIGHT * dupz)
|
||||
if (vid.height != BASEVIDHEIGHT * vid.dup)
|
||||
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 158);
|
||||
V_DrawFill(0, y+50, vid.width, BASEVIDHEIGHT, V_SNAPTOLEFT|31);
|
||||
|
||||
|
@ -5989,7 +6028,7 @@ static void M_DrawLevelPlatterMenu(void)
|
|||
}
|
||||
|
||||
// draw from top to bottom
|
||||
while (y < (vid.height/vid.dupy))
|
||||
while (y < (vid.height/vid.dup))
|
||||
{
|
||||
M_DrawLevelPlatterRow(iter, y);
|
||||
y += lsvseperation(iter);
|
||||
|
@ -7836,9 +7875,9 @@ static void M_DrawSoundTest(void)
|
|||
}
|
||||
}
|
||||
|
||||
y = (BASEVIDWIDTH-(vid.width/vid.dupx))/2;
|
||||
y = (BASEVIDWIDTH-(vid.width/vid.dup))/2;
|
||||
|
||||
V_DrawFill(y, 20, vid.width/vid.dupx, 24, 159);
|
||||
V_DrawFill(y, 20, vid.width/vid.dup, 24, 159);
|
||||
{
|
||||
static fixed_t st_scroll = -FRACUNIT;
|
||||
const char* titl;
|
||||
|
@ -8408,8 +8447,8 @@ static void M_DrawLoadGameData(void)
|
|||
INT32 i, prev_i = 1, savetodraw, x, y, hsep = 90;
|
||||
skin_t *charskin = NULL;
|
||||
|
||||
if (vid.width != BASEVIDWIDTH*vid.dupx)
|
||||
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dupx);
|
||||
if (vid.width != BASEVIDWIDTH*vid.dup)
|
||||
hsep = (hsep*vid.width)/(BASEVIDWIDTH*vid.dup);
|
||||
|
||||
for (i = 2; prev_i; i = -(i + ((UINT32)i >> 31))) // draws from outwards in; 2, -2, 1, -1, 0
|
||||
{
|
||||
|
@ -9394,7 +9433,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
|
|||
INT16 bgwidth = charbg->width;
|
||||
INT16 fgwidth = charfg->width;
|
||||
INT32 x, y;
|
||||
INT32 w = (vid.width/vid.dupx);
|
||||
INT32 w = (vid.width/vid.dup);
|
||||
|
||||
if (abs(char_scroll) > FRACUNIT/4)
|
||||
char_scroll -= FixedMul((char_scroll>>2), renderdeltatics);
|
||||
|
@ -9430,7 +9469,7 @@ static void M_DrawSetupChoosePlayerMenu(void)
|
|||
// Background and borders
|
||||
V_DrawFill(0, 0, bgwidth, vid.height, V_SNAPTOTOP|colormap[101]);
|
||||
{
|
||||
INT32 sw = (BASEVIDWIDTH * vid.dupx);
|
||||
INT32 sw = (BASEVIDWIDTH * vid.dup);
|
||||
INT32 bw = (vid.width - sw) / 2;
|
||||
col = colormap[106];
|
||||
if (bw)
|
||||
|
@ -10852,7 +10891,7 @@ void M_DrawMarathon(void)
|
|||
const char *cvstring;
|
||||
char *work;
|
||||
angle_t fa;
|
||||
INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy), xspan = (vid.width/dupz), yspan = (vid.height/dupz), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy;
|
||||
INT32 xspan = (vid.width/vid.dup), yspan = (vid.height/vid.dup), diffx = (xspan - BASEVIDWIDTH)/2, diffy = (yspan - BASEVIDHEIGHT)/2, maxy = BASEVIDHEIGHT + diffy;
|
||||
|
||||
curbgxspeed = 0;
|
||||
curbgyspeed = 18;
|
||||
|
@ -10925,16 +10964,17 @@ void M_DrawMarathon(void)
|
|||
INT32 trans = V_60TRANS+((cnt&~3)<<(V_ALPHASHIFT-2));
|
||||
INT32 height = fg->height / 2;
|
||||
char patchname[7] = "CEMGx0";
|
||||
INT32 dup;
|
||||
|
||||
dupz = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain.
|
||||
dupz = ((dupz>>FRACBITS) % height);
|
||||
dup = (w*7)/6; //(w*42*120)/(360*6); -- I don't know why this works but I'm not going to complain.
|
||||
dup = ((dup>>FRACBITS) % height);
|
||||
y = height/2;
|
||||
while (y+dupz >= -diffy)
|
||||
while (y+dup >= -diffy)
|
||||
y -= height;
|
||||
while (y-2-dupz < maxy)
|
||||
while (y-2-dup < maxy)
|
||||
{
|
||||
V_DrawFixedPatch(((BASEVIDWIDTH-190)<<(FRACBITS-1)), (y-2-dupz)<<FRACBITS, FRACUNIT/2, trans, fg, NULL);
|
||||
V_DrawFixedPatch(((BASEVIDWIDTH+190)<<(FRACBITS-1)), (y+dupz)<<FRACBITS, FRACUNIT/2, trans|V_FLIP, fg, NULL);
|
||||
V_DrawFixedPatch(((BASEVIDWIDTH-190)<<(FRACBITS-1)), (y-2-dup)<<FRACBITS, FRACUNIT/2, trans, fg, NULL);
|
||||
V_DrawFixedPatch(((BASEVIDWIDTH+190)<<(FRACBITS-1)), (y+dup)<<FRACBITS, FRACUNIT/2, trans|V_FLIP, fg, NULL);
|
||||
y += height;
|
||||
}
|
||||
|
||||
|
@ -10952,16 +10992,16 @@ void M_DrawMarathon(void)
|
|||
}
|
||||
|
||||
height = 18; // prevents the need for the next line
|
||||
//dupz = (w*height)/18;
|
||||
dupz = ((w>>FRACBITS) % height);
|
||||
y = dupz+(height/4);
|
||||
x = 105+dupz;
|
||||
//dup = (w*height)/18;
|
||||
dup = ((w>>FRACBITS) % height);
|
||||
y = dup+(height/4);
|
||||
x = 105+dup;
|
||||
while (y >= -diffy)
|
||||
{
|
||||
x -= height;
|
||||
y -= height;
|
||||
}
|
||||
while (y-dupz < maxy && x < (xspan/2))
|
||||
while (y-dup < maxy && x < (xspan/2))
|
||||
{
|
||||
V_DrawFill((BASEVIDWIDTH/2)-x-height, -diffy, height, diffy+y+height, 153);
|
||||
V_DrawFill((BASEVIDWIDTH/2)+x, (maxy-y)-height, height, height+y, 153);
|
||||
|
@ -11109,7 +11149,6 @@ static void M_EndGame(INT32 choice)
|
|||
|
||||
#define S_LINEY(n) currentMenu->y + SERVERHEADERHEIGHT + (n * SERVERLINEHEIGHT)
|
||||
|
||||
#ifndef NONET
|
||||
static UINT32 localservercount;
|
||||
|
||||
static void M_HandleServerPage(INT32 choice)
|
||||
|
@ -11293,6 +11332,8 @@ static void M_DrawConnectMenu(void)
|
|||
V_DrawSmallString(currentMenu->x+202, S_LINEY(i)+8, globalflags, "\x85" "Mod");
|
||||
if (serverlist[slindex].info.cheatsenabled)
|
||||
V_DrawSmallString(currentMenu->x+222, S_LINEY(i)+8, globalflags, "\x83" "Cheats");
|
||||
if (Net_IsNodeIPv6(serverlist[slindex].node))
|
||||
V_DrawSmallString(currentMenu->x+252, S_LINEY(i)+8, globalflags, "\x84" "IPv6");
|
||||
|
||||
V_DrawSmallString(currentMenu->x, S_LINEY(i)+8, globalflags,
|
||||
va("Ping: %u", (UINT32)LONG(serverlist[slindex].info.time)));
|
||||
|
@ -11381,11 +11422,9 @@ static int ServerListEntryComparator_modified(const void *entry1, const void *en
|
|||
// Default to strcmp.
|
||||
return strcmp(sa->info.servername, sb->info.servername);
|
||||
}
|
||||
#endif
|
||||
|
||||
void M_SortServerList(void)
|
||||
{
|
||||
#ifndef NONET
|
||||
switch(cv_serversort.value)
|
||||
{
|
||||
case 0: // Ping.
|
||||
|
@ -11407,10 +11446,8 @@ void M_SortServerList(void)
|
|||
qsort(serverlist, serverlistcount, sizeof(serverelem_t), ServerListEntryComparator_gametypename);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
#ifdef UPDATE_ALERT
|
||||
static boolean M_CheckMODVersion(int id)
|
||||
{
|
||||
|
@ -11609,7 +11646,6 @@ static void M_ChooseRoom(INT32 choice)
|
|||
if (currentMenu == &MP_ConnectDef)
|
||||
M_Refresh(0);
|
||||
}
|
||||
#endif //NONET
|
||||
|
||||
//===========================================================================
|
||||
// Start Server Menu
|
||||
|
@ -11657,7 +11693,6 @@ static void M_DrawServerMenu(void)
|
|||
{
|
||||
M_DrawGenericMenu();
|
||||
|
||||
#ifndef NONET
|
||||
// Room name
|
||||
if (currentMenu == &MP_ServerDef)
|
||||
{
|
||||
|
@ -11669,15 +11704,10 @@ static void M_DrawServerMenu(void)
|
|||
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
|
||||
V_YELLOWMAP, room_list[menuRoomIndex].name);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cv_nextmap.value)
|
||||
{
|
||||
#ifndef NONET
|
||||
#define imgheight MP_ServerMenu[mp_server_levelgt].alphaKey
|
||||
#else
|
||||
#define imgheight 100
|
||||
#endif
|
||||
patch_t *PictureOfLevel;
|
||||
lumpnum_t lumpnum;
|
||||
char headerstr[40];
|
||||
|
@ -11729,7 +11759,6 @@ static void M_ServerOptions(INT32 choice)
|
|||
{
|
||||
(void)choice;
|
||||
|
||||
#ifndef NONET
|
||||
if ((splitscreen && !netgame) || currentMenu == &MP_SplitServerDef)
|
||||
{
|
||||
OP_ServerOptionsMenu[ 1].status = IT_GRAYEDOUT; // Server name
|
||||
|
@ -11750,7 +11779,6 @@ static void M_ServerOptions(INT32 choice)
|
|||
OP_ServerOptionsMenu[37].status = IT_STRING | IT_CVAR;
|
||||
OP_ServerOptionsMenu[38].status = IT_STRING | IT_CVAR;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable fading because of different menu head. */
|
||||
if (currentMenu == &OP_MainDef)/* from Options menu */
|
||||
|
@ -11762,7 +11790,6 @@ static void M_ServerOptions(INT32 choice)
|
|||
M_SetupNextMenu(&OP_ServerOptionsDef);
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static void M_StartServerMenu(INT32 choice)
|
||||
{
|
||||
(void)choice;
|
||||
|
@ -12000,7 +12027,7 @@ static void M_HandleConnectIP(INT32 choice)
|
|||
// Rudimentary number and period enforcing - also allows letters so hostnames can be used instead
|
||||
// and square brackets for RFC 2732 IPv6 addresses
|
||||
if ((choice >= '-' && choice <= ':') ||
|
||||
(choice == '[' || choice == ']') ||
|
||||
(choice == '[' || choice == ']' || choice == '%') ||
|
||||
(choice >= 'A' && choice <= 'Z') ||
|
||||
(choice >= 'a' && choice <= 'z'))
|
||||
{
|
||||
|
@ -12029,7 +12056,6 @@ static void M_HandleConnectIP(INT32 choice)
|
|||
M_ClearMenus(true);
|
||||
}
|
||||
}
|
||||
#endif //!NONET
|
||||
|
||||
// ========================
|
||||
// MULTIPLAYER PLAYER SETUP
|
||||
|
@ -12691,11 +12717,7 @@ static void M_SetupMultiPlayer(INT32 choice)
|
|||
else
|
||||
MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER|IT_STRING);
|
||||
|
||||
// ditto with colour
|
||||
if (Playing() && G_GametypeHasTeams())
|
||||
MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT);
|
||||
else
|
||||
MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING);
|
||||
MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING);
|
||||
|
||||
multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL);
|
||||
|
||||
|
@ -12710,7 +12732,7 @@ static void M_SetupMultiPlayer2(INT32 choice)
|
|||
|
||||
multi_frame = 0;
|
||||
multi_tics = 4*FRACUNIT;
|
||||
|
||||
|
||||
strcpy (setupm_name, cv_playername2.string);
|
||||
|
||||
// set for splitscreen secondary player
|
||||
|
@ -12736,11 +12758,7 @@ static void M_SetupMultiPlayer2(INT32 choice)
|
|||
else
|
||||
MP_PlayerSetupMenu[1].status = (IT_KEYHANDLER | IT_STRING);
|
||||
|
||||
// ditto with colour
|
||||
if (Playing() && G_GametypeHasTeams())
|
||||
MP_PlayerSetupMenu[2].status = (IT_GRAYEDOUT);
|
||||
else
|
||||
MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING);
|
||||
MP_PlayerSetupMenu[2].status = (IT_KEYHANDLER|IT_STRING);
|
||||
|
||||
multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_WALK, NULL);
|
||||
|
||||
|
@ -13229,23 +13247,23 @@ static void M_Setup1PControlsMenu(INT32 choice)
|
|||
currentMenu->lastOn = itemOn;
|
||||
|
||||
// Unhide the nine non-P2 controls and their headers
|
||||
//OP_ChangeControlsMenu[18+0].status = IT_HEADER;
|
||||
//OP_ChangeControlsMenu[18+1].status = IT_SPACE;
|
||||
//OP_ChangeControlsMenu[19+0].status = IT_HEADER;
|
||||
//OP_ChangeControlsMenu[19+1].status = IT_SPACE;
|
||||
// ...
|
||||
OP_ChangeControlsMenu[18+2].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[18+3].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[18+4].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[18+5].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[18+6].status = IT_CALL|IT_STRING2;
|
||||
//OP_ChangeControlsMenu[18+7].status = IT_CALL|IT_STRING2;
|
||||
//OP_ChangeControlsMenu[18+8].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[18+9].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[19+2].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[19+3].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[19+4].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[19+5].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[19+6].status = IT_CALL|IT_STRING2;
|
||||
//OP_ChangeControlsMenu[19+7].status = IT_CALL|IT_STRING2;
|
||||
//OP_ChangeControlsMenu[19+8].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[19+9].status = IT_CALL|IT_STRING2;
|
||||
// ...
|
||||
OP_ChangeControlsMenu[28+0].status = IT_HEADER;
|
||||
OP_ChangeControlsMenu[28+1].status = IT_SPACE;
|
||||
OP_ChangeControlsMenu[29+0].status = IT_HEADER;
|
||||
OP_ChangeControlsMenu[29+1].status = IT_SPACE;
|
||||
// ...
|
||||
OP_ChangeControlsMenu[28+2].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[28+3].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[29+2].status = IT_CALL|IT_STRING2;
|
||||
OP_ChangeControlsMenu[29+3].status = IT_CALL|IT_STRING2;
|
||||
|
||||
OP_ChangeControlsDef.prevMenu = &OP_P1ControlsDef;
|
||||
OP_ChangeControlsDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); // remove second level
|
||||
|
@ -13261,23 +13279,23 @@ static void M_Setup2PControlsMenu(INT32 choice)
|
|||
currentMenu->lastOn = itemOn;
|
||||
|
||||
// Hide the nine non-P2 controls and their headers
|
||||
//OP_ChangeControlsMenu[18+0].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[18+1].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[19+0].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[19+1].status = IT_GRAYEDOUT2;
|
||||
// ...
|
||||
OP_ChangeControlsMenu[18+2].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[18+3].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[18+4].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[18+5].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[18+6].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[18+7].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[18+8].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[18+9].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[19+2].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[19+3].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[19+4].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[19+5].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[19+6].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[19+7].status = IT_GRAYEDOUT2;
|
||||
//OP_ChangeControlsMenu[19+8].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[19+9].status = IT_GRAYEDOUT2;
|
||||
// ...
|
||||
OP_ChangeControlsMenu[28+0].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[28+1].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[29+0].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[29+1].status = IT_GRAYEDOUT2;
|
||||
// ...
|
||||
OP_ChangeControlsMenu[28+2].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[28+3].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[29+2].status = IT_GRAYEDOUT2;
|
||||
OP_ChangeControlsMenu[29+3].status = IT_GRAYEDOUT2;
|
||||
|
||||
OP_ChangeControlsDef.prevMenu = &OP_P2ControlsDef;
|
||||
OP_ChangeControlsDef.menuid &= ~(((1 << MENUBITS) - 1) << MENUBITS); // remove second level
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "command.h"
|
||||
#include "f_finale.h" // for ttmode_enum
|
||||
#include "i_threads.h"
|
||||
#include "mserv.h"
|
||||
#include "netcode/mserv.h"
|
||||
#include "r_things.h" // for SKINNAMESIZE
|
||||
|
||||
// Compatibility with old-style named NiGHTS replay files.
|
||||
|
@ -74,7 +74,7 @@ typedef enum
|
|||
MN_MP_SERVER,
|
||||
MN_MP_CONNECT,
|
||||
MN_MP_ROOM,
|
||||
MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET
|
||||
MN_MP_PLAYERSETUP,
|
||||
MN_MP_SERVER_OPTIONS,
|
||||
|
||||
// Options
|
||||
|
|
439
src/m_misc.c
439
src/m_misc.c
|
@ -989,7 +989,7 @@ static inline boolean M_PNGLib(void)
|
|||
|
||||
static void M_PNGFrame(png_structp png_ptr, png_infop png_info_ptr, png_bytep png_buf)
|
||||
{
|
||||
png_uint_16 downscale = apng_downscale ? vid.dupx : 1;
|
||||
png_uint_16 downscale = apng_downscale ? vid.dup : 1;
|
||||
|
||||
png_uint_32 pitch = png_get_rowbytes(png_ptr, png_info_ptr);
|
||||
PNG_CONST png_uint_32 width = vid.width / downscale;
|
||||
|
@ -1055,7 +1055,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal)
|
|||
|
||||
apng_downscale = (!!cv_apng_downscale.value);
|
||||
|
||||
downscale = apng_downscale ? vid.dupx : 1;
|
||||
downscale = apng_downscale ? vid.dup : 1;
|
||||
|
||||
apng_FILE = fopen(filename,"wb+"); // + mode for reading
|
||||
if (!apng_FILE)
|
||||
|
@ -2207,430 +2207,11 @@ char *sizeu5(size_t num)
|
|||
return sizeu5_buf;
|
||||
}
|
||||
|
||||
#if defined (__GNUC__) && defined (__i386__) // from libkwave, under GPL
|
||||
// Alam: note libkwave memcpy code comes from mplayer's libvo/aclib_template.c, r699
|
||||
|
||||
/* for small memory blocks (<256 bytes) this version is faster */
|
||||
#define small_memcpy(dest,src,n)\
|
||||
{\
|
||||
register unsigned long int dummy;\
|
||||
__asm__ __volatile__(\
|
||||
"cld\n\t"\
|
||||
"rep; movsb"\
|
||||
:"=&D"(dest), "=&S"(src), "=&c"(dummy)\
|
||||
:"0" (dest), "1" (src),"2" (n)\
|
||||
: "memory", "cc");\
|
||||
}
|
||||
/* linux kernel __memcpy (from: /include/asm/string.h) */
|
||||
ATTRINLINE static FUNCINLINE void *__memcpy (void *dest, const void * src, size_t n)
|
||||
void *M_Memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
int d0, d1, d2;
|
||||
|
||||
if ( n < 4 )
|
||||
{
|
||||
small_memcpy(dest, src, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"rep ; movsl;"
|
||||
"testb $2,%b4;"
|
||||
"je 1f;"
|
||||
"movsw;"
|
||||
"1:\ttestb $1,%b4;"
|
||||
"je 2f;"
|
||||
"movsb;"
|
||||
"2:"
|
||||
: "=&c" (d0), "=&D" (d1), "=&S" (d2)
|
||||
:"0" (n/4), "q" (n),"1" ((long) dest),"2" ((long) src)
|
||||
: "memory");
|
||||
}
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
#define SSE_MMREG_SIZE 16
|
||||
#define MMX_MMREG_SIZE 8
|
||||
|
||||
#define MMX1_MIN_LEN 0x800 /* 2K blocks */
|
||||
#define MIN_LEN 0x40 /* 64-byte blocks */
|
||||
|
||||
/* SSE note: i tried to move 128 bytes a time instead of 64 but it
|
||||
didn't make any measureable difference. i'm using 64 for the sake of
|
||||
simplicity. [MF] */
|
||||
static /*FUNCTARGET("sse2")*/ void *sse_cpy(void * dest, const void * src, size_t n)
|
||||
{
|
||||
void *retval = dest;
|
||||
size_t i;
|
||||
|
||||
/* PREFETCH has effect even for MOVSB instruction ;) */
|
||||
__asm__ __volatile__ (
|
||||
"prefetchnta (%0);"
|
||||
"prefetchnta 32(%0);"
|
||||
"prefetchnta 64(%0);"
|
||||
"prefetchnta 96(%0);"
|
||||
"prefetchnta 128(%0);"
|
||||
"prefetchnta 160(%0);"
|
||||
"prefetchnta 192(%0);"
|
||||
"prefetchnta 224(%0);"
|
||||
"prefetchnta 256(%0);"
|
||||
"prefetchnta 288(%0);"
|
||||
: : "r" (src) );
|
||||
|
||||
if (n >= MIN_LEN)
|
||||
{
|
||||
register unsigned long int delta;
|
||||
/* Align destinition to MMREG_SIZE -boundary */
|
||||
delta = ((unsigned long int)dest)&(SSE_MMREG_SIZE-1);
|
||||
if (delta)
|
||||
{
|
||||
delta=SSE_MMREG_SIZE-delta;
|
||||
n -= delta;
|
||||
small_memcpy(dest, src, delta);
|
||||
}
|
||||
i = n >> 6; /* n/64 */
|
||||
n&=63;
|
||||
if (((unsigned long)src) & 15)
|
||||
/* if SRC is misaligned */
|
||||
for (; i>0; i--)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"prefetchnta 320(%0);"
|
||||
"prefetchnta 352(%0);"
|
||||
"movups (%0), %%xmm0;"
|
||||
"movups 16(%0), %%xmm1;"
|
||||
"movups 32(%0), %%xmm2;"
|
||||
"movups 48(%0), %%xmm3;"
|
||||
"movntps %%xmm0, (%1);"
|
||||
"movntps %%xmm1, 16(%1);"
|
||||
"movntps %%xmm2, 32(%1);"
|
||||
"movntps %%xmm3, 48(%1);"
|
||||
:: "r" (src), "r" (dest) : "memory");
|
||||
src = (const unsigned char *)src + 64;
|
||||
dest = (unsigned char *)dest + 64;
|
||||
}
|
||||
else
|
||||
/*
|
||||
Only if SRC is aligned on 16-byte boundary.
|
||||
It allows to use movaps instead of movups, which required data
|
||||
to be aligned or a general-protection exception (#GP) is generated.
|
||||
*/
|
||||
for (; i>0; i--)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"prefetchnta 320(%0);"
|
||||
"prefetchnta 352(%0);"
|
||||
"movaps (%0), %%xmm0;"
|
||||
"movaps 16(%0), %%xmm1;"
|
||||
"movaps 32(%0), %%xmm2;"
|
||||
"movaps 48(%0), %%xmm3;"
|
||||
"movntps %%xmm0, (%1);"
|
||||
"movntps %%xmm1, 16(%1);"
|
||||
"movntps %%xmm2, 32(%1);"
|
||||
"movntps %%xmm3, 48(%1);"
|
||||
:: "r" (src), "r" (dest) : "memory");
|
||||
src = ((const unsigned char *)src) + 64;
|
||||
dest = ((unsigned char *)dest) + 64;
|
||||
}
|
||||
/* since movntq is weakly-ordered, a "sfence"
|
||||
* is needed to become ordered again. */
|
||||
__asm__ __volatile__ ("sfence":::"memory");
|
||||
/* enables to use FPU */
|
||||
__asm__ __volatile__ ("emms":::"memory");
|
||||
}
|
||||
/*
|
||||
* Now do the tail of the block
|
||||
*/
|
||||
if (n) __memcpy(dest, src, n);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static FUNCTARGET("mmx") void *mmx2_cpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
void *retval = dest;
|
||||
size_t i;
|
||||
|
||||
/* PREFETCH has effect even for MOVSB instruction ;) */
|
||||
__asm__ __volatile__ (
|
||||
"prefetchnta (%0);"
|
||||
"prefetchnta 32(%0);"
|
||||
"prefetchnta 64(%0);"
|
||||
"prefetchnta 96(%0);"
|
||||
"prefetchnta 128(%0);"
|
||||
"prefetchnta 160(%0);"
|
||||
"prefetchnta 192(%0);"
|
||||
"prefetchnta 224(%0);"
|
||||
"prefetchnta 256(%0);"
|
||||
"prefetchnta 288(%0);"
|
||||
: : "r" (src));
|
||||
|
||||
if (n >= MIN_LEN)
|
||||
{
|
||||
register unsigned long int delta;
|
||||
/* Align destinition to MMREG_SIZE -boundary */
|
||||
delta = ((unsigned long int)dest)&(MMX_MMREG_SIZE-1);
|
||||
if (delta)
|
||||
{
|
||||
delta=MMX_MMREG_SIZE-delta;
|
||||
n -= delta;
|
||||
small_memcpy(dest, src, delta);
|
||||
}
|
||||
i = n >> 6; /* n/64 */
|
||||
n&=63;
|
||||
for (; i>0; i--)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"prefetchnta 320(%0);"
|
||||
"prefetchnta 352(%0);"
|
||||
"movq (%0), %%mm0;"
|
||||
"movq 8(%0), %%mm1;"
|
||||
"movq 16(%0), %%mm2;"
|
||||
"movq 24(%0), %%mm3;"
|
||||
"movq 32(%0), %%mm4;"
|
||||
"movq 40(%0), %%mm5;"
|
||||
"movq 48(%0), %%mm6;"
|
||||
"movq 56(%0), %%mm7;"
|
||||
"movntq %%mm0, (%1);"
|
||||
"movntq %%mm1, 8(%1);"
|
||||
"movntq %%mm2, 16(%1);"
|
||||
"movntq %%mm3, 24(%1);"
|
||||
"movntq %%mm4, 32(%1);"
|
||||
"movntq %%mm5, 40(%1);"
|
||||
"movntq %%mm6, 48(%1);"
|
||||
"movntq %%mm7, 56(%1);"
|
||||
:: "r" (src), "r" (dest) : "memory");
|
||||
src = ((const unsigned char *)src) + 64;
|
||||
dest = ((unsigned char *)dest) + 64;
|
||||
}
|
||||
/* since movntq is weakly-ordered, a "sfence"
|
||||
* is needed to become ordered again. */
|
||||
__asm__ __volatile__ ("sfence":::"memory");
|
||||
__asm__ __volatile__ ("emms":::"memory");
|
||||
}
|
||||
/*
|
||||
* Now do the tail of the block
|
||||
*/
|
||||
if (n) __memcpy(dest, src, n);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static FUNCTARGET("mmx") void *mmx1_cpy(void *dest, const void *src, size_t n) //3DNOW
|
||||
{
|
||||
void *retval = dest;
|
||||
size_t i;
|
||||
|
||||
/* PREFETCH has effect even for MOVSB instruction ;) */
|
||||
__asm__ __volatile__ (
|
||||
"prefetch (%0);"
|
||||
"prefetch 32(%0);"
|
||||
"prefetch 64(%0);"
|
||||
"prefetch 96(%0);"
|
||||
"prefetch 128(%0);"
|
||||
"prefetch 160(%0);"
|
||||
"prefetch 192(%0);"
|
||||
"prefetch 224(%0);"
|
||||
"prefetch 256(%0);"
|
||||
"prefetch 288(%0);"
|
||||
: : "r" (src));
|
||||
|
||||
if (n >= MMX1_MIN_LEN)
|
||||
{
|
||||
register unsigned long int delta;
|
||||
/* Align destinition to MMREG_SIZE -boundary */
|
||||
delta = ((unsigned long int)dest)&(MMX_MMREG_SIZE-1);
|
||||
if (delta)
|
||||
{
|
||||
delta=MMX_MMREG_SIZE-delta;
|
||||
n -= delta;
|
||||
small_memcpy(dest, src, delta);
|
||||
}
|
||||
i = n >> 6; /* n/64 */
|
||||
n&=63;
|
||||
for (; i>0; i--)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"prefetch 320(%0);"
|
||||
"prefetch 352(%0);"
|
||||
"movq (%0), %%mm0;"
|
||||
"movq 8(%0), %%mm1;"
|
||||
"movq 16(%0), %%mm2;"
|
||||
"movq 24(%0), %%mm3;"
|
||||
"movq 32(%0), %%mm4;"
|
||||
"movq 40(%0), %%mm5;"
|
||||
"movq 48(%0), %%mm6;"
|
||||
"movq 56(%0), %%mm7;"
|
||||
"movq %%mm0, (%1);"
|
||||
"movq %%mm1, 8(%1);"
|
||||
"movq %%mm2, 16(%1);"
|
||||
"movq %%mm3, 24(%1);"
|
||||
"movq %%mm4, 32(%1);"
|
||||
"movq %%mm5, 40(%1);"
|
||||
"movq %%mm6, 48(%1);"
|
||||
"movq %%mm7, 56(%1);"
|
||||
:: "r" (src), "r" (dest) : "memory");
|
||||
src = ((const unsigned char *)src) + 64;
|
||||
dest = ((unsigned char *)dest) + 64;
|
||||
}
|
||||
__asm__ __volatile__ ("femms":::"memory"); // same as mmx_cpy() but with a femms
|
||||
}
|
||||
/*
|
||||
* Now do the tail of the block
|
||||
*/
|
||||
if (n) __memcpy(dest, src, n);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Alam: why? memcpy may be __cdecl/_System and our code may be not the same type
|
||||
static void *cpu_cpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
if (src == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_MEMORY, "Memcpy from 0x0?!: %p %p %s\n", dest, src, sizeu1(n));
|
||||
return dest;
|
||||
}
|
||||
|
||||
if(dest == NULL)
|
||||
{
|
||||
CONS_Debug(DBG_MEMORY, "Memcpy to 0x0?!: %p %p %s\n", dest, src, sizeu1(n));
|
||||
return dest;
|
||||
}
|
||||
|
||||
return memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
static /*FUNCTARGET("mmx")*/ void *mmx_cpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
#if defined (_MSC_VER) && defined (_X86_)
|
||||
_asm
|
||||
{
|
||||
mov ecx, [n]
|
||||
mov esi, [src]
|
||||
mov edi, [dest]
|
||||
shr ecx, 6 // mit mmx: 64bytes per iteration
|
||||
jz lower_64 // if lower than 64 bytes
|
||||
loop_64: // MMX transfers multiples of 64bytes
|
||||
movq mm0, 0[ESI] // read sources
|
||||
movq mm1, 8[ESI]
|
||||
movq mm2, 16[ESI]
|
||||
movq mm3, 24[ESI]
|
||||
movq mm4, 32[ESI]
|
||||
movq mm5, 40[ESI]
|
||||
movq mm6, 48[ESI]
|
||||
movq mm7, 56[ESI]
|
||||
|
||||
movq 0[EDI], mm0 // write destination
|
||||
movq 8[EDI], mm1
|
||||
movq 16[EDI], mm2
|
||||
movq 24[EDI], mm3
|
||||
movq 32[EDI], mm4
|
||||
movq 40[EDI], mm5
|
||||
movq 48[EDI], mm6
|
||||
movq 56[EDI], mm7
|
||||
|
||||
add esi, 64
|
||||
add edi, 64
|
||||
dec ecx
|
||||
jnz loop_64
|
||||
emms // close mmx operation
|
||||
lower_64:// transfer rest of buffer
|
||||
mov ebx,esi
|
||||
sub ebx,src
|
||||
mov ecx,[n]
|
||||
sub ecx,ebx
|
||||
shr ecx, 3 // multiples of 8 bytes
|
||||
jz lower_8
|
||||
loop_8:
|
||||
movq mm0, [esi] // read source
|
||||
movq [edi], mm0 // write destination
|
||||
add esi, 8
|
||||
add edi, 8
|
||||
dec ecx
|
||||
jnz loop_8
|
||||
emms // close mmx operation
|
||||
lower_8:
|
||||
mov ebx,esi
|
||||
sub ebx,src
|
||||
mov ecx,[n]
|
||||
sub ecx,ebx
|
||||
rep movsb
|
||||
mov eax, [dest] // return dest
|
||||
}
|
||||
#elif defined (__GNUC__) && defined (__i386__)
|
||||
void *retval = dest;
|
||||
size_t i;
|
||||
|
||||
if (n >= MMX1_MIN_LEN)
|
||||
{
|
||||
register unsigned long int delta;
|
||||
/* Align destinition to MMREG_SIZE -boundary */
|
||||
delta = ((unsigned long int)dest)&(MMX_MMREG_SIZE-1);
|
||||
if (delta)
|
||||
{
|
||||
delta=MMX_MMREG_SIZE-delta;
|
||||
n -= delta;
|
||||
small_memcpy(dest, src, delta);
|
||||
}
|
||||
i = n >> 6; /* n/64 */
|
||||
n&=63;
|
||||
for (; i>0; i--)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"movq (%0), %%mm0;"
|
||||
"movq 8(%0), %%mm1;"
|
||||
"movq 16(%0), %%mm2;"
|
||||
"movq 24(%0), %%mm3;"
|
||||
"movq 32(%0), %%mm4;"
|
||||
"movq 40(%0), %%mm5;"
|
||||
"movq 48(%0), %%mm6;"
|
||||
"movq 56(%0), %%mm7;"
|
||||
"movq %%mm0, (%1);"
|
||||
"movq %%mm1, 8(%1);"
|
||||
"movq %%mm2, 16(%1);"
|
||||
"movq %%mm3, 24(%1);"
|
||||
"movq %%mm4, 32(%1);"
|
||||
"movq %%mm5, 40(%1);"
|
||||
"movq %%mm6, 48(%1);"
|
||||
"movq %%mm7, 56(%1);"
|
||||
:: "r" (src), "r" (dest) : "memory");
|
||||
src = ((const unsigned char *)src) + 64;
|
||||
dest = ((unsigned char *)dest) + 64;
|
||||
}
|
||||
__asm__ __volatile__ ("emms":::"memory");
|
||||
}
|
||||
/*
|
||||
* Now do the tail of the block
|
||||
*/
|
||||
if (n) __memcpy(dest, src, n);
|
||||
return retval;
|
||||
#else
|
||||
return cpu_cpy(dest, src, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *(*M_Memcpy)(void* dest, const void* src, size_t n) = cpu_cpy;
|
||||
|
||||
/** Memcpy that uses MMX, 3DNow, MMXExt or even SSE
|
||||
* Do not use on overlapped memory, use memmove for that
|
||||
*/
|
||||
void M_SetupMemcpy(void)
|
||||
{
|
||||
#if defined (__GNUC__) && defined (__i386__)
|
||||
if (R_SSE2)
|
||||
M_Memcpy = sse_cpy;
|
||||
else if (R_MMXExt)
|
||||
M_Memcpy = mmx2_cpy;
|
||||
else if (R_3DNow)
|
||||
M_Memcpy = mmx1_cpy;
|
||||
else
|
||||
#endif
|
||||
if (R_MMX)
|
||||
M_Memcpy = mmx_cpy;
|
||||
#if 0
|
||||
M_Memcpy = cpu_cpy;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Return the appropriate message for a file error or end of file.
|
||||
*/
|
||||
const char *M_FileError(FILE *fp)
|
||||
|
@ -2805,3 +2386,17 @@ boolean M_IsStringEmpty(const char *s)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Rounds off floating numbers and checks for 0 - 255 bounds
|
||||
int M_RoundUp(double number)
|
||||
{
|
||||
if (number > 255.0l)
|
||||
return 255;
|
||||
if (number < 0.0l)
|
||||
return 0;
|
||||
|
||||
if ((int)number <= (int)(number - 0.5f))
|
||||
return (int)number + 1;
|
||||
|
||||
return (int)number;
|
||||
}
|
||||
|
|
|
@ -112,6 +112,9 @@ boolean M_IsStringEmpty(const char *s);
|
|||
// counting bits, for weapon ammo code, usually
|
||||
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||
|
||||
// Rounds off floating numbers and checks for 0 - 255 bounds
|
||||
int M_RoundUp(double number);
|
||||
|
||||
#include "w_wad.h"
|
||||
extern char configfile[MAX_WADPATH];
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "m_perfstats.h"
|
||||
#include "v_video.h"
|
||||
#include "i_video.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "netcode/d_netcmd.h"
|
||||
#include "r_main.h"
|
||||
#include "i_system.h"
|
||||
#include "z_zone.h"
|
||||
|
@ -65,7 +65,10 @@ static ps_metric_t ps_removecount = {0};
|
|||
|
||||
ps_metric_t ps_checkposition_calls = {0};
|
||||
|
||||
ps_metric_t ps_lua_prethinkframe_time = {0};
|
||||
ps_metric_t ps_lua_thinkframe_time = {0};
|
||||
ps_metric_t ps_lua_postthinkframe_time = {0};
|
||||
|
||||
ps_metric_t ps_lua_mobjhooks = {0};
|
||||
|
||||
ps_metric_t ps_otherlogictime = {0};
|
||||
|
@ -157,7 +160,9 @@ perfstatrow_t gamelogic_rows[] = {
|
|||
{" mobjs ", " Mobjs: ", &ps_thlist_times[THINK_MOBJ], PS_TIME|PS_LEVEL},
|
||||
{" dynslop", " Dynamic slopes: ", &ps_thlist_times[THINK_DYNSLOPE], PS_TIME|PS_LEVEL},
|
||||
{" precip ", " Precipitation: ", &ps_thlist_times[THINK_PRECIP], PS_TIME|PS_LEVEL},
|
||||
{" lprethinkf", " LUAh_PreThinkFrame:", &ps_lua_prethinkframe_time, PS_TIME|PS_LEVEL},
|
||||
{" lthinkf", " LUAh_ThinkFrame:", &ps_lua_thinkframe_time, PS_TIME|PS_LEVEL},
|
||||
{" lpostthinkf", " LUAh_PostThinkFrame:", &ps_lua_postthinkframe_time, PS_TIME|PS_LEVEL},
|
||||
{" other ", " Other: ", &ps_otherlogictime, PS_TIME|PS_LEVEL},
|
||||
{0}
|
||||
};
|
||||
|
@ -192,10 +197,43 @@ int ps_frame_index = 0;
|
|||
int ps_tick_index = 0;
|
||||
|
||||
// dynamically allocated resizeable array for thinkframe hook stats
|
||||
ps_hookinfo_t *prethinkframe_hooks = NULL;
|
||||
int prethinkframe_hooks_length = 0;
|
||||
int prethinkframe_hooks_capacity = 16;
|
||||
|
||||
ps_hookinfo_t *thinkframe_hooks = NULL;
|
||||
int thinkframe_hooks_length = 0;
|
||||
int thinkframe_hooks_capacity = 16;
|
||||
|
||||
ps_hookinfo_t *postthinkframe_hooks = NULL;
|
||||
int postthinkframe_hooks_length = 0;
|
||||
int postthinkframe_hooks_capacity = 16;
|
||||
|
||||
void PS_SetPreThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
||||
{
|
||||
if (!prethinkframe_hooks)
|
||||
{
|
||||
// array needs to be initialized
|
||||
prethinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * prethinkframe_hooks_capacity, PU_STATIC, NULL);
|
||||
}
|
||||
if (index >= prethinkframe_hooks_capacity)
|
||||
{
|
||||
// array needs more space, realloc with double size
|
||||
int new_capacity = prethinkframe_hooks_capacity * 2;
|
||||
prethinkframe_hooks = Z_Realloc(prethinkframe_hooks,
|
||||
sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL);
|
||||
// initialize new memory with zeros so the pointers in the structs are null
|
||||
memset(&prethinkframe_hooks[prethinkframe_hooks_capacity], 0,
|
||||
sizeof(ps_hookinfo_t) * prethinkframe_hooks_capacity);
|
||||
prethinkframe_hooks_capacity = new_capacity;
|
||||
}
|
||||
prethinkframe_hooks[index].time_taken.value.p = time_taken;
|
||||
memcpy(prethinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
|
||||
// since the values are set sequentially from begin to end, the last call should leave
|
||||
// the correct value to this variable
|
||||
prethinkframe_hooks_length = index + 1;
|
||||
}
|
||||
|
||||
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
||||
{
|
||||
if (!thinkframe_hooks)
|
||||
|
@ -221,6 +259,31 @@ void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
|||
thinkframe_hooks_length = index + 1;
|
||||
}
|
||||
|
||||
void PS_SetPostThinkFrameHookInfo(int index, precise_t time_taken, char* short_src)
|
||||
{
|
||||
if (!postthinkframe_hooks)
|
||||
{
|
||||
// array needs to be initialized
|
||||
postthinkframe_hooks = Z_Calloc(sizeof(ps_hookinfo_t) * postthinkframe_hooks_capacity, PU_STATIC, NULL);
|
||||
}
|
||||
if (index >= postthinkframe_hooks_capacity)
|
||||
{
|
||||
// array needs more space, realloc with double size
|
||||
int new_capacity = postthinkframe_hooks_capacity * 2;
|
||||
postthinkframe_hooks = Z_Realloc(postthinkframe_hooks,
|
||||
sizeof(ps_hookinfo_t) * new_capacity, PU_STATIC, NULL);
|
||||
// initialize new memory with zeros so the pointers in the structs are null
|
||||
memset(&postthinkframe_hooks[postthinkframe_hooks_capacity], 0,
|
||||
sizeof(ps_hookinfo_t) * postthinkframe_hooks_capacity);
|
||||
postthinkframe_hooks_capacity = new_capacity;
|
||||
}
|
||||
postthinkframe_hooks[index].time_taken.value.p = time_taken;
|
||||
memcpy(postthinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char));
|
||||
// since the values are set sequentially from begin to end, the last call should leave
|
||||
// the correct value to this variable
|
||||
postthinkframe_hooks_length = index + 1;
|
||||
}
|
||||
|
||||
static boolean PS_HighResolution(void)
|
||||
{
|
||||
return (vid.width >= 640 && vid.height >= 400);
|
||||
|
@ -564,7 +627,9 @@ void PS_UpdateTickStats(void)
|
|||
ps_tictime.value.p -
|
||||
ps_playerthink_time.value.p -
|
||||
ps_thinkertime.value.p -
|
||||
ps_lua_thinkframe_time.value.p;
|
||||
ps_lua_prethinkframe_time.value.p -
|
||||
ps_lua_thinkframe_time.value.p -
|
||||
ps_lua_postthinkframe_time.value.p;
|
||||
|
||||
PS_CountThinkers();
|
||||
}
|
||||
|
@ -576,21 +641,35 @@ void PS_UpdateTickStats(void)
|
|||
PS_UpdateRowHistories(misc_calls_rows, false);
|
||||
}
|
||||
}
|
||||
if (cv_perfstats.value == 3 && cv_ps_samplesize.value > 1 && PS_IsLevelActive())
|
||||
if (cv_ps_samplesize.value > 1)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < thinkframe_hooks_length; i++)
|
||||
if(cv_perfstats.value >= 3 && PS_IsLevelActive())
|
||||
{
|
||||
PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false);
|
||||
int i;
|
||||
if (cv_perfstats.value == 3)
|
||||
{
|
||||
for (i = 0; i < thinkframe_hooks_length; i++)
|
||||
PS_UpdateMetricHistory(&thinkframe_hooks[i].time_taken, true, false, false);
|
||||
}
|
||||
else if (cv_perfstats.value == 4)
|
||||
{
|
||||
for (i = 0; i < prethinkframe_hooks_length; i++)
|
||||
PS_UpdateMetricHistory(&prethinkframe_hooks[i].time_taken, true, false, false);
|
||||
}
|
||||
else if (cv_perfstats.value == 5)
|
||||
{
|
||||
for (i = 0; i < postthinkframe_hooks_length; i++)
|
||||
PS_UpdateMetricHistory(&postthinkframe_hooks[i].time_taken, true, false, false);
|
||||
}
|
||||
}
|
||||
if (cv_perfstats.value)
|
||||
{
|
||||
ps_tick_index++;
|
||||
if (ps_tick_index >= cv_ps_samplesize.value)
|
||||
ps_tick_index = 0;
|
||||
if (ps_tick_samples_left)
|
||||
ps_tick_samples_left--;
|
||||
}
|
||||
}
|
||||
if (cv_perfstats.value && cv_ps_samplesize.value > 1)
|
||||
{
|
||||
ps_tick_index++;
|
||||
if (ps_tick_index >= cv_ps_samplesize.value)
|
||||
ps_tick_index = 0;
|
||||
if (ps_tick_samples_left)
|
||||
ps_tick_samples_left--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -610,7 +689,7 @@ static void PS_DrawDescriptorHeader(void)
|
|||
int samples_left = max(ps_frame_samples_left, ps_tick_samples_left);
|
||||
int x, y;
|
||||
|
||||
if (cv_perfstats.value == 3)
|
||||
if (cv_perfstats.value >= 3)
|
||||
{
|
||||
x = 2;
|
||||
y = 0;
|
||||
|
@ -697,7 +776,7 @@ static void PS_DrawGameLogicStats(void)
|
|||
PS_DrawPerfRows(x, y, V_PURPLEMAP, misc_calls_rows);
|
||||
}
|
||||
|
||||
static void PS_DrawThinkFrameStats(void)
|
||||
static void draw_think_frame_stats(int hook_length, ps_hookinfo_t *hook)
|
||||
{
|
||||
char s[100];
|
||||
int i;
|
||||
|
@ -711,7 +790,7 @@ static void PS_DrawThinkFrameStats(void)
|
|||
|
||||
PS_DrawDescriptorHeader();
|
||||
|
||||
for (i = 0; i < thinkframe_hooks_length; i++)
|
||||
for (i = 0; i < hook_length; i++)
|
||||
{
|
||||
|
||||
#define NEXT_ROW() \
|
||||
|
@ -724,7 +803,7 @@ if (y > 192) \
|
|||
break; \
|
||||
}
|
||||
|
||||
char* str = thinkframe_hooks[i].short_src;
|
||||
char* str = hook[i].short_src;
|
||||
char* tempstr = tempbuffer;
|
||||
int len = (int)strlen(str);
|
||||
char* str_ptr;
|
||||
|
@ -771,7 +850,7 @@ if (y > 192) \
|
|||
if (len > 20)
|
||||
str += len - 20;
|
||||
snprintf(s, sizeof s - 1, "%20s: %d", str,
|
||||
PS_GetMetricScreenValue(&thinkframe_hooks[i].time_taken, true));
|
||||
PS_GetMetricScreenValue(&hook[i].time_taken, true));
|
||||
V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s);
|
||||
NEXT_ROW()
|
||||
|
||||
|
@ -780,6 +859,21 @@ if (y > 192) \
|
|||
}
|
||||
}
|
||||
|
||||
static void PS_DrawPreThinkFrameStats(void)
|
||||
{
|
||||
draw_think_frame_stats(prethinkframe_hooks_length, prethinkframe_hooks);
|
||||
}
|
||||
|
||||
static void PS_DrawThinkFrameStats(void)
|
||||
{
|
||||
draw_think_frame_stats(thinkframe_hooks_length, thinkframe_hooks);
|
||||
}
|
||||
|
||||
static void PS_DrawPostThinkFrameStats(void)
|
||||
{
|
||||
draw_think_frame_stats(postthinkframe_hooks_length, postthinkframe_hooks);
|
||||
}
|
||||
|
||||
void M_DrawPerfStats(void)
|
||||
{
|
||||
if (cv_perfstats.value == 1) // rendering
|
||||
|
@ -793,7 +887,7 @@ void M_DrawPerfStats(void)
|
|||
// tics when frame skips happen
|
||||
PS_DrawGameLogicStats();
|
||||
}
|
||||
else if (cv_perfstats.value == 3) // lua thinkframe
|
||||
else if (cv_perfstats.value >= 3) // lua thinkframe
|
||||
{
|
||||
if (!PS_IsLevelActive())
|
||||
return;
|
||||
|
@ -802,13 +896,22 @@ void M_DrawPerfStats(void)
|
|||
// Low resolutions can't really use V_DrawSmallString that is used by thinkframe stats.
|
||||
// A low-res version using V_DrawThinString could be implemented,
|
||||
// but it would have much less space for information.
|
||||
V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Perfstats 3 is not available");
|
||||
V_DrawThinString(80, 92, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Lua Perfstats is not available");
|
||||
V_DrawThinString(80, 100, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "for resolutions below 640x400.");
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (cv_perfstats.value == 3)
|
||||
{
|
||||
PS_DrawThinkFrameStats();
|
||||
}
|
||||
else if (cv_perfstats.value == 4)
|
||||
{
|
||||
PS_DrawPreThinkFrameStats();
|
||||
}
|
||||
else if (cv_perfstats.value == 5)
|
||||
{
|
||||
PS_DrawPostThinkFrameStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -43,12 +43,16 @@ extern ps_metric_t ps_thlist_times[];
|
|||
|
||||
extern ps_metric_t ps_checkposition_calls;
|
||||
|
||||
extern ps_metric_t ps_lua_prethinkframe_time;
|
||||
extern ps_metric_t ps_lua_thinkframe_time;
|
||||
extern ps_metric_t ps_lua_postthinkframe_time;
|
||||
extern ps_metric_t ps_lua_mobjhooks;
|
||||
|
||||
extern ps_metric_t ps_otherlogictime;
|
||||
|
||||
void PS_SetPreThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
|
||||
void PS_SetThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
|
||||
void PS_SetPostThinkFrameHookInfo(int index, precise_t time_taken, char* short_src);
|
||||
|
||||
void PS_UpdateTickStats(void);
|
||||
|
||||
|
|
15
src/netcode/CMakeLists.txt
Normal file
15
src/netcode/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
target_sources(SRB2SDL2 PRIVATE
|
||||
d_clisrv.c
|
||||
server_connection.c
|
||||
client_connection.c
|
||||
tic_command.c
|
||||
net_command.c
|
||||
gamestate.c
|
||||
commands.c
|
||||
d_net.c
|
||||
d_netcmd.c
|
||||
d_netfil.c
|
||||
http-mserv.c
|
||||
i_tcp.c
|
||||
mserv.c
|
||||
)
|
13
src/netcode/Sourcefile
Normal file
13
src/netcode/Sourcefile
Normal file
|
@ -0,0 +1,13 @@
|
|||
d_clisrv.c
|
||||
server_connection.c
|
||||
client_connection.c
|
||||
tic_command.c
|
||||
net_command.c
|
||||
gamestate.c
|
||||
commands.c
|
||||
d_net.c
|
||||
d_netcmd.c
|
||||
d_netfil.c
|
||||
http-mserv.c
|
||||
i_tcp.c
|
||||
mserv.c
|
1178
src/netcode/client_connection.c
Normal file
1178
src/netcode/client_connection.c
Normal file
File diff suppressed because it is too large
Load diff
61
src/netcode/client_connection.h
Normal file
61
src/netcode/client_connection.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file client_connection.h
|
||||
/// \brief Client connection handling
|
||||
|
||||
#ifndef __D_CLIENT_CONNECTION__
|
||||
#define __D_CLIENT_CONNECTION__
|
||||
|
||||
#include "../doomtype.h"
|
||||
#include "d_clisrv.h"
|
||||
|
||||
#define MAXSERVERLIST (MAXNETNODES-1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SINT8 node;
|
||||
serverinfo_pak info;
|
||||
} serverelem_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CL_SEARCHING,
|
||||
CL_CHECKFILES,
|
||||
CL_DOWNLOADFILES,
|
||||
CL_ASKJOIN,
|
||||
CL_LOADFILES,
|
||||
CL_WAITJOINRESPONSE,
|
||||
CL_DOWNLOADSAVEGAME,
|
||||
CL_CONNECTED,
|
||||
CL_ABORTED,
|
||||
CL_ASKFULLFILELIST,
|
||||
CL_CONFIRMCONNECT
|
||||
} cl_mode_t;
|
||||
|
||||
extern serverelem_t serverlist[MAXSERVERLIST];
|
||||
extern UINT32 serverlistcount;
|
||||
|
||||
extern cl_mode_t cl_mode;
|
||||
extern boolean serverisfull; //lets us be aware if the server was full after we check files, but before downloading, so we can ask if the user still wants to download or not
|
||||
extern tic_t firstconnectattempttime;
|
||||
extern UINT8 mynode; // my address pointofview server
|
||||
|
||||
void CL_QueryServerList(msg_server_t *list);
|
||||
void CL_UpdateServerList(boolean internetsearch, INT32 room);
|
||||
|
||||
void CL_ConnectToServer(void);
|
||||
boolean CL_SendJoin(void);
|
||||
|
||||
void PT_ServerInfo(SINT8 node);
|
||||
void PT_MoreFilesNeeded(SINT8 node);
|
||||
void PT_ServerRefuse(SINT8 node);
|
||||
void PT_ServerCFG(SINT8 node);
|
||||
|
||||
#endif
|
492
src/netcode/commands.c
Normal file
492
src/netcode/commands.c
Normal file
|
@ -0,0 +1,492 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file commands.c
|
||||
/// \brief Various netgame commands, such as kick and ban
|
||||
|
||||
#include "commands.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "client_connection.h"
|
||||
#include "net_command.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "i_net.h"
|
||||
#include "protocol.h"
|
||||
#include "../byteptr.h"
|
||||
#include "../d_main.h"
|
||||
#include "../g_game.h"
|
||||
#include "../w_wad.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../doomstat.h"
|
||||
#include "../doomdef.h"
|
||||
#include "../r_local.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct banreason_s
|
||||
{
|
||||
char *reason;
|
||||
struct banreason_s *prev; //-1
|
||||
struct banreason_s *next; //+1
|
||||
} banreason_t;
|
||||
|
||||
static banreason_t *reasontail = NULL; //last entry, use prev
|
||||
static banreason_t *reasonhead = NULL; //1st entry, use next
|
||||
|
||||
void Ban_Add(const char *reason)
|
||||
{
|
||||
banreason_t *reasonlist = malloc(sizeof(*reasonlist));
|
||||
|
||||
if (!reasonlist)
|
||||
return;
|
||||
if (!reason)
|
||||
reason = "NA";
|
||||
|
||||
reasonlist->next = NULL;
|
||||
reasonlist->reason = Z_StrDup(reason);
|
||||
if ((reasonlist->prev = reasontail) == NULL)
|
||||
reasonhead = reasonlist;
|
||||
else
|
||||
reasontail->next = reasonlist;
|
||||
reasontail = reasonlist;
|
||||
}
|
||||
|
||||
static void Ban_Clear(void)
|
||||
{
|
||||
banreason_t *temp;
|
||||
|
||||
I_ClearBans();
|
||||
|
||||
reasontail = NULL;
|
||||
|
||||
while (reasonhead)
|
||||
{
|
||||
temp = reasonhead->next;
|
||||
Z_Free(reasonhead->reason);
|
||||
free(reasonhead);
|
||||
reasonhead = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void Ban_Load_File(boolean warning)
|
||||
{
|
||||
FILE *f;
|
||||
char *address, *mask;
|
||||
char buffer[MAX_WADPATH];
|
||||
|
||||
if (!I_ClearBans)
|
||||
return;
|
||||
|
||||
f = fopen(va("%s"PATHSEP"%s", srb2home, "ban.txt"), "r");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
if (warning)
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Could not open ban.txt for ban list\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
Ban_Clear();
|
||||
|
||||
for (; fgets(buffer, (int)sizeof(buffer), f);)
|
||||
{
|
||||
address = strtok(buffer, " \t\r\n");
|
||||
mask = strtok(NULL, " \t\r\n");
|
||||
if (address[0] == '[')
|
||||
{
|
||||
size_t len;
|
||||
address++;
|
||||
len = strlen(address);
|
||||
if (address[len-1] == ']')
|
||||
address[len-1] = '\0';
|
||||
}
|
||||
|
||||
I_SetBanAddress(address, mask);
|
||||
|
||||
Ban_Add(strtok(NULL, "\r\n"));
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void D_SaveBan(void)
|
||||
{
|
||||
FILE *f;
|
||||
banreason_t *reasonlist = reasonhead;
|
||||
const char *address, *mask;
|
||||
const char *path = va("%s"PATHSEP"%s", srb2home, "ban.txt");
|
||||
|
||||
if (!reasonhead)
|
||||
{
|
||||
remove(path);
|
||||
return;
|
||||
}
|
||||
|
||||
f = fopen(path, "w");
|
||||
|
||||
if (!f)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Could not save ban list into ban.txt\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0;(address = I_GetBanAddress(i)) != NULL;i++)
|
||||
{
|
||||
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
|
||||
fprintf(f, "%s 0", address);
|
||||
else
|
||||
fprintf(f, "%s %s", address, mask);
|
||||
|
||||
if (reasonlist && reasonlist->reason)
|
||||
fprintf(f, " %s\n", reasonlist->reason);
|
||||
else
|
||||
fprintf(f, " %s\n", "NA");
|
||||
|
||||
if (reasonlist) reasonlist = reasonlist->next;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
void Command_ShowBan(void) //Print out ban list
|
||||
{
|
||||
size_t i;
|
||||
const char *address, *mask;
|
||||
banreason_t *reasonlist = reasonhead;
|
||||
|
||||
if (I_GetBanAddress)
|
||||
CONS_Printf(M_GetText("Ban List:\n"));
|
||||
else
|
||||
return;
|
||||
|
||||
for (i = 0;(address = I_GetBanAddress(i)) != NULL;i++)
|
||||
{
|
||||
if (!I_GetBanMask || (mask = I_GetBanMask(i)) == NULL)
|
||||
CONS_Printf("%s: %s ", sizeu1(i+1), address);
|
||||
else
|
||||
CONS_Printf("%s: %s/%s ", sizeu1(i+1), address, mask);
|
||||
|
||||
if (reasonlist && reasonlist->reason)
|
||||
CONS_Printf("(%s)\n", reasonlist->reason);
|
||||
else
|
||||
CONS_Printf("\n");
|
||||
|
||||
if (reasonlist) reasonlist = reasonlist->next;
|
||||
}
|
||||
|
||||
if (i == 0 && !address)
|
||||
CONS_Printf(M_GetText("(empty)\n"));
|
||||
}
|
||||
|
||||
void Command_ClearBans(void)
|
||||
{
|
||||
if (!I_ClearBans)
|
||||
return;
|
||||
|
||||
Ban_Clear();
|
||||
D_SaveBan();
|
||||
}
|
||||
|
||||
void Command_Ban(void)
|
||||
{
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("Ban <playername/playernum> <reason>: ban and kick a player\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!netgame) // Don't kick Tails in splitscreen!
|
||||
{
|
||||
CONS_Printf(M_GetText("This only works in a netgame.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (server || IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
UINT8 buf[3 + MAX_REASONLENGTH];
|
||||
UINT8 *p = buf;
|
||||
const SINT8 pn = nametonum(COM_Argv(1));
|
||||
const INT32 node = playernode[(INT32)pn];
|
||||
|
||||
if (pn == -1 || pn == 0)
|
||||
return;
|
||||
|
||||
WRITEUINT8(p, pn);
|
||||
|
||||
if (server && I_Ban && !I_Ban(node)) // only the server is allowed to do this right now
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Too many bans! Geez, that's a lot of people you're excluding...\n"));
|
||||
WRITEUINT8(p, KICK_MSG_GO_AWAY);
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (server) // only the server is allowed to do this right now
|
||||
{
|
||||
Ban_Add(COM_Argv(2));
|
||||
D_SaveBan(); // save the ban list
|
||||
}
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
WRITEUINT8(p, KICK_MSG_BANNED);
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t j = COM_Argc();
|
||||
char message[MAX_REASONLENGTH];
|
||||
|
||||
//Steal from the motd code so you don't have to put the reason in quotes.
|
||||
strlcpy(message, COM_Argv(2), sizeof message);
|
||||
for (size_t i = 3; i < j; i++)
|
||||
{
|
||||
strlcat(message, " ", sizeof message);
|
||||
strlcat(message, COM_Argv(i), sizeof message);
|
||||
}
|
||||
|
||||
WRITEUINT8(p, KICK_MSG_CUSTOM_BAN);
|
||||
WRITESTRINGN(p, message, MAX_REASONLENGTH);
|
||||
SendNetXCmd(XD_KICK, &buf, p - buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
|
||||
|
||||
}
|
||||
|
||||
void Command_BanIP(void)
|
||||
{
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("banip <ip> <reason>: ban an ip address\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (server) // Only the server can use this, otherwise does nothing.
|
||||
{
|
||||
const char *address = (COM_Argv(1));
|
||||
const char *reason;
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
reason = NULL;
|
||||
else
|
||||
reason = COM_Argv(2);
|
||||
|
||||
|
||||
if (I_SetBanAddress && I_SetBanAddress(address, NULL))
|
||||
{
|
||||
if (reason)
|
||||
CONS_Printf("Banned IP address %s for: %s\n", address, reason);
|
||||
else
|
||||
CONS_Printf("Banned IP address %s\n", address);
|
||||
|
||||
Ban_Add(reason);
|
||||
D_SaveBan();
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Command_ReloadBan(void) //recheck ban.txt
|
||||
{
|
||||
Ban_Load_File(true);
|
||||
}
|
||||
|
||||
void Command_Kick(void)
|
||||
{
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("kick <playername/playernum> <reason>: kick a player\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!netgame) // Don't kick Tails in splitscreen!
|
||||
{
|
||||
CONS_Printf(M_GetText("This only works in a netgame.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (server || IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
UINT8 buf[3 + MAX_REASONLENGTH];
|
||||
UINT8 *p = buf;
|
||||
const SINT8 pn = nametonum(COM_Argv(1));
|
||||
|
||||
if (pn == -1 || pn == 0)
|
||||
return;
|
||||
|
||||
// Special case if we are trying to kick a player who is downloading the game state:
|
||||
// trigger a timeout instead of kicking them, because a kick would only
|
||||
// take effect after they have finished downloading
|
||||
if (server && playernode[pn] != UINT8_MAX && netnodes[playernode[pn]].sendingsavegame)
|
||||
{
|
||||
Net_ConnectionTimeout(playernode[pn]);
|
||||
return;
|
||||
}
|
||||
|
||||
WRITESINT8(p, pn);
|
||||
|
||||
if (COM_Argc() == 2)
|
||||
{
|
||||
WRITEUINT8(p, KICK_MSG_GO_AWAY);
|
||||
SendNetXCmd(XD_KICK, &buf, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t j = COM_Argc();
|
||||
char message[MAX_REASONLENGTH];
|
||||
|
||||
//Steal from the motd code so you don't have to put the reason in quotes.
|
||||
strlcpy(message, COM_Argv(2), sizeof message);
|
||||
for (size_t i = 3; i < j; i++)
|
||||
{
|
||||
strlcat(message, " ", sizeof message);
|
||||
strlcat(message, COM_Argv(i), sizeof message);
|
||||
}
|
||||
|
||||
WRITEUINT8(p, KICK_MSG_CUSTOM_KICK);
|
||||
WRITESTRINGN(p, message, MAX_REASONLENGTH);
|
||||
SendNetXCmd(XD_KICK, &buf, p - buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n"));
|
||||
}
|
||||
|
||||
void Command_connect(void)
|
||||
{
|
||||
if (COM_Argc() < 2 || *COM_Argv(1) == 0)
|
||||
{
|
||||
CONS_Printf(M_GetText(
|
||||
"Connect <serveraddress> (port): connect to a server\n"
|
||||
"Connect ANY: connect to the first lan server found\n"
|
||||
//"Connect SELF: connect to your own server.\n"
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
if (Playing() || titledemo)
|
||||
{
|
||||
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
server = false;
|
||||
/*
|
||||
if (!stricmp(COM_Argv(1), "self"))
|
||||
{
|
||||
servernode = 0;
|
||||
server = true;
|
||||
/// \bug should be but...
|
||||
//SV_SpawnServer();
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
// used in menu to connect to a server in the list
|
||||
if (netgame && !stricmp(COM_Argv(1), "node"))
|
||||
{
|
||||
servernode = (SINT8)atoi(COM_Argv(2));
|
||||
}
|
||||
else if (netgame)
|
||||
{
|
||||
CONS_Printf(M_GetText("You cannot connect while in a game. End this game first.\n"));
|
||||
return;
|
||||
}
|
||||
else if (I_NetOpenSocket)
|
||||
{
|
||||
I_NetOpenSocket();
|
||||
netgame = true;
|
||||
multiplayer = true;
|
||||
|
||||
if (!stricmp(COM_Argv(1), "any"))
|
||||
servernode = BROADCASTADDR;
|
||||
else if (I_NetMakeNodewPort)
|
||||
{
|
||||
if (COM_Argc() >= 3) // address AND port
|
||||
servernode = I_NetMakeNodewPort(COM_Argv(1), COM_Argv(2));
|
||||
else // address only, or address:port
|
||||
servernode = I_NetMakeNode(COM_Argv(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("There is no server identification with this network driver\n"));
|
||||
D_CloseConnection();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
CONS_Alert(CONS_ERROR, M_GetText("There is no network driver\n"));
|
||||
}
|
||||
|
||||
splitscreen = false;
|
||||
SplitScreen_OnChange();
|
||||
botingame = false;
|
||||
botskin = 0;
|
||||
CL_ConnectToServer();
|
||||
}
|
||||
|
||||
void Command_GetPlayerNum(void)
|
||||
{
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i])
|
||||
{
|
||||
if (serverplayer == i)
|
||||
CONS_Printf(M_GetText("num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]);
|
||||
else
|
||||
CONS_Printf(M_GetText("\x82num:%2d node:%2d %s\n"), i, playernode[i], player_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** Lists all players and their player numbers.
|
||||
*
|
||||
* \sa Command_GetPlayerNum
|
||||
*/
|
||||
void Command_Nodes(void)
|
||||
{
|
||||
size_t maxlen = 0;
|
||||
const char *address;
|
||||
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
const size_t plen = strlen(player_names[i]);
|
||||
if (playeringame[i] && plen > maxlen)
|
||||
maxlen = plen;
|
||||
}
|
||||
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
CONS_Printf("%.2u: %*s", i, (int)maxlen, player_names[i]);
|
||||
|
||||
if (playernode[i] != UINT8_MAX)
|
||||
{
|
||||
CONS_Printf(" - node %.2d", playernode[i]);
|
||||
if (I_GetNodeAddress && (address = I_GetNodeAddress(playernode[i])) != NULL)
|
||||
CONS_Printf(" - %s", address);
|
||||
}
|
||||
|
||||
if (IsPlayerAdmin(i))
|
||||
CONS_Printf(M_GetText(" (verified admin)"));
|
||||
|
||||
if (players[i].spectator)
|
||||
CONS_Printf(M_GetText(" (spectator)"));
|
||||
|
||||
CONS_Printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
33
src/netcode/commands.h
Normal file
33
src/netcode/commands.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file commands.h
|
||||
/// \brief Various netgame commands, such as kick and ban
|
||||
|
||||
#ifndef __COMMANDS__
|
||||
#define __COMMANDS__
|
||||
|
||||
#include "../doomdef.h"
|
||||
|
||||
#define MAX_REASONLENGTH 30
|
||||
|
||||
void Ban_Add(const char *reason);
|
||||
void D_SaveBan(void);
|
||||
void Ban_Load_File(boolean warning);
|
||||
void Command_ShowBan(void);
|
||||
void Command_ClearBans(void);
|
||||
void Command_Ban(void);
|
||||
void Command_BanIP(void);
|
||||
void Command_ReloadBan(void);
|
||||
void Command_Kick(void);
|
||||
void Command_connect(void);
|
||||
void Command_GetPlayerNum(void);
|
||||
void Command_Nodes(void);
|
||||
|
||||
#endif
|
1790
src/netcode/d_clisrv.c
Normal file
1790
src/netcode/d_clisrv.c
Normal file
File diff suppressed because it is too large
Load diff
136
src/netcode/d_clisrv.h
Normal file
136
src/netcode/d_clisrv.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file d_clisrv.h
|
||||
/// \brief high level networking stuff
|
||||
|
||||
#ifndef __D_CLISRV__
|
||||
#define __D_CLISRV__
|
||||
|
||||
#include "protocol.h"
|
||||
#include "../d_ticcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netcmd.h"
|
||||
#include "d_net.h"
|
||||
#include "../tables.h"
|
||||
#include "../d_player.h"
|
||||
#include "mserv.h"
|
||||
|
||||
#define CLIENTBACKUPTICS 32
|
||||
|
||||
#ifdef PACKETDROP
|
||||
void Command_Drop(void);
|
||||
void Command_Droprate(void);
|
||||
#endif
|
||||
#ifdef _DEBUG
|
||||
void Command_Numnodes(void);
|
||||
#endif
|
||||
|
||||
extern INT32 mapchangepending;
|
||||
|
||||
// Points inside doomcom
|
||||
extern doomdata_t *netbuffer;
|
||||
|
||||
#define BASEPACKETSIZE offsetof(doomdata_t, u)
|
||||
#define BASESERVERTICSSIZE offsetof(doomdata_t, u.serverpak.cmds[0])
|
||||
|
||||
typedef enum
|
||||
{
|
||||
KR_KICK = 1, //Kicked by server
|
||||
KR_PINGLIMIT = 2, //Broke Ping Limit
|
||||
KR_SYNCH = 3, //Synch Failure
|
||||
KR_TIMEOUT = 4, //Connection Timeout
|
||||
KR_BAN = 5, //Banned by server
|
||||
KR_LEAVE = 6, //Quit the game
|
||||
KR_IDLE = 7, //Remained still for too long
|
||||
} kickreason_t;
|
||||
|
||||
/* the max number of name changes in some time period */
|
||||
#define MAXNAMECHANGES (5)
|
||||
#define NAMECHANGERATE (60*TICRATE)
|
||||
|
||||
extern boolean server;
|
||||
extern boolean serverrunning;
|
||||
#define client (!server)
|
||||
extern boolean dedicated; // For dedicated server
|
||||
extern UINT16 software_MAXPACKETLENGTH;
|
||||
extern boolean acceptnewnode;
|
||||
extern SINT8 servernode;
|
||||
extern tic_t maketic;
|
||||
extern tic_t neededtic;
|
||||
extern INT16 consistancy[BACKUPTICS];
|
||||
|
||||
void Command_Ping_f(void);
|
||||
extern tic_t connectiontimeout;
|
||||
extern UINT16 pingmeasurecount;
|
||||
extern UINT32 realpingtable[MAXPLAYERS];
|
||||
extern UINT32 playerpingtable[MAXPLAYERS];
|
||||
extern tic_t servermaxping;
|
||||
|
||||
extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime;
|
||||
|
||||
// Used in d_net, the only dependence
|
||||
void D_ClientServerInit(void);
|
||||
|
||||
// Create any new ticcmds and broadcast to other players.
|
||||
void NetUpdate(void);
|
||||
|
||||
// Maintain connections to nodes without timing them all out.
|
||||
void NetKeepAlive(void);
|
||||
|
||||
void GetPackets(void);
|
||||
void ResetNode(INT32 node);
|
||||
INT16 Consistancy(void);
|
||||
|
||||
void SV_StartSinglePlayerServer(void);
|
||||
void SV_SpawnServer(void);
|
||||
void SV_StopServer(void);
|
||||
void SV_ResetServer(void);
|
||||
void CL_AddSplitscreenPlayer(void);
|
||||
void CL_RemoveSplitscreenPlayer(void);
|
||||
void CL_Reset(void);
|
||||
void CL_ClearPlayer(INT32 playernum);
|
||||
void CL_RemovePlayer(INT32 playernum, kickreason_t reason);
|
||||
void CL_HandleTimeout(void);
|
||||
// Is there a game running
|
||||
boolean Playing(void);
|
||||
|
||||
// Broadcasts special packets to other players
|
||||
// to notify of game exit
|
||||
void D_QuitNetGame(void);
|
||||
|
||||
//? How many ticks to run?
|
||||
boolean TryRunTics(tic_t realtic);
|
||||
|
||||
// extra data for lmps
|
||||
// these functions scare me. they contain magic.
|
||||
/*boolean AddLmpExtradata(UINT8 **demo_p, INT32 playernum);
|
||||
void ReadLmpExtraData(UINT8 **demo_pointer, INT32 playernum);*/
|
||||
|
||||
// translate a playername in a player number return -1 if not found and
|
||||
// print a error message in the console
|
||||
SINT8 nametonum(const char *name);
|
||||
|
||||
extern char motd[254], server_context[8];
|
||||
extern UINT8 playernode[MAXPLAYERS];
|
||||
|
||||
INT32 D_NumPlayers(void);
|
||||
INT32 D_NumNodes(void);
|
||||
INT32 D_NumBots(void);
|
||||
|
||||
tic_t GetLag(INT32 node);
|
||||
|
||||
void D_MD5PasswordPass(const UINT8 *buffer, size_t len, const char *salt, void *dest);
|
||||
|
||||
extern UINT8 (*adminpassmd5)[16];
|
||||
extern UINT32 adminpasscount;
|
||||
|
||||
extern boolean hu_stopped;
|
||||
|
||||
#endif
|
|
@ -16,19 +16,21 @@
|
|||
/// This protocol uses a mix of "goback n" and "selective repeat" implementation
|
||||
/// The NOTHING packet is sent when connection is idle to acknowledge packets
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "../doomdef.h"
|
||||
#include "../g_game.h"
|
||||
#include "../i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
#include "../i_system.h"
|
||||
#include "../m_argv.h"
|
||||
#include "d_net.h"
|
||||
#include "w_wad.h"
|
||||
#include "../w_wad.h"
|
||||
#include "d_netfil.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "z_zone.h"
|
||||
#include "tic_command.h"
|
||||
#include "net_command.h"
|
||||
#include "../z_zone.h"
|
||||
#include "i_tcp.h"
|
||||
#include "d_main.h" // srb2home
|
||||
#include "../d_main.h" // srb2home
|
||||
|
||||
//
|
||||
// NETWORKING
|
||||
|
@ -138,7 +140,6 @@ boolean Net_GetNetStat(void)
|
|||
#define URGENTFREESLOTNUM 10
|
||||
#define ACKTOSENDTIMEOUT (TICRATE/11)
|
||||
|
||||
#ifndef NONET
|
||||
typedef struct
|
||||
{
|
||||
UINT8 acknum;
|
||||
|
@ -152,7 +153,6 @@ typedef struct
|
|||
doomdata_t data;
|
||||
} pak;
|
||||
} ackpak_t;
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -160,10 +160,8 @@ typedef enum
|
|||
NF_TIMEOUT = 2, // Flag is set when the node got a timeout
|
||||
} node_flags_t;
|
||||
|
||||
#ifndef NONET
|
||||
// Table of packets that were not acknowleged can be resent (the sender window)
|
||||
static ackpak_t ackpak[MAXACKPACKETS];
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -191,7 +189,6 @@ typedef struct
|
|||
static node_t nodes[MAXNETNODES];
|
||||
#define NODETIMEOUT 14
|
||||
|
||||
#ifndef NONET
|
||||
// return <0 if a < b (mod 256)
|
||||
// 0 if a = n (mod 256)
|
||||
// >0 if a > b (mod 256)
|
||||
|
@ -214,7 +211,7 @@ FUNCMATH static INT32 cmpack(UINT8 a, UINT8 b)
|
|||
static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
|
||||
{
|
||||
node_t *node = &nodes[doomcom->remotenode];
|
||||
INT32 i, numfreeslot = 0;
|
||||
INT32 numfreeslot = 0;
|
||||
|
||||
if (cmpack((UINT8)((node->remotefirstack + MAXACKTOSEND) % 256), node->nextacknum) < 0)
|
||||
{
|
||||
|
@ -222,7 +219,7 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
|
|||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (!ackpak[i].acknum)
|
||||
{
|
||||
// For low priority packets, make sure to let freeslots so urgent packets can be sent
|
||||
|
@ -279,10 +276,10 @@ static boolean GetFreeAcknum(UINT8 *freeack, boolean lowtimer)
|
|||
*/
|
||||
INT32 Net_GetFreeAcks(boolean urgent)
|
||||
{
|
||||
INT32 i, numfreeslot = 0;
|
||||
INT32 numfreeslot = 0;
|
||||
INT32 n = 0; // Number of free acks found
|
||||
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (!ackpak[i].acknum)
|
||||
{
|
||||
// For low priority packets, make sure to let freeslots so urgent packets can be sent
|
||||
|
@ -316,10 +313,9 @@ static void RemoveAck(INT32 i)
|
|||
}
|
||||
|
||||
// We have got a packet, proceed the ack request and ack return
|
||||
static boolean Processackpak(void)
|
||||
static int Processackpak(void)
|
||||
{
|
||||
INT32 i;
|
||||
boolean goodpacket = true;
|
||||
int goodpacket = 0;
|
||||
node_t *node = &nodes[doomcom->remotenode];
|
||||
|
||||
// Received an ack return, so remove the ack in the list
|
||||
|
@ -327,7 +323,7 @@ static boolean Processackpak(void)
|
|||
{
|
||||
node->remotefirstack = netbuffer->ackreturn;
|
||||
// Search the ackbuffer and free it
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (ackpak[i].acknum && ackpak[i].destinationnode == node - nodes
|
||||
&& cmpack(ackpak[i].acknum, netbuffer->ackreturn) <= 0)
|
||||
{
|
||||
|
@ -344,20 +340,20 @@ static boolean Processackpak(void)
|
|||
{
|
||||
DEBFILE(va("Discard(1) ack %d (duplicated)\n", ack));
|
||||
duppacket++;
|
||||
goodpacket = false; // Discard packet (duplicate)
|
||||
goodpacket = 1; // Discard packet (duplicate)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if it is not already in the queue
|
||||
for (i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
|
||||
for (INT32 i = node->acktosend_tail; i != node->acktosend_head; i = (i+1) % MAXACKTOSEND)
|
||||
if (node->acktosend[i] == ack)
|
||||
{
|
||||
DEBFILE(va("Discard(2) ack %d (duplicated)\n", ack));
|
||||
duppacket++;
|
||||
goodpacket = false; // Discard packet (duplicate)
|
||||
goodpacket = 1; // Discard packet (duplicate)
|
||||
break;
|
||||
}
|
||||
if (goodpacket)
|
||||
if (goodpacket == 0)
|
||||
{
|
||||
// Is a good packet so increment the acknowledge number,
|
||||
// Then search for a "hole" in the queue
|
||||
|
@ -377,7 +373,7 @@ static boolean Processackpak(void)
|
|||
while (change)
|
||||
{
|
||||
change = false;
|
||||
for (i = node->acktosend_tail; i != node->acktosend_head;
|
||||
for (INT32 i = node->acktosend_tail; i != node->acktosend_head;
|
||||
i = (i+1) % MAXACKTOSEND)
|
||||
{
|
||||
if (cmpack(node->acktosend[i], nextfirstack) <= 0)
|
||||
|
@ -418,36 +414,29 @@ static boolean Processackpak(void)
|
|||
else // Buffer full discard packet, sender will resend it
|
||||
{ // We can admit the packet but we will not detect the duplication after :(
|
||||
DEBFILE("no more freeackret\n");
|
||||
goodpacket = false;
|
||||
goodpacket = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// return values: 0 = ok, 1 = duplicate, 2 = out of order
|
||||
return goodpacket;
|
||||
}
|
||||
#endif
|
||||
|
||||
// send special packet with only ack on it
|
||||
void Net_SendAcks(INT32 node)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)node;
|
||||
#else
|
||||
netbuffer->packettype = PT_NOTHING;
|
||||
M_Memcpy(netbuffer->u.textcmd, nodes[node].acktosend, MAXACKTOSEND);
|
||||
HSendPacket(node, false, 0, MAXACKTOSEND);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static void GotAcks(void)
|
||||
{
|
||||
INT32 i, j;
|
||||
|
||||
for (j = 0; j < MAXACKTOSEND; j++)
|
||||
for (INT32 j = 0; j < MAXACKTOSEND; j++)
|
||||
if (netbuffer->u.textcmd[j])
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (ackpak[i].acknum && ackpak[i].destinationnode == doomcom->remotenode)
|
||||
{
|
||||
if (ackpak[i].acknum == netbuffer->u.textcmd[j])
|
||||
|
@ -463,7 +452,6 @@ static void GotAcks(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void Net_ConnectionTimeout(INT32 node)
|
||||
{
|
||||
|
@ -472,14 +460,10 @@ void Net_ConnectionTimeout(INT32 node)
|
|||
return;
|
||||
nodes[node].flags |= NF_TIMEOUT;
|
||||
|
||||
// Send a very special packet to self (hack the reboundstore queue)
|
||||
// Main code will handle it
|
||||
reboundstore[rebound_head].packettype = PT_NODETIMEOUT;
|
||||
reboundstore[rebound_head].ack = 0;
|
||||
reboundstore[rebound_head].ackreturn = 0;
|
||||
reboundstore[rebound_head].u.textcmd[0] = (UINT8)node;
|
||||
reboundsize[rebound_head] = (INT16)(BASEPACKETSIZE + 1);
|
||||
rebound_head = (rebound_head+1) % MAXREBOUND;
|
||||
if (server)
|
||||
SendKicksForNode(node, KICK_MSG_TIMEOUT | KICK_MSG_KEEP_BODY);
|
||||
else
|
||||
CL_HandleTimeout();
|
||||
|
||||
// Do not redo it quickly (if we do not close connection it is
|
||||
// for a good reason!)
|
||||
|
@ -489,10 +473,8 @@ void Net_ConnectionTimeout(INT32 node)
|
|||
// Resend the data if needed
|
||||
void Net_AckTicker(void)
|
||||
{
|
||||
#ifndef NONET
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
{
|
||||
const INT32 nodei = ackpak[i].destinationnode;
|
||||
node_t *node = &nodes[nodei];
|
||||
|
@ -519,7 +501,7 @@ void Net_AckTicker(void)
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 1; i < MAXNETNODES; i++)
|
||||
for (INT32 i = 1; i < MAXNETNODES; i++)
|
||||
{
|
||||
// This is something like node open flag
|
||||
if (nodes[i].firstacktosend)
|
||||
|
@ -536,16 +518,12 @@ void Net_AckTicker(void)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remove last packet received ack before resending the ackreturn
|
||||
// (the higher layer doesn't have room, or something else ....)
|
||||
void Net_UnAcknowledgePacket(INT32 node)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)node;
|
||||
#else
|
||||
INT32 hm1 = (nodes[node].acktosend_head-1+MAXACKTOSEND) % MAXACKTOSEND;
|
||||
DEBFILE(va("UnAcknowledge node %d\n", node));
|
||||
if (!node)
|
||||
|
@ -577,10 +555,8 @@ void Net_UnAcknowledgePacket(INT32 node)
|
|||
if (!nodes[node].firstacktosend)
|
||||
nodes[node].firstacktosend = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
/** Checks if all acks have been received
|
||||
*
|
||||
* \return True if all acks have been received
|
||||
|
@ -588,15 +564,12 @@ void Net_UnAcknowledgePacket(INT32 node)
|
|||
*/
|
||||
static boolean Net_AllAcksReceived(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (ackpak[i].acknum)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Waits for all ackreturns
|
||||
*
|
||||
|
@ -605,9 +578,6 @@ static boolean Net_AllAcksReceived(void)
|
|||
*/
|
||||
void Net_WaitAllAckReceived(UINT32 timeout)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)timeout;
|
||||
#else
|
||||
tic_t tictac = I_GetTime();
|
||||
timeout = tictac + timeout*NEWTICRATE;
|
||||
|
||||
|
@ -623,7 +593,6 @@ void Net_WaitAllAckReceived(UINT32 timeout)
|
|||
HGetPacket();
|
||||
Net_AckTicker();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void InitNode(node_t *node)
|
||||
|
@ -637,14 +606,10 @@ static void InitNode(node_t *node)
|
|||
|
||||
static void InitAck(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
#ifndef NONET
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
ackpak[i].acknum = 0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAXNETNODES; i++)
|
||||
for (INT32 i = 0; i < MAXNETNODES; i++)
|
||||
InitNode(&nodes[i]);
|
||||
}
|
||||
|
||||
|
@ -655,17 +620,12 @@ static void InitAck(void)
|
|||
*/
|
||||
void Net_AbortPacketType(UINT8 packettype)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)packettype;
|
||||
#else
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (ackpak[i].acknum && (ackpak[i].pak.data.packettype == packettype
|
||||
|| packettype == UINT8_MAX))
|
||||
{
|
||||
ackpak[i].acknum = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
|
@ -675,10 +635,6 @@ void Net_AbortPacketType(UINT8 packettype)
|
|||
// remove a node, clear all ack from this node and reset askret
|
||||
void Net_CloseConnection(INT32 node)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)node;
|
||||
#else
|
||||
INT32 i;
|
||||
boolean forceclose = (node & FORCECLOSE) != 0;
|
||||
|
||||
if (node == -1)
|
||||
|
@ -708,7 +664,7 @@ void Net_CloseConnection(INT32 node)
|
|||
}
|
||||
|
||||
// check if we are waiting for an ack from this node
|
||||
for (i = 0; i < MAXACKPACKETS; i++)
|
||||
for (INT32 i = 0; i < MAXACKPACKETS; i++)
|
||||
if (ackpak[i].acknum && ackpak[i].destinationnode == node)
|
||||
{
|
||||
if (!forceclose)
|
||||
|
@ -722,10 +678,8 @@ void Net_CloseConnection(INT32 node)
|
|||
if (server)
|
||||
SV_AbortLuaFileTransfer(node);
|
||||
I_NetFreeNodenum(node);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
//
|
||||
// Checksum
|
||||
//
|
||||
|
@ -734,23 +688,20 @@ static UINT32 NetbufferChecksum(void)
|
|||
UINT32 c = 0x1234567;
|
||||
const INT32 l = doomcom->datalength - 4;
|
||||
const UINT8 *buf = (UINT8 *)netbuffer + 4;
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < l; i++, buf++)
|
||||
for (INT32 i = 0; i < l; i++, buf++)
|
||||
c += (*buf) * (i+1);
|
||||
|
||||
return LONG(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGFILE
|
||||
|
||||
static void fprintfstring(char *s, size_t len)
|
||||
{
|
||||
INT32 mode = 0;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
for (size_t i = 0; i < len; i++)
|
||||
if (s[i] < 32)
|
||||
{
|
||||
if (!mode)
|
||||
|
@ -810,6 +761,8 @@ static const char *packettypename[NUMPACKETTYPE] =
|
|||
"ASKLUAFILE",
|
||||
"HASLUAFILE",
|
||||
|
||||
"PT_BASICKEEPALIVE",
|
||||
|
||||
"FILEFRAGMENT",
|
||||
"FILEACK",
|
||||
"FILERECEIVED",
|
||||
|
@ -817,7 +770,6 @@ static const char *packettypename[NUMPACKETTYPE] =
|
|||
"TEXTCMD",
|
||||
"TEXTCMD2",
|
||||
"CLIENTJOIN",
|
||||
"NODETIMEOUT",
|
||||
"LOGIN",
|
||||
"TELLFILESNEEDED",
|
||||
"MOREFILESNEEDED",
|
||||
|
@ -921,7 +873,6 @@ void Command_Drop(void)
|
|||
{
|
||||
INT32 packetquantity;
|
||||
const char *packetname;
|
||||
size_t i;
|
||||
|
||||
if (COM_Argc() < 2)
|
||||
{
|
||||
|
@ -951,11 +902,11 @@ void Command_Drop(void)
|
|||
packetname = COM_Argv(1);
|
||||
|
||||
if (!(stricmp(packetname, "all") && stricmp(packetname, "any")))
|
||||
for (i = 0; i < NUMPACKETTYPE; i++)
|
||||
for (size_t i = 0; i < NUMPACKETTYPE; i++)
|
||||
packetdropquantity[i] = packetquantity;
|
||||
else
|
||||
{
|
||||
for (i = 0; i < NUMPACKETTYPE; i++)
|
||||
for (size_t i = 0; i < NUMPACKETTYPE; i++)
|
||||
if (!stricmp(packetname, packettypename[i]))
|
||||
{
|
||||
packetdropquantity[i] = packetquantity;
|
||||
|
@ -986,14 +937,12 @@ void Command_Droprate(void)
|
|||
packetdroprate = droprate;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static boolean ShouldDropPacket(void)
|
||||
{
|
||||
return (packetdropquantity[netbuffer->packettype])
|
||||
|| (packetdroprate != 0 && rand() < (RAND_MAX * (packetdroprate / 100.f))) || packetdroprate == 100;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// HSendPacket
|
||||
|
@ -1028,11 +977,6 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
|
|||
if (!netgame)
|
||||
I_Error("Tried to transmit to another node");
|
||||
|
||||
#ifdef NONET
|
||||
(void)node;
|
||||
(void)reliable;
|
||||
(void)acknum;
|
||||
#else
|
||||
// do this before GetFreeAcknum because this function backups
|
||||
// the current packet
|
||||
doomcom->remotenode = (INT16)node;
|
||||
|
@ -1093,8 +1037,6 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum, size_t packetlen
|
|||
}
|
||||
#endif
|
||||
|
||||
#endif // ndef NONET
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1112,10 +1054,7 @@ boolean HGetPacket(void)
|
|||
{
|
||||
M_Memcpy(netbuffer, &reboundstore[rebound_tail], reboundsize[rebound_tail]);
|
||||
doomcom->datalength = reboundsize[rebound_tail];
|
||||
if (netbuffer->packettype == PT_NODETIMEOUT)
|
||||
doomcom->remotenode = netbuffer->u.textcmd[0];
|
||||
else
|
||||
doomcom->remotenode = 0;
|
||||
doomcom->remotenode = 0;
|
||||
|
||||
rebound_tail = (rebound_tail+1) % MAXREBOUND;
|
||||
#ifdef DEBUGFILE
|
||||
|
@ -1128,11 +1067,10 @@ boolean HGetPacket(void)
|
|||
if (!netgame)
|
||||
return false;
|
||||
|
||||
#ifndef NONET
|
||||
|
||||
while(true)
|
||||
{
|
||||
//nodejustjoined = I_NetGet();
|
||||
int goodpacket;
|
||||
I_NetGet();
|
||||
|
||||
if (doomcom->remotenode == -1) // No packet received
|
||||
|
@ -1178,8 +1116,15 @@ boolean HGetPacket(void)
|
|||
}*/
|
||||
|
||||
// Proceed the ack and ackreturn field
|
||||
if (!Processackpak())
|
||||
goodpacket = Processackpak();
|
||||
if (goodpacket != 0)
|
||||
{
|
||||
// resend the ACK in case the previous ACK didn't reach the client.
|
||||
// prevents the client's netbuffer from locking up.
|
||||
if (goodpacket == 1)
|
||||
Net_SendAcks(doomcom->remotenode);
|
||||
continue; // discarded (duplicated)
|
||||
}
|
||||
|
||||
// A packet with just ackreturn
|
||||
if (netbuffer->packettype == PT_NOTHING)
|
||||
|
@ -1189,7 +1134,6 @@ boolean HGetPacket(void)
|
|||
}
|
||||
break;
|
||||
}
|
||||
#endif // ndef NONET
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1399,13 +1343,12 @@ void Command_Ping_f(void)
|
|||
int name_width = 0;
|
||||
int ms_width = 0;
|
||||
|
||||
int n;
|
||||
INT32 i;
|
||||
|
||||
pingc = 0;
|
||||
for (i = 1; i < MAXPLAYERS; ++i)
|
||||
for (INT32 i = 1; i < MAXPLAYERS; ++i)
|
||||
if (playeringame[i])
|
||||
{
|
||||
int n;
|
||||
|
||||
n = strlen(player_names[i]);
|
||||
if (n > name_width)
|
||||
name_width = n;
|
||||
|
@ -1425,7 +1368,7 @@ void Command_Ping_f(void)
|
|||
|
||||
qsort(pingv, pingc, sizeof (struct pingcell), &pingcellcmp);
|
||||
|
||||
for (i = 0; i < pingc; ++i)
|
||||
for (INT32 i = 0; i < pingc; ++i)
|
||||
{
|
||||
CONS_Printf("%02d : %-*s %*d ms\n",
|
||||
pingv[i].num,
|
||||
|
@ -1441,15 +1384,13 @@ void Command_Ping_f(void)
|
|||
|
||||
void D_CloseConnection(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
// wait the ackreturn with timout of 5 Sec
|
||||
Net_WaitAllAckReceived(5);
|
||||
|
||||
// close all connection
|
||||
for (i = 0; i < MAXNETNODES; i++)
|
||||
for (INT32 i = 0; i < MAXNETNODES; i++)
|
||||
Net_CloseConnection(i|FORCECLOSE);
|
||||
|
||||
InitAck();
|
|
@ -18,6 +18,8 @@
|
|||
#ifndef __D_NET__
|
||||
#define __D_NET__
|
||||
|
||||
#include "../doomtype.h"
|
||||
|
||||
// Max computers in a game
|
||||
// 127 is probably as high as this can go, because
|
||||
// SINT8 is used for nodes sometimes >:(
|
||||
|
@ -37,10 +39,24 @@ boolean Net_GetNetStat(void);
|
|||
extern INT32 getbytes;
|
||||
extern INT64 sendbytes; // Realtime updated
|
||||
|
||||
extern SINT8 nodetoplayer[MAXNETNODES];
|
||||
extern SINT8 nodetoplayer2[MAXNETNODES]; // Say the numplayer for this node if any (splitscreen)
|
||||
extern UINT8 playerpernode[MAXNETNODES]; // Used specially for splitscreen
|
||||
extern boolean nodeingame[MAXNETNODES]; // Set false as nodes leave game
|
||||
typedef struct netnode_s
|
||||
{
|
||||
boolean ingame; // set false as nodes leave game
|
||||
tic_t freezetimeout; // Until when can this node freeze the server before getting a timeout?
|
||||
|
||||
SINT8 player;
|
||||
SINT8 player2; // say the numplayer for this node if any (splitscreen)
|
||||
UINT8 numplayers; // used specialy for scplitscreen
|
||||
|
||||
tic_t tic; // what tic the client have received
|
||||
tic_t supposedtic; // nettics prevision for smaller packet
|
||||
|
||||
boolean sendingsavegame; // Are we sending the savegame?
|
||||
boolean resendingsavegame; // Are we resending the savegame?
|
||||
tic_t savegameresendcooldown; // How long before we can resend again?
|
||||
} netnode_t;
|
||||
|
||||
extern netnode_t netnodes[MAXNETNODES];
|
||||
|
||||
extern boolean serverrunning;
|
||||
|
||||
|
@ -52,11 +68,9 @@ boolean HSendPacket(INT32 node, boolean reliable, UINT8 acknum,
|
|||
size_t packetlength);
|
||||
boolean HGetPacket(void);
|
||||
void D_SetDoomcom(void);
|
||||
#ifndef NONET
|
||||
void D_SaveBan(void);
|
||||
#endif
|
||||
boolean D_CheckNetGame(void);
|
||||
void D_CloseConnection(void);
|
||||
boolean Net_IsNodeIPv6(INT32 node);
|
||||
void Net_UnAcknowledgePacket(INT32 node);
|
||||
void Net_CloseConnection(INT32 node);
|
||||
void Net_ConnectionTimeout(INT32 node);
|
|
@ -12,44 +12,46 @@
|
|||
/// commands are executed through the command buffer
|
||||
/// like console commands, other miscellaneous commands (at the end)
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "../doomdef.h"
|
||||
|
||||
#include "console.h"
|
||||
#include "command.h"
|
||||
#include "i_time.h"
|
||||
#include "i_system.h"
|
||||
#include "g_game.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "g_input.h"
|
||||
#include "m_menu.h"
|
||||
#include "r_local.h"
|
||||
#include "r_skins.h"
|
||||
#include "p_local.h"
|
||||
#include "p_setup.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_sound.h"
|
||||
#include "m_misc.h"
|
||||
#include "am_map.h"
|
||||
#include "byteptr.h"
|
||||
#include "../console.h"
|
||||
#include "../command.h"
|
||||
#include "../i_time.h"
|
||||
#include "../i_system.h"
|
||||
#include "../g_game.h"
|
||||
#include "../hu_stuff.h"
|
||||
#include "../g_input.h"
|
||||
#include "../m_menu.h"
|
||||
#include "../r_local.h"
|
||||
#include "../r_skins.h"
|
||||
#include "../p_local.h"
|
||||
#include "../p_setup.h"
|
||||
#include "../s_sound.h"
|
||||
#include "../i_sound.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../am_map.h"
|
||||
#include "../byteptr.h"
|
||||
#include "d_netfil.h"
|
||||
#include "p_spec.h"
|
||||
#include "m_cheat.h"
|
||||
#include "../p_spec.h"
|
||||
#include "../m_cheat.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "server_connection.h"
|
||||
#include "net_command.h"
|
||||
#include "d_net.h"
|
||||
#include "v_video.h"
|
||||
#include "d_main.h"
|
||||
#include "m_random.h"
|
||||
#include "f_finale.h"
|
||||
#include "filesrch.h"
|
||||
#include "../v_video.h"
|
||||
#include "../d_main.h"
|
||||
#include "../m_random.h"
|
||||
#include "../f_finale.h"
|
||||
#include "../filesrch.h"
|
||||
#include "mserv.h"
|
||||
#include "z_zone.h"
|
||||
#include "lua_script.h"
|
||||
#include "lua_hook.h"
|
||||
#include "m_cond.h"
|
||||
#include "m_anigif.h"
|
||||
#include "md5.h"
|
||||
#include "m_perfstats.h"
|
||||
#include "u_list.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../lua_script.h"
|
||||
#include "../lua_hook.h"
|
||||
#include "../m_cond.h"
|
||||
#include "../m_anigif.h"
|
||||
#include "../md5.h"
|
||||
#include "../m_perfstats.h"
|
||||
#include "../u_list.h"
|
||||
|
||||
#ifdef NETGAME_DEVMODE
|
||||
#define CV_RESTRICT CV_NETVAR
|
||||
|
@ -148,6 +150,7 @@ static void Command_Clearscores_f(void);
|
|||
|
||||
// Remote Administration
|
||||
static void Command_Changepassword_f(void);
|
||||
static void Command_Clearpassword_f(void);
|
||||
static void Command_Login_f(void);
|
||||
static void Got_Verification(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Removal(UINT8 **cp, INT32 playernum);
|
||||
|
@ -225,6 +228,7 @@ consvar_t cv_seenames = CVAR_INIT ("seenames", "Ally/Foe", CV_SAVE|CV_ALLOWLUA,
|
|||
consvar_t cv_allowseenames = CVAR_INIT ("allowseenames", "Yes", CV_SAVE|CV_NETVAR|CV_ALLOWLUA, CV_YesNo, NULL);
|
||||
|
||||
// names
|
||||
static char *lastskinnames[2];
|
||||
consvar_t cv_playername = CVAR_INIT ("name", "Sonic", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name_OnChange);
|
||||
consvar_t cv_playername2 = CVAR_INIT ("name2", "Tails", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Name2_OnChange);
|
||||
// player colors
|
||||
|
@ -376,7 +380,7 @@ consvar_t cv_mute = CVAR_INIT ("mute", "Off", CV_NETVAR|CV_CALL|CV_ALLOWLUA, CV_
|
|||
consvar_t cv_sleep = CVAR_INIT ("cpusleep", "1", CV_SAVE, sleeping_cons_t, NULL);
|
||||
|
||||
static CV_PossibleValue_t perfstats_cons_t[] = {
|
||||
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {0, NULL}};
|
||||
{0, "Off"}, {1, "Rendering"}, {2, "Logic"}, {3, "ThinkFrame"}, {4, "PreThinkFrame"}, {5, "PostThinkFrame"}, {0, NULL}};
|
||||
consvar_t cv_perfstats = CVAR_INIT ("perfstats", "Off", CV_CALL, perfstats_cons_t, PS_PerfStats_OnChange);
|
||||
static CV_PossibleValue_t ps_samplesize_cons_t[] = {
|
||||
{1, "MIN"}, {1000, "MAX"}, {0, NULL}};
|
||||
|
@ -465,6 +469,7 @@ void D_RegisterServerCommands(void)
|
|||
|
||||
// Remote Administration
|
||||
COM_AddCommand("password", Command_Changepassword_f, COM_LUA);
|
||||
COM_AddCommand("clearpassword", Command_Clearpassword_f, COM_LUA);
|
||||
COM_AddCommand("login", Command_Login_f, COM_LUA); // useful in dedicated to kick off remote admin
|
||||
COM_AddCommand("promote", Command_Verify_f, COM_LUA);
|
||||
RegisterNetXCmd(XD_VERIFIED, Got_Verification);
|
||||
|
@ -594,13 +599,11 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_maxsend);
|
||||
CV_RegisterVar(&cv_noticedownload);
|
||||
CV_RegisterVar(&cv_downloadspeed);
|
||||
#ifndef NONET
|
||||
CV_RegisterVar(&cv_allownewplayer);
|
||||
CV_RegisterVar(&cv_joinnextround);
|
||||
CV_RegisterVar(&cv_showjoinaddress);
|
||||
CV_RegisterVar(&cv_blamecfail);
|
||||
CV_RegisterVar(&cv_dedicatedidletime);
|
||||
#endif
|
||||
CV_RegisterVar(&cv_idletime);
|
||||
|
||||
COM_AddCommand("ping", Command_Ping_f, COM_LUA);
|
||||
CV_RegisterVar(&cv_nettimeout);
|
||||
|
@ -619,6 +622,10 @@ void D_RegisterServerCommands(void)
|
|||
CV_RegisterVar(&cv_addons_folder);
|
||||
|
||||
CV_RegisterVar(&cv_dummyconsvar);
|
||||
|
||||
CV_RegisterVar(&cv_chatspamprotection);
|
||||
CV_RegisterVar(&cv_chatspamspeed);
|
||||
CV_RegisterVar(&cv_chatspamburst);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
|
@ -762,7 +769,6 @@ void D_RegisterClientCommands(void)
|
|||
CV_RegisterVar(&cv_chatheight);
|
||||
CV_RegisterVar(&cv_chatwidth);
|
||||
CV_RegisterVar(&cv_chattime);
|
||||
CV_RegisterVar(&cv_chatspamprotection);
|
||||
CV_RegisterVar(&cv_chatbacktint);
|
||||
CV_RegisterVar(&cv_consolechat);
|
||||
CV_RegisterVar(&cv_chatnotifications);
|
||||
|
@ -1205,45 +1211,47 @@ UINT8 CanChangeSkin(INT32 playernum)
|
|||
|
||||
static void ForceAllSkins(INT32 forcedskin)
|
||||
{
|
||||
INT32 i;
|
||||
for (i = 0; i < MAXPLAYERS; ++i)
|
||||
for (INT32 i = 0; i < MAXPLAYERS; ++i)
|
||||
{
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
||||
SetPlayerSkinByNum(i, forcedskin);
|
||||
|
||||
// If it's me (or my brother), set appropriate skin value in cv_skin/cv_skin2
|
||||
if (!dedicated) // But don't do this for dedicated servers, of course.
|
||||
{
|
||||
if (i == consoleplayer)
|
||||
CV_StealthSet(&cv_skin, skins[forcedskin].name);
|
||||
else if (i == secondarydisplayplayer)
|
||||
CV_StealthSet(&cv_skin2, skins[forcedskin].name);
|
||||
}
|
||||
if (playeringame[i])
|
||||
SetPlayerSkinByNum(i, forcedskin);
|
||||
}
|
||||
}
|
||||
|
||||
static INT32 snacpending = 0, snac2pending = 0, chmappending = 0;
|
||||
|
||||
static void SetSkinLocal(INT32 playernum, INT32 skinnum)
|
||||
{
|
||||
if (metalrecording && playernum == consoleplayer)
|
||||
{
|
||||
// Starring Metal Sonic as themselves, obviously.
|
||||
SetPlayerSkinByNum(playernum, 5);
|
||||
return;
|
||||
}
|
||||
|
||||
if (skinnum != -1 && R_SkinUsable(playernum, skinnum))
|
||||
SetPlayerSkinByNum(playernum, skinnum);
|
||||
else
|
||||
SetPlayerSkinByNum(playernum, GetPlayerDefaultSkin(playernum));
|
||||
}
|
||||
|
||||
static void SetColorLocal(INT32 playernum, UINT16 color)
|
||||
{
|
||||
players[playernum].skincolor = color;
|
||||
|
||||
if (players[playernum].mo && !players[playernum].powers[pw_dye])
|
||||
players[playernum].mo->color = P_GetPlayerColor(&players[playernum]);
|
||||
}
|
||||
|
||||
// name, color, or skin has changed
|
||||
//
|
||||
static void SendNameAndColor(void)
|
||||
{
|
||||
char buf[MAXPLAYERNAME+6];
|
||||
char buf[MAXPLAYERNAME+7];
|
||||
char *p;
|
||||
|
||||
p = buf;
|
||||
|
||||
// normal player colors
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
if (players[consoleplayer].ctfteam == 1 && cv_playercolor.value != skincolor_redteam)
|
||||
CV_StealthSetValue(&cv_playercolor, skincolor_redteam);
|
||||
else if (players[consoleplayer].ctfteam == 2 && cv_playercolor.value != skincolor_blueteam)
|
||||
CV_StealthSetValue(&cv_playercolor, skincolor_blueteam);
|
||||
}
|
||||
|
||||
// don't allow inaccessible colors
|
||||
if (!skincolors[cv_playercolor.value].accessible)
|
||||
{
|
||||
|
@ -1274,50 +1282,15 @@ static void SendNameAndColor(void)
|
|||
// If you're not in a netgame, merely update the skin, color, and name.
|
||||
if (!netgame)
|
||||
{
|
||||
INT32 foundskin;
|
||||
|
||||
CleanupPlayerName(consoleplayer, cv_playername.zstring);
|
||||
strcpy(player_names[consoleplayer], cv_playername.zstring);
|
||||
|
||||
players[consoleplayer].skincolor = cv_playercolor.value;
|
||||
SetColorLocal(consoleplayer, cv_playercolor.value);
|
||||
|
||||
if (players[consoleplayer].mo && !players[consoleplayer].powers[pw_dye])
|
||||
players[consoleplayer].mo->color = players[consoleplayer].skincolor;
|
||||
|
||||
if (metalrecording)
|
||||
{ // Starring Metal Sonic as themselves, obviously.
|
||||
SetPlayerSkinByNum(consoleplayer, 5);
|
||||
CV_StealthSet(&cv_skin, skins[5].name);
|
||||
}
|
||||
else if ((foundskin = R_SkinAvailable(cv_skin.string)) != -1 && R_SkinUsable(consoleplayer, foundskin))
|
||||
{
|
||||
//boolean notsame;
|
||||
|
||||
cv_skin.value = foundskin;
|
||||
|
||||
//notsame = (cv_skin.value != players[consoleplayer].skin);
|
||||
|
||||
SetPlayerSkin(consoleplayer, cv_skin.string);
|
||||
CV_StealthSet(&cv_skin, skins[cv_skin.value].name);
|
||||
|
||||
/*if (notsame)
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor, skins[cv_skin.value].prefcolor);
|
||||
|
||||
players[consoleplayer].skincolor = cv_playercolor.value % numskincolors;
|
||||
|
||||
if (players[consoleplayer].mo)
|
||||
players[consoleplayer].mo->color = (UINT16)players[consoleplayer].skincolor;
|
||||
}*/
|
||||
}
|
||||
if (splitscreen)
|
||||
SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string));
|
||||
else
|
||||
{
|
||||
cv_skin.value = players[consoleplayer].skin;
|
||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||
// will always be same as current
|
||||
SetPlayerSkin(consoleplayer, cv_skin.string);
|
||||
}
|
||||
|
||||
SetSkinLocal(consoleplayer, pickedchar);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1334,10 +1307,6 @@ static void SendNameAndColor(void)
|
|||
else // Cleanup name if changing it
|
||||
CleanupPlayerName(consoleplayer, cv_playername.zstring);
|
||||
|
||||
// Don't change skin if the server doesn't want you to.
|
||||
if (!CanChangeSkin(consoleplayer))
|
||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||
|
||||
// check if player has the skin loaded (cv_skin may have
|
||||
// the name of a skin that was available in the previous game)
|
||||
cv_skin.value = R_SkinAvailable(cv_skin.string);
|
||||
|
@ -1369,16 +1338,6 @@ static void SendNameAndColor2(void)
|
|||
else // HACK
|
||||
secondplaya = 1;
|
||||
|
||||
// normal player colors
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
if (players[secondplaya].ctfteam == 1 && cv_playercolor2.value != skincolor_redteam)
|
||||
CV_StealthSetValue(&cv_playercolor2, skincolor_redteam);
|
||||
else if (players[secondplaya].ctfteam == 2 && cv_playercolor2.value != skincolor_blueteam)
|
||||
CV_StealthSetValue(&cv_playercolor2, skincolor_blueteam);
|
||||
}
|
||||
|
||||
// don't allow inaccessible colors
|
||||
if (!skincolors[cv_playercolor2.value].accessible)
|
||||
{
|
||||
if (players[secondplaya].skincolor && skincolors[players[secondplaya].skincolor].accessible)
|
||||
|
@ -1400,63 +1359,24 @@ static void SendNameAndColor2(void)
|
|||
if (!Playing())
|
||||
return;
|
||||
|
||||
// If you're not in a netgame, merely update the skin, color, and name.
|
||||
if (botingame)
|
||||
{
|
||||
players[secondplaya].skincolor = botcolor;
|
||||
if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye])
|
||||
players[secondplaya].mo->color = players[secondplaya].skincolor;
|
||||
|
||||
SetColorLocal(secondplaya, botcolor);
|
||||
SetPlayerSkinByNum(secondplaya, botskin-1);
|
||||
return;
|
||||
}
|
||||
else if (!netgame)
|
||||
{
|
||||
INT32 foundskin;
|
||||
|
||||
// If you're not in a netgame, merely update the skin, color, and name.
|
||||
CleanupPlayerName(secondplaya, cv_playername2.zstring);
|
||||
strcpy(player_names[secondplaya], cv_playername2.zstring);
|
||||
|
||||
// don't use secondarydisplayplayer: the second player must be 1
|
||||
players[secondplaya].skincolor = cv_playercolor2.value;
|
||||
if (players[secondplaya].mo && !players[secondplaya].powers[pw_dye])
|
||||
players[secondplaya].mo->color = players[secondplaya].skincolor;
|
||||
SetColorLocal(secondplaya, cv_playercolor2.value);
|
||||
|
||||
if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player
|
||||
{
|
||||
const INT32 forcedskin = cv_forceskin.value;
|
||||
|
||||
SetPlayerSkinByNum(secondplaya, forcedskin);
|
||||
CV_StealthSet(&cv_skin2, skins[forcedskin].name);
|
||||
}
|
||||
else if ((foundskin = R_SkinAvailable(cv_skin2.string)) != -1 && R_SkinUsable(secondplaya, foundskin))
|
||||
{
|
||||
//boolean notsame;
|
||||
|
||||
cv_skin2.value = foundskin;
|
||||
|
||||
//notsame = (cv_skin2.value != players[secondplaya].skin);
|
||||
|
||||
SetPlayerSkin(secondplaya, cv_skin2.string);
|
||||
CV_StealthSet(&cv_skin2, skins[cv_skin2.value].name);
|
||||
|
||||
/*if (notsame)
|
||||
{
|
||||
CV_StealthSetValue(&cv_playercolor2, skins[players[secondplaya].skin].prefcolor);
|
||||
|
||||
players[secondplaya].skincolor = cv_playercolor2.value % numskincolors;
|
||||
|
||||
if (players[secondplaya].mo)
|
||||
players[secondplaya].mo->color = players[secondplaya].skincolor;
|
||||
}*/
|
||||
}
|
||||
if (cv_forceskin.value >= 0)
|
||||
SetSkinLocal(secondplaya, cv_forceskin.value);
|
||||
else
|
||||
{
|
||||
cv_skin2.value = players[secondplaya].skin;
|
||||
CV_StealthSet(&cv_skin2, skins[players[secondplaya].skin].name);
|
||||
// will always be same as current
|
||||
SetPlayerSkin(secondplaya, cv_skin2.string);
|
||||
}
|
||||
SetSkinLocal(secondplaya, R_SkinAvailable(cv_skin2.string));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1500,7 +1420,7 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
// set color
|
||||
p->skincolor = color % numskincolors;
|
||||
if (p->mo)
|
||||
p->mo->color = (UINT16)p->skincolor;
|
||||
p->mo->color = P_GetPlayerColor(p);
|
||||
|
||||
// normal player colors
|
||||
if (server && (p != &players[consoleplayer] && p != &players[secondarydisplayplayer]))
|
||||
|
@ -1509,15 +1429,6 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
UINT32 unlockShift = 0;
|
||||
UINT32 i;
|
||||
|
||||
// team colors
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
if (p->ctfteam == 1 && p->skincolor != skincolor_redteam)
|
||||
kick = true;
|
||||
else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam)
|
||||
kick = true;
|
||||
}
|
||||
|
||||
// don't allow inaccessible colors
|
||||
if (skincolors[p->skincolor].accessible == false)
|
||||
kick = true;
|
||||
|
@ -1558,16 +1469,9 @@ static void Got_NameAndColor(UINT8 **cp, INT32 playernum)
|
|||
}
|
||||
|
||||
// set skin
|
||||
if (cv_forceskin.value >= 0 && (netgame || multiplayer)) // Server wants everyone to use the same player
|
||||
{
|
||||
const INT32 forcedskin = cv_forceskin.value;
|
||||
INT32 forcedskin = R_GetForcedSkin(playernum);
|
||||
if (forcedskin != -1 && (netgame || multiplayer)) // Server wants everyone to use the same player (or the level is forcing one.)
|
||||
SetPlayerSkinByNum(playernum, forcedskin);
|
||||
|
||||
if (playernum == consoleplayer)
|
||||
CV_StealthSet(&cv_skin, skins[forcedskin].name);
|
||||
else if (playernum == secondarydisplayplayer)
|
||||
CV_StealthSet(&cv_skin2, skins[forcedskin].name);
|
||||
}
|
||||
else
|
||||
SetPlayerSkinByNum(playernum, skin);
|
||||
}
|
||||
|
@ -1843,8 +1747,7 @@ void D_MapChange(INT32 mapnum, INT32 newgametype, boolean pultmode, boolean rese
|
|||
// reset players if there is a new one
|
||||
if (!IsPlayerAdmin(consoleplayer))
|
||||
{
|
||||
if (SV_SpawnServer())
|
||||
buf[0] &= ~(1<<1);
|
||||
SV_SpawnServer();
|
||||
if (!Playing()) // you failed to start a server somehow, so cancel the map change
|
||||
return;
|
||||
}
|
||||
|
@ -2177,7 +2080,6 @@ static void Got_Mapcmd(UINT8 **cp, INT32 playernum)
|
|||
{
|
||||
SetPlayerSkinByNum(0, cv_chooseskin.value-1);
|
||||
players[0].skincolor = skins[players[0].skin].prefcolor;
|
||||
CV_StealthSetValue(&cv_playercolor, players[0].skincolor);
|
||||
}
|
||||
|
||||
mapnumber = M_MapNumber(mapname[3], mapname[4]);
|
||||
|
@ -2931,17 +2833,6 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
|||
displayplayer = consoleplayer;
|
||||
}
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
{
|
||||
if (NetPacket.packet.newteam)
|
||||
{
|
||||
if (playernum == consoleplayer) //CTF and Team Match colors.
|
||||
CV_SetValue(&cv_playercolor, NetPacket.packet.newteam + 5);
|
||||
else if (playernum == secondarydisplayplayer)
|
||||
CV_SetValue(&cv_playercolor2, NetPacket.packet.newteam + 5);
|
||||
}
|
||||
}
|
||||
|
||||
// In tag, check to see if you still have a game.
|
||||
if (G_TagGametype())
|
||||
P_CheckSurvivors();
|
||||
|
@ -2955,8 +2846,15 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
|||
|
||||
void D_SetPassword(const char *pw)
|
||||
{
|
||||
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5);
|
||||
adminpasswordset = true;
|
||||
adminpassmd5 = Z_Realloc(adminpassmd5, sizeof(*adminpassmd5) * ++adminpasscount, PU_STATIC, NULL);
|
||||
D_MD5PasswordPass((const UINT8 *)pw, strlen(pw), BASESALT, &adminpassmd5[adminpasscount-1]);
|
||||
}
|
||||
|
||||
void D_ClearPassword(void)
|
||||
{
|
||||
Z_Free(adminpassmd5);
|
||||
adminpassmd5 = NULL;
|
||||
adminpasscount = 0;
|
||||
}
|
||||
|
||||
// Remote Administration
|
||||
|
@ -2974,12 +2872,30 @@ static void Command_Changepassword_f(void)
|
|||
|
||||
if (COM_Argc() != 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("password <password>: change remote admin password\n"));
|
||||
CONS_Printf(M_GetText("password <password>: add remote admin password\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
D_SetPassword(COM_Argv(1));
|
||||
CONS_Printf(M_GetText("Password set.\n"));
|
||||
CONS_Printf(M_GetText("Password added.\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remote Administration
|
||||
static void Command_Clearpassword_f(void)
|
||||
{
|
||||
#ifdef NOMD5
|
||||
// If we have no MD5 support then completely disable XD_LOGIN responses for security.
|
||||
CONS_Alert(CONS_NOTICE, "Remote administration commands are not supported in this build.\n");
|
||||
#else
|
||||
if (client) // cannot change remotely
|
||||
{
|
||||
CONS_Printf(M_GetText("Only the server can use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
D_ClearPassword();
|
||||
CONS_Printf(M_GetText("Passwords cleared.\n"));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -3755,11 +3671,11 @@ static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
|
|||
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
char filename[MAX_WADPATH+1];
|
||||
filestatus_t ncs = FS_NOTCHECKED;
|
||||
UINT8 md5sum[16];
|
||||
|
||||
READSTRINGN(*cp, filename, 240);
|
||||
READSTRINGN(*cp, filename, MAX_WADPATH);
|
||||
READMEM(*cp, md5sum, 16);
|
||||
|
||||
if (playernum != serverplayer)
|
||||
|
@ -4820,11 +4736,16 @@ static void ForceSkin_OnChange(void)
|
|||
return;
|
||||
|
||||
if (cv_forceskin.value < 0)
|
||||
{
|
||||
CONS_Printf("The server has lifted the forced skin restrictions.\n");
|
||||
if (Playing())
|
||||
D_SendPlayerConfig();
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf("The server is restricting all players to skin \"%s\".\n",skins[cv_forceskin.value].name);
|
||||
ForceAllSkins(cv_forceskin.value);
|
||||
if (Playing())
|
||||
ForceAllSkins(cv_forceskin.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4838,7 +4759,6 @@ static void Name_OnChange(void)
|
|||
}
|
||||
else
|
||||
SendNameAndColor();
|
||||
|
||||
}
|
||||
|
||||
static void Name2_OnChange(void)
|
||||
|
@ -4861,19 +4781,33 @@ static void Skin_OnChange(void)
|
|||
if (!Playing())
|
||||
return; // do whatever you want
|
||||
|
||||
if (!(cv_debug || devparm) && !(multiplayer || netgame) // In single player.
|
||||
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
|
||||
if (lastskinnames[0] == NULL)
|
||||
lastskinnames[0] = Z_StrDup(cv_skin.string);
|
||||
|
||||
if (!(multiplayer || netgame)) // In single player.
|
||||
{
|
||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||
if (!(cv_debug || devparm)
|
||||
&& (gamestate != GS_WAITINGPLAYERS)) // allows command line -warp x +skin y
|
||||
{
|
||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Just do it here if devmode is enabled
|
||||
SetSkinLocal(consoleplayer, R_SkinAvailable(cv_skin.string));
|
||||
return;
|
||||
}
|
||||
|
||||
if (CanChangeSkin(consoleplayer) && !P_PlayerMoving(consoleplayer))
|
||||
{
|
||||
SendNameAndColor();
|
||||
Z_Free(lastskinnames[0]);
|
||||
lastskinnames[0] = Z_StrDup(cv_skin.string);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||
CV_StealthSet(&cv_skin, lastskinnames[0]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4887,12 +4821,19 @@ static void Skin2_OnChange(void)
|
|||
if (!Playing() || !splitscreen)
|
||||
return; // do whatever you want
|
||||
|
||||
if (lastskinnames[1] == NULL)
|
||||
lastskinnames[1] = Z_StrDup(cv_skin2.string);
|
||||
|
||||
if (CanChangeSkin(secondarydisplayplayer) && !P_PlayerMoving(secondarydisplayplayer))
|
||||
{
|
||||
SendNameAndColor2();
|
||||
Z_Free(lastskinnames[1]);
|
||||
lastskinnames[1] = Z_StrDup(cv_skin.string);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You can't change your skin at the moment.\n"));
|
||||
CV_StealthSet(&cv_skin2, skins[players[secondarydisplayplayer].skin].name);
|
||||
CV_StealthSet(&cv_skin2, lastskinnames[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4902,15 +4843,18 @@ static void Skin2_OnChange(void)
|
|||
*/
|
||||
static void Color_OnChange(void)
|
||||
{
|
||||
if (!Playing()) {
|
||||
if (!Playing())
|
||||
{
|
||||
if (!cv_playercolor.value || !skincolors[cv_playercolor.value].accessible)
|
||||
CV_StealthSetValue(&cv_playercolor, lastgoodcolor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(cv_debug || devparm) && !(multiplayer || netgame)) // In single player.
|
||||
if (!(multiplayer || netgame)) // In single player.
|
||||
{
|
||||
CV_StealthSet(&cv_skin, skins[players[consoleplayer].skin].name);
|
||||
// Just do it here if devmode is enabled
|
||||
if (cv_debug || devparm)
|
||||
SetColorLocal(consoleplayer, cv_playercolor.value);
|
||||
return;
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#ifndef __D_NETCMD__
|
||||
#define __D_NETCMD__
|
||||
|
||||
#include "command.h"
|
||||
#include "../command.h"
|
||||
|
||||
// console vars
|
||||
extern consvar_t cv_playername;
|
||||
|
@ -209,6 +209,7 @@ void ClearAdminPlayers(void);
|
|||
void RemoveAdminPlayer(INT32 playernum);
|
||||
void ItemFinder_OnChange(void);
|
||||
void D_SetPassword(const char *pw);
|
||||
void D_ClearPassword(void);
|
||||
|
||||
// used for the player setup menu
|
||||
UINT8 CanChangeSkin(INT32 playernum);
|
|
@ -31,24 +31,25 @@
|
|||
#include <sys/utime.h>
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_main.h"
|
||||
#include "g_game.h"
|
||||
#include "i_time.h"
|
||||
#include "../doomdef.h"
|
||||
#include "../doomstat.h"
|
||||
#include "../d_main.h"
|
||||
#include "../g_game.h"
|
||||
#include "../i_time.h"
|
||||
#include "i_net.h"
|
||||
#include "i_system.h"
|
||||
#include "m_argv.h"
|
||||
#include "../i_system.h"
|
||||
#include "../m_argv.h"
|
||||
#include "d_net.h"
|
||||
#include "w_wad.h"
|
||||
#include "../w_wad.h"
|
||||
#include "d_netfil.h"
|
||||
#include "z_zone.h"
|
||||
#include "byteptr.h"
|
||||
#include "p_setup.h"
|
||||
#include "m_misc.h"
|
||||
#include "m_menu.h"
|
||||
#include "md5.h"
|
||||
#include "filesrch.h"
|
||||
#include "net_command.h"
|
||||
#include "../z_zone.h"
|
||||
#include "../byteptr.h"
|
||||
#include "../p_setup.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../m_menu.h"
|
||||
#include "../md5.h"
|
||||
#include "../filesrch.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
|
@ -103,26 +104,31 @@ typedef struct
|
|||
} pauseddownload_t;
|
||||
static pauseddownload_t *pauseddownload = NULL;
|
||||
|
||||
#ifndef NONET
|
||||
// for cl loading screen
|
||||
INT32 lastfilenum = -1;
|
||||
INT32 downloadcompletednum = 0;
|
||||
UINT32 downloadcompletedsize = 0;
|
||||
INT32 totalfilesrequestednum = 0;
|
||||
UINT32 totalfilesrequestedsize = 0;
|
||||
#endif
|
||||
|
||||
luafiletransfer_t *luafiletransfers = NULL;
|
||||
boolean waitingforluafiletransfer = false;
|
||||
boolean waitingforluafilecommand = false;
|
||||
char luafiledir[256 + 16] = "luafiles";
|
||||
|
||||
// max file size to send to a player (in kilobytes)
|
||||
static CV_PossibleValue_t maxsend_cons_t[] = {{0, "MIN"}, {204800, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_maxsend = CVAR_INIT ("maxsend", "4096", CV_SAVE|CV_NETVAR, maxsend_cons_t, NULL);
|
||||
|
||||
consvar_t cv_noticedownload = CVAR_INIT ("noticedownload", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
// Speed of file downloading (in packets per tic)
|
||||
static CV_PossibleValue_t downloadspeed_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_downloadspeed = CVAR_INIT ("downloadspeed", "16", CV_SAVE|CV_NETVAR, downloadspeed_cons_t, NULL);
|
||||
|
||||
static UINT16 GetWadNumFromFileNeededId(UINT8 id)
|
||||
{
|
||||
UINT16 wadnum;
|
||||
|
||||
for (wadnum = mainwads; wadnum < numwadfiles; wadnum++)
|
||||
for (UINT16 wadnum = mainwads; wadnum < numwadfiles; wadnum++)
|
||||
{
|
||||
if (!wadfiles[wadnum]->important)
|
||||
continue;
|
||||
|
@ -142,14 +148,13 @@ static UINT16 GetWadNumFromFileNeededId(UINT8 id)
|
|||
*/
|
||||
UINT8 *PutFileNeeded(UINT16 firstfile)
|
||||
{
|
||||
size_t i;
|
||||
UINT8 count = 0;
|
||||
UINT8 *p_start = netbuffer->packettype == PT_MOREFILESNEEDED ? netbuffer->u.filesneededcfg.files : netbuffer->u.serverinfo.fileneeded;
|
||||
UINT8 *p = p_start;
|
||||
char wadfilename[MAX_WADPATH] = "";
|
||||
UINT8 filestatus, folder;
|
||||
|
||||
for (i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad
|
||||
for (size_t i = mainwads; i < numwadfiles; i++) //mainwads, otherwise we start on the first mainwad
|
||||
{
|
||||
// If it has only music/sound lumps, don't put it in the list
|
||||
if (!wadfiles[i]->important)
|
||||
|
@ -224,7 +229,6 @@ void FreeFileNeeded(void)
|
|||
*/
|
||||
void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 firstfile)
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 *p;
|
||||
UINT8 filestatus;
|
||||
|
||||
|
@ -233,7 +237,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
|
|||
|
||||
AllocFileNeeded(fileneedednum);
|
||||
|
||||
for (i = firstfile; i < fileneedednum; i++)
|
||||
for (INT32 i = firstfile; i < fileneedednum; i++)
|
||||
{
|
||||
fileneeded[i].type = FILENEEDED_WAD;
|
||||
fileneeded[i].status = FS_NOTCHECKED; // We haven't even started looking for the file yet
|
||||
|
@ -250,9 +254,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr, UINT16 fi
|
|||
|
||||
void CL_PrepareDownloadSaveGame(const char *tmpsave)
|
||||
{
|
||||
#ifndef NONET
|
||||
lastfilenum = -1;
|
||||
#endif
|
||||
|
||||
FreeFileNeeded();
|
||||
AllocFileNeeded(1);
|
||||
|
@ -275,9 +277,9 @@ void CL_PrepareDownloadSaveGame(const char *tmpsave)
|
|||
*/
|
||||
boolean CL_CheckDownloadable(void)
|
||||
{
|
||||
UINT8 i,dlstatus = 0;
|
||||
UINT8 dlstatus = 0;
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (UINT8 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||
{
|
||||
if (fileneeded[i].willsend == 1)
|
||||
|
@ -298,7 +300,7 @@ boolean CL_CheckDownloadable(void)
|
|||
|
||||
// not downloadable, put reason in console
|
||||
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (UINT8 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||
{
|
||||
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
|
||||
|
@ -368,14 +370,13 @@ void CL_AbortDownloadResume(void)
|
|||
boolean CL_SendFileRequest(void)
|
||||
{
|
||||
char *p;
|
||||
INT32 i;
|
||||
INT64 totalfreespaceneeded = 0, availablefreespace;
|
||||
|
||||
#ifdef PARANOIA
|
||||
if (M_CheckParm("-nodownload"))
|
||||
I_Error("Attempted to download files in -nodownload mode");
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
|
||||
&& (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
||||
{
|
||||
|
@ -385,7 +386,7 @@ boolean CL_SendFileRequest(void)
|
|||
|
||||
netbuffer->packettype = PT_REQUESTFILE;
|
||||
p = (char *)netbuffer->u.textcmd;
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
|
||||
{
|
||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||
|
@ -413,26 +414,31 @@ boolean CL_SendFileRequest(void)
|
|||
}
|
||||
|
||||
// get request filepak and put it on the send queue
|
||||
// returns false if a requested file was not found or cannot be sent
|
||||
boolean PT_RequestFile(INT32 node)
|
||||
void PT_RequestFile(SINT8 node)
|
||||
{
|
||||
UINT8 *p = netbuffer->u.textcmd;
|
||||
UINT8 id;
|
||||
|
||||
if (client || !cv_downloading.value)
|
||||
{
|
||||
Net_CloseConnection(node); // close connection if you are not the server or disabled downloading
|
||||
return;
|
||||
}
|
||||
|
||||
while (p < netbuffer->u.textcmd + MAXTEXTCMD-1) // Don't allow hacked client to overflow
|
||||
{
|
||||
id = READUINT8(p);
|
||||
UINT8 id = READUINT8(p);
|
||||
if (id == 0xFF)
|
||||
break;
|
||||
|
||||
if (!AddFileToSendQueue(node, id))
|
||||
{
|
||||
SV_AbortSendFiles(node);
|
||||
return false; // don't read the rest of the files
|
||||
Net_CloseConnection(node); // close connection if one of the requested files could not be sent
|
||||
return; // don't read the rest of the files
|
||||
}
|
||||
}
|
||||
|
||||
return true; // no problems with any files
|
||||
return; // no problems with any files
|
||||
}
|
||||
|
||||
/** Checks if the files needed aren't already loaded or on the disk
|
||||
|
@ -531,9 +537,7 @@ INT32 CL_CheckFiles(void)
|
|||
// Load it now
|
||||
boolean CL_LoadServerFiles(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
if (fileneeded[i].status == FS_OPEN)
|
||||
continue; // Already loaded
|
||||
|
@ -629,11 +633,10 @@ void AddLuaFileTransfer(const char *filename, const char *mode)
|
|||
|
||||
static void SV_PrepareSendLuaFileToNextNode(void)
|
||||
{
|
||||
INT32 i;
|
||||
UINT8 success = 1;
|
||||
|
||||
// Find a client to send the file to
|
||||
for (i = 1; i < MAXNETNODES; i++)
|
||||
for (INT32 i = 1; i < MAXNETNODES; i++)
|
||||
if (luafiletransfers->nodestatus[i] == LFTNS_WAITING) // Node waiting
|
||||
{
|
||||
// Tell the client we're about to send them the file
|
||||
|
@ -655,13 +658,12 @@ static void SV_PrepareSendLuaFileToNextNode(void)
|
|||
void SV_PrepareSendLuaFile(void)
|
||||
{
|
||||
char *binfilename;
|
||||
INT32 i;
|
||||
|
||||
luafiletransfers->ongoing = true;
|
||||
|
||||
// Set status to "waiting" for everyone
|
||||
for (i = 0; i < MAXNETNODES; i++)
|
||||
luafiletransfers->nodestatus[i] = (nodeingame[i] ? LFTNS_WAITING : LFTNS_NONE);
|
||||
for (INT32 i = 0; i < MAXNETNODES; i++)
|
||||
luafiletransfers->nodestatus[i] = (netnodes[i].ingame ? LFTNS_WAITING : LFTNS_NONE);
|
||||
|
||||
if (FIL_ReadFileOK(luafiletransfers->realfilename))
|
||||
{
|
||||
|
@ -1137,12 +1139,13 @@ void FileSendTicker(void)
|
|||
}
|
||||
}
|
||||
|
||||
void PT_FileAck(void)
|
||||
void PT_FileAck(SINT8 node)
|
||||
{
|
||||
fileack_pak *packet = &netbuffer->u.fileack;
|
||||
INT32 node = doomcom->remotenode;
|
||||
filetran_t *trans = &transfer[node];
|
||||
INT32 i, j;
|
||||
|
||||
if (client)
|
||||
return;
|
||||
|
||||
// Wrong file id? Ignore it, it's probably a late packet
|
||||
if (!(trans->txlist && packet->fileid == trans->txlist->fileid))
|
||||
|
@ -1161,11 +1164,11 @@ void PT_FileAck(void)
|
|||
trans->dontsenduntil = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < packet->numsegments; i++)
|
||||
for (INT32 i = 0; i < packet->numsegments; i++)
|
||||
{
|
||||
fileacksegment_t *segment = &packet->segments[i];
|
||||
|
||||
for (j = 0; j < 32; j++)
|
||||
for (INT32 j = 0; j < 32; j++)
|
||||
if (LONG(segment->acks) & (1 << j))
|
||||
{
|
||||
if (LONG(segment->start) * FILEFRAGMENTSIZE >= trans->txlist->size)
|
||||
|
@ -1190,24 +1193,23 @@ void PT_FileAck(void)
|
|||
}
|
||||
}
|
||||
|
||||
void PT_FileReceived(void)
|
||||
void PT_FileReceived(SINT8 node)
|
||||
{
|
||||
filetx_t *trans = transfer[doomcom->remotenode].txlist;
|
||||
filetx_t *trans = transfer[node].txlist;
|
||||
|
||||
if (trans && netbuffer->u.filereceived == trans->fileid)
|
||||
SV_EndFileSend(doomcom->remotenode);
|
||||
if (server && trans && netbuffer->u.filereceived == trans->fileid)
|
||||
SV_EndFileSend(node);
|
||||
}
|
||||
|
||||
static void SendAckPacket(fileack_pak *packet, UINT8 fileid)
|
||||
{
|
||||
size_t packetsize;
|
||||
INT32 i;
|
||||
|
||||
packetsize = sizeof(*packet) + packet->numsegments * sizeof(*packet->segments);
|
||||
|
||||
// Finalise the packet
|
||||
packet->fileid = fileid;
|
||||
for (i = 0; i < packet->numsegments; i++)
|
||||
for (INT32 i = 0; i < packet->numsegments; i++)
|
||||
{
|
||||
packet->segments[i].start = LONG(packet->segments[i].start);
|
||||
packet->segments[i].acks = LONG(packet->segments[i].acks);
|
||||
|
@ -1247,9 +1249,7 @@ static void AddFragmentToAckPacket(fileack_pak *packet, UINT8 iteration, UINT32
|
|||
|
||||
void FileReceiveTicker(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
{
|
||||
fileneeded_t *file = &fileneeded[i];
|
||||
|
||||
|
@ -1263,8 +1263,7 @@ void FileReceiveTicker(void)
|
|||
if (file->ackresendposition != UINT32_MAX && file->status == FS_DOWNLOADING)
|
||||
{
|
||||
// Acknowledge ~70 MB/s, whichs means the client sends ~18 KB/s
|
||||
INT32 j;
|
||||
for (j = 0; j < 2048; j++)
|
||||
for (INT32 j = 0; j < 2048; j++)
|
||||
{
|
||||
if (file->receivedfragments[file->ackresendposition])
|
||||
AddFragmentToAckPacket(file->ackpacket, file->iteration, file->ackresendposition, i);
|
||||
|
@ -1281,8 +1280,27 @@ void FileReceiveTicker(void)
|
|||
}
|
||||
}
|
||||
|
||||
void PT_FileFragment(void)
|
||||
void PT_FileFragment(SINT8 node, INT32 netconsole)
|
||||
{
|
||||
if (netnodes[node].ingame)
|
||||
{
|
||||
// Only accept PT_FILEFRAGMENT from the server.
|
||||
if (node != servernode)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("%s received from non-host %d\n"), "PT_FILEFRAGMENT", node);
|
||||
if (server)
|
||||
SendKick(netconsole, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||
return;
|
||||
}
|
||||
if (server)
|
||||
return;
|
||||
}
|
||||
else if (server || node != servernode)
|
||||
{
|
||||
Net_CloseConnection(node);
|
||||
return;
|
||||
}
|
||||
|
||||
INT32 filenum = netbuffer->u.filetxpak.fileid;
|
||||
fileneeded_t *file = &fileneeded[filenum];
|
||||
UINT32 fragmentpos = LONG(netbuffer->u.filetxpak.position);
|
||||
|
@ -1439,9 +1457,7 @@ void PT_FileFragment(void)
|
|||
I_Error("Received a file not requested (file id: %d, file status: %s)\n", filenum, s);
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
lastfilenum = filenum;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** \brief Checks if a node is downloading a file
|
||||
|
@ -1469,15 +1485,14 @@ void SV_AbortSendFiles(INT32 node)
|
|||
|
||||
void CloseNetFile(void)
|
||||
{
|
||||
INT32 i;
|
||||
// Is sending?
|
||||
for (i = 0; i < MAXNETNODES; i++)
|
||||
for (INT32 i = 0; i < MAXNETNODES; i++)
|
||||
SV_AbortSendFiles(i);
|
||||
|
||||
// Receiving a file?
|
||||
if (fileneeded)
|
||||
{
|
||||
for (i = 0; i < fileneedednum; i++)
|
||||
for (INT32 i = 0; i < fileneedednum; i++)
|
||||
if (fileneeded[i].status == FS_DOWNLOADING && fileneeded[i].file)
|
||||
{
|
||||
fclose(fileneeded[i].file);
|
||||
|
@ -1510,9 +1525,7 @@ void CloseNetFile(void)
|
|||
|
||||
void Command_Downloads_f(void)
|
||||
{
|
||||
INT32 node;
|
||||
|
||||
for (node = 0; node < MAXNETNODES; node++)
|
||||
for (INT32 node = 0; node < MAXNETNODES; node++)
|
||||
if (transfer[node].txlist
|
||||
&& transfer[node].txlist->ram == SF_FILE) // Node is downloading a file?
|
||||
{
|
||||
|
@ -1546,14 +1559,11 @@ void Command_Downloads_f(void)
|
|||
|
||||
void nameonly(char *s)
|
||||
{
|
||||
size_t j, len;
|
||||
void *ns;
|
||||
|
||||
for (j = strlen(s); j != (size_t)-1; j--)
|
||||
for (size_t j = strlen(s); j != (size_t)-1; j--)
|
||||
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
|
||||
{
|
||||
ns = &(s[j+1]);
|
||||
len = strlen(ns);
|
||||
void *ns = &(s[j+1]);
|
||||
size_t len = strlen(ns);
|
||||
#if 0
|
||||
M_Memcpy(s, ns, len+1);
|
||||
#else
|
||||
|
@ -1566,9 +1576,9 @@ void nameonly(char *s)
|
|||
// Returns the length in characters of the last element of a path.
|
||||
size_t nameonlylength(const char *s)
|
||||
{
|
||||
size_t j, len = strlen(s);
|
||||
size_t len = strlen(s);
|
||||
|
||||
for (j = len; j != (size_t)-1; j--)
|
||||
for (size_t j = len; j != (size_t)-1; j--)
|
||||
if ((s[j] == '\\') || (s[j] == ':') || (s[j] == '/'))
|
||||
return len - j - 1;
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "d_net.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "w_wad.h"
|
||||
#include "../w_wad.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -70,13 +70,13 @@ extern INT32 fileneedednum;
|
|||
extern fileneeded_t *fileneeded;
|
||||
extern char downloaddir[512];
|
||||
|
||||
#ifndef NONET
|
||||
extern INT32 lastfilenum;
|
||||
extern INT32 downloadcompletednum;
|
||||
extern UINT32 downloadcompletedsize;
|
||||
extern INT32 totalfilesrequestednum;
|
||||
extern UINT32 totalfilesrequestedsize;
|
||||
#endif
|
||||
|
||||
extern consvar_t cv_maxsend, cv_noticedownload, cv_downloadspeed;
|
||||
|
||||
void AllocFileNeeded(INT32 size);
|
||||
void FreeFileNeeded(void);
|
||||
|
@ -90,16 +90,16 @@ void AddRamToSendQueue(INT32 node, void *data, size_t size, freemethod_t freemet
|
|||
UINT8 fileid);
|
||||
|
||||
void FileSendTicker(void);
|
||||
void PT_FileAck(void);
|
||||
void PT_FileReceived(void);
|
||||
void PT_FileAck(SINT8 node);
|
||||
void PT_FileReceived(SINT8 node);
|
||||
boolean SendingFile(INT32 node);
|
||||
|
||||
void FileReceiveTicker(void);
|
||||
void PT_FileFragment(void);
|
||||
void PT_FileFragment(SINT8 node, INT32 netconsole);
|
||||
|
||||
boolean CL_CheckDownloadable(void);
|
||||
boolean CL_SendFileRequest(void);
|
||||
boolean PT_RequestFile(INT32 node);
|
||||
void PT_RequestFile(SINT8 node);
|
||||
|
||||
typedef enum
|
||||
{
|
336
src/netcode/gamestate.c
Normal file
336
src/netcode/gamestate.c
Normal file
|
@ -0,0 +1,336 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file gamestate.c
|
||||
/// \brief Gamestate (re)sending
|
||||
|
||||
#include "d_clisrv.h"
|
||||
#include "d_netfil.h"
|
||||
#include "gamestate.h"
|
||||
#include "i_net.h"
|
||||
#include "protocol.h"
|
||||
#include "server_connection.h"
|
||||
#include "../am_map.h"
|
||||
#include "../byteptr.h"
|
||||
#include "../console.h"
|
||||
#include "../d_main.h"
|
||||
#include "../doomstat.h"
|
||||
#include "../doomtype.h"
|
||||
#include "../f_finale.h"
|
||||
#include "../g_demo.h"
|
||||
#include "../g_game.h"
|
||||
#include "../i_time.h"
|
||||
#include "../lua_script.h"
|
||||
#include "../lzf.h"
|
||||
#include "../m_misc.h"
|
||||
#include "../p_local.h"
|
||||
#include "../p_saveg.h"
|
||||
#include "../r_main.h"
|
||||
#include "../tables.h"
|
||||
#include "../z_zone.h"
|
||||
#if defined (__GNUC__) || defined (__unix__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#define SAVEGAMESIZE (768*1024)
|
||||
|
||||
UINT8 hu_redownloadinggamestate = 0;
|
||||
boolean cl_redownloadinggamestate = false;
|
||||
|
||||
boolean SV_ResendingSavegameToAnyone(void)
|
||||
{
|
||||
for (INT32 i = 0; i < MAXNETNODES; i++)
|
||||
if (netnodes[i].resendingsavegame)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void SV_SendSaveGame(INT32 node, boolean resending)
|
||||
{
|
||||
size_t length, compressedlen;
|
||||
UINT8 *savebuffer;
|
||||
UINT8 *compressedsave;
|
||||
UINT8 *buffertosend;
|
||||
|
||||
// first save it in a malloced buffer
|
||||
savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!savebuffer)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Leave room for the uncompressed length.
|
||||
save_p = savebuffer + sizeof(UINT32);
|
||||
|
||||
P_SaveNetGame(resending);
|
||||
|
||||
length = save_p - savebuffer;
|
||||
if (length > SAVEGAMESIZE)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
I_Error("Savegame buffer overrun");
|
||||
}
|
||||
|
||||
// Allocate space for compressed save: one byte fewer than for the
|
||||
// uncompressed data to ensure that the compression is worthwhile.
|
||||
compressedsave = malloc(length - 1);
|
||||
if (!compressedsave)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Attempt to compress it.
|
||||
if((compressedlen = lzf_compress(savebuffer + sizeof(UINT32), length - sizeof(UINT32), compressedsave + sizeof(UINT32), length - sizeof(UINT32) - 1)))
|
||||
{
|
||||
// Compressing succeeded; send compressed data
|
||||
|
||||
free(savebuffer);
|
||||
|
||||
// State that we're compressed.
|
||||
buffertosend = compressedsave;
|
||||
WRITEUINT32(compressedsave, length - sizeof(UINT32));
|
||||
length = compressedlen + sizeof(UINT32);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Compression failed to make it smaller; send original
|
||||
|
||||
free(compressedsave);
|
||||
|
||||
// State that we're not compressed
|
||||
buffertosend = savebuffer;
|
||||
WRITEUINT32(savebuffer, 0);
|
||||
}
|
||||
|
||||
AddRamToSendQueue(node, buffertosend, length, SF_RAM, 0);
|
||||
save_p = NULL;
|
||||
|
||||
// Remember when we started sending the savegame so we can handle timeouts
|
||||
netnodes[node].sendingsavegame = true;
|
||||
netnodes[node].freezetimeout = I_GetTime() + jointimeout + length / 1024; // 1 extra tic for each kilobyte
|
||||
}
|
||||
|
||||
#ifdef DUMPCONSISTENCY
|
||||
#define TMPSAVENAME "badmath.sav"
|
||||
static consvar_t cv_dumpconsistency = CVAR_INIT ("dumpconsistency", "Off", CV_SAVE|CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
void SV_SavedGame(void)
|
||||
{
|
||||
size_t length;
|
||||
UINT8 *savebuffer;
|
||||
char tmpsave[256];
|
||||
|
||||
if (!cv_dumpconsistency.value)
|
||||
return;
|
||||
|
||||
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
|
||||
|
||||
// first save it in a malloced buffer
|
||||
save_p = savebuffer = (UINT8 *)malloc(SAVEGAMESIZE);
|
||||
if (!save_p)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("No more free memory for savegame\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
P_SaveNetGame(false);
|
||||
|
||||
length = save_p - savebuffer;
|
||||
if (length > SAVEGAMESIZE)
|
||||
{
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
I_Error("Savegame buffer overrun");
|
||||
}
|
||||
|
||||
// then save it!
|
||||
if (!FIL_WriteFile(tmpsave, savebuffer, length))
|
||||
CONS_Printf(M_GetText("Didn't save %s for netgame"), tmpsave);
|
||||
|
||||
free(savebuffer);
|
||||
save_p = NULL;
|
||||
}
|
||||
|
||||
#undef TMPSAVENAME
|
||||
#endif
|
||||
#define TMPSAVENAME "$$$.sav"
|
||||
|
||||
|
||||
void CL_LoadReceivedSavegame(boolean reloading)
|
||||
{
|
||||
UINT8 *savebuffer = NULL;
|
||||
size_t length, decompressedlen;
|
||||
char tmpsave[256];
|
||||
|
||||
FreeFileNeeded();
|
||||
|
||||
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
|
||||
|
||||
length = FIL_ReadFile(tmpsave, &savebuffer);
|
||||
|
||||
CONS_Printf(M_GetText("Loading savegame length %s\n"), sizeu1(length));
|
||||
if (!length)
|
||||
{
|
||||
I_Error("Can't read savegame sent");
|
||||
return;
|
||||
}
|
||||
|
||||
save_p = savebuffer;
|
||||
|
||||
// Decompress saved game if necessary.
|
||||
decompressedlen = READUINT32(save_p);
|
||||
if(decompressedlen > 0)
|
||||
{
|
||||
UINT8 *decompressedbuffer = Z_Malloc(decompressedlen, PU_STATIC, NULL);
|
||||
lzf_decompress(save_p, length - sizeof(UINT32), decompressedbuffer, decompressedlen);
|
||||
Z_Free(savebuffer);
|
||||
save_p = savebuffer = decompressedbuffer;
|
||||
}
|
||||
|
||||
paused = false;
|
||||
demoplayback = false;
|
||||
titlemapinaction = TITLEMAP_OFF;
|
||||
titledemo = false;
|
||||
automapactive = false;
|
||||
|
||||
// load a base level
|
||||
if (P_LoadNetGame(reloading))
|
||||
{
|
||||
const UINT8 actnum = mapheaderinfo[gamemap-1]->actnum;
|
||||
CONS_Printf(M_GetText("Map is now \"%s"), G_BuildMapName(gamemap));
|
||||
if (strcmp(mapheaderinfo[gamemap-1]->lvlttl, ""))
|
||||
{
|
||||
CONS_Printf(": %s", mapheaderinfo[gamemap-1]->lvlttl);
|
||||
if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE))
|
||||
CONS_Printf(M_GetText(" Zone"));
|
||||
if (actnum > 0)
|
||||
CONS_Printf(" %2d", actnum);
|
||||
}
|
||||
CONS_Printf("\"\n");
|
||||
}
|
||||
|
||||
// done
|
||||
Z_Free(savebuffer);
|
||||
save_p = NULL;
|
||||
if (unlink(tmpsave) == -1)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Can't delete %s\n"), tmpsave);
|
||||
consistancy[gametic%BACKUPTICS] = Consistancy();
|
||||
CON_ToggleOff();
|
||||
|
||||
// Tell the server we have received and reloaded the gamestate
|
||||
// so they know they can resume the game
|
||||
netbuffer->packettype = PT_RECEIVEDGAMESTATE;
|
||||
HSendPacket(servernode, true, 0, 0);
|
||||
}
|
||||
|
||||
void CL_ReloadReceivedSavegame(void)
|
||||
{
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
LUA_InvalidatePlayer(&players[i]);
|
||||
sprintf(player_names[i], "Player %d", i + 1);
|
||||
}
|
||||
|
||||
CL_LoadReceivedSavegame(true);
|
||||
|
||||
neededtic = max(neededtic, gametic);
|
||||
maketic = neededtic;
|
||||
|
||||
ticcmd_oldangleturn[0] = players[consoleplayer].oldrelangleturn;
|
||||
P_ForceLocalAngle(&players[consoleplayer], (angle_t)(players[consoleplayer].angleturn << 16));
|
||||
if (splitscreen)
|
||||
{
|
||||
ticcmd_oldangleturn[1] = players[secondarydisplayplayer].oldrelangleturn;
|
||||
P_ForceLocalAngle(&players[secondarydisplayplayer], (angle_t)(players[secondarydisplayplayer].angleturn << 16));
|
||||
}
|
||||
|
||||
camera.subsector = R_PointInSubsector(camera.x, camera.y);
|
||||
camera2.subsector = R_PointInSubsector(camera2.x, camera2.y);
|
||||
|
||||
cl_redownloadinggamestate = false;
|
||||
|
||||
CONS_Printf(M_GetText("Game state reloaded\n"));
|
||||
}
|
||||
|
||||
void Command_ResendGamestate(void)
|
||||
{
|
||||
SINT8 playernum;
|
||||
|
||||
if (COM_Argc() == 1)
|
||||
{
|
||||
CONS_Printf(M_GetText("resendgamestate <playername/playernum>: resend the game state to a player\n"));
|
||||
return;
|
||||
}
|
||||
else if (client)
|
||||
{
|
||||
CONS_Printf(M_GetText("Only the server can use this.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
playernum = nametonum(COM_Argv(1));
|
||||
if (playernum == -1 || playernum == 0)
|
||||
return;
|
||||
|
||||
// Send a PT_WILLRESENDGAMESTATE packet to the client so they know what's going on
|
||||
netbuffer->packettype = PT_WILLRESENDGAMESTATE;
|
||||
if (!HSendPacket(playernode[playernum], true, 0, 0))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("A problem occurred, please try again.\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PT_CanReceiveGamestate(SINT8 node)
|
||||
{
|
||||
if (client || netnodes[node].sendingsavegame)
|
||||
return;
|
||||
|
||||
CONS_Printf(M_GetText("Resending game state to %s...\n"), player_names[netnodes[node].player]);
|
||||
|
||||
SV_SendSaveGame(node, true); // Resend a complete game state
|
||||
netnodes[node].resendingsavegame = true;
|
||||
}
|
||||
|
||||
void PT_ReceivedGamestate(SINT8 node)
|
||||
{
|
||||
netnodes[node].sendingsavegame = false;
|
||||
netnodes[node].resendingsavegame = false;
|
||||
netnodes[node].savegameresendcooldown = I_GetTime() + 5 * TICRATE;
|
||||
}
|
||||
|
||||
void PT_WillResendGamestate(SINT8 node)
|
||||
{
|
||||
(void)node;
|
||||
|
||||
char tmpsave[256];
|
||||
|
||||
if (server || cl_redownloadinggamestate)
|
||||
return;
|
||||
|
||||
// Send back a PT_CANRECEIVEGAMESTATE packet to the server
|
||||
// so they know they can start sending the game state
|
||||
netbuffer->packettype = PT_CANRECEIVEGAMESTATE;
|
||||
if (!HSendPacket(servernode, true, 0, 0))
|
||||
return;
|
||||
|
||||
CONS_Printf(M_GetText("Reloading game state...\n"));
|
||||
|
||||
sprintf(tmpsave, "%s" PATHSEP TMPSAVENAME, srb2home);
|
||||
|
||||
// Don't get a corrupt savegame error because tmpsave already exists
|
||||
if (FIL_FileExists(tmpsave) && unlink(tmpsave) == -1)
|
||||
I_Error("Can't delete %s\n", tmpsave);
|
||||
|
||||
CL_PrepareDownloadSaveGame(tmpsave);
|
||||
|
||||
cl_redownloadinggamestate = true;
|
||||
}
|
31
src/netcode/gamestate.h
Normal file
31
src/netcode/gamestate.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
// SONIC ROBO BLAST 2
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
||||
// Copyright (C) 1999-2023 by Sonic Team Junior.
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file gamestate.h
|
||||
/// \brief Gamestate (re)sending
|
||||
|
||||
#ifndef __GAMESTATE__
|
||||
#define __GAMESTATE__
|
||||
|
||||
#include "../doomtype.h"
|
||||
|
||||
extern UINT8 hu_redownloadinggamestate;
|
||||
extern boolean cl_redownloadinggamestate;
|
||||
|
||||
boolean SV_ResendingSavegameToAnyone(void);
|
||||
void SV_SendSaveGame(INT32 node, boolean resending);
|
||||
void SV_SavedGame(void);
|
||||
void CL_LoadReceivedSavegame(boolean reloading);
|
||||
void CL_ReloadReceivedSavegame(void);
|
||||
void Command_ResendGamestate(void);
|
||||
void PT_CanReceiveGamestate(SINT8 node);
|
||||
void PT_ReceivedGamestate(SINT8 node);
|
||||
void PT_WillResendGamestate(SINT8 node);
|
||||
|
||||
#endif
|
|
@ -18,14 +18,15 @@ Documentation available here.
|
|||
#include <curl/curl.h>
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "../doomdef.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "command.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_menu.h"
|
||||
#include "client_connection.h"
|
||||
#include "../command.h"
|
||||
#include "../m_argv.h"
|
||||
#include "../m_menu.h"
|
||||
#include "mserv.h"
|
||||
#include "i_tcp.h"/* for current_port */
|
||||
#include "i_threads.h"
|
||||
#include "../i_threads.h"
|
||||
|
||||
/* reasonable default I guess?? */
|
||||
#define DEFAULT_BUFFER_SIZE (4096)
|
||||
|
@ -34,6 +35,10 @@ Documentation available here.
|
|||
#define Blame( ... ) \
|
||||
CONS_Printf("\x85" __VA_ARGS__)
|
||||
|
||||
#define PROTO_ANY 0
|
||||
#define PROTO_V4 1
|
||||
#define PROTO_V6 2
|
||||
|
||||
static void MasterServer_Debug_OnChange (void);
|
||||
|
||||
consvar_t cv_masterserver_timeout = CVAR_INIT
|
||||
|
@ -58,12 +63,17 @@ consvar_t cv_masterserver_token = CVAR_INIT
|
|||
|
||||
static int hms_started;
|
||||
|
||||
static boolean hms_allow_ipv6;
|
||||
|
||||
static char *hms_api;
|
||||
#ifdef HAVE_THREADS
|
||||
static I_mutex hms_api_mutex;
|
||||
#endif
|
||||
|
||||
static char *hms_server_token;
|
||||
#ifndef NO_IPV6
|
||||
static char *hms_server_token_ipv6;
|
||||
#endif
|
||||
|
||||
static char hms_useragent[512];
|
||||
|
||||
|
@ -95,7 +105,7 @@ init_user_agent_once(void)
|
|||
{
|
||||
if (hms_useragent[0] != '\0')
|
||||
return;
|
||||
|
||||
|
||||
get_user_agent(hms_useragent, 512);
|
||||
}
|
||||
|
||||
|
@ -125,7 +135,7 @@ HMS_on_read (char *s, size_t _1, size_t n, void *userdata)
|
|||
}
|
||||
|
||||
static struct HMS_buffer *
|
||||
HMS_connect (const char *format, ...)
|
||||
HMS_connect (int proto, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
CURL *curl;
|
||||
|
@ -135,8 +145,14 @@ HMS_connect (const char *format, ...)
|
|||
size_t token_length;
|
||||
struct HMS_buffer *buffer;
|
||||
|
||||
#ifdef NO_IPV6
|
||||
if (proto == PROTO_V6)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (! hms_started)
|
||||
{
|
||||
hms_allow_ipv6 = !M_CheckParm("-noipv6");
|
||||
if (curl_global_init(CURL_GLOBAL_ALL) != 0)
|
||||
{
|
||||
Contact_error();
|
||||
|
@ -218,7 +234,9 @@ HMS_connect (const char *format, ...)
|
|||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
|
||||
|
||||
#ifndef NO_IPV6
|
||||
if (M_CheckParm("-noipv6"))
|
||||
if (proto == PROTO_V6)
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6);
|
||||
if (proto == PROTO_V4)
|
||||
#endif
|
||||
curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
||||
|
||||
|
@ -308,7 +326,7 @@ HMS_fetch_rooms (int joining, int query_id)
|
|||
|
||||
(void)query_id;
|
||||
|
||||
hms = HMS_connect("rooms");
|
||||
hms = HMS_connect(PROTO_ANY, "rooms");
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
@ -408,7 +426,7 @@ HMS_register (void)
|
|||
|
||||
char *title;
|
||||
|
||||
hms = HMS_connect("rooms/%d/register", ms_RoomId);
|
||||
hms = HMS_connect(PROTO_V4, "rooms/%d/register", ms_RoomId);
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
@ -440,6 +458,27 @@ HMS_register (void)
|
|||
|
||||
HMS_end(hms);
|
||||
|
||||
#ifndef NO_IPV6
|
||||
if (!hms_allow_ipv6)
|
||||
return ok;
|
||||
|
||||
hms = HMS_connect(PROTO_V6, "rooms/%d/register", ms_RoomId);
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post);
|
||||
|
||||
ok = HMS_do(hms);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
hms_server_token_ipv6 = strdup(strtok(hms->buffer, "\n"));
|
||||
}
|
||||
|
||||
HMS_end(hms);
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -449,7 +488,7 @@ HMS_unlist (void)
|
|||
struct HMS_buffer *hms;
|
||||
int ok;
|
||||
|
||||
hms = HMS_connect("servers/%s/unlist", hms_server_token);
|
||||
hms = HMS_connect(PROTO_V4, "servers/%s/unlist", hms_server_token);
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
@ -461,6 +500,23 @@ HMS_unlist (void)
|
|||
|
||||
free(hms_server_token);
|
||||
|
||||
#ifndef NO_IPV6
|
||||
if (hms_server_token_ipv6 && hms_allow_ipv6)
|
||||
{
|
||||
hms = HMS_connect(PROTO_V6, "servers/%s/unlist", hms_server_token_ipv6);
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
||||
curl_easy_setopt(hms->curl, CURLOPT_CUSTOMREQUEST, "POST");
|
||||
|
||||
ok = HMS_do(hms);
|
||||
HMS_end(hms);
|
||||
|
||||
free(hms_server_token_ipv6);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -474,7 +530,7 @@ HMS_update (void)
|
|||
|
||||
char *title;
|
||||
|
||||
hms = HMS_connect("servers/%s/update", hms_server_token);
|
||||
hms = HMS_connect(PROTO_V4, "servers/%s/update", hms_server_token);
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
||||
|
@ -493,6 +549,21 @@ HMS_update (void)
|
|||
ok = HMS_do(hms);
|
||||
HMS_end(hms);
|
||||
|
||||
#ifndef NO_IPV6
|
||||
if (hms_server_token_ipv6 && hms_allow_ipv6)
|
||||
{
|
||||
hms = HMS_connect(PROTO_V6, "servers/%s/update", hms_server_token_ipv6);
|
||||
|
||||
if (! hms)
|
||||
return ok;
|
||||
|
||||
curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post);
|
||||
|
||||
ok = HMS_do(hms);
|
||||
HMS_end(hms);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
@ -504,7 +575,7 @@ HMS_list_servers (void)
|
|||
char *list;
|
||||
char *p;
|
||||
|
||||
hms = HMS_connect("servers");
|
||||
hms = HMS_connect(PROTO_ANY, "servers");
|
||||
|
||||
if (! hms)
|
||||
return;
|
||||
|
@ -553,10 +624,10 @@ HMS_fetch_servers (msg_server_t *list, int room_number, int query_id)
|
|||
|
||||
if (room_number > 0)
|
||||
{
|
||||
hms = HMS_connect("rooms/%d/servers", room_number);
|
||||
hms = HMS_connect(PROTO_ANY, "rooms/%d/servers", room_number);
|
||||
}
|
||||
else
|
||||
hms = HMS_connect("servers");
|
||||
hms = HMS_connect(PROTO_ANY, "servers");
|
||||
|
||||
if (! hms)
|
||||
return NULL;
|
||||
|
@ -660,7 +731,7 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size)
|
|||
char *version;
|
||||
char *version_name;
|
||||
|
||||
hms = HMS_connect("versions/%d", MODID);
|
||||
hms = HMS_connect(PROTO_ANY, "versions/%d", MODID);
|
||||
|
||||
if (! hms)
|
||||
return 0;
|
|
@ -18,8 +18,8 @@
|
|||
#pragma interface
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "command.h"
|
||||
#include "../doomdef.h"
|
||||
#include "../command.h"
|
||||
|
||||
/// \brief program net id
|
||||
#define DOOMCOM_ID (INT32)0x12345678l
|
|
@ -36,111 +36,104 @@
|
|||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "../doomdef.h"
|
||||
|
||||
#if defined (NOMD5) && !defined (NONET)
|
||||
//#define NONET
|
||||
#ifdef USE_WINSOCK1
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#ifndef USE_WINSOCK
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __APPLE_CC__
|
||||
#ifndef _BSD_SOCKLEN_T_
|
||||
#define _BSD_SOCKLEN_T_
|
||||
#endif //_BSD_SOCKLEN_T_
|
||||
#endif //__APPLE_CC__
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif //normal BSD API
|
||||
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)
|
||||
#include <sys/time.h>
|
||||
#endif // UNIXCOMMON
|
||||
#endif
|
||||
|
||||
#ifdef NONET
|
||||
#undef HAVE_MINIUPNPC
|
||||
#else
|
||||
#ifdef USE_WINSOCK1
|
||||
#include <winsock.h>
|
||||
#else
|
||||
#ifndef USE_WINSOCK
|
||||
#include <arpa/inet.h>
|
||||
#ifdef __APPLE_CC__
|
||||
#ifndef _BSD_SOCKLEN_T_
|
||||
#define _BSD_SOCKLEN_T_
|
||||
#endif //_BSD_SOCKLEN_T_
|
||||
#endif //__APPLE_CC__
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/ioctl.h>
|
||||
#endif //normal BSD API
|
||||
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#if defined (__unix__) || defined (__APPLE__) || defined (UNIXCOMMON)
|
||||
#include <sys/time.h>
|
||||
#endif // UNIXCOMMON
|
||||
#ifdef USE_WINSOCK
|
||||
// some undefined under win32
|
||||
#undef errno
|
||||
//#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right?
|
||||
#define errno h_errno // some very strange things happen when not using h_error?!?
|
||||
#ifdef EWOULDBLOCK
|
||||
#undef EWOULDBLOCK
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINSOCK
|
||||
// some undefined under win32
|
||||
#undef errno
|
||||
//#define errno WSAGetLastError() //Alam_GBC: this is the correct way, right?
|
||||
#define errno h_errno // some very strange things happen when not using h_error?!?
|
||||
#ifdef EWOULDBLOCK
|
||||
#undef EWOULDBLOCK
|
||||
#endif
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#ifdef EMSGSIZE
|
||||
#undef EMSGSIZE
|
||||
#endif
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#ifdef ECONNREFUSED
|
||||
#undef ECONNREFUSED
|
||||
#endif
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#ifdef ETIMEDOUT
|
||||
#undef ETIMEDOUT
|
||||
#endif
|
||||
#define ETIMEDOUT WSAETIMEDOUT
|
||||
#ifndef IOC_VENDOR
|
||||
#define IOC_VENDOR 0x18000000
|
||||
#endif
|
||||
#ifndef _WSAIOW
|
||||
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
|
||||
#endif
|
||||
#ifndef SIO_UDP_CONNRESET
|
||||
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
|
||||
#endif
|
||||
#ifndef AI_ADDRCONFIG
|
||||
#define AI_ADDRCONFIG 0x00000400
|
||||
#endif
|
||||
#ifndef STATUS_INVALID_PARAMETER
|
||||
#define STATUS_INVALID_PARAMETER 0xC000000D
|
||||
#endif
|
||||
#endif // USE_WINSOCK
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct sockaddr any;
|
||||
struct sockaddr_in ip4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 ip6;
|
||||
#define EWOULDBLOCK WSAEWOULDBLOCK
|
||||
#ifdef EMSGSIZE
|
||||
#undef EMSGSIZE
|
||||
#endif
|
||||
} mysockaddr_t;
|
||||
|
||||
#ifdef HAVE_MINIUPNPC
|
||||
#ifdef MINIUPNP_STATICLIB
|
||||
#include "miniwget.h"
|
||||
#include "miniupnpc.h"
|
||||
#include "upnpcommands.h"
|
||||
#else
|
||||
#include "miniupnpc/miniwget.h"
|
||||
#include "miniupnpc/miniupnpc.h"
|
||||
#include "miniupnpc/upnpcommands.h"
|
||||
#define EMSGSIZE WSAEMSGSIZE
|
||||
#ifdef ECONNREFUSED
|
||||
#undef ECONNREFUSED
|
||||
#endif
|
||||
static boolean UPNP_support = true;
|
||||
#endif // HAVE_MINIUPNC
|
||||
#define ECONNREFUSED WSAECONNREFUSED
|
||||
#ifdef ETIMEDOUT
|
||||
#undef ETIMEDOUT
|
||||
#endif
|
||||
#define ETIMEDOUT WSAETIMEDOUT
|
||||
#ifdef EHOSTUNREACH
|
||||
#undef EHOSTUNREACH
|
||||
#endif
|
||||
#define EHOSTUNREACH WSAEHOSTUNREACH
|
||||
#ifndef IOC_VENDOR
|
||||
#define IOC_VENDOR 0x18000000
|
||||
#endif
|
||||
#ifndef _WSAIOW
|
||||
#define _WSAIOW(x,y) (IOC_IN|(x)|(y))
|
||||
#endif
|
||||
#ifndef SIO_UDP_CONNRESET
|
||||
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR,12)
|
||||
#endif
|
||||
#ifndef AI_ADDRCONFIG
|
||||
#define AI_ADDRCONFIG 0x00000400
|
||||
#endif
|
||||
#ifndef STATUS_INVALID_PARAMETER
|
||||
#define STATUS_INVALID_PARAMETER 0xC000000D
|
||||
#endif
|
||||
#endif // USE_WINSOCK
|
||||
|
||||
#endif // !NONET
|
||||
typedef union
|
||||
{
|
||||
struct sockaddr any;
|
||||
struct sockaddr_in ip4;
|
||||
#ifdef HAVE_IPV6
|
||||
struct sockaddr_in6 ip6;
|
||||
#endif
|
||||
} mysockaddr_t;
|
||||
|
||||
#ifdef HAVE_MINIUPNPC
|
||||
#ifdef STATIC_MINIUPNPC
|
||||
#define STATICLIB
|
||||
#endif
|
||||
#include "miniupnpc/miniwget.h"
|
||||
#include "miniupnpc/miniupnpc.h"
|
||||
#include "miniupnpc/upnpcommands.h"
|
||||
#undef STATICLIB
|
||||
static UINT8 UPNP_support = TRUE;
|
||||
#endif // HAVE_MINIUPNC
|
||||
|
||||
#define MAXBANS 100
|
||||
|
||||
#include "i_system.h"
|
||||
#include "../i_system.h"
|
||||
#include "i_net.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netfil.h"
|
||||
#include "i_tcp.h"
|
||||
#include "m_argv.h"
|
||||
#include "../m_argv.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "../doomstat.h"
|
||||
|
||||
// win32
|
||||
#ifdef USE_WINSOCK
|
||||
|
@ -153,7 +146,7 @@
|
|||
#define SELECTTEST
|
||||
#define DEFAULTPORT "5029"
|
||||
|
||||
#if defined (USE_WINSOCK) && !defined (NONET)
|
||||
#ifdef USE_WINSOCK
|
||||
typedef SOCKET SOCKET_TYPE;
|
||||
#define ERRSOCKET (SOCKET_ERROR)
|
||||
#else
|
||||
|
@ -165,22 +158,22 @@
|
|||
#define ERRSOCKET (-1)
|
||||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
// define socklen_t in DOS/Windows if it is not already defined
|
||||
#ifdef USE_WINSOCK1
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET};
|
||||
static size_t mysocketses = 0;
|
||||
static int myfamily[MAXNETNODES+1] = {0};
|
||||
static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET};
|
||||
static mysockaddr_t clientaddress[MAXNETNODES+1];
|
||||
static mysockaddr_t broadcastaddress[MAXNETNODES+1];
|
||||
static size_t broadcastaddresses = 0;
|
||||
static boolean nodeconnected[MAXNETNODES+1];
|
||||
static mysockaddr_t banned[MAXBANS];
|
||||
static UINT8 bannedmask[MAXBANS];
|
||||
#define IPV6_MULTICAST_ADDRESS "ff15::57e1:1a12"
|
||||
|
||||
// define socklen_t in DOS/Windows if it is not already defined
|
||||
#ifdef USE_WINSOCK1
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
static SOCKET_TYPE mysockets[MAXNETNODES+1] = {ERRSOCKET};
|
||||
static size_t mysocketses = 0;
|
||||
static int myfamily[MAXNETNODES+1] = {0};
|
||||
static SOCKET_TYPE nodesocket[MAXNETNODES+1] = {ERRSOCKET};
|
||||
static mysockaddr_t clientaddress[MAXNETNODES+1];
|
||||
static mysockaddr_t broadcastaddress[MAXNETNODES+1];
|
||||
static size_t broadcastaddresses = 0;
|
||||
static boolean nodeconnected[MAXNETNODES+1];
|
||||
static mysockaddr_t banned[MAXBANS];
|
||||
static UINT8 bannedmask[MAXBANS];
|
||||
|
||||
static size_t numbans = 0;
|
||||
static boolean SOCK_bannednode[MAXNETNODES+1]; /// \note do we really need the +1?
|
||||
|
@ -189,7 +182,6 @@ static boolean init_tcp_driver = false;
|
|||
static const char *serverport_name = DEFAULTPORT;
|
||||
static const char *clientport_name;/* any port */
|
||||
|
||||
#ifndef NONET
|
||||
#ifdef USE_WINSOCK
|
||||
// stupid microsoft makes things complicated
|
||||
static char *get_WSAErrorStr(int e)
|
||||
|
@ -268,24 +260,21 @@ static const char* inet_ntopA(short af, const void *cp, char *buf, socklen_t len
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_MINIUPNPC // based on old XChat patch
|
||||
static void I_ShutdownUPnP(void);
|
||||
static struct UPNPUrls urls;
|
||||
static struct IGDdatas data;
|
||||
static char lanaddr[64];
|
||||
|
||||
static void I_ShutdownUPnP(void)
|
||||
{
|
||||
FreeUPNPUrls(&urls);
|
||||
}
|
||||
|
||||
static inline void I_InitUPnP(void)
|
||||
{
|
||||
const char * const deviceTypes[] = {
|
||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
|
||||
"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
|
||||
0
|
||||
};
|
||||
struct UPNPDev * devlist = NULL;
|
||||
int upnp_error = -2;
|
||||
int scope_id = 0;
|
||||
int status_code = 0;
|
||||
CONS_Printf(M_GetText("Looking for UPnP Internet Gateway Device\n"));
|
||||
devlist = upnpDiscoverDevices(deviceTypes, 500, NULL, NULL, 0, false, 2, &upnp_error, 0);
|
||||
devlist = upnpDiscover(2000, NULL, NULL, 0, false, &upnp_error);
|
||||
if (devlist)
|
||||
{
|
||||
struct UPNPDev *dev = devlist;
|
||||
|
@ -305,7 +294,7 @@ static inline void I_InitUPnP(void)
|
|||
|
||||
UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
|
||||
CONS_Printf(M_GetText("Local LAN IP address: %s\n"), lanaddr);
|
||||
descXML = miniwget(dev->descURL, &descXMLsize, scope_id, &status_code);
|
||||
descXML = miniwget(dev->descURL, &descXMLsize);
|
||||
if (descXML)
|
||||
{
|
||||
parserootdesc(descXML, descXMLsize, &data);
|
||||
|
@ -313,7 +302,7 @@ static inline void I_InitUPnP(void)
|
|||
descXML = NULL;
|
||||
memset(&urls, 0, sizeof(struct UPNPUrls));
|
||||
memset(&data, 0, sizeof(struct IGDdatas));
|
||||
GetUPNPUrls(&urls, &data, dev->descURL, status_code);
|
||||
GetUPNPUrls(&urls, &data, dev->descURL);
|
||||
I_AddExitFunc(I_ShutdownUPnP);
|
||||
}
|
||||
freeUPNPDevlist(devlist);
|
||||
|
@ -341,12 +330,6 @@ static inline void I_UPnP_rem(const char *port, const char * servicetype)
|
|||
UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype,
|
||||
port, servicetype, NULL);
|
||||
}
|
||||
|
||||
static void I_ShutdownUPnP(void)
|
||||
{
|
||||
I_UPnP_rem(serverport_name, "UDP");
|
||||
FreeUPNPUrls(&urls);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *SOCK_AddrToStr(mysockaddr_t *sk)
|
||||
|
@ -398,47 +381,47 @@ static const char *SOCK_AddrToStr(mysockaddr_t *sk)
|
|||
#endif
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char *SOCK_GetNodeAddress(INT32 node)
|
||||
{
|
||||
if (node == 0)
|
||||
return "self";
|
||||
#ifdef NONET
|
||||
return NULL;
|
||||
#else
|
||||
if (!nodeconnected[node])
|
||||
return NULL;
|
||||
return SOCK_AddrToStr(&clientaddress[node]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *SOCK_GetBanAddress(size_t ban)
|
||||
{
|
||||
if (ban >= numbans)
|
||||
return NULL;
|
||||
#ifdef NONET
|
||||
return NULL;
|
||||
#else
|
||||
return SOCK_AddrToStr(&banned[ban]);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *SOCK_GetBanMask(size_t ban)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)ban;
|
||||
#else
|
||||
static char s[16]; //255.255.255.255 netmask? no, just CDIR for only
|
||||
if (ban >= numbans)
|
||||
return NULL;
|
||||
if (sprintf(s,"%d",bannedmask[ban]) > 0)
|
||||
return s;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
#ifdef HAVE_IPV6
|
||||
static boolean SOCK_cmpipv6(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
|
||||
{
|
||||
UINT8 bitmask;
|
||||
I_Assert(mask <= 128);
|
||||
if (memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, mask / 8) != 0)
|
||||
return false;
|
||||
if (mask % 8 == 0)
|
||||
return true;
|
||||
bitmask = 255 << (mask % 8);
|
||||
return (a->ip6.sin6_addr.s6_addr[mask / 8] & bitmask) == (b->ip6.sin6_addr.s6_addr[mask / 8] & bitmask);
|
||||
}
|
||||
#endif
|
||||
|
||||
static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
|
||||
{
|
||||
UINT32 bitmask = INADDR_NONE;
|
||||
|
@ -451,7 +434,7 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
|
|||
&& (b->ip4.sin_port == 0 || (a->ip4.sin_port == b->ip4.sin_port));
|
||||
#ifdef HAVE_IPV6
|
||||
else if (b->any.sa_family == AF_INET6)
|
||||
return !memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(b->ip6.sin6_addr))
|
||||
return SOCK_cmpipv6(a, b, mask)
|
||||
&& (b->ip6.sin6_port == 0 || (a->ip6.sin6_port == b->ip6.sin6_port));
|
||||
#endif
|
||||
else
|
||||
|
@ -466,24 +449,20 @@ static boolean SOCK_cmpaddr(mysockaddr_t *a, mysockaddr_t *b, UINT8 mask)
|
|||
*/
|
||||
static void cleanupnodes(void)
|
||||
{
|
||||
SINT8 j;
|
||||
|
||||
if (!Playing())
|
||||
return;
|
||||
|
||||
// Why can't I start at zero?
|
||||
for (j = 1; j < MAXNETNODES; j++)
|
||||
if (!(nodeingame[j] || SendingFile(j)))
|
||||
for (SINT8 j = 1; j < MAXNETNODES; j++)
|
||||
if (!(netnodes[j].ingame || SendingFile(j)))
|
||||
nodeconnected[j] = false;
|
||||
}
|
||||
|
||||
static SINT8 getfreenode(void)
|
||||
{
|
||||
SINT8 j;
|
||||
|
||||
cleanupnodes();
|
||||
|
||||
for (j = 0; j < MAXNETNODES; j++)
|
||||
for (SINT8 j = 0; j < MAXNETNODES; j++)
|
||||
if (!nodeconnected[j])
|
||||
{
|
||||
nodeconnected[j] = true;
|
||||
|
@ -496,8 +475,8 @@ static SINT8 getfreenode(void)
|
|||
* downloading a needed wad, but it's better than not letting anyone join...
|
||||
*/
|
||||
/*I_Error("No more free nodes!!1!11!11!!1111\n");
|
||||
for (j = 1; j < MAXNETNODES; j++)
|
||||
if (!nodeingame[j])
|
||||
for (SINT8 j = 1; j < MAXNETNODES; j++)
|
||||
if (!netnodes[j].ingame)
|
||||
return j;*/
|
||||
|
||||
return -1;
|
||||
|
@ -508,28 +487,27 @@ void Command_Numnodes(void)
|
|||
{
|
||||
INT32 connected = 0;
|
||||
INT32 ingame = 0;
|
||||
INT32 i;
|
||||
|
||||
for (i = 1; i < MAXNETNODES; i++)
|
||||
for (INT32 i = 1; i < MAXNETNODES; i++)
|
||||
{
|
||||
if (!(nodeconnected[i] || nodeingame[i]))
|
||||
if (!(nodeconnected[i] || netnodes[i].ingame))
|
||||
continue;
|
||||
|
||||
if (nodeconnected[i])
|
||||
connected++;
|
||||
if (nodeingame[i])
|
||||
if (netnodes[i].ingame)
|
||||
ingame++;
|
||||
|
||||
CONS_Printf("%2d - ", i);
|
||||
if (nodetoplayer[i] != -1)
|
||||
CONS_Printf("player %.2d", nodetoplayer[i]);
|
||||
if (netnodes[i].player != -1)
|
||||
CONS_Printf("player %.2d", netnodes[i].player);
|
||||
else
|
||||
CONS_Printf(" ");
|
||||
if (nodeconnected[i])
|
||||
CONS_Printf(" - connected");
|
||||
else
|
||||
CONS_Printf(" - ");
|
||||
if (nodeingame[i])
|
||||
if (netnodes[i].ingame)
|
||||
CONS_Printf(" - ingame");
|
||||
else
|
||||
CONS_Printf(" - ");
|
||||
|
@ -542,19 +520,17 @@ void Command_Numnodes(void)
|
|||
connected, ingame);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
// Returns true if a packet was received from a new node, false in all other cases
|
||||
static boolean SOCK_Get(void)
|
||||
{
|
||||
size_t i, n;
|
||||
size_t i;
|
||||
int j;
|
||||
ssize_t c;
|
||||
mysockaddr_t fromaddress;
|
||||
socklen_t fromlen;
|
||||
|
||||
for (n = 0; n < mysocketses; n++)
|
||||
for (size_t n = 0; n < mysocketses; n++)
|
||||
{
|
||||
fromlen = (socklen_t)sizeof(fromaddress);
|
||||
c = recvfrom(mysockets[n], (char *)&doomcom->data, MAXPACKETLENGTH, 0,
|
||||
|
@ -607,20 +583,17 @@ static boolean SOCK_Get(void)
|
|||
doomcom->remotenode = -1; // no packet
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
// check if we can send (do not go over the buffer)
|
||||
#ifndef NONET
|
||||
|
||||
static fd_set masterset;
|
||||
|
||||
#ifdef SELECTTEST
|
||||
static boolean FD_CPY(fd_set *src, fd_set *dst, SOCKET_TYPE *fd, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
boolean testset = false;
|
||||
FD_ZERO(dst);
|
||||
for (i = 0; i < len;i++)
|
||||
for (size_t i = 0; i < len;i++)
|
||||
{
|
||||
if(fd[i] != (SOCKET_TYPE)ERRSOCKET &&
|
||||
FD_ISSET(fd[i], src) && !FD_ISSET(fd[i], dst)) // no checking for dups
|
||||
|
@ -660,9 +633,7 @@ static boolean SOCK_CanGet(void)
|
|||
return false;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr)
|
||||
{
|
||||
socklen_t d4 = (socklen_t)sizeof(struct sockaddr_in);
|
||||
|
@ -670,6 +641,7 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
|
|||
socklen_t d6 = (socklen_t)sizeof(struct sockaddr_in6);
|
||||
#endif
|
||||
socklen_t d, da = (socklen_t)sizeof(mysockaddr_t);
|
||||
ssize_t status;
|
||||
|
||||
switch (sockaddr->any.sa_family)
|
||||
{
|
||||
|
@ -680,22 +652,26 @@ static inline ssize_t SOCK_SendToAddr(SOCKET_TYPE socket, mysockaddr_t *sockaddr
|
|||
default: d = da; break;
|
||||
}
|
||||
|
||||
return sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
|
||||
status = sendto(socket, (char *)&doomcom->data, doomcom->datalength, 0, &sockaddr->any, d);
|
||||
if (status == -1)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, "Unable to send packet to %s: %s\n", SOCK_AddrToStr(sockaddr), strerror(errno));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static void SOCK_Send(void)
|
||||
{
|
||||
ssize_t c = ERRSOCKET;
|
||||
size_t i, j;
|
||||
|
||||
if (!nodeconnected[doomcom->remotenode])
|
||||
return;
|
||||
|
||||
if (doomcom->remotenode == BROADCASTADDR)
|
||||
{
|
||||
for (i = 0; i < mysocketses; i++)
|
||||
for (size_t i = 0; i < mysocketses; i++)
|
||||
{
|
||||
for (j = 0; j < broadcastaddresses; j++)
|
||||
for (size_t j = 0; j < broadcastaddresses; j++)
|
||||
{
|
||||
if (myfamily[i] == broadcastaddress[j].any.sa_family)
|
||||
SOCK_SendToAddr(mysockets[i], &broadcastaddress[j]);
|
||||
|
@ -705,7 +681,7 @@ static void SOCK_Send(void)
|
|||
}
|
||||
else if (nodesocket[doomcom->remotenode] == (SOCKET_TYPE)ERRSOCKET)
|
||||
{
|
||||
for (i = 0; i < mysocketses; i++)
|
||||
for (size_t i = 0; i < mysocketses; i++)
|
||||
{
|
||||
if (myfamily[i] == clientaddress[doomcom->remotenode].any.sa_family)
|
||||
SOCK_SendToAddr(mysockets[i], &clientaddress[doomcom->remotenode]);
|
||||
|
@ -720,14 +696,12 @@ static void SOCK_Send(void)
|
|||
if (c == ERRSOCKET)
|
||||
{
|
||||
int e = errno; // save error code so it can't be modified later
|
||||
if (e != ECONNREFUSED && e != EWOULDBLOCK)
|
||||
if (e != ECONNREFUSED && e != EWOULDBLOCK && e != EHOSTUNREACH)
|
||||
I_Error("SOCK_Send, error sending to node %d (%s) #%u: %s", doomcom->remotenode,
|
||||
SOCK_GetNodeAddress(doomcom->remotenode), e, strerror(e));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef NONET
|
||||
static void SOCK_FreeNodenum(INT32 numnode)
|
||||
{
|
||||
// can't disconnect from self :)
|
||||
|
@ -742,12 +716,10 @@ static void SOCK_FreeNodenum(INT32 numnode)
|
|||
// put invalid address
|
||||
memset(&clientaddress[numnode], 0, sizeof (clientaddress[numnode]));
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// UDPsocket
|
||||
//
|
||||
#ifndef NONET
|
||||
|
||||
// allocate a socket
|
||||
static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen)
|
||||
|
@ -824,6 +796,24 @@ static SOCKET_TYPE UDP_Bind(int family, struct sockaddr *addr, socklen_t addrlen
|
|||
return (SOCKET_TYPE)ERRSOCKET;
|
||||
}
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (family == AF_INET6)
|
||||
{
|
||||
// we need to set all of this *after* binding to an address!
|
||||
if (memcmp(&straddr.ip6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) //IN6_ARE_ADDR_EQUAL
|
||||
{
|
||||
struct ipv6_mreq maddr;
|
||||
|
||||
inet_pton(AF_INET6, IPV6_MULTICAST_ADDRESS, &maddr.ipv6mr_multiaddr);
|
||||
maddr.ipv6mr_interface = 0;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&maddr, sizeof(maddr)) != 0)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Could not register multicast address\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef FIONBIO
|
||||
// make it non blocking
|
||||
opt = true;
|
||||
|
@ -1004,65 +994,28 @@ static boolean UDP_Socket(void)
|
|||
// ip + udp
|
||||
packetheaderlength = 20 + 8; // for stats
|
||||
|
||||
hints.ai_family = AF_INET;
|
||||
gaie = I_getaddrinfo("127.0.0.1", "0", &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
while (runp != NULL && s < MAXNETNODES+1)
|
||||
{
|
||||
memcpy(&clientaddress[s], runp->ai_addr, runp->ai_addrlen);
|
||||
s++;
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
I_freeaddrinfo(ai);
|
||||
}
|
||||
else
|
||||
{
|
||||
clientaddress[s].any.sa_family = AF_INET;
|
||||
clientaddress[s].ip4.sin_port = htons(0);
|
||||
clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip
|
||||
s++;
|
||||
}
|
||||
clientaddress[s].any.sa_family = AF_INET;
|
||||
clientaddress[s].ip4.sin_port = htons(0);
|
||||
clientaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); //GetLocalAddress(); // my own ip
|
||||
s++;
|
||||
|
||||
s = 0;
|
||||
|
||||
// setup broadcast adress to BROADCASTADDR entry
|
||||
gaie = I_getaddrinfo("255.255.255.255", "0", &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
while (runp != NULL && s < MAXNETNODES+1)
|
||||
{
|
||||
memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
|
||||
s++;
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
I_freeaddrinfo(ai);
|
||||
}
|
||||
else
|
||||
{
|
||||
broadcastaddress[s].any.sa_family = AF_INET;
|
||||
broadcastaddress[s].ip4.sin_port = htons(0);
|
||||
broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||
s++;
|
||||
}
|
||||
broadcastaddress[s].any.sa_family = AF_INET;
|
||||
broadcastaddress[s].ip4.sin_port = htons(atoi(DEFAULTPORT));
|
||||
broadcastaddress[s].ip4.sin_addr.s_addr = htonl(INADDR_BROADCAST);
|
||||
s++;
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
if (b_ipv6)
|
||||
{
|
||||
hints.ai_family = AF_INET6;
|
||||
gaie = I_getaddrinfo("ff02::1", "0", &hints, &ai);
|
||||
if (gaie == 0)
|
||||
{
|
||||
runp = ai;
|
||||
while (runp != NULL && s < MAXNETNODES+1)
|
||||
{
|
||||
memcpy(&broadcastaddress[s], runp->ai_addr, runp->ai_addrlen);
|
||||
s++;
|
||||
runp = runp->ai_next;
|
||||
}
|
||||
I_freeaddrinfo(ai);
|
||||
}
|
||||
broadcastaddress[s].any.sa_family = AF_INET6;
|
||||
broadcastaddress[s].ip6.sin6_port = htons(atoi(DEFAULTPORT));
|
||||
broadcastaddress[s].ip6.sin6_flowinfo = 0;
|
||||
inet_pton(AF_INET6, IPV6_MULTICAST_ADDRESS, &broadcastaddress[s].ip6.sin6_addr);
|
||||
broadcastaddress[s].ip6.sin6_scope_id = 0;
|
||||
s++;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1072,12 +1025,10 @@ static boolean UDP_Socket(void)
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
boolean I_InitTcpDriver(void)
|
||||
{
|
||||
boolean tcp_was_up = init_tcp_driver;
|
||||
#ifndef NONET
|
||||
if (!init_tcp_driver)
|
||||
{
|
||||
#ifdef USE_WINSOCK
|
||||
|
@ -1132,25 +1083,23 @@ boolean I_InitTcpDriver(void)
|
|||
#endif
|
||||
init_tcp_driver = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!tcp_was_up && init_tcp_driver)
|
||||
{
|
||||
I_AddExitFunc(I_ShutdownTcpDriver);
|
||||
#ifdef HAVE_MINIUPNPC
|
||||
if (M_CheckParm("-noUPnP"))
|
||||
UPNP_support = false;
|
||||
else
|
||||
if (M_CheckParm("-useUPnP"))
|
||||
I_InitUPnP();
|
||||
else
|
||||
UPNP_support = false;
|
||||
#endif
|
||||
}
|
||||
return init_tcp_driver;
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static void SOCK_CloseSocket(void)
|
||||
{
|
||||
size_t i;
|
||||
for (i=0; i < MAXNETNODES+1; i++)
|
||||
for (size_t i=0; i < MAXNETNODES+1; i++)
|
||||
{
|
||||
if (mysockets[i] != (SOCKET_TYPE)ERRSOCKET
|
||||
&& FD_ISSET(mysockets[i], &masterset))
|
||||
|
@ -1161,11 +1110,9 @@ static void SOCK_CloseSocket(void)
|
|||
mysockets[i] = ERRSOCKET;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void I_ShutdownTcpDriver(void)
|
||||
{
|
||||
#ifndef NONET
|
||||
SOCK_CloseSocket();
|
||||
|
||||
CONS_Printf("I_ShutdownTcpDriver: ");
|
||||
|
@ -1175,10 +1122,8 @@ void I_ShutdownTcpDriver(void)
|
|||
#endif
|
||||
CONS_Printf("shut down\n");
|
||||
init_tcp_driver = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NONET
|
||||
static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
|
||||
{
|
||||
SINT8 newnode = -1;
|
||||
|
@ -1234,17 +1179,13 @@ static SINT8 SOCK_NetMakeNodewPort(const char *address, const char *port)
|
|||
I_freeaddrinfo(ai);
|
||||
return newnode;
|
||||
}
|
||||
#endif
|
||||
|
||||
static boolean SOCK_OpenSocket(void)
|
||||
{
|
||||
#ifndef NONET
|
||||
size_t i;
|
||||
|
||||
memset(clientaddress, 0, sizeof (clientaddress));
|
||||
|
||||
nodeconnected[0] = true; // always connected to self
|
||||
for (i = 1; i < MAXNETNODES; i++)
|
||||
for (size_t i = 1; i < MAXNETNODES; i++)
|
||||
nodeconnected[i] = false;
|
||||
nodeconnected[BROADCASTADDR] = true;
|
||||
I_NetSend = SOCK_Send;
|
||||
|
@ -1262,18 +1203,12 @@ static boolean SOCK_OpenSocket(void)
|
|||
// build the socket but close it first
|
||||
SOCK_CloseSocket();
|
||||
return UDP_Socket();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean SOCK_Ban(INT32 node)
|
||||
{
|
||||
if (node > MAXNETNODES)
|
||||
return false;
|
||||
#ifdef NONET
|
||||
return false;
|
||||
#else
|
||||
if (numbans == MAXBANS)
|
||||
return false;
|
||||
|
||||
|
@ -1292,16 +1227,10 @@ static boolean SOCK_Ban(INT32 node)
|
|||
#endif
|
||||
numbans++;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
||||
{
|
||||
#ifdef NONET
|
||||
(void)address;
|
||||
(void)mask;
|
||||
return false;
|
||||
#else
|
||||
struct my_addrinfo *ai, *runp, hints;
|
||||
int gaie;
|
||||
|
||||
|
@ -1346,7 +1275,6 @@ static boolean SOCK_SetBanAddress(const char *address, const char *mask)
|
|||
I_freeaddrinfo(ai);
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void SOCK_ClearBans(void)
|
||||
|
@ -1452,4 +1380,13 @@ boolean I_InitTcpNetwork(void)
|
|||
return ret;
|
||||
}
|
||||
|
||||
boolean Net_IsNodeIPv6(INT32 node)
|
||||
{
|
||||
#ifdef NO_IPV6
|
||||
return false;
|
||||
#else
|
||||
return clientaddress[node].any.sa_family == AF_INET6;
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "i_addrinfo.c"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue