games/qtv: New port: QuakeWorld match broadcasting tool
The maximum number of players and spectators in QuakeWorld is 32. QTV allows hundreds and even thousands of spectators to watch the game at the same time. Also, a delay of about 10 seconds has been added so that spectators cannot prompt players with information about opponents during the game via voice chats. In such a dynamic game as QuakeWorld, a lot can change in a few seconds and the information will be out of date.
This commit is contained in:
parent
7927033436
commit
5578dbccb5
@ -819,6 +819,7 @@
|
||||
SUBDIR += qonk
|
||||
SUBDIR += qqwing
|
||||
SUBDIR += qstat
|
||||
SUBDIR += qtv
|
||||
SUBDIR += quackle
|
||||
SUBDIR += quadra
|
||||
SUBDIR += quadrapassel
|
||||
|
||||
49
games/qtv/Makefile
Normal file
49
games/qtv/Makefile
Normal file
@ -0,0 +1,49 @@
|
||||
PORTNAME= qtv
|
||||
DISTVERSION= 1.15
|
||||
CATEGORIES= games
|
||||
|
||||
MAINTAINER= vvd@FreeBSD.org
|
||||
COMMENT= QuakeWorld match broadcasting tool
|
||||
WWW= https://github.com/QW-Group/qtv/
|
||||
|
||||
LICENSE= GPLv2
|
||||
LICENSE_FILE= ${WRKSRC}/LICENSE.md
|
||||
|
||||
USES= cmake
|
||||
|
||||
USE_GITHUB= yes
|
||||
GH_ACCOUNT= QW-Group
|
||||
USE_RC_SUBR= ${PORTNAME}
|
||||
|
||||
EXTRACT_AFTER_ARGS= --exclude .git* \
|
||||
--exclude */.git* \
|
||||
--exclude build_cmake.sh \
|
||||
--exclude resources/example-configs/"PLACE YOUR QTV.BIN HERE" \
|
||||
--exclude resources/metaqtv* \
|
||||
--exclude tools*
|
||||
|
||||
QWDIR= ${PREFIX}/quake
|
||||
SUB_LIST= QWDIR=${QWDIR} QWUSER=${USERS}
|
||||
USERS= qw
|
||||
GROUPS= qw
|
||||
PLIST_SUB= QWGROUP=${GROUPS}
|
||||
PORTDOCS= README.md
|
||||
|
||||
OPTIONS_DEFINE= DOCS
|
||||
|
||||
do-install:
|
||||
${INSTALL_PROGRAM} ${BUILD_WRKSRC}/${PORTNAME} ${STAGEDIR}${PREFIX}/bin
|
||||
cd ${WRKSRC}/resources/example-configs && \
|
||||
${COPYTREE_SHARE} ${PORTNAME} ${STAGEDIR}${QWDIR}
|
||||
${MV} ${STAGEDIR}${QWDIR}/${PORTNAME}/listip.cfg \
|
||||
${STAGEDIR}${QWDIR}/${PORTNAME}/listip.cfg.sample
|
||||
${INSTALL_DATA} ${WRKSRC}/resources/example-configs/${PORTNAME}.cfg \
|
||||
${STAGEDIR}${QWDIR}/${PORTNAME}/${PORTNAME}.cfg.sample
|
||||
|
||||
do-install-DOCS-on:
|
||||
${MKDIR} ${STAGEDIR}${DOCSDIR}
|
||||
${INSTALL_DATA} ${PORTDOCS:S,^,${WRKSRC}/,} ${STAGEDIR}${DOCSDIR}
|
||||
${INSTALL_DATA} ${WRKSRC}/resources/example-configs/README.1ST \
|
||||
${STAGEDIR}${DOCSDIR}
|
||||
|
||||
.include <bsd.port.mk>
|
||||
3
games/qtv/distinfo
Normal file
3
games/qtv/distinfo
Normal file
@ -0,0 +1,3 @@
|
||||
TIMESTAMP = 1739923712
|
||||
SHA256 (QW-Group-qtv-1.15_GH0.tar.gz) = ab9e699bb0894dd8274c8c7c56d7bba44e75b2a123baf17212aa2f60aef6111c
|
||||
SIZE (QW-Group-qtv-1.15_GH0.tar.gz) = 1000884
|
||||
20
games/qtv/files/patch-src_fs.c
Normal file
20
games/qtv/files/patch-src_fs.c
Normal file
@ -0,0 +1,20 @@
|
||||
--- src/fs.c.orig 2025-02-16 14:10:58 UTC
|
||||
+++ src/fs.c
|
||||
@@ -119,6 +119,7 @@ void FS_StripPathAndExtension(char *filepath)
|
||||
size_t lastslash = (size_t) -1;
|
||||
size_t lastdot = (size_t) -1;
|
||||
size_t i = 0;
|
||||
+ char temp_filepath[MAX_QPATH];
|
||||
|
||||
for ( ; filepath[i]; i++)
|
||||
{
|
||||
@@ -131,7 +132,8 @@ void FS_StripPathAndExtension(char *filepath)
|
||||
if (lastdot == (size_t) -1 || lastdot < lastslash)
|
||||
lastdot = i;
|
||||
|
||||
- strlcpy(filepath, filepath + lastslash + 1, lastdot - lastslash);
|
||||
+ strlcpy(temp_filepath, filepath + lastslash + 1, lastdot - lastslash);
|
||||
+ strlcpy(filepath, temp_filepath, sizeof(temp_filepath));
|
||||
}
|
||||
|
||||
// return file extension with dot, or empty string if dot not found at all
|
||||
15
games/qtv/files/patch-src_main.c
Normal file
15
games/qtv/files/patch-src_main.c
Normal file
@ -0,0 +1,15 @@
|
||||
--- src/main.c.orig 2025-02-16 14:10:58 UTC
|
||||
+++ src/main.c
|
||||
@@ -274,6 +274,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
#endif // _WIN32
|
||||
|
||||
+ // Disable buffering for stdout and stderr to avoid issues when output
|
||||
+ // is redirected to a file or pipe instead of being displayed in a
|
||||
+ // terminal.
|
||||
+ setbuf(stdout, NULL);
|
||||
+ setbuf(stderr, NULL);
|
||||
+
|
||||
memset(&g_cluster, 0, sizeof(g_cluster));
|
||||
|
||||
g_cluster.tcpsocket = INVALID_SOCKET;
|
||||
18
games/qtv/files/patch-src_net__utils.c
Normal file
18
games/qtv/files/patch-src_net__utils.c
Normal file
@ -0,0 +1,18 @@
|
||||
--- src/net_utils.c.orig 2025-02-16 14:10:58 UTC
|
||||
+++ src/net_utils.c
|
||||
@@ -60,11 +60,13 @@ char *Net_BaseAdrToString (struct sockaddr_in *a, char
|
||||
// Windows have inet_ntop only starting from Vista. Sigh.
|
||||
#ifdef _WIN32
|
||||
const char *result = inet_ntoa(a->sin_addr);
|
||||
+ strlcpy(buf, result ? result : "", bufsize);
|
||||
#else
|
||||
const char *result = inet_ntop(a->sin_family, &a->sin_addr, buf, bufsize);
|
||||
+ if (!result) {
|
||||
+ strlcpy(buf, "", bufsize);
|
||||
+ }
|
||||
#endif
|
||||
-
|
||||
- strlcpy(buf, result ? result : "", bufsize);
|
||||
|
||||
return buf;
|
||||
}
|
||||
106
games/qtv/files/qtv.in
Executable file
106
games/qtv/files/qtv.in
Executable file
@ -0,0 +1,106 @@
|
||||
#!/bin/sh
|
||||
|
||||
# PROVIDE: qtv
|
||||
# REQUIRE: LOGIN
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf or /etc/rc.conf.local to
|
||||
# enable qtv:
|
||||
# qtv_(instance_)?enable (bool): Set to "NO" by default.
|
||||
# Set it to "YES" to enable qtv.
|
||||
# qtv_(instance_)?args (str): Custom additional arguments to be passed
|
||||
# to qtv (default empty).
|
||||
# qtv_(instance_)?user (str): User to run qtv as. Default to
|
||||
# "%%QWUSER%%" created by the port.
|
||||
# qtv_(instance_)?log (path): Console log file (default
|
||||
# /var/log/${name}(_instance)?.log).
|
||||
# qtv_(instance_)?qwdir (path): QuakeWorld root directory
|
||||
# (default %%QWDIR%%).
|
||||
# qtv_instances (str): Set to "" by default.
|
||||
# If defined, list of instances to enable.
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
case $0 in
|
||||
/etc/rc*)
|
||||
# during boot (shutdown) $0 is /etc/rc (/etc/rc.shutdown),
|
||||
# so get the name of the script from $_file
|
||||
name=$_file
|
||||
;;
|
||||
*)
|
||||
name=$0
|
||||
;;
|
||||
esac
|
||||
|
||||
name=${name##*/}
|
||||
rcvar="${name}_enable"
|
||||
|
||||
load_rc_config "${name}"
|
||||
|
||||
eval "${rcvar}=\${${rcvar}:-'NO'}"
|
||||
eval "__args=\${${name}_args:-''}"
|
||||
eval "__user=\${${name}_user:-'%%QWUSER%%'}"
|
||||
eval "__log=\${${name}_log:-/var/log/${name}.log}"
|
||||
eval "__qwdir=\${${name}_qwdir:-'%%QWDIR%%'}"
|
||||
eval "${name}_chdir=${__qwdir}"
|
||||
eval "__instances=\${${name}_instances:-''}"
|
||||
|
||||
pidfiledir="/var/run"
|
||||
pidfile="${pidfiledir}/${name}.pid"
|
||||
|
||||
if [ -n "$2" ]; then
|
||||
instance="$2"
|
||||
load_rc_config ${name}_${instance}
|
||||
case "${__instances}" in
|
||||
"$2 "*|*" $2 "*|*" $2"|"$2")
|
||||
eval "__args=\${${name}_${instance}_args:-${__args}}"
|
||||
eval "__user=\${${name}_${instance}_user:-${__user}}"
|
||||
eval "__log=\${${name}_${instance}_log:-/var/log/${name}_${instance}.log}"
|
||||
eval "__qwdir=\${${name}_${instance}_qwdir:-${__qwdir}}"
|
||||
eval "${name}_chdir=${__qwdir}"
|
||||
pidfile="${pidfiledir}/${name}_${instance}.pid"
|
||||
;;
|
||||
*)
|
||||
err 1 "$2 not found in ${name}_instances" ;;
|
||||
esac
|
||||
else
|
||||
if [ -n "${__instances}" -a -n "$1" ]; then
|
||||
for instance in ${__instances}; do
|
||||
eval "_enable=\${${name}_${instance}_enable}"
|
||||
eval "__enable=\${_enable:-\${${name}_enable}}"
|
||||
case "${__enable}" in
|
||||
[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
|
||||
continue
|
||||
;;
|
||||
[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
|
||||
;;
|
||||
*)
|
||||
if [ -z "${_enable}" ]; then
|
||||
_var=${name}_enable
|
||||
else
|
||||
_var=${name}_${instance}_enable
|
||||
fi
|
||||
warn "Bad value '${__enable}' for ${_var}. " \
|
||||
"Instance ${instance} skipped."
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
echo "===> ${name} instance: ${instance}"
|
||||
%%PREFIX%%/etc/rc.d/${name} $1 ${instance}
|
||||
retcode="$?"
|
||||
if [ "0${retcode}" -eq 0 ]; then
|
||||
success="${instance} ${success}"
|
||||
else
|
||||
failed="${instance} (retcode=${retcode}) ${failed}"
|
||||
fi
|
||||
done
|
||||
echo "===> ${name} instances success: ${success}"
|
||||
echo "===> ${name} instances failed: ${failed}"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
command="/usr/sbin/daemon"
|
||||
command_args="-P ${pidfile} -u ${__user} -R 5 -f -H -o ${__log} -m 3 %%PREFIX%%/bin/qtv ${__args}"
|
||||
|
||||
run_rc_command "$1"
|
||||
8
games/qtv/pkg-descr
Normal file
8
games/qtv/pkg-descr
Normal file
@ -0,0 +1,8 @@
|
||||
QTV is a QuakeWorld match broadcasting tool.
|
||||
|
||||
The maximum number of players and spectators in QuakeWorld is 32. QTV allows
|
||||
hundreds and even thousands of spectators to watch the game at the same time.
|
||||
Also, a delay of about 10 seconds has been added so that spectators cannot
|
||||
prompt players with information about opponents during the game via voice chats.
|
||||
In such a dynamic game as QuakeWorld, a lot can change in a few seconds and the
|
||||
information will be out of date.
|
||||
102
games/qtv/pkg-plist
Normal file
102
games/qtv/pkg-plist
Normal file
@ -0,0 +1,102 @@
|
||||
bin/qtv
|
||||
quake/qtv/levelshots/1on1.jpg
|
||||
quake/qtv/levelshots/1on1r.jpg
|
||||
quake/qtv/levelshots/2fort5.jpg
|
||||
quake/qtv/levelshots/2fort5l.jpg
|
||||
quake/qtv/levelshots/2fort5r.jpg
|
||||
quake/qtv/levelshots/2tech4.jpg
|
||||
quake/qtv/levelshots/32seq.jpg
|
||||
quake/qtv/levelshots/32smooth.jpg
|
||||
quake/qtv/levelshots/_notfound.jpg
|
||||
quake/qtv/levelshots/a2.jpg
|
||||
quake/qtv/levelshots/aerowalk.jpg
|
||||
quake/qtv/levelshots/amphi.jpg
|
||||
quake/qtv/levelshots/bam4.jpg
|
||||
quake/qtv/levelshots/bases.jpg
|
||||
quake/qtv/levelshots/battle.jpg
|
||||
quake/qtv/levelshots/blitzkrieg2.jpg
|
||||
quake/qtv/levelshots/border1.jpg
|
||||
quake/qtv/levelshots/castle.jpg
|
||||
quake/qtv/levelshots/cmt1b.jpg
|
||||
quake/qtv/levelshots/cmt2.jpg
|
||||
quake/qtv/levelshots/cmt3.jpg
|
||||
quake/qtv/levelshots/cmt4.jpg
|
||||
quake/qtv/levelshots/cmt5b.jpg
|
||||
quake/qtv/levelshots/death32c.jpg
|
||||
quake/qtv/levelshots/dm1.jpg
|
||||
quake/qtv/levelshots/dm2.jpg
|
||||
quake/qtv/levelshots/dm3.jpg
|
||||
quake/qtv/levelshots/dm4.jpg
|
||||
quake/qtv/levelshots/dm5.jpg
|
||||
quake/qtv/levelshots/dm6.jpg
|
||||
quake/qtv/levelshots/e1m1.jpg
|
||||
quake/qtv/levelshots/e1m2.jpg
|
||||
quake/qtv/levelshots/e1m3.jpg
|
||||
quake/qtv/levelshots/e1m4.jpg
|
||||
quake/qtv/levelshots/e1m5.jpg
|
||||
quake/qtv/levelshots/e1m6.jpg
|
||||
quake/qtv/levelshots/e1m7.jpg
|
||||
quake/qtv/levelshots/e1m8.jpg
|
||||
quake/qtv/levelshots/e2m1.jpg
|
||||
quake/qtv/levelshots/e2m2.jpg
|
||||
quake/qtv/levelshots/e2m3.jpg
|
||||
quake/qtv/levelshots/e2m4.jpg
|
||||
quake/qtv/levelshots/e2m5.jpg
|
||||
quake/qtv/levelshots/e2m6.jpg
|
||||
quake/qtv/levelshots/e2m7.jpg
|
||||
quake/qtv/levelshots/e3m1.jpg
|
||||
quake/qtv/levelshots/e3m2.jpg
|
||||
quake/qtv/levelshots/e3m3.jpg
|
||||
quake/qtv/levelshots/e3m4.jpg
|
||||
quake/qtv/levelshots/e3m5.jpg
|
||||
quake/qtv/levelshots/e3m6.jpg
|
||||
quake/qtv/levelshots/e3m7.jpg
|
||||
quake/qtv/levelshots/e4m1.jpg
|
||||
quake/qtv/levelshots/e4m2.jpg
|
||||
quake/qtv/levelshots/e4m3.jpg
|
||||
quake/qtv/levelshots/e4m4.jpg
|
||||
quake/qtv/levelshots/e4m5.jpg
|
||||
quake/qtv/levelshots/e4m6.jpg
|
||||
quake/qtv/levelshots/e4m7.jpg
|
||||
quake/qtv/levelshots/e4m8.jpg
|
||||
quake/qtv/levelshots/end.jpg
|
||||
quake/qtv/levelshots/endif.jpg
|
||||
quake/qtv/levelshots/engbat.jpg
|
||||
quake/qtv/levelshots/genders2.jpg
|
||||
quake/qtv/levelshots/hammer.jpg
|
||||
quake/qtv/levelshots/hammerv2.jpg
|
||||
quake/qtv/levelshots/hammerv3.jpg
|
||||
quake/qtv/levelshots/hippos.jpg
|
||||
quake/qtv/levelshots/hohoho.jpg
|
||||
quake/qtv/levelshots/hunted.jpg
|
||||
quake/qtv/levelshots/mbases.jpg
|
||||
quake/qtv/levelshots/pkeg1.jpg
|
||||
quake/qtv/levelshots/povdmm4.jpg
|
||||
quake/qtv/levelshots/qffldm2.jpg
|
||||
quake/qtv/levelshots/qffldm5.jpg
|
||||
quake/qtv/levelshots/rock1.jpg
|
||||
quake/qtv/levelshots/rs_zz1.jpg
|
||||
quake/qtv/levelshots/schloss.jpg
|
||||
quake/qtv/levelshots/skull.jpg
|
||||
quake/qtv/levelshots/sniprwar.jpg
|
||||
quake/qtv/levelshots/spinev2.jpg
|
||||
quake/qtv/levelshots/start.jpg
|
||||
quake/qtv/levelshots/ukcldm2.jpg
|
||||
quake/qtv/levelshots/vote40.jpg
|
||||
quake/qtv/levelshots/well6.jpg
|
||||
quake/qtv/levelshots/xmastree.jpg
|
||||
quake/qtv/levelshots/xpress3.jpg
|
||||
quake/qtv/levelshots/ztndm1.jpg
|
||||
quake/qtv/levelshots/ztndm2.jpg
|
||||
quake/qtv/levelshots/ztndm3.jpg
|
||||
quake/qtv/levelshots/ztndm4.jpg
|
||||
quake/qtv/levelshots/ztndm5.jpg
|
||||
quake/qtv/levelshots/ztndm6.jpg
|
||||
@sample(,%%QWGROUP%%,0640) quake/qtv/listip.cfg.sample
|
||||
@sample(,%%QWGROUP%%,0640) quake/qtv/qtv.cfg.sample
|
||||
quake/qtv/qtvbg01.png
|
||||
quake/qtv/save.png
|
||||
quake/qtv/script.js
|
||||
quake/qtv/stream.png
|
||||
quake/qtv/style.css
|
||||
%%PORTDOCS%%%%DOCSDIR%%/README.1ST
|
||||
Loading…
x
Reference in New Issue
Block a user